mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
feat(rollup): sync finalized batches from L1 (#515)
* feat(rollup): sync finalized batches from L1 * tweak * address comments * address comments * tweak * address comments * Update rollup/eventwatcher/eventwatcher.go Co-authored-by: Péter Garamvölgyi <peter@scroll.io> * address comments * address comments * address comments * add s.rollupSyncService.Stop() * add block chunk batch tests * fix goimports-lint * address comments * address comments * remove * add TestUnpackLog test * add decodeChunkRanges tests * add commit batch version check * fix goimport & golint * tweak * fixes * add TestRollupSyncServiceStartAndStop * add TestGetChunkRanges * address comments * add TestValidateBatch * add TestCalculateFinalizedBatchMeta * address comments * address comments * fix * address comments * address comments * fix * tweak log * fix * tweak logs * increase wait time * add --rollup.verify flag * add flag check in s.rollupSyncService.Stop() * bump version * refactor * tweak configs * tweak * refactor getLocalInfoForBatch * use syscall.Kill(os.Getpid(), syscall.SIGTERM) to shutdown * refactor decodeChunkBlockRanges * nit * address comments * address comments * add WithdrawRoot and StateRoot in FinalizedBatchMeta * address comments * address comments * add ctx.Err() check in retry * add configs in gen_config.go * bump version * fix goimport & golint * try to fix goimport * revert change * fix goimport & golint * tweak * bump version * add l2 block -> batch index mapping * bump version * add mainnet config * bump version * address comments * rename some vars * feat: add more detailed logs in crash case (#547) add more detailed logs in crash case * trigger ci * re-add batch finalization progress log * remove block number -> batch index mapping --------- Co-authored-by: Péter Garamvölgyi <peter@scroll.io> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
This commit is contained in:
parent
bbf42042e2
commit
441212200a
28 changed files with 19845 additions and 22 deletions
|
|
@ -165,6 +165,7 @@ var (
|
||||||
utils.L1ConfirmationsFlag,
|
utils.L1ConfirmationsFlag,
|
||||||
utils.L1DeploymentBlockFlag,
|
utils.L1DeploymentBlockFlag,
|
||||||
utils.CircuitCapacityCheckEnabledFlag,
|
utils.CircuitCapacityCheckEnabledFlag,
|
||||||
|
utils.RollupVerifyEnabledFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
|
|
|
||||||
|
|
@ -836,6 +836,12 @@ var (
|
||||||
Usage: "Enable circuit capacity check during block validation",
|
Usage: "Enable circuit capacity check during block validation",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rollup verify service settings
|
||||||
|
RollupVerifyEnabledFlag = cli.BoolFlag{
|
||||||
|
Name: "rollup.verify",
|
||||||
|
Usage: "Enable verification of batch consistency between L1 and L2 in rollup",
|
||||||
|
}
|
||||||
|
|
||||||
// Max block range for `eth_getLogs` method
|
// Max block range for `eth_getLogs` method
|
||||||
MaxBlockRangeFlag = cli.Int64Flag{
|
MaxBlockRangeFlag = cli.Int64Flag{
|
||||||
Name: "rpc.getlogs.maxrange",
|
Name: "rpc.getlogs.maxrange",
|
||||||
|
|
@ -1546,6 +1552,12 @@ func setCircuitCapacityCheck(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setEnableRollupVerify(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
|
if ctx.GlobalIsSet(RollupVerifyEnabledFlag.Name) {
|
||||||
|
cfg.EnableRollupVerify = ctx.GlobalBool(RollupVerifyEnabledFlag.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setMaxBlockRange(ctx *cli.Context, cfg *ethconfig.Config) {
|
func setMaxBlockRange(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
if ctx.GlobalIsSet(MaxBlockRangeFlag.Name) {
|
if ctx.GlobalIsSet(MaxBlockRangeFlag.Name) {
|
||||||
cfg.MaxBlockRange = ctx.GlobalInt64(MaxBlockRangeFlag.Name)
|
cfg.MaxBlockRange = ctx.GlobalInt64(MaxBlockRangeFlag.Name)
|
||||||
|
|
@ -1620,6 +1632,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
setWhitelist(ctx, cfg)
|
setWhitelist(ctx, cfg)
|
||||||
setLes(ctx, cfg)
|
setLes(ctx, cfg)
|
||||||
setCircuitCapacityCheck(ctx, cfg)
|
setCircuitCapacityCheck(ctx, cfg)
|
||||||
|
setEnableRollupVerify(ctx, cfg)
|
||||||
setMaxBlockRange(ctx, cfg)
|
setMaxBlockRange(ctx, cfg)
|
||||||
|
|
||||||
// Cap the cache allowance and tune the garbage collector
|
// Cap the cache allowance and tune the garbage collector
|
||||||
|
|
|
||||||
146
core/rawdb/accessors_rollup_event.go
Normal file
146
core/rawdb/accessors_rollup_event.go
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
package rawdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/ethdb"
|
||||||
|
"github.com/scroll-tech/go-ethereum/log"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChunkBlockRange represents the range of blocks within a chunk.
|
||||||
|
type ChunkBlockRange struct {
|
||||||
|
StartBlockNumber uint64
|
||||||
|
EndBlockNumber uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// FinalizedBatchMeta holds metadata for finalized batches.
|
||||||
|
type FinalizedBatchMeta struct {
|
||||||
|
BatchHash common.Hash
|
||||||
|
TotalL1MessagePopped uint64 // total number of L1 messages popped before and in this batch.
|
||||||
|
StateRoot common.Hash
|
||||||
|
WithdrawRoot common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteRollupEventSyncedL1BlockNumber stores the latest synced L1 block number related to rollup events in the database.
|
||||||
|
func WriteRollupEventSyncedL1BlockNumber(db ethdb.KeyValueWriter, l1BlockNumber uint64) {
|
||||||
|
value := big.NewInt(0).SetUint64(l1BlockNumber).Bytes()
|
||||||
|
if err := db.Put(rollupEventSyncedL1BlockNumberKey, value); err != nil {
|
||||||
|
log.Crit("failed to store rollup event synced L1 block number for rollup event", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadRollupEventSyncedL1BlockNumber fetches the highest synced L1 block number associated with rollup events from the database.
|
||||||
|
func ReadRollupEventSyncedL1BlockNumber(db ethdb.Reader) *uint64 {
|
||||||
|
data, err := db.Get(rollupEventSyncedL1BlockNumberKey)
|
||||||
|
if err != nil && isNotFoundErr(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("failed to read rollup event synced L1 block number from database", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
number := new(big.Int).SetBytes(data)
|
||||||
|
if !number.IsUint64() {
|
||||||
|
log.Crit("unexpected rollup event synced L1 block number in database", "number", number)
|
||||||
|
}
|
||||||
|
|
||||||
|
rollupEventSyncedL1BlockNumber := number.Uint64()
|
||||||
|
return &rollupEventSyncedL1BlockNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteBatchChunkRanges writes the block ranges for each chunk within a batch to the database.
|
||||||
|
// It serializes the chunk ranges using RLP and stores them under a key derived from the batch index.
|
||||||
|
func WriteBatchChunkRanges(db ethdb.KeyValueWriter, batchIndex uint64, chunkBlockRanges []*ChunkBlockRange) {
|
||||||
|
bytes, err := rlp.EncodeToBytes(chunkBlockRanges)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("failed to RLP encode batch chunk ranges", "batch index", batchIndex, "err", err)
|
||||||
|
}
|
||||||
|
if err := db.Put(batchChunkRangesKey(batchIndex), bytes); err != nil {
|
||||||
|
log.Crit("failed to store batch chunk ranges", "batch index", batchIndex, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBatchChunkRanges removes the block ranges of all chunks associated with a specific batch from the database.
|
||||||
|
// Note: Only non-finalized batches can be reverted.
|
||||||
|
func DeleteBatchChunkRanges(db ethdb.KeyValueWriter, batchIndex uint64) {
|
||||||
|
if err := db.Delete(batchChunkRangesKey(batchIndex)); err != nil {
|
||||||
|
log.Crit("failed to delete batch chunk ranges", "batch index", batchIndex, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBatchChunkRanges retrieves the block ranges of all chunks associated with a specific batch from the database.
|
||||||
|
// It returns a list of ChunkBlockRange pointers, or nil if no chunk ranges are found for the given batch index.
|
||||||
|
func ReadBatchChunkRanges(db ethdb.Reader, batchIndex uint64) []*ChunkBlockRange {
|
||||||
|
data, err := db.Get(batchChunkRangesKey(batchIndex))
|
||||||
|
if err != nil && isNotFoundErr(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("failed to read batch chunk ranges from database", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cr := new([]*ChunkBlockRange)
|
||||||
|
if err := rlp.Decode(bytes.NewReader(data), cr); err != nil {
|
||||||
|
log.Crit("Invalid ChunkBlockRange RLP", "batch index", batchIndex, "data", data, "err", err)
|
||||||
|
}
|
||||||
|
return *cr
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteFinalizedBatchMeta stores the metadata of a finalized batch in the database.
|
||||||
|
func WriteFinalizedBatchMeta(db ethdb.KeyValueWriter, batchIndex uint64, finalizedBatchMeta *FinalizedBatchMeta) {
|
||||||
|
var err error
|
||||||
|
bytes, err := rlp.EncodeToBytes(finalizedBatchMeta)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("failed to RLP encode batch metadata", "batch index", batchIndex, "err", err)
|
||||||
|
}
|
||||||
|
if err := db.Put(batchMetaKey(batchIndex), bytes); err != nil {
|
||||||
|
log.Crit("failed to store batch metadata", "batch index", batchIndex, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFinalizedBatchMeta fetches the metadata of a finalized batch from the database.
|
||||||
|
func ReadFinalizedBatchMeta(db ethdb.Reader, batchIndex uint64) *FinalizedBatchMeta {
|
||||||
|
data, err := db.Get(batchMetaKey(batchIndex))
|
||||||
|
if err != nil && isNotFoundErr(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("failed to read finalized batch metadata from database", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fbm := new(FinalizedBatchMeta)
|
||||||
|
if err := rlp.Decode(bytes.NewReader(data), fbm); err != nil {
|
||||||
|
log.Crit("Invalid FinalizedBatchMeta RLP", "batch index", batchIndex, "data", data, "err", err)
|
||||||
|
}
|
||||||
|
return fbm
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteFinalizedL2BlockNumber stores the highest finalized L2 block number in the database.
|
||||||
|
func WriteFinalizedL2BlockNumber(db ethdb.KeyValueWriter, l2BlockNumber uint64) {
|
||||||
|
value := big.NewInt(0).SetUint64(l2BlockNumber).Bytes()
|
||||||
|
if err := db.Put(finalizedL2BlockNumberKey, value); err != nil {
|
||||||
|
log.Crit("failed to store finalized L2 block number for rollup event", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFinalizedL2BlockNumber fetches the highest finalized L2 block number from the database.
|
||||||
|
func ReadFinalizedL2BlockNumber(db ethdb.Reader) *uint64 {
|
||||||
|
data, err := db.Get(finalizedL2BlockNumberKey)
|
||||||
|
if err != nil && isNotFoundErr(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("failed to read finalized L2 block number from database", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
number := new(big.Int).SetBytes(data)
|
||||||
|
if !number.IsUint64() {
|
||||||
|
log.Crit("unexpected finalized L2 block number in database", "number", number)
|
||||||
|
}
|
||||||
|
|
||||||
|
finalizedL2BlockNumber := number.Uint64()
|
||||||
|
return &finalizedL2BlockNumber
|
||||||
|
}
|
||||||
186
core/rawdb/accessors_rollup_event_test.go
Normal file
186
core/rawdb/accessors_rollup_event_test.go
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
package rawdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWriteRollupEventSyncedL1BlockNumber(t *testing.T) {
|
||||||
|
blockNumbers := []uint64{
|
||||||
|
1,
|
||||||
|
1 << 2,
|
||||||
|
1 << 8,
|
||||||
|
1 << 16,
|
||||||
|
1 << 32,
|
||||||
|
}
|
||||||
|
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
|
||||||
|
// read non-existing value
|
||||||
|
if got := ReadRollupEventSyncedL1BlockNumber(db); got != nil {
|
||||||
|
t.Fatal("Expected 0 for non-existing value", "got", *got)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, num := range blockNumbers {
|
||||||
|
WriteRollupEventSyncedL1BlockNumber(db, num)
|
||||||
|
got := ReadRollupEventSyncedL1BlockNumber(db)
|
||||||
|
|
||||||
|
if *got != num {
|
||||||
|
t.Fatal("Block number mismatch", "expected", num, "got", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFinalizedL2BlockNumber(t *testing.T) {
|
||||||
|
blockNumbers := []uint64{
|
||||||
|
1,
|
||||||
|
1 << 2,
|
||||||
|
1 << 8,
|
||||||
|
1 << 16,
|
||||||
|
1 << 32,
|
||||||
|
}
|
||||||
|
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
|
||||||
|
// read non-existing value
|
||||||
|
if got := ReadFinalizedL2BlockNumber(db); got != nil {
|
||||||
|
t.Fatal("Expected 0 for non-existing value", "got", *got)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, num := range blockNumbers {
|
||||||
|
WriteFinalizedL2BlockNumber(db, num)
|
||||||
|
got := ReadFinalizedL2BlockNumber(db)
|
||||||
|
|
||||||
|
if *got != num {
|
||||||
|
t.Fatal("Block number mismatch", "expected", num, "got", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFinalizedBatchMeta(t *testing.T) {
|
||||||
|
batches := []*FinalizedBatchMeta{
|
||||||
|
{
|
||||||
|
BatchHash: common.BytesToHash([]byte("batch1")),
|
||||||
|
TotalL1MessagePopped: 123,
|
||||||
|
StateRoot: common.BytesToHash([]byte("stateRoot1")),
|
||||||
|
WithdrawRoot: common.BytesToHash([]byte("withdrawRoot1")),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BatchHash: common.BytesToHash([]byte("batch2")),
|
||||||
|
TotalL1MessagePopped: 456,
|
||||||
|
StateRoot: common.BytesToHash([]byte("stateRoot2")),
|
||||||
|
WithdrawRoot: common.BytesToHash([]byte("withdrawRoot2")),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BatchHash: common.BytesToHash([]byte("batch3")),
|
||||||
|
TotalL1MessagePopped: 789,
|
||||||
|
StateRoot: common.BytesToHash([]byte("stateRoot3")),
|
||||||
|
WithdrawRoot: common.BytesToHash([]byte("withdrawRoot3")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
|
||||||
|
for i, batch := range batches {
|
||||||
|
batchIndex := uint64(i)
|
||||||
|
WriteFinalizedBatchMeta(db, batchIndex, batch)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, batch := range batches {
|
||||||
|
batchIndex := uint64(i)
|
||||||
|
readBatch := ReadFinalizedBatchMeta(db, batchIndex)
|
||||||
|
if readBatch == nil {
|
||||||
|
t.Fatal("Failed to read batch from database")
|
||||||
|
}
|
||||||
|
if readBatch.BatchHash != batch.BatchHash || readBatch.TotalL1MessagePopped != batch.TotalL1MessagePopped ||
|
||||||
|
readBatch.StateRoot != batch.StateRoot || readBatch.WithdrawRoot != batch.WithdrawRoot {
|
||||||
|
t.Fatal("Mismatch in read batch", "expected", batch, "got", readBatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// over-write
|
||||||
|
newBatch := &FinalizedBatchMeta{
|
||||||
|
BatchHash: common.BytesToHash([]byte("newBatch")),
|
||||||
|
TotalL1MessagePopped: 999,
|
||||||
|
StateRoot: common.BytesToHash([]byte("newStateRoot")),
|
||||||
|
WithdrawRoot: common.BytesToHash([]byte("newWithdrawRoot")),
|
||||||
|
}
|
||||||
|
WriteFinalizedBatchMeta(db, 0, newBatch) // over-writing the batch with index 0
|
||||||
|
readBatch := ReadFinalizedBatchMeta(db, 0)
|
||||||
|
if readBatch.BatchHash != newBatch.BatchHash || readBatch.TotalL1MessagePopped != newBatch.TotalL1MessagePopped ||
|
||||||
|
readBatch.StateRoot != newBatch.StateRoot || readBatch.WithdrawRoot != newBatch.WithdrawRoot {
|
||||||
|
t.Fatal("Mismatch after over-writing batch", "expected", newBatch, "got", readBatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read non-existing value
|
||||||
|
nonExistingIndex := uint64(len(batches) + 1)
|
||||||
|
readBatch = ReadFinalizedBatchMeta(db, nonExistingIndex)
|
||||||
|
if readBatch != nil {
|
||||||
|
t.Fatal("Expected nil for non-existing value", "got", readBatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBatchChunkRanges(t *testing.T) {
|
||||||
|
chunks := [][]*ChunkBlockRange{
|
||||||
|
{
|
||||||
|
{StartBlockNumber: 1, EndBlockNumber: 100},
|
||||||
|
{StartBlockNumber: 101, EndBlockNumber: 200},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{StartBlockNumber: 201, EndBlockNumber: 300},
|
||||||
|
{StartBlockNumber: 301, EndBlockNumber: 400},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{StartBlockNumber: 401, EndBlockNumber: 500},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
|
||||||
|
for i, chunkRange := range chunks {
|
||||||
|
batchIndex := uint64(i)
|
||||||
|
WriteBatchChunkRanges(db, batchIndex, chunkRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, chunkRange := range chunks {
|
||||||
|
batchIndex := uint64(i)
|
||||||
|
readChunkRange := ReadBatchChunkRanges(db, batchIndex)
|
||||||
|
if len(readChunkRange) != len(chunkRange) {
|
||||||
|
t.Fatal("Mismatch in number of chunk ranges", "expected", len(chunkRange), "got", len(readChunkRange))
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, cr := range readChunkRange {
|
||||||
|
if cr.StartBlockNumber != chunkRange[j].StartBlockNumber || cr.EndBlockNumber != chunkRange[j].EndBlockNumber {
|
||||||
|
t.Fatal("Mismatch in chunk range", "batch index", batchIndex, "expected", chunkRange[j], "got", cr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// over-write
|
||||||
|
newRange := []*ChunkBlockRange{{StartBlockNumber: 1001, EndBlockNumber: 1100}}
|
||||||
|
WriteBatchChunkRanges(db, 0, newRange)
|
||||||
|
readChunkRange := ReadBatchChunkRanges(db, 0)
|
||||||
|
if len(readChunkRange) != 1 || readChunkRange[0].StartBlockNumber != 1001 || readChunkRange[0].EndBlockNumber != 1100 {
|
||||||
|
t.Fatal("Over-write failed for chunk range", "expected", newRange, "got", readChunkRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read non-existing value
|
||||||
|
if readChunkRange = ReadBatchChunkRanges(db, uint64(len(chunks)+1)); readChunkRange != nil {
|
||||||
|
t.Fatal("Expected nil for non-existing value", "got", readChunkRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete: revert batch
|
||||||
|
for i := range chunks {
|
||||||
|
batchIndex := uint64(i)
|
||||||
|
DeleteBatchChunkRanges(db, batchIndex)
|
||||||
|
|
||||||
|
readChunkRange := ReadBatchChunkRanges(db, batchIndex)
|
||||||
|
if readChunkRange != nil {
|
||||||
|
t.Fatal("Chunk range was not deleted", "batch index", batchIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete non-existing value: ensure the delete operation handles non-existing values without errors.
|
||||||
|
DeleteBatchChunkRanges(db, uint64(len(chunks)+1))
|
||||||
|
}
|
||||||
|
|
@ -110,6 +110,12 @@ var (
|
||||||
firstQueueIndexNotInL2BlockPrefix = []byte("q") // firstQueueIndexNotInL2BlockPrefix + L2 block hash -> enqueue index
|
firstQueueIndexNotInL2BlockPrefix = []byte("q") // firstQueueIndexNotInL2BlockPrefix + L2 block hash -> enqueue index
|
||||||
highestSyncedQueueIndexKey = []byte("HighestSyncedQueueIndex")
|
highestSyncedQueueIndexKey = []byte("HighestSyncedQueueIndex")
|
||||||
|
|
||||||
|
// Scroll rollup event store
|
||||||
|
rollupEventSyncedL1BlockNumberKey = []byte("R-LastRollupEventSyncedL1BlockNumber")
|
||||||
|
batchChunkRangesPrefix = []byte("R-bcr")
|
||||||
|
batchMetaPrefix = []byte("R-bm")
|
||||||
|
finalizedL2BlockNumberKey = []byte("R-finalized")
|
||||||
|
|
||||||
// Row consumption
|
// Row consumption
|
||||||
rowConsumptionPrefix = []byte("rc") // rowConsumptionPrefix + hash -> row consumption by block
|
rowConsumptionPrefix = []byte("rc") // rowConsumptionPrefix + hash -> row consumption by block
|
||||||
|
|
||||||
|
|
@ -292,3 +298,13 @@ func SkippedTransactionKey(txHash common.Hash) []byte {
|
||||||
func SkippedTransactionHashKey(index uint64) []byte {
|
func SkippedTransactionHashKey(index uint64) []byte {
|
||||||
return append(skippedTransactionHashPrefix, encodeBigEndian(index)...)
|
return append(skippedTransactionHashPrefix, encodeBigEndian(index)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// batchChunkRangesKey = batchChunkRangesPrefix + batch index (uint64 big endian)
|
||||||
|
func batchChunkRangesKey(batchIndex uint64) []byte {
|
||||||
|
return append(batchChunkRangesPrefix, encodeBigEndian(batchIndex)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// batchMetaKey = batchMetaPrefix + batch index (uint64 big endian)
|
||||||
|
func batchMetaKey(batchIndex uint64) []byte {
|
||||||
|
return append(batchMetaPrefix, encodeBigEndian(batchIndex)...)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ import (
|
||||||
"github.com/scroll-tech/go-ethereum/p2p/enode"
|
"github.com/scroll-tech/go-ethereum/p2p/enode"
|
||||||
"github.com/scroll-tech/go-ethereum/params"
|
"github.com/scroll-tech/go-ethereum/params"
|
||||||
"github.com/scroll-tech/go-ethereum/rlp"
|
"github.com/scroll-tech/go-ethereum/rlp"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rollup/rollup_sync_service"
|
||||||
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
|
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
|
||||||
"github.com/scroll-tech/go-ethereum/rpc"
|
"github.com/scroll-tech/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -70,6 +71,7 @@ type Ethereum struct {
|
||||||
// Handlers
|
// Handlers
|
||||||
txPool *core.TxPool
|
txPool *core.TxPool
|
||||||
syncService *sync_service.SyncService
|
syncService *sync_service.SyncService
|
||||||
|
rollupSyncService *rollup_sync_service.RollupSyncService
|
||||||
blockchain *core.BlockChain
|
blockchain *core.BlockChain
|
||||||
handler *handler
|
handler *handler
|
||||||
ethDialCandidates enode.Iterator
|
ethDialCandidates enode.Iterator
|
||||||
|
|
@ -216,6 +218,15 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client sync_service.EthCl
|
||||||
}
|
}
|
||||||
eth.syncService.Start()
|
eth.syncService.Start()
|
||||||
|
|
||||||
|
if config.EnableRollupVerify {
|
||||||
|
// initialize and start rollup event sync service
|
||||||
|
eth.rollupSyncService, err = rollup_sync_service.NewRollupSyncService(context.Background(), chainConfig, eth.chainDb, l1Client, eth.blockchain, stack.Config().L1DeploymentBlock)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot initialize rollup event sync service: %w", err)
|
||||||
|
}
|
||||||
|
eth.rollupSyncService.Start()
|
||||||
|
}
|
||||||
|
|
||||||
// Permit the downloader to use the trie cache allowance during fast sync
|
// Permit the downloader to use the trie cache allowance during fast sync
|
||||||
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
||||||
checkpoint := config.Checkpoint
|
checkpoint := config.Checkpoint
|
||||||
|
|
@ -572,6 +583,9 @@ func (s *Ethereum) Stop() error {
|
||||||
close(s.closeBloomHandler)
|
close(s.closeBloomHandler)
|
||||||
s.txPool.Stop()
|
s.txPool.Stop()
|
||||||
s.syncService.Stop()
|
s.syncService.Stop()
|
||||||
|
if s.config.EnableRollupVerify {
|
||||||
|
s.rollupSyncService.Stop()
|
||||||
|
}
|
||||||
s.miner.Close()
|
s.miner.Close()
|
||||||
s.blockchain.Stop()
|
s.blockchain.Stop()
|
||||||
s.engine.Close()
|
s.engine.Close()
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,9 @@ type Config struct {
|
||||||
// Check circuit capacity in block validator
|
// Check circuit capacity in block validator
|
||||||
CheckCircuitCapacity bool
|
CheckCircuitCapacity bool
|
||||||
|
|
||||||
|
// Enable verification of batch consistency between L1 and L2 in rollup
|
||||||
|
EnableRollupVerify bool
|
||||||
|
|
||||||
// Max block range for eth_getLogs api method
|
// Max block range for eth_getLogs api method
|
||||||
MaxBlockRange int64
|
MaxBlockRange int64
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
OverrideArrowGlacier *big.Int `toml:",omitempty"`
|
OverrideArrowGlacier *big.Int `toml:",omitempty"`
|
||||||
MPTWitness int
|
MPTWitness int
|
||||||
CheckCircuitCapacity bool
|
CheckCircuitCapacity bool
|
||||||
|
EnableRollupVerify bool
|
||||||
MaxBlockRange int64
|
MaxBlockRange int64
|
||||||
}
|
}
|
||||||
var enc Config
|
var enc Config
|
||||||
|
|
@ -109,6 +110,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
enc.OverrideArrowGlacier = c.OverrideArrowGlacier
|
enc.OverrideArrowGlacier = c.OverrideArrowGlacier
|
||||||
enc.MPTWitness = c.MPTWitness
|
enc.MPTWitness = c.MPTWitness
|
||||||
enc.CheckCircuitCapacity = c.CheckCircuitCapacity
|
enc.CheckCircuitCapacity = c.CheckCircuitCapacity
|
||||||
|
enc.EnableRollupVerify = c.EnableRollupVerify
|
||||||
enc.MaxBlockRange = c.MaxBlockRange
|
enc.MaxBlockRange = c.MaxBlockRange
|
||||||
return &enc, nil
|
return &enc, nil
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +162,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
OverrideArrowGlacier *big.Int `toml:",omitempty"`
|
OverrideArrowGlacier *big.Int `toml:",omitempty"`
|
||||||
MPTWitness *int
|
MPTWitness *int
|
||||||
CheckCircuitCapacity *bool
|
CheckCircuitCapacity *bool
|
||||||
|
EnableRollupVerify *bool
|
||||||
MaxBlockRange *int64
|
MaxBlockRange *int64
|
||||||
}
|
}
|
||||||
var dec Config
|
var dec Config
|
||||||
|
|
@ -298,6 +301,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
if dec.CheckCircuitCapacity != nil {
|
if dec.CheckCircuitCapacity != nil {
|
||||||
c.CheckCircuitCapacity = *dec.CheckCircuitCapacity
|
c.CheckCircuitCapacity = *dec.CheckCircuitCapacity
|
||||||
}
|
}
|
||||||
|
if dec.EnableRollupVerify != nil {
|
||||||
|
c.EnableRollupVerify = *dec.EnableRollupVerify
|
||||||
|
}
|
||||||
if dec.MaxBlockRange != nil {
|
if dec.MaxBlockRange != nil {
|
||||||
c.MaxBlockRange = *dec.MaxBlockRange
|
c.MaxBlockRange = *dec.MaxBlockRange
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
go.mod
12
go.mod
|
|
@ -54,10 +54,10 @@ require (
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
|
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
|
||||||
golang.org/x/crypto v0.6.0
|
golang.org/x/crypto v0.14.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.4.0
|
||||||
golang.org/x/sys v0.5.0
|
golang.org/x/sys v0.13.0
|
||||||
golang.org/x/text v0.7.0
|
golang.org/x/text v0.13.0
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
||||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
|
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
|
||||||
|
|
@ -91,8 +91,8 @@ require (
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||||
golang.org/x/net v0.6.0 // indirect
|
golang.org/x/net v0.16.0 // indirect
|
||||||
golang.org/x/term v0.5.0 // indirect
|
golang.org/x/term v0.13.0 // indirect
|
||||||
google.golang.org/protobuf v1.23.0 // indirect
|
google.golang.org/protobuf v1.23.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|
|
||||||
19
go.sum
19
go.sum
|
|
@ -442,8 +442,9 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
|
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||||
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
|
@ -497,8 +498,9 @@ golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
|
||||||
|
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
|
@ -513,8 +515,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
|
@ -555,13 +557,15 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||||
|
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
|
@ -570,8 +574,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,7 @@ var (
|
||||||
L1ChainId: 5,
|
L1ChainId: 5,
|
||||||
L1MessageQueueAddress: common.HexToAddress("0x79DB48002Aa861C8cb189cabc21c6B1468BC83BB"),
|
L1MessageQueueAddress: common.HexToAddress("0x79DB48002Aa861C8cb189cabc21c6B1468BC83BB"),
|
||||||
NumL1MessagesPerBlock: 0,
|
NumL1MessagesPerBlock: 0,
|
||||||
|
ScrollChainAddress: common.HexToAddress("0x3C584eC7f0f2764CC715ac3180Ae9828465E9833"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -331,6 +332,7 @@ var (
|
||||||
L1ChainId: 11155111,
|
L1ChainId: 11155111,
|
||||||
L1MessageQueueAddress: common.HexToAddress("0xF0B2293F5D834eAe920c6974D50957A1732de763"),
|
L1MessageQueueAddress: common.HexToAddress("0xF0B2293F5D834eAe920c6974D50957A1732de763"),
|
||||||
NumL1MessagesPerBlock: 10,
|
NumL1MessagesPerBlock: 10,
|
||||||
|
ScrollChainAddress: common.HexToAddress("0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -368,6 +370,7 @@ var (
|
||||||
L1ChainId: 1,
|
L1ChainId: 1,
|
||||||
L1MessageQueueAddress: common.HexToAddress("0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"),
|
L1MessageQueueAddress: common.HexToAddress("0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"),
|
||||||
NumL1MessagesPerBlock: 10,
|
NumL1MessagesPerBlock: 10,
|
||||||
|
ScrollChainAddress: common.HexToAddress("0xa13BAF47339d63B743e7Da8741db5456DAc1E556"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +388,7 @@ var (
|
||||||
EnableEIP1559: true,
|
EnableEIP1559: true,
|
||||||
MaxTxPerBlock: nil,
|
MaxTxPerBlock: nil,
|
||||||
MaxTxPayloadBytesPerBlock: nil,
|
MaxTxPayloadBytesPerBlock: nil,
|
||||||
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0},
|
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
|
|
@ -401,7 +404,7 @@ var (
|
||||||
EnableEIP1559: true,
|
EnableEIP1559: true,
|
||||||
MaxTxPerBlock: nil,
|
MaxTxPerBlock: nil,
|
||||||
MaxTxPayloadBytesPerBlock: nil,
|
MaxTxPayloadBytesPerBlock: nil,
|
||||||
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0},
|
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil,
|
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil,
|
||||||
|
|
@ -412,7 +415,7 @@ var (
|
||||||
EnableEIP1559: true,
|
EnableEIP1559: true,
|
||||||
MaxTxPerBlock: nil,
|
MaxTxPerBlock: nil,
|
||||||
MaxTxPayloadBytesPerBlock: nil,
|
MaxTxPayloadBytesPerBlock: nil,
|
||||||
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0},
|
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
|
||||||
}}
|
}}
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||||
|
|
||||||
|
|
@ -424,7 +427,7 @@ var (
|
||||||
EnableEIP1559: true,
|
EnableEIP1559: true,
|
||||||
MaxTxPerBlock: nil,
|
MaxTxPerBlock: nil,
|
||||||
MaxTxPayloadBytesPerBlock: nil,
|
MaxTxPayloadBytesPerBlock: nil,
|
||||||
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0},
|
L1Config: &L1Config{5, common.HexToAddress("0x0000000000000000000000000000000000000000"), 0, common.HexToAddress("0x0000000000000000000000000000000000000000")},
|
||||||
}}
|
}}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -542,11 +545,12 @@ type ScrollConfig struct {
|
||||||
L1Config *L1Config `json:"l1Config,omitempty"`
|
L1Config *L1Config `json:"l1Config,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// L1Config contains the l1 parameters needed to collect l1 messages in the sequencer
|
// L1Config contains the l1 parameters needed to sync l1 contract events (e.g., l1 messages, commit/revert/finalize batches) in the sequencer
|
||||||
type L1Config struct {
|
type L1Config struct {
|
||||||
L1ChainId uint64 `json:"l1ChainId,string,omitempty"`
|
L1ChainId uint64 `json:"l1ChainId,string,omitempty"`
|
||||||
L1MessageQueueAddress common.Address `json:"l1MessageQueueAddress,omitempty"`
|
L1MessageQueueAddress common.Address `json:"l1MessageQueueAddress,omitempty"`
|
||||||
NumL1MessagesPerBlock uint64 `json:"numL1MessagesPerBlock,string,omitempty"`
|
NumL1MessagesPerBlock uint64 `json:"numL1MessagesPerBlock,string,omitempty"`
|
||||||
|
ScrollChainAddress common.Address `json:"scrollChainAddress,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *L1Config) String() string {
|
func (c *L1Config) String() string {
|
||||||
|
|
@ -554,8 +558,8 @@ func (c *L1Config) String() string {
|
||||||
return "<nil>"
|
return "<nil>"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("{l1ChainId: %v, l1MessageQueueAddress: %v, numL1MessagesPerBlock: %v}",
|
return fmt.Sprintf("{l1ChainId: %v, l1MessageQueueAddress: %v, numL1MessagesPerBlock: %v, ScrollChainAddress: %v}",
|
||||||
c.L1ChainId, c.L1MessageQueueAddress, c.NumL1MessagesPerBlock)
|
c.L1ChainId, c.L1MessageQueueAddress.Hex(), c.NumL1MessagesPerBlock, c.ScrollChainAddress.Hex())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s ScrollConfig) BaseFeeEnabled() bool {
|
func (s ScrollConfig) BaseFeeEnabled() bool {
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VersionMajor = 5 // Major version component of the current release
|
VersionMajor = 5 // Major version component of the current release
|
||||||
VersionMinor = 0 // Minor version component of the current release
|
VersionMinor = 1 // Minor version component of the current release
|
||||||
VersionPatch = 3 // Patch version component of the current release
|
VersionPatch = 0 // Patch version component of the current release
|
||||||
VersionMeta = "mainnet" // Version metadata to append to the version string
|
VersionMeta = "mainnet" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
55
rollup/rollup_sync_service/abi.go
Normal file
55
rollup/rollup_sync_service/abi.go
Normal file
File diff suppressed because one or more lines are too long
82
rollup/rollup_sync_service/abi_test.go
Normal file
82
rollup/rollup_sync_service/abi_test.go
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEventSignatures(t *testing.T) {
|
||||||
|
scrollChainABI, err := scrollChainMetaData.GetAbi()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("failed to get scroll chain abi", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, crypto.Keccak256Hash([]byte("CommitBatch(uint256,bytes32)")), scrollChainABI.Events["CommitBatch"].ID)
|
||||||
|
assert.Equal(t, crypto.Keccak256Hash([]byte("RevertBatch(uint256,bytes32)")), scrollChainABI.Events["RevertBatch"].ID)
|
||||||
|
assert.Equal(t, crypto.Keccak256Hash([]byte("FinalizeBatch(uint256,bytes32,bytes32,bytes32)")), scrollChainABI.Events["FinalizeBatch"].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnpackLog(t *testing.T) {
|
||||||
|
scrollChainABI, err := scrollChainMetaData.GetAbi()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
mockBatchIndex := big.NewInt(123)
|
||||||
|
mockBatchHash := crypto.Keccak256Hash([]byte("mockBatch"))
|
||||||
|
mockStateRoot := crypto.Keccak256Hash([]byte("mockStateRoot"))
|
||||||
|
mockWithdrawRoot := crypto.Keccak256Hash([]byte("mockWithdrawRoot"))
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
eventName string
|
||||||
|
mockLog types.Log
|
||||||
|
expected interface{}
|
||||||
|
out interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"CommitBatch",
|
||||||
|
types.Log{
|
||||||
|
Data: []byte{},
|
||||||
|
Topics: []common.Hash{scrollChainABI.Events["CommitBatch"].ID, common.BigToHash(mockBatchIndex), mockBatchHash},
|
||||||
|
},
|
||||||
|
&L1CommitBatchEvent{BatchIndex: mockBatchIndex, BatchHash: mockBatchHash},
|
||||||
|
&L1CommitBatchEvent{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"RevertBatch",
|
||||||
|
types.Log{
|
||||||
|
Data: []byte{},
|
||||||
|
Topics: []common.Hash{scrollChainABI.Events["RevertBatch"].ID, common.BigToHash(mockBatchIndex), mockBatchHash},
|
||||||
|
},
|
||||||
|
&L1RevertBatchEvent{BatchIndex: mockBatchIndex, BatchHash: mockBatchHash},
|
||||||
|
&L1RevertBatchEvent{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"FinalizeBatch",
|
||||||
|
types.Log{
|
||||||
|
Data: append(mockStateRoot.Bytes(), mockWithdrawRoot.Bytes()...),
|
||||||
|
Topics: []common.Hash{scrollChainABI.Events["FinalizeBatch"].ID, common.BigToHash(mockBatchIndex), mockBatchHash},
|
||||||
|
},
|
||||||
|
&L1FinalizeBatchEvent{
|
||||||
|
BatchIndex: mockBatchIndex,
|
||||||
|
BatchHash: mockBatchHash,
|
||||||
|
StateRoot: mockStateRoot,
|
||||||
|
WithdrawRoot: mockWithdrawRoot,
|
||||||
|
},
|
||||||
|
&L1FinalizeBatchEvent{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.eventName, func(t *testing.T) {
|
||||||
|
err := UnpackLog(scrollChainABI, tt.out, tt.eventName, tt.mockLog)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.expected, tt.out)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
123
rollup/rollup_sync_service/batch_header.go
Normal file
123
rollup/rollup_sync_service/batch_header.go
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const batchHeaderVersion = 0
|
||||||
|
|
||||||
|
// BatchHeader contains batch header info to be committed.
|
||||||
|
type BatchHeader struct {
|
||||||
|
// Encoded in BatchHeaderV0Codec
|
||||||
|
version uint8
|
||||||
|
batchIndex uint64
|
||||||
|
l1MessagePopped uint64
|
||||||
|
totalL1MessagePopped uint64
|
||||||
|
dataHash common.Hash
|
||||||
|
parentBatchHash common.Hash
|
||||||
|
skippedL1MessageBitmap []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBatchHeader creates a new BatchHeader
|
||||||
|
func NewBatchHeader(version uint8, batchIndex, totalL1MessagePoppedBefore uint64, parentBatchHash common.Hash, chunks []*Chunk) (*BatchHeader, error) {
|
||||||
|
// buffer for storing chunk hashes in order to compute the batch data hash
|
||||||
|
var dataBytes []byte
|
||||||
|
|
||||||
|
// skipped L1 message bitmap, an array of 256-bit bitmaps
|
||||||
|
var skippedBitmap []*big.Int
|
||||||
|
|
||||||
|
// the first queue index that belongs to this batch
|
||||||
|
baseIndex := totalL1MessagePoppedBefore
|
||||||
|
|
||||||
|
// the next queue index that we need to process
|
||||||
|
nextIndex := totalL1MessagePoppedBefore
|
||||||
|
|
||||||
|
for chunkID, chunk := range chunks {
|
||||||
|
// build data hash
|
||||||
|
totalL1MessagePoppedBeforeChunk := nextIndex
|
||||||
|
chunkHash, err := chunk.Hash(totalL1MessagePoppedBeforeChunk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dataBytes = append(dataBytes, chunkHash.Bytes()...)
|
||||||
|
|
||||||
|
// build skip bitmap
|
||||||
|
for blockID, block := range chunk.Blocks {
|
||||||
|
for _, tx := range block.Transactions {
|
||||||
|
if tx.Type != types.L1MessageTxType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
currentIndex := tx.Nonce
|
||||||
|
|
||||||
|
if currentIndex < nextIndex {
|
||||||
|
return nil, fmt.Errorf("unexpected batch payload, expected queue index: %d, got: %d. Batch index: %d, chunk index in batch: %d, block index in chunk: %d, block hash: %v, transaction hash: %v", nextIndex, currentIndex, batchIndex, chunkID, blockID, block.Header.Hash(), tx.TxHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark skipped messages
|
||||||
|
for skippedIndex := nextIndex; skippedIndex < currentIndex; skippedIndex++ {
|
||||||
|
quo := int((skippedIndex - baseIndex) / 256)
|
||||||
|
rem := int((skippedIndex - baseIndex) % 256)
|
||||||
|
for len(skippedBitmap) <= quo {
|
||||||
|
bitmap := big.NewInt(0)
|
||||||
|
skippedBitmap = append(skippedBitmap, bitmap)
|
||||||
|
}
|
||||||
|
skippedBitmap[quo].SetBit(skippedBitmap[quo], rem, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// process included message
|
||||||
|
quo := int((currentIndex - baseIndex) / 256)
|
||||||
|
for len(skippedBitmap) <= quo {
|
||||||
|
bitmap := big.NewInt(0)
|
||||||
|
skippedBitmap = append(skippedBitmap, bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
nextIndex = currentIndex + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute data hash
|
||||||
|
dataHash := crypto.Keccak256Hash(dataBytes)
|
||||||
|
|
||||||
|
// compute skipped bitmap
|
||||||
|
bitmapBytes := make([]byte, len(skippedBitmap)*32)
|
||||||
|
for ii, num := range skippedBitmap {
|
||||||
|
bytes := num.Bytes()
|
||||||
|
padding := 32 - len(bytes)
|
||||||
|
copy(bitmapBytes[32*ii+padding:], bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &BatchHeader{
|
||||||
|
version: version,
|
||||||
|
batchIndex: batchIndex,
|
||||||
|
l1MessagePopped: nextIndex - totalL1MessagePoppedBefore,
|
||||||
|
totalL1MessagePopped: nextIndex,
|
||||||
|
dataHash: dataHash,
|
||||||
|
parentBatchHash: parentBatchHash,
|
||||||
|
skippedL1MessageBitmap: bitmapBytes,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes the BatchHeader into RollupV2 BatchHeaderV0Codec Encoding.
|
||||||
|
func (b *BatchHeader) Encode() []byte {
|
||||||
|
batchBytes := make([]byte, 89+len(b.skippedL1MessageBitmap))
|
||||||
|
batchBytes[0] = b.version
|
||||||
|
binary.BigEndian.PutUint64(batchBytes[1:], b.batchIndex)
|
||||||
|
binary.BigEndian.PutUint64(batchBytes[9:], b.l1MessagePopped)
|
||||||
|
binary.BigEndian.PutUint64(batchBytes[17:], b.totalL1MessagePopped)
|
||||||
|
copy(batchBytes[25:], b.dataHash[:])
|
||||||
|
copy(batchBytes[57:], b.parentBatchHash[:])
|
||||||
|
copy(batchBytes[89:], b.skippedL1MessageBitmap[:])
|
||||||
|
return batchBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash calculates the hash of the batch header.
|
||||||
|
func (b *BatchHeader) Hash() common.Hash {
|
||||||
|
return crypto.Keccak256Hash(b.Encode())
|
||||||
|
}
|
||||||
167
rollup/rollup_sync_service/block.go
Normal file
167
rollup/rollup_sync_service/block.go
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const blockContextByteSize = 60
|
||||||
|
|
||||||
|
// WrappedBlock contains the block's Header, Transactions and WithdrawTrieRoot hash.
|
||||||
|
type WrappedBlock struct {
|
||||||
|
Header *types.Header `json:"header"`
|
||||||
|
// Transactions is only used for recover types.Transactions, the from of types.TransactionData field is missing.
|
||||||
|
Transactions []*types.TransactionData `json:"transactions"`
|
||||||
|
WithdrawRoot common.Hash `json:"withdraw_trie_root,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockContext represents the essential data of a block in the ScrollChain.
|
||||||
|
// It provides an overview of block attributes including hash values, block numbers, gas details, and transaction counts.
|
||||||
|
type BlockContext struct {
|
||||||
|
BlockHash common.Hash
|
||||||
|
ParentHash common.Hash
|
||||||
|
BlockNumber uint64
|
||||||
|
Timestamp uint64
|
||||||
|
BaseFee *big.Int
|
||||||
|
GasLimit uint64
|
||||||
|
NumTransactions uint16
|
||||||
|
NumL1Messages uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// numL1Messages returns the number of L1 messages in this block.
|
||||||
|
// This number is the sum of included and skipped L1 messages.
|
||||||
|
func (w *WrappedBlock) numL1Messages(totalL1MessagePoppedBefore uint64) uint64 {
|
||||||
|
var lastQueueIndex *uint64
|
||||||
|
for _, txData := range w.Transactions {
|
||||||
|
if txData.Type == types.L1MessageTxType {
|
||||||
|
lastQueueIndex = &txData.Nonce
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lastQueueIndex == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
// note: last queue index included before this block is totalL1MessagePoppedBefore - 1
|
||||||
|
// TODO: cache results
|
||||||
|
return *lastQueueIndex - totalL1MessagePoppedBefore + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes the WrappedBlock into RollupV2 BlockContext Encoding.
|
||||||
|
func (w *WrappedBlock) Encode(totalL1MessagePoppedBefore uint64) ([]byte, error) {
|
||||||
|
bytes := make([]byte, 60)
|
||||||
|
|
||||||
|
if !w.Header.Number.IsUint64() {
|
||||||
|
return nil, errors.New("block number is not uint64")
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: numL1Messages includes skipped messages
|
||||||
|
numL1Messages := w.numL1Messages(totalL1MessagePoppedBefore)
|
||||||
|
if numL1Messages > math.MaxUint16 {
|
||||||
|
return nil, errors.New("number of L1 messages exceeds max uint16")
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: numTransactions includes skipped messages
|
||||||
|
numL2Transactions := w.numL2Transactions()
|
||||||
|
numTransactions := numL1Messages + numL2Transactions
|
||||||
|
if numTransactions > math.MaxUint16 {
|
||||||
|
return nil, errors.New("number of transactions exceeds max uint16")
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint64(bytes[0:], w.Header.Number.Uint64())
|
||||||
|
binary.BigEndian.PutUint64(bytes[8:], w.Header.Time)
|
||||||
|
// TODO: [16:47] Currently, baseFee is 0, because we disable EIP-1559.
|
||||||
|
binary.BigEndian.PutUint64(bytes[48:], w.Header.GasLimit)
|
||||||
|
binary.BigEndian.PutUint16(bytes[56:], uint16(numTransactions))
|
||||||
|
binary.BigEndian.PutUint16(bytes[58:], uint16(numL1Messages))
|
||||||
|
|
||||||
|
return bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func txsToTxsData(txs types.Transactions) []*types.TransactionData {
|
||||||
|
txsData := make([]*types.TransactionData, len(txs))
|
||||||
|
for i, tx := range txs {
|
||||||
|
v, r, s := tx.RawSignatureValues()
|
||||||
|
|
||||||
|
nonce := tx.Nonce()
|
||||||
|
|
||||||
|
// We need QueueIndex in `NewBatchHeader`. However, `TransactionData`
|
||||||
|
// does not have this field. Since `L1MessageTx` do not have a nonce,
|
||||||
|
// we reuse this field for storing the queue index.
|
||||||
|
if msg := tx.AsL1MessageTx(); msg != nil {
|
||||||
|
nonce = msg.QueueIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
txsData[i] = &types.TransactionData{
|
||||||
|
Type: tx.Type(),
|
||||||
|
TxHash: tx.Hash().String(),
|
||||||
|
Nonce: nonce,
|
||||||
|
ChainId: (*hexutil.Big)(tx.ChainId()),
|
||||||
|
Gas: tx.Gas(),
|
||||||
|
GasPrice: (*hexutil.Big)(tx.GasPrice()),
|
||||||
|
To: tx.To(),
|
||||||
|
Value: (*hexutil.Big)(tx.Value()),
|
||||||
|
Data: hexutil.Encode(tx.Data()),
|
||||||
|
IsCreate: tx.To() == nil,
|
||||||
|
V: (*hexutil.Big)(v),
|
||||||
|
R: (*hexutil.Big)(r),
|
||||||
|
S: (*hexutil.Big)(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return txsData
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertTxDataToRLPEncoding(txData *types.TransactionData) ([]byte, error) {
|
||||||
|
data, err := hexutil.Decode(txData.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode txData.Data: %s, err: %w", txData.Data, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := types.NewTx(&types.LegacyTx{
|
||||||
|
Nonce: txData.Nonce,
|
||||||
|
To: txData.To,
|
||||||
|
Value: txData.Value.ToInt(),
|
||||||
|
Gas: txData.Gas,
|
||||||
|
GasPrice: txData.GasPrice.ToInt(),
|
||||||
|
Data: data,
|
||||||
|
V: txData.V.ToInt(),
|
||||||
|
R: txData.R.ToInt(),
|
||||||
|
S: txData.S.ToInt(),
|
||||||
|
})
|
||||||
|
|
||||||
|
rlpTxData, err := tx.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to marshal binary of the tx: %+v, err: %w", tx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rlpTxData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WrappedBlock) numL2Transactions() uint64 {
|
||||||
|
var count uint64
|
||||||
|
for _, txData := range w.Transactions {
|
||||||
|
if txData.Type != types.L1MessageTxType {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeBlockContext(encodedBlockContext []byte) (*BlockContext, error) {
|
||||||
|
if len(encodedBlockContext) != blockContextByteSize {
|
||||||
|
return nil, errors.New("block encoding is not 60 bytes long")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &BlockContext{
|
||||||
|
BlockNumber: binary.BigEndian.Uint64(encodedBlockContext[0:8]),
|
||||||
|
Timestamp: binary.BigEndian.Uint64(encodedBlockContext[8:16]),
|
||||||
|
GasLimit: binary.BigEndian.Uint64(encodedBlockContext[48:56]),
|
||||||
|
NumTransactions: binary.BigEndian.Uint16(encodedBlockContext[56:58]),
|
||||||
|
NumL1Messages: binary.BigEndian.Uint16(encodedBlockContext[58:60]),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
155
rollup/rollup_sync_service/chunk.go
Normal file
155
rollup/rollup_sync_service/chunk.go
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/rawdb"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Chunk contains blocks to be encoded
|
||||||
|
type Chunk struct {
|
||||||
|
Blocks []*WrappedBlock `json:"blocks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumL1Messages returns the number of L1 messages in this chunk.
|
||||||
|
// This number is the sum of included and skipped L1 messages.
|
||||||
|
func (c *Chunk) NumL1Messages(totalL1MessagePoppedBefore uint64) uint64 {
|
||||||
|
var numL1Messages uint64
|
||||||
|
for _, block := range c.Blocks {
|
||||||
|
numL1MessagesInBlock := block.numL1Messages(totalL1MessagePoppedBefore)
|
||||||
|
numL1Messages += numL1MessagesInBlock
|
||||||
|
totalL1MessagePoppedBefore += numL1MessagesInBlock
|
||||||
|
}
|
||||||
|
// TODO: cache results
|
||||||
|
return numL1Messages
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes the Chunk into RollupV2 Chunk Encoding.
|
||||||
|
func (c *Chunk) Encode(totalL1MessagePoppedBefore uint64) ([]byte, error) {
|
||||||
|
numBlocks := len(c.Blocks)
|
||||||
|
|
||||||
|
if numBlocks > 255 {
|
||||||
|
return nil, errors.New("number of blocks exceeds 1 byte")
|
||||||
|
}
|
||||||
|
if numBlocks == 0 {
|
||||||
|
return nil, errors.New("number of blocks is 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
var chunkBytes []byte
|
||||||
|
chunkBytes = append(chunkBytes, byte(numBlocks))
|
||||||
|
|
||||||
|
var l2TxDataBytes []byte
|
||||||
|
|
||||||
|
for _, block := range c.Blocks {
|
||||||
|
blockBytes, err := block.Encode(totalL1MessagePoppedBefore)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to encode block: %v", err)
|
||||||
|
}
|
||||||
|
totalL1MessagePoppedBefore += block.numL1Messages(totalL1MessagePoppedBefore)
|
||||||
|
|
||||||
|
if len(blockBytes) != 60 {
|
||||||
|
return nil, fmt.Errorf("block encoding is not 60 bytes long %x", len(blockBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkBytes = append(chunkBytes, blockBytes...)
|
||||||
|
|
||||||
|
// Append rlp-encoded l2Txs
|
||||||
|
for _, txData := range block.Transactions {
|
||||||
|
if txData.Type == types.L1MessageTxType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rlpTxData, err := convertTxDataToRLPEncoding(txData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var txLen [4]byte
|
||||||
|
binary.BigEndian.PutUint32(txLen[:], uint32(len(rlpTxData)))
|
||||||
|
l2TxDataBytes = append(l2TxDataBytes, txLen[:]...)
|
||||||
|
l2TxDataBytes = append(l2TxDataBytes, rlpTxData...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkBytes = append(chunkBytes, l2TxDataBytes...)
|
||||||
|
|
||||||
|
return chunkBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash hashes the Chunk into RollupV2 Chunk Hash
|
||||||
|
func (c *Chunk) Hash(totalL1MessagePoppedBefore uint64) (common.Hash, error) {
|
||||||
|
chunkBytes, err := c.Encode(totalL1MessagePoppedBefore)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
numBlocks := chunkBytes[0]
|
||||||
|
|
||||||
|
// concatenate block contexts
|
||||||
|
var dataBytes []byte
|
||||||
|
for i := 0; i < int(numBlocks); i++ {
|
||||||
|
// only the first 58 bytes of each BlockContext are needed for the hashing process
|
||||||
|
dataBytes = append(dataBytes, chunkBytes[1+60*i:60*i+59]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// concatenate l1 and l2 tx hashes
|
||||||
|
for _, block := range c.Blocks {
|
||||||
|
var l1TxHashes []byte
|
||||||
|
var l2TxHashes []byte
|
||||||
|
for _, txData := range block.Transactions {
|
||||||
|
txHash := strings.TrimPrefix(txData.TxHash, "0x")
|
||||||
|
hashBytes, err := hex.DecodeString(txHash)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
if txData.Type == types.L1MessageTxType {
|
||||||
|
l1TxHashes = append(l1TxHashes, hashBytes...)
|
||||||
|
} else {
|
||||||
|
l2TxHashes = append(l2TxHashes, hashBytes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataBytes = append(dataBytes, l1TxHashes...)
|
||||||
|
dataBytes = append(dataBytes, l2TxHashes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := crypto.Keccak256Hash(dataBytes)
|
||||||
|
return hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeChunkBlockRanges decodes the provided chunks into a list of block ranges. Each chunk
|
||||||
|
// contains information about multiple blocks, which are decoded and their ranges (from the
|
||||||
|
// start block to the end block) are returned.
|
||||||
|
func DecodeChunkBlockRanges(chunks [][]byte) ([]*rawdb.ChunkBlockRange, error) {
|
||||||
|
var chunkBlockRanges []*rawdb.ChunkBlockRange
|
||||||
|
for _, chunk := range chunks {
|
||||||
|
if len(chunk) < 1 {
|
||||||
|
return nil, fmt.Errorf("invalid chunk, length is less than 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
numBlocks := int(chunk[0])
|
||||||
|
if len(chunk) < 1+numBlocks*blockContextByteSize {
|
||||||
|
return nil, fmt.Errorf("chunk size doesn't match with numBlocks")
|
||||||
|
}
|
||||||
|
|
||||||
|
blockContexts := make([]*BlockContext, numBlocks)
|
||||||
|
for i := 0; i < numBlocks; i++ {
|
||||||
|
startIdx := 1 + i*blockContextByteSize // add 1 to skip numBlocks byte
|
||||||
|
endIdx := startIdx + blockContextByteSize
|
||||||
|
blockContext, err := decodeBlockContext(chunk[startIdx:endIdx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blockContexts[i] = blockContext
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkBlockRanges = append(chunkBlockRanges, &rawdb.ChunkBlockRange{
|
||||||
|
StartBlockNumber: blockContexts[0].BlockNumber,
|
||||||
|
EndBlockNumber: blockContexts[len(blockContexts)-1].BlockNumber,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return chunkBlockRanges, nil
|
||||||
|
}
|
||||||
92
rollup/rollup_sync_service/l1client.go
Normal file
92
rollup/rollup_sync_service/l1client.go
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum"
|
||||||
|
"github.com/scroll-tech/go-ethereum/accounts/abi"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/log"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rpc"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
|
||||||
|
)
|
||||||
|
|
||||||
|
// L1Client is a wrapper around EthClient that adds
|
||||||
|
// methods for conveniently collecting rollup events of ScrollChain contract.
|
||||||
|
type L1Client struct {
|
||||||
|
ctx context.Context
|
||||||
|
client sync_service.EthClient
|
||||||
|
scrollChainAddress common.Address
|
||||||
|
l1CommitBatchEventSignature common.Hash
|
||||||
|
l1RevertBatchEventSignature common.Hash
|
||||||
|
l1FinalizeBatchEventSignature common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// newL1Client initializes a new L1Client instance with the provided configuration.
|
||||||
|
// It checks for a valid scrollChainAddress and verifies the chain ID.
|
||||||
|
func newL1Client(ctx context.Context, l1Client sync_service.EthClient, l1ChainId uint64, scrollChainAddress common.Address, scrollChainABI *abi.ABI) (*L1Client, error) {
|
||||||
|
if scrollChainAddress == (common.Address{}) {
|
||||||
|
return nil, errors.New("must pass non-zero scrollChainAddress to L1Client")
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check: compare chain IDs
|
||||||
|
got, err := l1Client.ChainID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to query L1 chain ID, err: %w", err)
|
||||||
|
}
|
||||||
|
if got.Cmp(big.NewInt(0).SetUint64(l1ChainId)) != 0 {
|
||||||
|
return nil, fmt.Errorf("unexpected chain ID, expected: %v, got: %v", l1ChainId, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := L1Client{
|
||||||
|
ctx: ctx,
|
||||||
|
client: l1Client,
|
||||||
|
scrollChainAddress: scrollChainAddress,
|
||||||
|
l1CommitBatchEventSignature: scrollChainABI.Events["CommitBatch"].ID,
|
||||||
|
l1RevertBatchEventSignature: scrollChainABI.Events["RevertBatch"].ID,
|
||||||
|
l1FinalizeBatchEventSignature: scrollChainABI.Events["FinalizeBatch"].ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetcRollupEventsInRange retrieves and parses commit/revert/finalize rollup events between block numbers: [from, to].
|
||||||
|
func (c *L1Client) fetchRollupEventsInRange(ctx context.Context, from, to uint64) ([]types.Log, error) {
|
||||||
|
log.Trace("L1Client fetchRollupEventsInRange", "fromBlock", from, "toBlock", to)
|
||||||
|
|
||||||
|
query := ethereum.FilterQuery{
|
||||||
|
FromBlock: big.NewInt(int64(from)), // inclusive
|
||||||
|
ToBlock: big.NewInt(int64(to)), // inclusive
|
||||||
|
Addresses: []common.Address{
|
||||||
|
c.scrollChainAddress,
|
||||||
|
},
|
||||||
|
Topics: make([][]common.Hash, 1),
|
||||||
|
}
|
||||||
|
query.Topics[0] = make([]common.Hash, 3)
|
||||||
|
query.Topics[0][0] = c.l1CommitBatchEventSignature
|
||||||
|
query.Topics[0][1] = c.l1RevertBatchEventSignature
|
||||||
|
query.Topics[0][2] = c.l1FinalizeBatchEventSignature
|
||||||
|
|
||||||
|
logs, err := c.client.FilterLogs(c.ctx, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to filter logs, err: %w", err)
|
||||||
|
}
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLatestFinalizedBlockNumber fetches the block number of the latest finalized block from the L1 chain.
|
||||||
|
func (c *L1Client) getLatestFinalizedBlockNumber(ctx context.Context) (uint64, error) {
|
||||||
|
header, err := c.client.HeaderByNumber(ctx, big.NewInt(int64(rpc.FinalizedBlockNumber)))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if !header.Number.IsInt64() {
|
||||||
|
return 0, fmt.Errorf("received unexpected block number in L1Client: %v", header.Number)
|
||||||
|
}
|
||||||
|
return header.Number.Uint64(), nil
|
||||||
|
}
|
||||||
70
rollup/rollup_sync_service/l1client_test.go
Normal file
70
rollup/rollup_sync_service/l1client_test.go
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestL1Client(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
mockClient := &mockEthClient{}
|
||||||
|
|
||||||
|
scrollChainABI, err := scrollChainMetaData.GetAbi()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("failed to get scroll chain abi", "err", err)
|
||||||
|
}
|
||||||
|
scrollChainAddress := common.HexToAddress("0x0123456789abcdef")
|
||||||
|
l1Client, err := newL1Client(ctx, mockClient, 11155111, scrollChainAddress, scrollChainABI)
|
||||||
|
require.NoError(t, err, "Failed to initialize L1Client")
|
||||||
|
|
||||||
|
blockNumber, err := l1Client.getLatestFinalizedBlockNumber(ctx)
|
||||||
|
assert.NoError(t, err, "Error getting latest confirmed block number")
|
||||||
|
assert.Equal(t, uint64(36), blockNumber, "Unexpected block number")
|
||||||
|
|
||||||
|
logs, err := l1Client.fetchRollupEventsInRange(ctx, 0, blockNumber)
|
||||||
|
assert.NoError(t, err, "Error fetching rollup events in range")
|
||||||
|
assert.Empty(t, logs, "Expected no logs from fetchRollupEventsInRange")
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockEthClient struct {
|
||||||
|
commitBatchRLP []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockEthClient) BlockNumber(ctx context.Context) (uint64, error) {
|
||||||
|
return 11155111, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockEthClient) ChainID(ctx context.Context) (*big.Int, error) {
|
||||||
|
return big.NewInt(11155111), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockEthClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
|
||||||
|
return []types.Log{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockEthClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||||
|
return &types.Header{
|
||||||
|
Number: big.NewInt(100 - 64),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockEthClient) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockEthClient) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
|
||||||
|
var tx types.Transaction
|
||||||
|
if err := rlp.DecodeBytes(m.commitBatchRLP, &tx); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
return &tx, false, nil
|
||||||
|
}
|
||||||
420
rollup/rollup_sync_service/rollup_sync_service.go
Normal file
420
rollup/rollup_sync_service/rollup_sync_service.go
Normal file
|
|
@ -0,0 +1,420 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/accounts/abi"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/rawdb"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/ethdb"
|
||||||
|
"github.com/scroll-tech/go-ethereum/log"
|
||||||
|
"github.com/scroll-tech/go-ethereum/params"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/rollup/rcfg"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rollup/withdrawtrie"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// defaultFetchBlockRange is the number of blocks that we collect in a single eth_getLogs query.
|
||||||
|
defaultFetchBlockRange = uint64(100)
|
||||||
|
|
||||||
|
// defaultSyncInterval is the frequency at which we query for new rollup event.
|
||||||
|
defaultSyncInterval = 60 * time.Second
|
||||||
|
|
||||||
|
// defaultMaxRetries is the maximum number of retries allowed when the local node is not synced up to the required block height.
|
||||||
|
defaultMaxRetries = 20
|
||||||
|
|
||||||
|
// defaultGetBlockInRangeRetryDelay is the time delay between retries when attempting to get blocks in range.
|
||||||
|
// The service will wait for this duration if it detects that the local node has not synced up to the block height
|
||||||
|
// of a specific L1 batch finalize event.
|
||||||
|
defaultGetBlockInRangeRetryDelay = 60 * time.Second
|
||||||
|
|
||||||
|
// defaultLogInterval is the frequency at which we print the latestProcessedBlock.
|
||||||
|
defaultLogInterval = 5 * time.Minute
|
||||||
|
)
|
||||||
|
|
||||||
|
// RollupSyncService collects ScrollChain batch commit/revert/finalize events and stores metadata into db.
|
||||||
|
type RollupSyncService struct {
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
client *L1Client
|
||||||
|
db ethdb.Database
|
||||||
|
latestProcessedBlock uint64
|
||||||
|
scrollChainABI *abi.ABI
|
||||||
|
l1CommitBatchEventSignature common.Hash
|
||||||
|
l1RevertBatchEventSignature common.Hash
|
||||||
|
l1FinalizeBatchEventSignature common.Hash
|
||||||
|
bc *core.BlockChain
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRollupSyncService(ctx context.Context, genesisConfig *params.ChainConfig, db ethdb.Database, l1Client sync_service.EthClient, bc *core.BlockChain, l1DeploymentBlock uint64) (*RollupSyncService, error) {
|
||||||
|
// terminate if the caller does not provide an L1 client (e.g. in tests)
|
||||||
|
if l1Client == nil || (reflect.ValueOf(l1Client).Kind() == reflect.Ptr && reflect.ValueOf(l1Client).IsNil()) {
|
||||||
|
log.Warn("No L1 client provided, L1 rollup sync service will not run")
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if genesisConfig.Scroll.L1Config == nil {
|
||||||
|
return nil, fmt.Errorf("missing L1 config in genesis")
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollChainABI, err := scrollChainMetaData.GetAbi()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get scroll chain abi: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newL1Client(ctx, l1Client, genesisConfig.Scroll.L1Config.L1ChainId, genesisConfig.Scroll.L1Config.ScrollChainAddress, scrollChainABI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to initialize l1 client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the latestProcessedBlock with the block just before the L1 deployment block.
|
||||||
|
// This serves as a default value when there's no L1 rollup events synced in the database.
|
||||||
|
var latestProcessedBlock uint64
|
||||||
|
if l1DeploymentBlock > 0 {
|
||||||
|
latestProcessedBlock = l1DeploymentBlock - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
block := rawdb.ReadRollupEventSyncedL1BlockNumber(db)
|
||||||
|
if block != nil {
|
||||||
|
// restart from latest synced block number
|
||||||
|
latestProcessedBlock = *block
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
service := RollupSyncService{
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
client: client,
|
||||||
|
db: db,
|
||||||
|
latestProcessedBlock: latestProcessedBlock,
|
||||||
|
scrollChainABI: scrollChainABI,
|
||||||
|
l1CommitBatchEventSignature: scrollChainABI.Events["CommitBatch"].ID,
|
||||||
|
l1RevertBatchEventSignature: scrollChainABI.Events["RevertBatch"].ID,
|
||||||
|
l1FinalizeBatchEventSignature: scrollChainABI.Events["FinalizeBatch"].ID,
|
||||||
|
bc: bc,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &service, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RollupSyncService) Start() {
|
||||||
|
if s == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Starting rollup event sync background service", "latest processed block", s.latestProcessedBlock)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
syncTicker := time.NewTicker(defaultSyncInterval)
|
||||||
|
defer syncTicker.Stop()
|
||||||
|
|
||||||
|
logTicker := time.NewTicker(defaultLogInterval)
|
||||||
|
defer logTicker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-syncTicker.C:
|
||||||
|
s.fetchRollupEvents()
|
||||||
|
case <-logTicker.C:
|
||||||
|
log.Info("Sync rollup events progress update", "latestProcessedBlock", s.latestProcessedBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RollupSyncService) Stop() {
|
||||||
|
if s == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Stopping rollup event sync background service")
|
||||||
|
|
||||||
|
if s.cancel != nil {
|
||||||
|
s.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RollupSyncService) fetchRollupEvents() {
|
||||||
|
latestConfirmed, err := s.client.getLatestFinalizedBlockNumber(s.ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("failed to get latest confirmed block number", "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Trace("Sync service fetch rollup events", "latest processed block", s.latestProcessedBlock, "latest confirmed", latestConfirmed)
|
||||||
|
|
||||||
|
// query in batches
|
||||||
|
for from := s.latestProcessedBlock + 1; from <= latestConfirmed; from += defaultFetchBlockRange {
|
||||||
|
if s.ctx.Err() != nil {
|
||||||
|
log.Info("Context canceled", "reason", s.ctx.Err())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
to := from + defaultFetchBlockRange - 1
|
||||||
|
if to > latestConfirmed {
|
||||||
|
to = latestConfirmed
|
||||||
|
}
|
||||||
|
|
||||||
|
logs, err := s.client.fetchRollupEventsInRange(s.ctx, from, to)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to fetch rollup events in range", "from block", from, "to block", to, "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.parseAndUpdateRollupEventLogs(logs, to); err != nil {
|
||||||
|
log.Error("failed to parse and update rollup event logs", "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.latestProcessedBlock = to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endBlockNumber uint64) error {
|
||||||
|
for _, vLog := range logs {
|
||||||
|
switch vLog.Topics[0] {
|
||||||
|
case s.l1CommitBatchEventSignature:
|
||||||
|
event := &L1CommitBatchEvent{}
|
||||||
|
if err := UnpackLog(s.scrollChainABI, event, "CommitBatch", vLog); err != nil {
|
||||||
|
return fmt.Errorf("failed to unpack commit rollup event log, err: %w", err)
|
||||||
|
}
|
||||||
|
batchIndex := event.BatchIndex.Uint64()
|
||||||
|
log.Trace("found new CommitBatch event", "batch index", batchIndex)
|
||||||
|
|
||||||
|
chunkBlockRanges, err := s.getChunkRanges(batchIndex, &vLog)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get chunk ranges, err: %w", err)
|
||||||
|
}
|
||||||
|
rawdb.WriteBatchChunkRanges(s.db, batchIndex, chunkBlockRanges)
|
||||||
|
|
||||||
|
case s.l1RevertBatchEventSignature:
|
||||||
|
event := &L1RevertBatchEvent{}
|
||||||
|
if err := UnpackLog(s.scrollChainABI, event, "RevertBatch", vLog); err != nil {
|
||||||
|
return fmt.Errorf("failed to unpack revert rollup event log, err: %w", err)
|
||||||
|
}
|
||||||
|
batchIndex := event.BatchIndex.Uint64()
|
||||||
|
log.Trace("found new RevertBatch event", "batch index", batchIndex)
|
||||||
|
|
||||||
|
rawdb.DeleteBatchChunkRanges(s.db, batchIndex)
|
||||||
|
|
||||||
|
case s.l1FinalizeBatchEventSignature:
|
||||||
|
event := &L1FinalizeBatchEvent{}
|
||||||
|
if err := UnpackLog(s.scrollChainABI, event, "FinalizeBatch", vLog); err != nil {
|
||||||
|
return fmt.Errorf("failed to unpack finalized rollup event log, err: %w", err)
|
||||||
|
}
|
||||||
|
batchIndex := event.BatchIndex.Uint64()
|
||||||
|
log.Trace("found new FinalizeBatch event", "batch index", batchIndex)
|
||||||
|
|
||||||
|
parentBatchMeta, chunks, err := s.getLocalInfoForBatch(batchIndex)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get local node info, batch index: %v, err: %w", batchIndex, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endBlock, finalizedBatchMeta, err := validateBatch(event, parentBatchMeta, chunks)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawdb.WriteFinalizedL2BlockNumber(s.db, endBlock)
|
||||||
|
rawdb.WriteFinalizedBatchMeta(s.db, batchIndex, finalizedBatchMeta)
|
||||||
|
|
||||||
|
if batchIndex%100 == 0 {
|
||||||
|
log.Info("finalized batch progress", "batch index", batchIndex, "finalized l2 block height", endBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown event, topic: %v, tx hash: %v", vLog.Topics[0].Hex(), vLog.TxHash.Hex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: the batch updates above are idempotent, if we crash
|
||||||
|
// before this line and reexecute the previous steps, we will
|
||||||
|
// get the same result.
|
||||||
|
rawdb.WriteRollupEventSyncedL1BlockNumber(s.db, endBlockNumber)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RollupSyncService) getLocalInfoForBatch(batchIndex uint64) (*rawdb.FinalizedBatchMeta, []*Chunk, error) {
|
||||||
|
chunkBlockRanges := rawdb.ReadBatchChunkRanges(s.db, batchIndex)
|
||||||
|
if len(chunkBlockRanges) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("failed to get batch chunk ranges, empty chunk block ranges")
|
||||||
|
}
|
||||||
|
|
||||||
|
endBlockNumber := chunkBlockRanges[len(chunkBlockRanges)-1].EndBlockNumber
|
||||||
|
for i := 0; i < defaultMaxRetries; i++ {
|
||||||
|
if s.ctx.Err() != nil {
|
||||||
|
log.Info("Context canceled", "reason", s.ctx.Err())
|
||||||
|
return nil, nil, s.ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
localSyncedBlockHeight := s.bc.CurrentBlock().Number().Uint64()
|
||||||
|
if localSyncedBlockHeight >= endBlockNumber {
|
||||||
|
break // ready to proceed, exit retry loop
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("local node is not synced up to the required block height, waiting for next retry",
|
||||||
|
"retries", i+1, "local synced block height", localSyncedBlockHeight, "required end block number", endBlockNumber)
|
||||||
|
time.Sleep(defaultGetBlockInRangeRetryDelay)
|
||||||
|
}
|
||||||
|
|
||||||
|
localSyncedBlockHeight := s.bc.CurrentBlock().Number().Uint64()
|
||||||
|
if localSyncedBlockHeight < endBlockNumber {
|
||||||
|
return nil, nil, fmt.Errorf("local node is not synced up to the required block height: %v, local synced block height: %v", endBlockNumber, localSyncedBlockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks := make([]*Chunk, len(chunkBlockRanges))
|
||||||
|
for i, cr := range chunkBlockRanges {
|
||||||
|
chunks[i] = &Chunk{Blocks: make([]*WrappedBlock, cr.EndBlockNumber-cr.StartBlockNumber+1)}
|
||||||
|
for j := cr.StartBlockNumber; j <= cr.EndBlockNumber; j++ {
|
||||||
|
block := s.bc.GetBlockByNumber(j)
|
||||||
|
if block == nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to get block by number: %v", i)
|
||||||
|
}
|
||||||
|
txData := txsToTxsData(block.Transactions())
|
||||||
|
state, err := s.bc.StateAt(block.Root())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to get block state, block: %v, err: %w", block.Hash().Hex(), err)
|
||||||
|
}
|
||||||
|
withdrawRoot := withdrawtrie.ReadWTRSlot(rcfg.L2MessageQueueAddress, state)
|
||||||
|
chunks[i].Blocks[j-cr.StartBlockNumber] = &WrappedBlock{
|
||||||
|
Header: block.Header(),
|
||||||
|
Transactions: txData,
|
||||||
|
WithdrawRoot: withdrawRoot,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get metadata of parent batch: default to genesis batch metadata.
|
||||||
|
parentBatchMeta := &rawdb.FinalizedBatchMeta{}
|
||||||
|
if batchIndex > 0 {
|
||||||
|
parentBatchMeta = rawdb.ReadFinalizedBatchMeta(s.db, batchIndex-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentBatchMeta, chunks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RollupSyncService) getChunkRanges(batchIndex uint64, vLog *types.Log) ([]*rawdb.ChunkBlockRange, error) {
|
||||||
|
if batchIndex == 0 {
|
||||||
|
return []*rawdb.ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 0}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, _, err := s.client.client.TransactionByHash(context.Background(), vLog.TxHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get transaction, err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.decodeChunkBlockRanges(tx.Data())
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeChunkBlockRanges decodes chunks in a batch based on the commit batch transaction's calldata.
|
||||||
|
func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.ChunkBlockRange, error) {
|
||||||
|
const methodIDLength = 4
|
||||||
|
if len(txData) < methodIDLength {
|
||||||
|
return nil, fmt.Errorf("transaction data is too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
method, err := s.scrollChainABI.MethodById(txData[:methodIDLength])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get method by ID, ID: %v, err: %w", txData[:4], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values, err := method.Inputs.Unpack(txData[methodIDLength:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unpack transaction data using ABI: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type commitBatchArgs struct {
|
||||||
|
Version uint8
|
||||||
|
ParentBatchHeader []byte
|
||||||
|
Chunks [][]byte
|
||||||
|
SkippedL1MessageBitmap []byte
|
||||||
|
}
|
||||||
|
var args commitBatchArgs
|
||||||
|
err = method.Inputs.Copy(&args, values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode calldata into commitBatch args, err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.Version != batchHeaderVersion {
|
||||||
|
return nil, fmt.Errorf("unexpected batch version, expected: %d, got: %v", batchHeaderVersion, args.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecodeChunkBlockRanges(args.Chunks)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateBatch verifies the consistency between the L1 contract and L2 node data.
|
||||||
|
// The function will terminate the node and exit if any consistency check fails.
|
||||||
|
// It returns the number of the end block, a finalized batch meta data, and an error if any.
|
||||||
|
func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*Chunk) (uint64, *rawdb.FinalizedBatchMeta, error) {
|
||||||
|
if len(chunks) == 0 {
|
||||||
|
return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
startChunk := chunks[0]
|
||||||
|
if len(startChunk.Blocks) == 0 {
|
||||||
|
return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0")
|
||||||
|
}
|
||||||
|
startBlock := startChunk.Blocks[0]
|
||||||
|
|
||||||
|
endChunk := chunks[len(chunks)-1]
|
||||||
|
if len(endChunk.Blocks) == 0 {
|
||||||
|
return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0")
|
||||||
|
}
|
||||||
|
endBlock := endChunk.Blocks[len(endChunk.Blocks)-1]
|
||||||
|
|
||||||
|
localStateRoot := endBlock.Header.Root
|
||||||
|
if localStateRoot != event.StateRoot {
|
||||||
|
log.Error("State root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized state root", event.StateRoot.Hex(), "l2 state root", localStateRoot.Hex())
|
||||||
|
syscall.Kill(os.Getpid(), syscall.SIGTERM)
|
||||||
|
return 0, nil, fmt.Errorf("state root mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
localWithdrawRoot := endBlock.WithdrawRoot
|
||||||
|
if localWithdrawRoot != event.WithdrawRoot {
|
||||||
|
log.Error("Withdraw root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized withdraw root", event.WithdrawRoot.Hex(), "l2 withdraw root", localWithdrawRoot.Hex())
|
||||||
|
syscall.Kill(os.Getpid(), syscall.SIGTERM)
|
||||||
|
return 0, nil, fmt.Errorf("withdraw root mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: All params for NewBatchHeader are calculated locally based on the block data.
|
||||||
|
batchHeader, err := NewBatchHeader(batchHeaderVersion, event.BatchIndex.Uint64(), parentBatchMeta.TotalL1MessagePopped, parentBatchMeta.BatchHash, chunks)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("failed to construct batch header, err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: If the batch headers match, this ensures the consistency of blocks and transactions
|
||||||
|
// (including skipped transactions) between L1 and L2.
|
||||||
|
localBatchHash := batchHeader.Hash()
|
||||||
|
if localBatchHash != event.BatchHash {
|
||||||
|
log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex())
|
||||||
|
chunksJson, _ := json.Marshal(chunks)
|
||||||
|
log.Error("Chunks", "chunks", string(chunksJson))
|
||||||
|
syscall.Kill(os.Getpid(), syscall.SIGTERM)
|
||||||
|
return 0, nil, fmt.Errorf("batch hash mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
totalL1MessagePopped := parentBatchMeta.TotalL1MessagePopped
|
||||||
|
for _, chunk := range chunks {
|
||||||
|
totalL1MessagePopped += chunk.NumL1Messages(totalL1MessagePopped)
|
||||||
|
}
|
||||||
|
finalizedBatchMeta := &rawdb.FinalizedBatchMeta{
|
||||||
|
BatchHash: localBatchHash,
|
||||||
|
TotalL1MessagePopped: totalL1MessagePopped,
|
||||||
|
StateRoot: localStateRoot,
|
||||||
|
WithdrawRoot: localWithdrawRoot,
|
||||||
|
}
|
||||||
|
return endBlock.Header.Number.Uint64(), finalizedBatchMeta, nil
|
||||||
|
}
|
||||||
207
rollup/rollup_sync_service/rollup_sync_service_test.go
Normal file
207
rollup/rollup_sync_service/rollup_sync_service_test.go
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
package rollup_sync_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/rawdb"
|
||||||
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
|
"github.com/scroll-tech/go-ethereum/ethdb/memorydb"
|
||||||
|
"github.com/scroll-tech/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRollupSyncServiceStartAndStop(t *testing.T) {
|
||||||
|
genesisConfig := ¶ms.ChainConfig{
|
||||||
|
Scroll: params.ScrollConfig{
|
||||||
|
L1Config: ¶ms.L1Config{
|
||||||
|
L1ChainId: 11155111,
|
||||||
|
ScrollChainAddress: common.HexToAddress("0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
db := rawdb.NewDatabase(memorydb.New())
|
||||||
|
l1Client := &mockEthClient{}
|
||||||
|
bc := &core.BlockChain{}
|
||||||
|
service, err := NewRollupSyncService(context.Background(), genesisConfig, db, l1Client, bc, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to new rollup sync service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NotNil(t, service)
|
||||||
|
service.Start()
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
service.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecodeChunkRanges(t *testing.T) {
|
||||||
|
scrollChainABI, err := scrollChainMetaData.GetAbi()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
service := &RollupSyncService{
|
||||||
|
scrollChainABI: scrollChainABI,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile("./testdata/commit_batch_transaction.json")
|
||||||
|
require.NoError(t, err, "Failed to read json file")
|
||||||
|
|
||||||
|
type transactionJson struct {
|
||||||
|
CallData string `json:"calldata"`
|
||||||
|
}
|
||||||
|
var txObj transactionJson
|
||||||
|
err = json.Unmarshal(data, &txObj)
|
||||||
|
require.NoError(t, err, "Failed to unmarshal transaction json")
|
||||||
|
|
||||||
|
testTxData, err := hex.DecodeString(txObj.CallData[2:])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to decode string: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges, err := service.decodeChunkBlockRanges(testTxData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to decode chunk ranges: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedRanges := []*rawdb.ChunkBlockRange{
|
||||||
|
{StartBlockNumber: 335921, EndBlockNumber: 335928},
|
||||||
|
{StartBlockNumber: 335929, EndBlockNumber: 335933},
|
||||||
|
{StartBlockNumber: 335934, EndBlockNumber: 335938},
|
||||||
|
{StartBlockNumber: 335939, EndBlockNumber: 335942},
|
||||||
|
{StartBlockNumber: 335943, EndBlockNumber: 335945},
|
||||||
|
{StartBlockNumber: 335946, EndBlockNumber: 335949},
|
||||||
|
{StartBlockNumber: 335950, EndBlockNumber: 335956},
|
||||||
|
{StartBlockNumber: 335957, EndBlockNumber: 335962},
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expectedRanges) != len(ranges) {
|
||||||
|
t.Fatalf("Expected range length %v, got %v", len(expectedRanges), len(ranges))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range ranges {
|
||||||
|
if *expectedRanges[i] != *ranges[i] {
|
||||||
|
t.Fatalf("Mismatch at index %d: expected %v, got %v", i, *expectedRanges[i], *ranges[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetChunkRanges(t *testing.T) {
|
||||||
|
genesisConfig := ¶ms.ChainConfig{
|
||||||
|
Scroll: params.ScrollConfig{
|
||||||
|
L1Config: ¶ms.L1Config{
|
||||||
|
L1ChainId: 11155111,
|
||||||
|
ScrollChainAddress: common.HexToAddress("0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
db := rawdb.NewDatabase(memorydb.New())
|
||||||
|
|
||||||
|
rlpData, err := os.ReadFile("./testdata/commit_batch_tx.rlp")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read RLP data: %v", err)
|
||||||
|
}
|
||||||
|
l1Client := &mockEthClient{
|
||||||
|
commitBatchRLP: rlpData,
|
||||||
|
}
|
||||||
|
bc := &core.BlockChain{}
|
||||||
|
service, err := NewRollupSyncService(context.Background(), genesisConfig, db, l1Client, bc, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to new rollup sync service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vLog := &types.Log{
|
||||||
|
TxHash: common.HexToHash("0x0"),
|
||||||
|
}
|
||||||
|
ranges, err := service.getChunkRanges(1, vLog)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expectedRanges := []*rawdb.ChunkBlockRange{
|
||||||
|
{StartBlockNumber: 911145, EndBlockNumber: 911151},
|
||||||
|
{StartBlockNumber: 911152, EndBlockNumber: 911155},
|
||||||
|
{StartBlockNumber: 911156, EndBlockNumber: 911159},
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expectedRanges) != len(ranges) {
|
||||||
|
t.Fatalf("Expected range length %v, got %v", len(expectedRanges), len(ranges))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range ranges {
|
||||||
|
if *expectedRanges[i] != *ranges[i] {
|
||||||
|
t.Fatalf("Mismatch at index %d: expected %v, got %v", i, *expectedRanges[i], *ranges[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateBatch(t *testing.T) {
|
||||||
|
templateBlockTrace1, err := os.ReadFile("./testdata/blockTrace_02.json")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wrappedBlock1 := &WrappedBlock{}
|
||||||
|
err = json.Unmarshal(templateBlockTrace1, wrappedBlock1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
chunk1 := &Chunk{Blocks: []*WrappedBlock{wrappedBlock1}}
|
||||||
|
|
||||||
|
templateBlockTrace2, err := os.ReadFile("./testdata/blockTrace_03.json")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wrappedBlock2 := &WrappedBlock{}
|
||||||
|
err = json.Unmarshal(templateBlockTrace2, wrappedBlock2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
chunk2 := &Chunk{Blocks: []*WrappedBlock{wrappedBlock2}}
|
||||||
|
|
||||||
|
templateBlockTrace3, err := os.ReadFile("./testdata/blockTrace_04.json")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wrappedBlock3 := &WrappedBlock{}
|
||||||
|
err = json.Unmarshal(templateBlockTrace3, wrappedBlock3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
chunk3 := &Chunk{Blocks: []*WrappedBlock{wrappedBlock3}}
|
||||||
|
|
||||||
|
parentBatchMeta1 := &rawdb.FinalizedBatchMeta{}
|
||||||
|
event1 := &L1FinalizeBatchEvent{
|
||||||
|
BatchIndex: big.NewInt(0),
|
||||||
|
BatchHash: common.HexToHash("0xd0f52bc254646e639bf24cc34606319a111975b2fdc431b1381eb6199bc09790"),
|
||||||
|
StateRoot: chunk3.Blocks[len(chunk3.Blocks)-1].Header.Root,
|
||||||
|
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
|
||||||
|
}
|
||||||
|
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*Chunk{chunk1, chunk2, chunk3})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, uint64(13), endBlock1)
|
||||||
|
|
||||||
|
templateBlockTrace4, err := os.ReadFile("./testdata/blockTrace_05.json")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wrappedBlock4 := &WrappedBlock{}
|
||||||
|
err = json.Unmarshal(templateBlockTrace4, wrappedBlock4)
|
||||||
|
require.NoError(t, err)
|
||||||
|
chunk4 := &Chunk{Blocks: []*WrappedBlock{wrappedBlock4}}
|
||||||
|
|
||||||
|
parentBatchMeta2 := &rawdb.FinalizedBatchMeta{
|
||||||
|
BatchHash: event1.BatchHash,
|
||||||
|
TotalL1MessagePopped: 11,
|
||||||
|
StateRoot: chunk3.Blocks[len(chunk3.Blocks)-1].Header.Root,
|
||||||
|
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
|
||||||
|
}
|
||||||
|
assert.Equal(t, parentBatchMeta2, finalizedBatchMeta1)
|
||||||
|
event2 := &L1FinalizeBatchEvent{
|
||||||
|
BatchIndex: big.NewInt(1),
|
||||||
|
BatchHash: common.HexToHash("0xfb77bf8f3bf449126ebbf403fdccfcf78636e34d72d62eed8da0e8c9fd38fa63"),
|
||||||
|
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
|
||||||
|
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
|
||||||
|
}
|
||||||
|
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*Chunk{chunk4})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, uint64(17), endBlock2)
|
||||||
|
|
||||||
|
parentBatchMeta3 := &rawdb.FinalizedBatchMeta{
|
||||||
|
BatchHash: event2.BatchHash,
|
||||||
|
TotalL1MessagePopped: 42,
|
||||||
|
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
|
||||||
|
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
|
||||||
|
}
|
||||||
|
assert.Equal(t, parentBatchMeta3, finalizedBatchMeta2)
|
||||||
|
}
|
||||||
591
rollup/rollup_sync_service/testdata/blockTrace_02.json
vendored
Normal file
591
rollup/rollup_sync_service/testdata/blockTrace_02.json
vendored
Normal file
|
|
@ -0,0 +1,591 @@
|
||||||
|
{
|
||||||
|
"withdrawTrieRoot": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coinbase": {
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"parentHash": "0xe17f08d25ef61a8ee12aa29704b901345a597f5e45a9a0f603ae0f70845b54dc",
|
||||||
|
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"miner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"stateRoot": "0x25b792bfd6d6456451f996e9383225e026fff469da205bb916768c0a78fd16af",
|
||||||
|
"transactionsRoot": "0x3057754c197f33e1fe799e996db6232b5257412feea05b3c1754738f0b33fe32",
|
||||||
|
"receiptsRoot": "0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x2",
|
||||||
|
"number": "0x2",
|
||||||
|
"gasLimit": "0x355418d1e8184",
|
||||||
|
"gasUsed": "0xa410",
|
||||||
|
"timestamp": "0x63807b2a",
|
||||||
|
"extraData": "0xd983010a0d846765746889676f312e31372e3133856c696e75780000000000004b54a94f0df14333e63c8a13dfe6097c1a08b5fd2c225a8dc0f199dae245aead55d6f774a980a0c925be407748d56a14106afda7ddc1dec342e7ee3b0d58a8df01",
|
||||||
|
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"nonce": "0x0000000000000000",
|
||||||
|
"baseFeePerGas": "0x1de9",
|
||||||
|
"hash": "0xc7b6c7022c8386cdaf6fcd3d4f8d03dce257ae3664a072fdce511ecefce73ad0"
|
||||||
|
},
|
||||||
|
"row_consumption": [
|
||||||
|
{
|
||||||
|
"name": "evm",
|
||||||
|
"row_number": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "state",
|
||||||
|
"row_number": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bytecode",
|
||||||
|
"row_number": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "copy",
|
||||||
|
"row_number": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keccak",
|
||||||
|
"row_number": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tx",
|
||||||
|
"row_number": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rlp",
|
||||||
|
"row_number": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "exp",
|
||||||
|
"row_number": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pi",
|
||||||
|
"row_number": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "poseidon",
|
||||||
|
"row_number": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mpt",
|
||||||
|
"row_number": 11
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transactions": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"nonce": 0,
|
||||||
|
"txHash": "0xb2febc1213baec968f6575789108e175273b8da8f412468098893084229f1542",
|
||||||
|
"gas": 500000,
|
||||||
|
"gasPrice": "0x3b9aec2e",
|
||||||
|
"from": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"to": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2",
|
||||||
|
"chainId": "0xcf55",
|
||||||
|
"value": "0x152d02c7e14af6000000",
|
||||||
|
"data": "0x",
|
||||||
|
"isCreate": false,
|
||||||
|
"v": "0x19ece",
|
||||||
|
"r": "0xab07ae99c67aa78e7ba5cf6781e90cc32b219b1de102513d56548a41e86df514",
|
||||||
|
"s": "0x34cbd19feacd73e8ce64d00c4d1996b9b5243c578fd7f51bfaec288bbaf42a8b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"nonce": 1,
|
||||||
|
"txHash": "0xe6ac2ffc543d07f1e280912a2abe3aa659bf83773740681151297ada1bb211dd",
|
||||||
|
"gas": 500000,
|
||||||
|
"gasPrice": "0x3b9aec2e",
|
||||||
|
"from": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"to": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed",
|
||||||
|
"chainId": "0xcf55",
|
||||||
|
"value": "0x152d02c7e14af6000000",
|
||||||
|
"data": "0x",
|
||||||
|
"isCreate": false,
|
||||||
|
"v": "0x19ece",
|
||||||
|
"r": "0xf039985866d8256f10c1be4f7b2cace28d8f20bde27e2604393eb095b7f77316",
|
||||||
|
"s": "0x5a3e6e81065f2b4604bcec5bd4aba684835996fc3f879380aac1c09c6eed32f1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageTrace": {
|
||||||
|
"rootBefore": "0x2579122e8f9ec1e862e7d415cef2fb495d7698a8e5f0dddc5651ba4236336e7d",
|
||||||
|
"rootAfter": "0x25b792bfd6d6456451f996e9383225e026fff469da205bb916768c0a78fd16af",
|
||||||
|
"proofs": {
|
||||||
|
"0x01bae6BF68E9A03Fb2bc0615b1bf0d69ce9411eD": [
|
||||||
|
"0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c0404000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x1C5A77d9FA7eF466951B2F01F724BCa3A5820b63": [
|
||||||
|
"0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c0404000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0xc0c4C8bAEA3f6Acb49b6E1fb9e2ADEcEeaCB0cA2": [
|
||||||
|
"0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c0404000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"executionResults": [
|
||||||
|
{
|
||||||
|
"gas": 21000,
|
||||||
|
"failed": false,
|
||||||
|
"returnValue": "",
|
||||||
|
"from": {
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x200000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x0",
|
||||||
|
"codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"accountAfter": [
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 1,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffead2fd381eb5006a6eb8",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x152d02c7e14af6000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 1,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffead2fd381eb5006a6eb8",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"structLogs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gas": 21000,
|
||||||
|
"failed": false,
|
||||||
|
"returnValue": "",
|
||||||
|
"from": {
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 1,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffead2fd381eb5006a6eb8",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x0",
|
||||||
|
"codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"accountAfter": [
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x152d02c7e14af6000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"structLogs": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mptwitness": [
|
||||||
|
{
|
||||||
|
"address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed",
|
||||||
|
"accountKey": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x7d6e333642ba5156dcddf0e5a898765d49fbf2ce15d4e762e8c19e8f2e127925",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xdf92dc6c0dd1c7fde78079ea62863977463f07e542966c6393f4d8cd6cce3117",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x7d6e333642ba5156dcddf0e5a898765d49fbf2ce15d4e762e8c19e8f2e127925",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xdf92dc6c0dd1c7fde78079ea62863977463f07e542966c6393f4d8cd6cce3117",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x7d6e333642ba5156dcddf0e5a898765d49fbf2ce15d4e762e8c19e8f2e127925",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xdf92dc6c0dd1c7fde78079ea62863977463f07e542966c6393f4d8cd6cce3117",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
{
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x200000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x200000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2",
|
||||||
|
"accountKey": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed",
|
||||||
|
"accountKey": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
{
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x200000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2",
|
||||||
|
"accountKey": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed",
|
||||||
|
"accountKey": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806",
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x1",
|
||||||
|
"root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"value": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b",
|
||||||
|
"sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x45c70c4b7345dd1705ed019271dd1d7fbe2a1054ecefaf3fd2a22388a483072e",
|
||||||
|
"sibling": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x152d02c7e14af6000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63",
|
||||||
|
"accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"value": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806",
|
||||||
|
"sibling": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x0",
|
||||||
|
"root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"value": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806",
|
||||||
|
"sibling": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"leaf": {
|
||||||
|
"value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15",
|
||||||
|
"sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
{
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nonce": 2,
|
||||||
|
"balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2",
|
||||||
|
"accountKey": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616",
|
||||||
|
"accountPath": [
|
||||||
|
{
|
||||||
|
"pathPart": "0x1",
|
||||||
|
"root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"value": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b",
|
||||||
|
"sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x45c70c4b7345dd1705ed019271dd1d7fbe2a1054ecefaf3fd2a22388a483072e",
|
||||||
|
"sibling": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pathPart": "0x3",
|
||||||
|
"root": "0xaf16fd780a8c7616b95b20da69f4ff26e0253238e996f9516445d6d6bf92b725",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"value": "0x5bbe97e7e66485b203f9dfea64eb7fa7df06959b12cbde2beba14f8f91133a13",
|
||||||
|
"sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02",
|
||||||
|
"sibling": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "0x794953bb5d8aa00f90383ff435ce2ea58e30e1da1061e69455c38496766ec10f",
|
||||||
|
"sibling": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"leaf": {
|
||||||
|
"value": "0x45c70c4b7345dd1705ed019271dd1d7fbe2a1054ecefaf3fd2a22388a483072e",
|
||||||
|
"sibling": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accountUpdate": [
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x152d02c7e14af6000000",
|
||||||
|
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"statePath": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"stateUpdate": [
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12879
rollup/rollup_sync_service/testdata/blockTrace_03.json
vendored
Normal file
12879
rollup/rollup_sync_service/testdata/blockTrace_03.json
vendored
Normal file
File diff suppressed because one or more lines are too long
870
rollup/rollup_sync_service/testdata/blockTrace_04.json
vendored
Normal file
870
rollup/rollup_sync_service/testdata/blockTrace_04.json
vendored
Normal file
|
|
@ -0,0 +1,870 @@
|
||||||
|
{
|
||||||
|
"coinbase": {
|
||||||
|
"address": "0x5300000000000000000000000000000000000005",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x2aa86921dcd2c0",
|
||||||
|
"keccakCodeHash": "0x256e306f068f0847c8aab5819879b2ff45c021ce2e2f428be51be663415b1d60",
|
||||||
|
"poseidonCodeHash": "0x2c49d7de76e39008575f2f090bb3e90912bad475ea8102c8565c249a75575df5",
|
||||||
|
"codeSize": 1652
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"parentHash": "0xe761181afb179bc4e6848ecc4e32af82c0eeff4aca77024f985d1dffb0ba0013",
|
||||||
|
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"miner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"stateRoot": "0x155c42b3ffa9b88987b02bc8f89fb31f2b555bb8bff971d6fcd92e04a144c248",
|
||||||
|
"transactionsRoot": "0x891f5907147c83867e1e7b200b9d26fb43c3c08f81202d04235c84a2aa79f72f",
|
||||||
|
"receiptsRoot": "0x7ad169feb178baf74f7c0a12a28570bd69bd10e616acad2caea09a55fd1fb541",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x2",
|
||||||
|
"number": "0xd",
|
||||||
|
"gasLimit": "0x7a1200",
|
||||||
|
"gasUsed": "0x5dc0",
|
||||||
|
"timestamp": "0x646b6e13",
|
||||||
|
"extraData": "0xd983030201846765746889676f312e31382e3130856c696e7578000000000000f942387d5a3dba7786280b806f022e2afaec53939149ac7b132b4ef1cf5cdf393d688543d984ae15b1896185ea13f9e7ae18b22b65e5ffec9128195d7cde6fa700",
|
||||||
|
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"nonce": "0x0000000000000000",
|
||||||
|
"baseFeePerGas": null,
|
||||||
|
"hash": "0x09f75bc27efe18cd77a82491370442ea5a6066e910b73dc99fe1caff950c357b"
|
||||||
|
},
|
||||||
|
"row_consumption": [
|
||||||
|
],
|
||||||
|
"transactions": [
|
||||||
|
{
|
||||||
|
"type": 126,
|
||||||
|
"nonce": 10,
|
||||||
|
"txHash": "0xed6dff31c5516b3b9d169781865276cf27501aadd45c131bf8c841c5e619e56a",
|
||||||
|
"gas": 24000,
|
||||||
|
"gasPrice": "0x0",
|
||||||
|
"from": "0x478cdd110520a8e733e2acf9e543d2c687ea5239",
|
||||||
|
"to": "0x1a258d17bf244c4df02d40343a7626a9d321e105",
|
||||||
|
"chainId": "0x0",
|
||||||
|
"value": "0x0",
|
||||||
|
"data": "0x8ef1332e000000000000000000000000ea08a65b1829af779261e768d609e59279b510f2000000000000000000000000f2ec6b6206f6208e8f9b394efc1a01c1cbde77750000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4232e87480000000000000000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf0000000000000000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"isCreate": false,
|
||||||
|
"v": "0x0",
|
||||||
|
"r": "0x0",
|
||||||
|
"s": "0x0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"nonce": 11,
|
||||||
|
"txHash": "0xed6dff31c5516b3b9d169781865276cf27501aadd45c131bf8c841c5e619e56a",
|
||||||
|
"gas": 24000,
|
||||||
|
"gasPrice": "0x0",
|
||||||
|
"from": "0x478cdd110520a8e733e2acf9e543d2c687ea5239",
|
||||||
|
"to": "0x1a258d17bf244c4df02d40343a7626a9d321e105",
|
||||||
|
"chainId": "0x0",
|
||||||
|
"value": "0x0",
|
||||||
|
"data": "0x",
|
||||||
|
"isCreate": false,
|
||||||
|
"v": "0x0",
|
||||||
|
"r": "0x0",
|
||||||
|
"s": "0x0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageTrace": {
|
||||||
|
"rootBefore": "0x16d403e1c55dee3e020457262414ee7a20596922c08cac631385d8ea6d6c2c2b",
|
||||||
|
"rootAfter": "0x155c42b3ffa9b88987b02bc8f89fb31f2b555bb8bff971d6fcd92e04a144c248",
|
||||||
|
"proofs": {
|
||||||
|
"0x1a258d17bF244C4dF02d40343a7626A9D321e105": [
|
||||||
|
"0x000f2d6436a450dc3daf4f111527f3e187a9641e7c5cbc4f53a386e6e4114bb8202cc33de5af63f5deca2409302103a4523463a3a16529835d526795e8966079db",
|
||||||
|
"0x0029ce00b3e5ddca3bd22d3a923b95239ed11243363803b8e1f5a89fb37ee3c6e52c0d8469864d5ee8e0d62944e8dc1de68f78b094d3ef7cf72a21b372866bab0a",
|
||||||
|
"0x001dcee8089ea21f679f1af199cc93ccb35fdea1257b9ffeac0ae5c89654a0dbce20790d9030fd3f822620f7395f1af3ca53789e7451f811c2364f2b4fa19be9fd",
|
||||||
|
"0x000d62fbf3a623b87d67d8f97132a8f1759360c03c1b78ea3654238eb6c72fd5dd0742c02437cc0294c49133a28968ba1f913963d9c2892254da675958cd4a4b2e",
|
||||||
|
"0x0026875849a967c3af8bbd7ac6efb4ef8250efaee44c8bd85ac026d541c7f509ac18ae138a98367696a39f7abe0a53fd3b32283fa843bdc4a2485d65b3b9651670",
|
||||||
|
"0x0125375fd5ae821cd3e835e2fba4ae79971635b7288d549ba8ba66bea36603686c05080000000000000000000000000000000000000000000000000867000000000000000130644e72e131a029b85045b68181585d2833e84879b9705b0e1847ce1160000030221b0e9cf191ce544dcc5c8927fd08af82cb88be110d9533468ffd2d575aed31f2125c021fb94759cb1993a2f07eae01792311e13f209441ff8969cf1eb8351cafbbe8f01ed4c292d9a27be523919a274441a076b20c7d713d192dbe6485c2201a258d17bf244c4df02d40343a7626a9d321e105000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x478CDd110520a8e733e2ACF9e543d2c687EA5239": [
|
||||||
|
"0x000f2d6436a450dc3daf4f111527f3e187a9641e7c5cbc4f53a386e6e4114bb8202cc33de5af63f5deca2409302103a4523463a3a16529835d526795e8966079db",
|
||||||
|
"0x0029ce00b3e5ddca3bd22d3a923b95239ed11243363803b8e1f5a89fb37ee3c6e52c0d8469864d5ee8e0d62944e8dc1de68f78b094d3ef7cf72a21b372866bab0a",
|
||||||
|
"0x000bf7d923da6cc335d4074262981bf4615b43a8eb2a4dd6f2eda4fd8e1503d9311c4e63762bb10044749243a2b52db21797da53a89ba6b8ceb5cee1596150ac45",
|
||||||
|
"0x002b29daef215b12b331bf75a98e595b8a10a91928f479cca3562db3859315055a1cb697055013d78d58072071584b3e40e8d846948c8e829cbbe9915e4bcf08f0",
|
||||||
|
"0x00000000000000000000000000000000000000000000000000000000000000000007b1a84d4b19493ba2ca6a59dbc42d0e8559a7f8fb0c066bb8b1d90ceee9ce5c",
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000000000e9e173703b7c89f67443e861d959df35575c16617ea238fd235d8612f9020ba",
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000000000ea71dd32b28e075772420197e740ad0ed7990e3f6e5be7f5051f0c0709defce",
|
||||||
|
"0x000000000000000000000000000000000000000000000000000000000000000000186f00dca57567f28233cef5140efd49b1624b0ec3aef5b7f7ee42f03c3b6231",
|
||||||
|
"0x0006aac99418e9b09baea374df117e64523910d04427251eec6a9b482b6433bc54186c0fb6b2462a9c851df47ab11054dac43ed5b3f9d8d8a5fcf2fd0f9eb3e147",
|
||||||
|
"0x0109c2edb6138e8d6dc8f0b8b5ae98dd721c7053061887757f6749c484bddf92fa05080000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4702098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b6486420478cdd110520a8e733e2acf9e543d2c687ea5239000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x5300000000000000000000000000000000000000": [
|
||||||
|
"0x000f2d6436a450dc3daf4f111527f3e187a9641e7c5cbc4f53a386e6e4114bb8202cc33de5af63f5deca2409302103a4523463a3a16529835d526795e8966079db",
|
||||||
|
"0x0029ce00b3e5ddca3bd22d3a923b95239ed11243363803b8e1f5a89fb37ee3c6e52c0d8469864d5ee8e0d62944e8dc1de68f78b094d3ef7cf72a21b372866bab0a",
|
||||||
|
"0x001dcee8089ea21f679f1af199cc93ccb35fdea1257b9ffeac0ae5c89654a0dbce20790d9030fd3f822620f7395f1af3ca53789e7451f811c2364f2b4fa19be9fd",
|
||||||
|
"0x000d62fbf3a623b87d67d8f97132a8f1759360c03c1b78ea3654238eb6c72fd5dd0742c02437cc0294c49133a28968ba1f913963d9c2892254da675958cd4a4b2e",
|
||||||
|
"0x0026875849a967c3af8bbd7ac6efb4ef8250efaee44c8bd85ac026d541c7f509ac18ae138a98367696a39f7abe0a53fd3b32283fa843bdc4a2485d65b3b9651670",
|
||||||
|
"0x000a3197466e4643551413444b60bbf8ab0ced04566326492fdf1993586eec3fe10000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x002143f0cbad38f9696bb9c0be84281e5b517a06983edef7c75485b7a06473c97921dd9af8de7aade9fba53909b1a98ae938236ceec8ba6346ba3ba75c039194d7",
|
||||||
|
"0x0115d04fcf1fe3d9a4cc7a76b70fafcd7b9304b42108af39d9e500be391563775c0508000000000000000000000000000000000000000000000000064d000000000000000000000000000000000000000000000000000000000000000000000000000000002908ab50d1edc9dac80a344f44731acf807809c545e3388816b97a9882b5d4f974ae902ff6a84825a9cde7cc5f26e8c414e88139716c3423ed908f0a60c996011c70d94e9dc7c85d39f6877b01e59a87c057882957d9fd16c55025dfdcaa4d93205300000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x5300000000000000000000000000000000000002": [
|
||||||
|
"0x000f2d6436a450dc3daf4f111527f3e187a9641e7c5cbc4f53a386e6e4114bb8202cc33de5af63f5deca2409302103a4523463a3a16529835d526795e8966079db",
|
||||||
|
"0x000150eaa497ee8904a3d2dc8350c03963fb1786ea5253d5cc16f321afcd862cee107e99fa497bffacfb8ab50a44b93c9a74bc7c669323c7fbd0560a657342c55a",
|
||||||
|
"0x000877a6983a09f78254ca94a086eb673296f5583aa33855bfbdbe6d2fadf0ff0107b2e01ad456a3ec4c88478c604ad6a15c6fb572259e49ef4cc781940fe1375e",
|
||||||
|
"0x0013b6a97296cf294d19f634904a7fa973d9714b90cc42e0456ad428b7278f338e0accad868d7f4aaa755b29eae6ad523415a9df210ffced28d7d33fa6d5a319b3",
|
||||||
|
"0x0011de0e672d258d43c785592fc939bc105441bafc9c1455901723358b0a73d5cc29562af63a2293f036058180ce56f5269c6a3d4d18d8e1dc75ef03cb8f51f8b9",
|
||||||
|
"0x01236b0ff4611519fb52869dd99bedcb730ebe17544687c5064da49f42f741831d05080000000000000000000000000000000000000000000000000873000000000000000000000000000000000000000000000000000000000000000000000000000000001bd955d4ef171429eb11fade67006376e84bf94630ddb9b9948c3f385ce0f05aa48c68219d344cebd30fca18d0777f587e55052ae6161c88fa4c16407211ddaa0d39d683afa3720f93c44224e2b95a5871a5a2207b5323f7fbf8f1862120ba90205300000000000000000000000000000000000002000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x5300000000000000000000000000000000000005": [
|
||||||
|
"0x000f2d6436a450dc3daf4f111527f3e187a9641e7c5cbc4f53a386e6e4114bb8202cc33de5af63f5deca2409302103a4523463a3a16529835d526795e8966079db",
|
||||||
|
"0x0029ce00b3e5ddca3bd22d3a923b95239ed11243363803b8e1f5a89fb37ee3c6e52c0d8469864d5ee8e0d62944e8dc1de68f78b094d3ef7cf72a21b372866bab0a",
|
||||||
|
"0x000bf7d923da6cc335d4074262981bf4615b43a8eb2a4dd6f2eda4fd8e1503d9311c4e63762bb10044749243a2b52db21797da53a89ba6b8ceb5cee1596150ac45",
|
||||||
|
"0x002b29daef215b12b331bf75a98e595b8a10a91928f479cca3562db3859315055a1cb697055013d78d58072071584b3e40e8d846948c8e829cbbe9915e4bcf08f0",
|
||||||
|
"0x011facf302b106912bccc8194dff4cb12139e7f04288d3f5eefb57ccf4d842ba22050800000000000000000000000000000000000000000000000006740000000000000000000000000000000000000000000000000000000000000000002aa86921dcd2c018f4988204e816e17e42d9f9a2a468d8ca70ad453a88d3e371a0d9f743b799a6256e306f068f0847c8aab5819879b2ff45c021ce2e2f428be51be663415b1d602c49d7de76e39008575f2f090bb3e90912bad475ea8102c8565c249a75575df5205300000000000000000000000000000000000005000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"storageProofs": {
|
||||||
|
"0x1a258d17bF244C4dF02d40343a7626A9D321e105": {
|
||||||
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": [
|
||||||
|
"0x001914b8a8cb4d4339d89ed1d5e6cd54ec609082fdf42fadb2d4101f3214f2a2290a1746dfbdf492c00e2854b46eda6adad88ad1b0583997db4121cb7d8e6de5ca",
|
||||||
|
"0x00084878451370def5a5648862c037adb6ae24f29b9237a1823638ca29d573bdd42446af3926a42a7e8b65f9a5fdd5a00e82e4f2b9684816fdc5d52c238bef604a",
|
||||||
|
"0x00027f6e365685a83e63cde58e13d22b99c130a578178f8198d755171a2ff97bf303e187b8ea9652424a9d9dac9bc16796838b196f141c6db57136643f22b48468",
|
||||||
|
"0x00149dad479c283104bb461dcce598d82aacff80a5844d863d8f64e0d3f3e83b1a0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x001f232429e01853a7456bc8bb4cbc3a35c132f7783e2b300306bceb64a44ce81e0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x0027e1c425d61d4468534c93b8aa80c34bbdea9ec2d69df7a730ecacf0089b22640000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x001f4bdfdda0df475064a0ea35302dddc6401b8c93afad9a7569afb9f2534750560000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x0001fc65caf9a60abae81bcb17c4854fa114100528e73ab1e649fac03ed9fa764e304459eb829e92aa3009534c4eba916b2900783c694385d2e7f87004e7649215",
|
||||||
|
"0x01249c7b39f739f430be8e1e2cae0f1db06dfe2f8d4cc631d312d5b98efb3e7402010100000000000000000000000000008eebfef33eb00149852cadb631838ad9bfcce84820b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"0x5300000000000000000000000000000000000000": {
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000000": [
|
||||||
|
"0x0004f706d28ba7344cc73128f383e7f4df4c79f296a56e1bbc24cdfab5bc4cba5c2a970eaf68f6e47243e30bea39087adc0082afa5fd55fc5537baccd03f786953",
|
||||||
|
"0x00296af6438bc81ff661ef6d1bb16d33d6784e88ae39ff28258e56e4e72d5607052bb61b23d947a704c29df01936e7c557bf9ec541243566a336b43f8aeca37eed",
|
||||||
|
"0x001750ff1780c9b253cfcbd6274a4f79f3a95819e0856c31f0a6025e30ac3a5b261b73cc5623d88d2687f0fa6006bc823149c779b9e751477a6f2b83773062ddbe",
|
||||||
|
"0x0004c8c2bf27ee6712f4175555679ff662b9423a1d7205fe31e77999106cfb5a2f0efef64a4ef3d151d1364174e0e72745aeee51bf93fb17f8071e6daf4571a736",
|
||||||
|
"0x001de6dfed408db1b0cf580652da17c9277834302d9ee2c39ab074675ca61fd9e02ea58d0958b74734329987e16d8afa4d83a7acc46417a7f7dbc1fd42e305b394",
|
||||||
|
"0x001dd3e7dce636d92fdb4dd8b65cb4e5b8ffd3d64e54a51d93a527826bb1ec3a480000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x02",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"0x5300000000000000000000000000000000000002": {
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000001": [
|
||||||
|
"0x00024a2d3ee220db30dece4b39c0cffc2ba97ddded52a3f2da3aeed1f485d0a7220000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x001da3cd3096ffd62c95bad392eedc1c578e7ccf248898c49c5ed82abb49a4b31a2b63c0d58a64939cf9026618503b904e267eeb0e465e15812b85485e81fb856c",
|
||||||
|
"0x01232927899d46fea05cc897a4f4671f808aa83c4eaf89396dfab15480fee91e8e010100000000000000000000000000005300000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000004",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000002": [
|
||||||
|
"0x00024a2d3ee220db30dece4b39c0cffc2ba97ddded52a3f2da3aeed1f485d0a7220000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x001da3cd3096ffd62c95bad392eedc1c578e7ccf248898c49c5ed82abb49a4b31a2b63c0d58a64939cf9026618503b904e267eeb0e465e15812b85485e81fb856c",
|
||||||
|
"0x012098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864010100000000000000000000000000006f4c950442e1af093bcff730381e63ae9171b87a200000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
],
|
||||||
|
"0x0000000000000000000000000000000000000000000000000000000000000003": [
|
||||||
|
"0x00024a2d3ee220db30dece4b39c0cffc2ba97ddded52a3f2da3aeed1f485d0a7220000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x001da3cd3096ffd62c95bad392eedc1c578e7ccf248898c49c5ed82abb49a4b31a2b63c0d58a64939cf9026618503b904e267eeb0e465e15812b85485e81fb856c",
|
||||||
|
"0x012098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864010100000000000000000000000000006f4c950442e1af093bcff730381e63ae9171b87a200000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"executionResults": [
|
||||||
|
{
|
||||||
|
"gas": 24000,
|
||||||
|
"failed": true,
|
||||||
|
"returnValue": "",
|
||||||
|
"from": {
|
||||||
|
"address": "0x478cdd110520a8e733e2acf9e543d2c687ea5239",
|
||||||
|
"nonce": 10,
|
||||||
|
"balance": "0x0",
|
||||||
|
"keccakCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
|
||||||
|
"poseidonCodeHash": "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864",
|
||||||
|
"codeSize": 0
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"address": "0x1a258d17bf244c4df02d40343a7626a9d321e105",
|
||||||
|
"nonce": 1,
|
||||||
|
"balance": "0x30644e72e131a029b85045b68181585d2833e84879b9705b0e1847ce11600000",
|
||||||
|
"keccakCodeHash": "0x31f2125c021fb94759cb1993a2f07eae01792311e13f209441ff8969cf1eb835",
|
||||||
|
"poseidonCodeHash": "0x1cafbbe8f01ed4c292d9a27be523919a274441a076b20c7d713d192dbe6485c2",
|
||||||
|
"codeSize": 2151
|
||||||
|
},
|
||||||
|
"accountAfter": [
|
||||||
|
{
|
||||||
|
"address": "0x478cdd110520a8e733e2acf9e543d2c687ea5239",
|
||||||
|
"nonce": 11,
|
||||||
|
"balance": "0x0",
|
||||||
|
"keccakCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
|
||||||
|
"poseidonCodeHash": "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864",
|
||||||
|
"codeSize": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x1a258d17bf244c4df02d40343a7626a9d321e105",
|
||||||
|
"nonce": 1,
|
||||||
|
"balance": "0x30644e72e131a029b85045b68181585d2833e84879b9705b0e1847ce11600000",
|
||||||
|
"keccakCodeHash": "0x31f2125c021fb94759cb1993a2f07eae01792311e13f209441ff8969cf1eb835",
|
||||||
|
"poseidonCodeHash": "0x1cafbbe8f01ed4c292d9a27be523919a274441a076b20c7d713d192dbe6485c2",
|
||||||
|
"codeSize": 2151
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0x5300000000000000000000000000000000000005",
|
||||||
|
"nonce": 0,
|
||||||
|
"balance": "0x2aa86921dcd2c0",
|
||||||
|
"keccakCodeHash": "0x256e306f068f0847c8aab5819879b2ff45c021ce2e2f428be51be663415b1d60",
|
||||||
|
"poseidonCodeHash": "0x2c49d7de76e39008575f2f090bb3e90912bad475ea8102c8565c249a75575df5",
|
||||||
|
"codeSize": 1652
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"poseidonCodeHash": "0x1cafbbe8f01ed4c292d9a27be523919a274441a076b20c7d713d192dbe6485c2",
|
||||||
|
"byteCode": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220366737524a7ac8fa76e3b2cd04bb1e0b8aa75e165c32f59b0076ead59d529de564736f6c634300080a0033",
|
||||||
|
"structLogs": [
|
||||||
|
{
|
||||||
|
"pc": 0,
|
||||||
|
"op": "PUSH1",
|
||||||
|
"gas": 320,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 2,
|
||||||
|
"op": "PUSH1",
|
||||||
|
"gas": 317,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x80"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 4,
|
||||||
|
"op": "MSTORE",
|
||||||
|
"gas": 314,
|
||||||
|
"gasCost": 12,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x80",
|
||||||
|
"0x40"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 5,
|
||||||
|
"op": "PUSH1",
|
||||||
|
"gas": 302,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 7,
|
||||||
|
"op": "CALLDATASIZE",
|
||||||
|
"gas": 299,
|
||||||
|
"gasCost": 2,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 8,
|
||||||
|
"op": "LT",
|
||||||
|
"gas": 297,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x4",
|
||||||
|
"0x184"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 9,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 294,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 12,
|
||||||
|
"op": "JUMPI",
|
||||||
|
"gas": 291,
|
||||||
|
"gasCost": 10,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x0",
|
||||||
|
"0x4e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 13,
|
||||||
|
"op": "PUSH1",
|
||||||
|
"gas": 281,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 15,
|
||||||
|
"op": "CALLDATALOAD",
|
||||||
|
"gas": 278,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 16,
|
||||||
|
"op": "PUSH1",
|
||||||
|
"gas": 275,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e000000000000000000000000ea08a65b1829af779261e768d609e592"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 18,
|
||||||
|
"op": "SHR",
|
||||||
|
"gas": 272,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e000000000000000000000000ea08a65b1829af779261e768d609e592",
|
||||||
|
"0xe0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 19,
|
||||||
|
"op": "DUP1",
|
||||||
|
"gas": 269,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 20,
|
||||||
|
"op": "PUSH4",
|
||||||
|
"gas": 266,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 25,
|
||||||
|
"op": "EQ",
|
||||||
|
"gas": 263,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x3659cfe6"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 26,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 260,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 29,
|
||||||
|
"op": "JUMPI",
|
||||||
|
"gas": 257,
|
||||||
|
"gasCost": 10,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0",
|
||||||
|
"0x65"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 30,
|
||||||
|
"op": "DUP1",
|
||||||
|
"gas": 247,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 31,
|
||||||
|
"op": "PUSH4",
|
||||||
|
"gas": 244,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 36,
|
||||||
|
"op": "EQ",
|
||||||
|
"gas": 241,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x4f1ef286"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 37,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 238,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 40,
|
||||||
|
"op": "JUMPI",
|
||||||
|
"gas": 235,
|
||||||
|
"gasCost": 10,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0",
|
||||||
|
"0x85"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 41,
|
||||||
|
"op": "DUP1",
|
||||||
|
"gas": 225,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 42,
|
||||||
|
"op": "PUSH4",
|
||||||
|
"gas": 222,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 47,
|
||||||
|
"op": "EQ",
|
||||||
|
"gas": 219,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5c60da1b"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 48,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 216,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 51,
|
||||||
|
"op": "JUMPI",
|
||||||
|
"gas": 213,
|
||||||
|
"gasCost": 10,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0",
|
||||||
|
"0x98"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 52,
|
||||||
|
"op": "DUP1",
|
||||||
|
"gas": 203,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 53,
|
||||||
|
"op": "PUSH4",
|
||||||
|
"gas": 200,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 58,
|
||||||
|
"op": "EQ",
|
||||||
|
"gas": 197,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8f283970"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 59,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 194,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 62,
|
||||||
|
"op": "JUMPI",
|
||||||
|
"gas": 191,
|
||||||
|
"gasCost": 10,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0",
|
||||||
|
"0xc9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 63,
|
||||||
|
"op": "DUP1",
|
||||||
|
"gas": 181,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 64,
|
||||||
|
"op": "PUSH4",
|
||||||
|
"gas": 178,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 69,
|
||||||
|
"op": "EQ",
|
||||||
|
"gas": 175,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0xf851a440"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 70,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 172,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 73,
|
||||||
|
"op": "JUMPI",
|
||||||
|
"gas": 169,
|
||||||
|
"gasCost": 10,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x0",
|
||||||
|
"0xe9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 74,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 159,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 77,
|
||||||
|
"op": "JUMP",
|
||||||
|
"gas": 156,
|
||||||
|
"gasCost": 8,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 93,
|
||||||
|
"op": "JUMPDEST",
|
||||||
|
"gas": 148,
|
||||||
|
"gasCost": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 94,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 147,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 97,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 144,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 100,
|
||||||
|
"op": "JUMP",
|
||||||
|
"gas": 141,
|
||||||
|
"gasCost": 8,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0xfe"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 254,
|
||||||
|
"op": "JUMPDEST",
|
||||||
|
"gas": 133,
|
||||||
|
"gasCost": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 255,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 132,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 258,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 129,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 261,
|
||||||
|
"op": "JUMP",
|
||||||
|
"gas": 126,
|
||||||
|
"gasCost": 8,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x29b"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 667,
|
||||||
|
"op": "JUMPDEST",
|
||||||
|
"gas": 118,
|
||||||
|
"gasCost": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 668,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 117,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 671,
|
||||||
|
"op": "PUSH2",
|
||||||
|
"gas": 114,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 674,
|
||||||
|
"op": "JUMP",
|
||||||
|
"gas": 111,
|
||||||
|
"gasCost": 8,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3",
|
||||||
|
"0x368"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 872,
|
||||||
|
"op": "JUMPDEST",
|
||||||
|
"gas": 103,
|
||||||
|
"gasCost": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 873,
|
||||||
|
"op": "PUSH1",
|
||||||
|
"gas": 102,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 875,
|
||||||
|
"op": "PUSH32",
|
||||||
|
"gas": 99,
|
||||||
|
"gasCost": 3,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3",
|
||||||
|
"0x0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 908,
|
||||||
|
"op": "JUMPDEST",
|
||||||
|
"gas": 96,
|
||||||
|
"gasCost": 1,
|
||||||
|
"depth": 1,
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3",
|
||||||
|
"0x0",
|
||||||
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": 909,
|
||||||
|
"op": "SLOAD",
|
||||||
|
"gas": 95,
|
||||||
|
"gasCost": 2100,
|
||||||
|
"depth": 1,
|
||||||
|
"error": "out of gas",
|
||||||
|
"stack": [
|
||||||
|
"0x8ef1332e",
|
||||||
|
"0x5b",
|
||||||
|
"0x106",
|
||||||
|
"0x2a3",
|
||||||
|
"0x0",
|
||||||
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"
|
||||||
|
],
|
||||||
|
"storage": {
|
||||||
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000008eebfef33eb00149852cadb631838ad9bfcce848"
|
||||||
|
},
|
||||||
|
"extraData": {
|
||||||
|
"proofList": [
|
||||||
|
{
|
||||||
|
"address": "0x1a258d17bf244c4df02d40343a7626a9d321e105",
|
||||||
|
"nonce": 1,
|
||||||
|
"balance": "0x30644e72e131a029b85045b68181585d2833e84879b9705b0e1847ce11600000",
|
||||||
|
"keccakCodeHash": "0x31f2125c021fb94759cb1993a2f07eae01792311e13f209441ff8969cf1eb835",
|
||||||
|
"poseidonCodeHash": "0x1cafbbe8f01ed4c292d9a27be523919a274441a076b20c7d713d192dbe6485c2",
|
||||||
|
"codeSize": 2151,
|
||||||
|
"storage": {
|
||||||
|
"key": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103",
|
||||||
|
"value": "0x0000000000000000000000008eebfef33eb00149852cadb631838ad9bfcce848"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"withdraw_trie_root": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
3713
rollup/rollup_sync_service/testdata/blockTrace_05.json
vendored
Normal file
3713
rollup/rollup_sync_service/testdata/blockTrace_05.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
3
rollup/rollup_sync_service/testdata/commit_batch_transaction.json
vendored
Normal file
3
rollup/rollup_sync_service/testdata/commit_batch_transaction.json
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
rollup/rollup_sync_service/testdata/commit_batch_tx.rlp
vendored
Normal file
BIN
rollup/rollup_sync_service/testdata/commit_batch_tx.rlp
vendored
Normal file
Binary file not shown.
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/scroll-tech/go-ethereum"
|
"github.com/scroll-tech/go-ethereum"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
"github.com/scroll-tech/go-ethereum/core/types"
|
"github.com/scroll-tech/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -16,4 +17,5 @@ type EthClient interface {
|
||||||
FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
|
FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
|
||||||
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
|
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
|
||||||
SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
|
SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
|
||||||
|
TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue