feat(L1 follower and rollup verifier): support CodecV7 in L1 follower mode and rollup verifier (#1105)

* port changes from #1013

* port changes from #1068

* go.mod tidy

* fix compile error

* fix goimports

* fix log

* address review comments

* upgrade golang.org/x/net to 0.23.0

* port changes from #1018

* fix tests and linter errors

* address review comments

* refactor rollup sync service / verifier to use CalldataBlobSource to retrieve data from L1

* add configuration and initialize blob clients

* fix unit tests

* remove unused code

* address review comments

* address more review comments

* implement first version of new da-codec and to handle multiple batches submitted in one transaction

* add CommitBatchDAV7 and handle multiple commit events submitted in a single transactions

* fix bug due to previous batch being empty when processing the first batch within a set of batches

* Allow using MPT

* update to latest da-codec

* add field to CommittedBatchMeta to store LastL1MessageQueueHash for CodecV7 batches

* adjust rollup verifier to support CodecV7 batches

* address review comments

* fix issues after merge

* go mod tidy

* fix unit tests

* update da-codec

* add test TestValidateBatchCodecV7

* go mod tidy

* do not log error on shutdown

* add sanity check for version to deserialization of committedBatchMetaV7

* chore: auto version bump [bot]

* address review comments

* chore: auto version bump [bot]

---------

Co-authored-by: Ömer Faruk Irmak <omerfirmak@gmail.com>
Co-authored-by: Thegaram <Thegaram@users.noreply.github.com>
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
This commit is contained in:
Jonas Theis 2025-02-13 17:28:21 +08:00 committed by GitHub
parent 127845d3d0
commit 7de11edcd9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 5288 additions and 145 deletions

View file

@ -2,8 +2,11 @@ package rawdb
import ( import (
"bytes" "bytes"
"fmt"
"math/big" "math/big"
"github.com/scroll-tech/da-codec/encoding"
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/log"
@ -18,12 +21,26 @@ type ChunkBlockRange struct {
// CommittedBatchMeta holds metadata for committed batches. // CommittedBatchMeta holds metadata for committed batches.
type CommittedBatchMeta struct { type CommittedBatchMeta struct {
Version uint8
ChunkBlockRanges []*ChunkBlockRange
// introduced with CodecV7
LastL1MessageQueueHash common.Hash
}
type committedBatchMetaV0 struct {
Version uint8 Version uint8
// BlobVersionedHashes are the versioned hashes of the blobs in the batch. Currently unused. Left for compatibility. // BlobVersionedHashes are the versioned hashes of the blobs in the batch. Currently unused. Left for compatibility.
BlobVersionedHashes []common.Hash BlobVersionedHashes []common.Hash
ChunkBlockRanges []*ChunkBlockRange ChunkBlockRanges []*ChunkBlockRange
} }
type committedBatchMetaV7 struct {
Version uint8
ChunkBlockRanges []*ChunkBlockRange
LastL1MessageQueueHash common.Hash
}
// FinalizedBatchMeta holds metadata for finalized batches. // FinalizedBatchMeta holds metadata for finalized batches.
type FinalizedBatchMeta struct { type FinalizedBatchMeta struct {
BatchHash common.Hash BatchHash common.Hash
@ -143,9 +160,23 @@ func ReadLastFinalizedBatchIndex(db ethdb.Reader) *uint64 {
// WriteCommittedBatchMeta stores the CommittedBatchMeta for a specific batch in the database. // WriteCommittedBatchMeta stores the CommittedBatchMeta for a specific batch in the database.
func WriteCommittedBatchMeta(db ethdb.KeyValueWriter, batchIndex uint64, committedBatchMeta *CommittedBatchMeta) { func WriteCommittedBatchMeta(db ethdb.KeyValueWriter, batchIndex uint64, committedBatchMeta *CommittedBatchMeta) {
value, err := rlp.EncodeToBytes(committedBatchMeta) var committedBatchMetaToStore any
if encoding.CodecVersion(committedBatchMeta.Version) < encoding.CodecV7 {
committedBatchMetaToStore = &committedBatchMetaV0{
Version: committedBatchMeta.Version,
ChunkBlockRanges: committedBatchMeta.ChunkBlockRanges,
}
} else {
committedBatchMetaToStore = &committedBatchMetaV7{
Version: committedBatchMeta.Version,
ChunkBlockRanges: committedBatchMeta.ChunkBlockRanges,
LastL1MessageQueueHash: committedBatchMeta.LastL1MessageQueueHash,
}
}
value, err := rlp.EncodeToBytes(committedBatchMetaToStore)
if err != nil { if err != nil {
log.Crit("failed to RLP encode committed batch metadata", "batch index", batchIndex, "committed batch meta", committedBatchMeta, "err", err) log.Crit("failed to RLP encode committed batch metadata", "batch index", batchIndex, "committed batch meta", committedBatchMetaToStore, "err", err)
} }
if err := db.Put(committedBatchMetaKey(batchIndex), value); err != nil { if err := db.Put(committedBatchMetaKey(batchIndex), value); err != nil {
log.Crit("failed to store committed batch metadata", "batch index", batchIndex, "value", value, "err", err) log.Crit("failed to store committed batch metadata", "batch index", batchIndex, "value", value, "err", err)
@ -153,20 +184,38 @@ func WriteCommittedBatchMeta(db ethdb.KeyValueWriter, batchIndex uint64, committ
} }
// ReadCommittedBatchMeta fetches the CommittedBatchMeta for a specific batch from the database. // ReadCommittedBatchMeta fetches the CommittedBatchMeta for a specific batch from the database.
func ReadCommittedBatchMeta(db ethdb.Reader, batchIndex uint64) *CommittedBatchMeta { func ReadCommittedBatchMeta(db ethdb.Reader, batchIndex uint64) (*CommittedBatchMeta, error) {
data, err := db.Get(committedBatchMetaKey(batchIndex)) data, err := db.Get(committedBatchMetaKey(batchIndex))
if err != nil && isNotFoundErr(err) { if err != nil && isNotFoundErr(err) {
return nil return nil, nil
} }
if err != nil { if err != nil {
log.Crit("failed to read committed batch metadata from database", "batch index", batchIndex, "err", err) return nil, fmt.Errorf("failed to read committed batch metadata from database: batch index %d, err: %w", batchIndex, err)
} }
cbm := new(CommittedBatchMeta) // Try decoding from the newest format for future proofness, then the older one for old data.
if err := rlp.Decode(bytes.NewReader(data), cbm); err != nil { cbm7 := new(committedBatchMetaV7)
log.Crit("Invalid CommittedBatchMeta RLP", "batch index", batchIndex, "data", data, "err", err) if err = rlp.Decode(bytes.NewReader(data), cbm7); err == nil {
if encoding.CodecVersion(cbm7.Version) < encoding.CodecV7 {
return nil, fmt.Errorf("unexpected committed batch metadata version: batch index %d, version %d", batchIndex, cbm7.Version)
} }
return cbm return &CommittedBatchMeta{
Version: cbm7.Version,
ChunkBlockRanges: cbm7.ChunkBlockRanges,
LastL1MessageQueueHash: cbm7.LastL1MessageQueueHash,
}, nil
}
cbm0 := new(committedBatchMetaV0)
if err = rlp.Decode(bytes.NewReader(data), cbm0); err != nil {
return nil, fmt.Errorf("failed to decode committed batch metadata: batch index %d, err: %w", batchIndex, err)
}
return &CommittedBatchMeta{
Version: cbm0.Version,
ChunkBlockRanges: cbm0.ChunkBlockRanges,
LastL1MessageQueueHash: common.Hash{},
}, nil
} }
// DeleteCommittedBatchMeta removes the block ranges of all chunks associated with a specific batch from the database. // DeleteCommittedBatchMeta removes the block ranges of all chunks associated with a specific batch from the database.

View file

@ -3,6 +3,8 @@ package rawdb
import ( import (
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
) )
@ -158,7 +160,6 @@ func TestWriteReadDeleteCommittedBatchMeta(t *testing.T) {
batchIndex: 0, batchIndex: 0,
meta: &CommittedBatchMeta{ meta: &CommittedBatchMeta{
Version: 0, Version: 0,
BlobVersionedHashes: []common.Hash{},
ChunkBlockRanges: []*ChunkBlockRange{}, ChunkBlockRanges: []*ChunkBlockRange{},
}, },
}, },
@ -166,27 +167,39 @@ func TestWriteReadDeleteCommittedBatchMeta(t *testing.T) {
batchIndex: 1, batchIndex: 1,
meta: &CommittedBatchMeta{ meta: &CommittedBatchMeta{
Version: 1, Version: 1,
BlobVersionedHashes: []common.Hash{common.HexToHash("0x1234")},
ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}}, ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}},
}, },
}, },
{
batchIndex: 1,
meta: &CommittedBatchMeta{
Version: 2,
ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}},
},
},
{
batchIndex: 1,
meta: &CommittedBatchMeta{
Version: 7,
ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}},
LastL1MessageQueueHash: common.Hash{1, 2, 3, 4, 5, 6, 7},
},
},
{ {
batchIndex: 255, batchIndex: 255,
meta: &CommittedBatchMeta{ meta: &CommittedBatchMeta{
Version: 255, Version: 255,
BlobVersionedHashes: []common.Hash{common.HexToHash("0xabcd"), common.HexToHash("0xef01")},
ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}, {StartBlockNumber: 11, EndBlockNumber: 20}}, ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}, {StartBlockNumber: 11, EndBlockNumber: 20}},
LastL1MessageQueueHash: common.Hash{255},
}, },
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
WriteCommittedBatchMeta(db, tc.batchIndex, tc.meta) WriteCommittedBatchMeta(db, tc.batchIndex, tc.meta)
got := ReadCommittedBatchMeta(db, tc.batchIndex) got, err := ReadCommittedBatchMeta(db, tc.batchIndex)
require.NoError(t, err)
if got == nil { require.NotNil(t, got)
t.Fatalf("Expected non-nil value for batch index %d", tc.batchIndex)
}
if !compareCommittedBatchMeta(tc.meta, got) { if !compareCommittedBatchMeta(tc.meta, got) {
t.Fatalf("CommittedBatchMeta mismatch for batch index %d, expected %+v, got %+v", tc.batchIndex, tc.meta, got) t.Fatalf("CommittedBatchMeta mismatch for batch index %d, expected %+v, got %+v", tc.batchIndex, tc.meta, got)
@ -194,7 +207,9 @@ func TestWriteReadDeleteCommittedBatchMeta(t *testing.T) {
} }
// reading a non-existing value // reading a non-existing value
if got := ReadCommittedBatchMeta(db, 256); got != nil { got, err := ReadCommittedBatchMeta(db, 256)
require.NoError(t, err)
if got != nil {
t.Fatalf("Expected nil for non-existing value, got %+v", got) t.Fatalf("Expected nil for non-existing value, got %+v", got)
} }
@ -202,10 +217,9 @@ func TestWriteReadDeleteCommittedBatchMeta(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
DeleteCommittedBatchMeta(db, tc.batchIndex) DeleteCommittedBatchMeta(db, tc.batchIndex)
readChunkRange := ReadCommittedBatchMeta(db, tc.batchIndex) readChunkRange, err := ReadCommittedBatchMeta(db, tc.batchIndex)
if readChunkRange != nil { require.NoError(t, err)
t.Fatal("Committed batch metadata was not deleted", "batch index", tc.batchIndex) require.Nil(t, readChunkRange, "Committed batch metadata was not deleted", "batch index", tc.batchIndex)
}
} }
// delete non-existing value: ensure the delete operation handles non-existing values without errors. // delete non-existing value: ensure the delete operation handles non-existing values without errors.
@ -218,18 +232,18 @@ func TestOverwriteCommittedBatchMeta(t *testing.T) {
batchIndex := uint64(42) batchIndex := uint64(42)
initialMeta := &CommittedBatchMeta{ initialMeta := &CommittedBatchMeta{
Version: 1, Version: 1,
BlobVersionedHashes: []common.Hash{common.HexToHash("0x1234")},
ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}}, ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 10}},
} }
newMeta := &CommittedBatchMeta{ newMeta := &CommittedBatchMeta{
Version: 2, Version: 255,
BlobVersionedHashes: []common.Hash{common.HexToHash("0x5678"), common.HexToHash("0x9abc")},
ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 20}, {StartBlockNumber: 21, EndBlockNumber: 30}}, ChunkBlockRanges: []*ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 20}, {StartBlockNumber: 21, EndBlockNumber: 30}},
LastL1MessageQueueHash: common.Hash{255},
} }
// write initial meta // write initial meta
WriteCommittedBatchMeta(db, batchIndex, initialMeta) WriteCommittedBatchMeta(db, batchIndex, initialMeta)
got := ReadCommittedBatchMeta(db, batchIndex) got, err := ReadCommittedBatchMeta(db, batchIndex)
require.NoError(t, err)
if !compareCommittedBatchMeta(initialMeta, got) { if !compareCommittedBatchMeta(initialMeta, got) {
t.Fatalf("Initial write failed, expected %+v, got %+v", initialMeta, got) t.Fatalf("Initial write failed, expected %+v, got %+v", initialMeta, got)
@ -237,7 +251,8 @@ func TestOverwriteCommittedBatchMeta(t *testing.T) {
// overwrite with new meta // overwrite with new meta
WriteCommittedBatchMeta(db, batchIndex, newMeta) WriteCommittedBatchMeta(db, batchIndex, newMeta)
got = ReadCommittedBatchMeta(db, batchIndex) got, err = ReadCommittedBatchMeta(db, batchIndex)
require.NoError(t, err)
if !compareCommittedBatchMeta(newMeta, got) { if !compareCommittedBatchMeta(newMeta, got) {
t.Fatalf("Overwrite failed, expected %+v, got %+v", newMeta, got) t.Fatalf("Overwrite failed, expected %+v, got %+v", newMeta, got)
@ -245,7 +260,8 @@ func TestOverwriteCommittedBatchMeta(t *testing.T) {
// read non-existing batch index // read non-existing batch index
nonExistingIndex := uint64(999) nonExistingIndex := uint64(999)
got = ReadCommittedBatchMeta(db, nonExistingIndex) got, err = ReadCommittedBatchMeta(db, nonExistingIndex)
require.NoError(t, err)
if got != nil { if got != nil {
t.Fatalf("Expected nil for non-existing batch index, got %+v", got) t.Fatalf("Expected nil for non-existing batch index, got %+v", got)
@ -256,14 +272,7 @@ func compareCommittedBatchMeta(a, b *CommittedBatchMeta) bool {
if a.Version != b.Version { if a.Version != b.Version {
return false return false
} }
if len(a.BlobVersionedHashes) != len(b.BlobVersionedHashes) {
return false
}
for i := range a.BlobVersionedHashes {
if a.BlobVersionedHashes[i] != b.BlobVersionedHashes[i] {
return false
}
}
if len(a.ChunkBlockRanges) != len(b.ChunkBlockRanges) { if len(a.ChunkBlockRanges) != len(b.ChunkBlockRanges) {
return false return false
} }
@ -272,5 +281,6 @@ func compareCommittedBatchMeta(a, b *CommittedBatchMeta) bool {
return false return false
} }
} }
return true
return a.LastL1MessageQueueHash == b.LastL1MessageQueueHash
} }

2
go.mod
View file

@ -50,7 +50,7 @@ require (
github.com/prometheus/tsdb v0.7.1 github.com/prometheus/tsdb v0.7.1
github.com/rjeczalik/notify v0.9.1 github.com/rjeczalik/notify v0.9.1
github.com/rs/cors v1.7.0 github.com/rs/cors v1.7.0
github.com/scroll-tech/da-codec v0.1.3-0.20241218102542-9852fa4e1be5 github.com/scroll-tech/da-codec v0.1.3-0.20250210041951-d028c537b995
github.com/scroll-tech/zktrie v0.8.4 github.com/scroll-tech/zktrie v0.8.4
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sourcegraph/conc v0.3.0 github.com/sourcegraph/conc v0.3.0

4
go.sum
View file

@ -396,8 +396,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scroll-tech/da-codec v0.1.3-0.20241218102542-9852fa4e1be5 h1:vZ75srkZCStjDWq/kqZGLoucf7Y7qXC13nKjQVZ0zp8= github.com/scroll-tech/da-codec v0.1.3-0.20250210041951-d028c537b995 h1:Zo1p42CUS9pADSKoDD0ZoDxf4dQ3gttqWZlV+RSeImk=
github.com/scroll-tech/da-codec v0.1.3-0.20241218102542-9852fa4e1be5/go.mod h1:XfQhUl3msmE6dpZEbR/LIwiMxywPQcUQsch9URgXDzs= github.com/scroll-tech/da-codec v0.1.3-0.20250210041951-d028c537b995/go.mod h1:UZhhjzqYsyEhcvY0Y+SP+oMdeOUqFn/UXpbAYuPGzg0=
github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE=
github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 5 // Major version component of the current release VersionMajor = 5 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release VersionMinor = 8 // Minor version component of the current release
VersionPatch = 6 // Patch version component of the current release VersionPatch = 7 // 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
) )

View file

@ -8,6 +8,7 @@ import (
"github.com/scroll-tech/da-codec/encoding" "github.com/scroll-tech/da-codec/encoding"
"github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/accounts/abi"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
"github.com/scroll-tech/go-ethereum/rollup/da_syncer/blob_client" "github.com/scroll-tech/go-ethereum/rollup/da_syncer/blob_client"
"github.com/scroll-tech/go-ethereum/rollup/da_syncer/serrors" "github.com/scroll-tech/go-ethereum/rollup/da_syncer/serrors"
@ -95,6 +96,30 @@ func (ds *CalldataBlobSource) L1Finalized() uint64 {
func (ds *CalldataBlobSource) processRollupEventsToDA(rollupEvents l1.RollupEvents) (Entries, error) { func (ds *CalldataBlobSource) processRollupEventsToDA(rollupEvents l1.RollupEvents) (Entries, error) {
var entries Entries var entries Entries
// we keep track of the last commit transaction hash, so we can process all events created in the same tx together.
// if we have a different commit transaction, we need to create a new commit batch DA.
var lastCommitTransactionHash common.Hash
// we keep track of the commit events created in the same tx, so we can process them together.
var lastCommitEvents []*l1.CommitBatchEvent
// getAndAppendCommitBatchDA is a helper function that gets the commit batch DA for the last commit events and appends it to the entries list.
// It also resets the last commit events and last commit transaction hash.
// This is necessary because we need to process all events created in the same tx together.
// However, we only know all events created in the same tx when we see a different commit transaction (next iteration of the loop).
// Therefore, we need to process the last commit events when we see a different event (finalize, revert) or commit transaction (or when we reach the end of the rollup events).
getAndAppendCommitBatchDA := func() error {
commitBatchDAEntries, err := ds.getCommitBatchDA(lastCommitEvents)
if err != nil {
return fmt.Errorf("failed to get commit batch da: %v, err: %w", lastCommitEvents[0].BatchIndex().Uint64(), err)
}
entries = append(entries, commitBatchDAEntries...)
lastCommitEvents = nil
lastCommitTransactionHash = common.Hash{}
return nil
}
var entry Entry var entry Entry
var err error var err error
for _, rollupEvent := range rollupEvents { for _, rollupEvent := range rollupEvents {
@ -105,11 +130,25 @@ func (ds *CalldataBlobSource) processRollupEventsToDA(rollupEvents l1.RollupEven
if !ok { if !ok {
return nil, fmt.Errorf("unexpected type of rollup event: %T", rollupEvent) return nil, fmt.Errorf("unexpected type of rollup event: %T", rollupEvent)
} }
if entry, err = ds.getCommitBatchDA(commitEvent); err != nil {
return nil, fmt.Errorf("failed to get commit batch da: %v, err: %w", rollupEvent.BatchIndex().Uint64(), err) // if this is a different commit transaction, we need to create a new DA
if lastCommitTransactionHash != commitEvent.TxHash() && len(lastCommitEvents) > 0 {
if err = getAndAppendCommitBatchDA(); err != nil {
return nil, fmt.Errorf("failed to get and append commit batch DA: %w", err)
}
} }
// add commit event to the list of previous commit events, so we can process events created in the same tx together
lastCommitTransactionHash = commitEvent.TxHash()
lastCommitEvents = append(lastCommitEvents, commitEvent)
case l1.RevertEventType: case l1.RevertEventType:
// if we have any previous commit events, we need to create a new DA before processing the revert event
if len(lastCommitEvents) > 0 {
if err = getAndAppendCommitBatchDA(); err != nil {
return nil, fmt.Errorf("failed to get and append commit batch DA: %w", err)
}
}
revertEvent, ok := rollupEvent.(*l1.RevertBatchEvent) revertEvent, ok := rollupEvent.(*l1.RevertBatchEvent)
// this should never happen because we just check event type // this should never happen because we just check event type
if !ok { if !ok {
@ -117,8 +156,15 @@ func (ds *CalldataBlobSource) processRollupEventsToDA(rollupEvents l1.RollupEven
} }
entry = NewRevertBatch(revertEvent) entry = NewRevertBatch(revertEvent)
entries = append(entries, entry)
case l1.FinalizeEventType: case l1.FinalizeEventType:
// if we have any previous commit events, we need to create a new DA before processing the finalized event
if len(lastCommitEvents) > 0 {
if err = getAndAppendCommitBatchDA(); err != nil {
return nil, fmt.Errorf("failed to get and append commit batch DA: %w", err)
}
}
finalizeEvent, ok := rollupEvent.(*l1.FinalizeBatchEvent) finalizeEvent, ok := rollupEvent.(*l1.FinalizeBatchEvent)
// this should never happen because we just check event type // this should never happen because we just check event type
if !ok { if !ok {
@ -126,37 +172,95 @@ func (ds *CalldataBlobSource) processRollupEventsToDA(rollupEvents l1.RollupEven
} }
entry = NewFinalizeBatch(finalizeEvent) entry = NewFinalizeBatch(finalizeEvent)
entries = append(entries, entry)
default: default:
return nil, fmt.Errorf("unknown rollup event, type: %v", rollupEvent.Type()) return nil, fmt.Errorf("unknown rollup event, type: %v", rollupEvent.Type())
} }
entries = append(entries, entry)
} }
// if we have any previous commit events, we need to process them before returning
if len(lastCommitEvents) > 0 {
if err = getAndAppendCommitBatchDA(); err != nil {
return nil, fmt.Errorf("failed to get and append commit batch DA: %w", err)
}
}
return entries, nil return entries, nil
} }
func (ds *CalldataBlobSource) getCommitBatchDA(commitEvent *l1.CommitBatchEvent) (Entry, error) { func (ds *CalldataBlobSource) getCommitBatchDA(commitEvents []*l1.CommitBatchEvent) (Entries, error) {
if commitEvent.BatchIndex().Uint64() == 0 { if len(commitEvents) == 0 {
return NewCommitBatchDAV0Empty(), nil return nil, fmt.Errorf("commit events are empty")
} }
args, err := ds.l1Reader.FetchCommitTxData(commitEvent) if commitEvents[0].BatchIndex().Uint64() == 0 {
return Entries{NewCommitBatchDAV0Empty()}, nil
}
firstCommitEvent := commitEvents[0]
args, err := ds.l1Reader.FetchCommitTxData(firstCommitEvent)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch commit tx data of batch %d, tx hash: %v, err: %w", commitEvent.BatchIndex().Uint64(), commitEvent.TxHash().Hex(), err) return nil, fmt.Errorf("failed to fetch commit tx data of batch %d, tx hash: %v, err: %w", firstCommitEvent.BatchIndex().Uint64(), firstCommitEvent.TxHash().Hex(), err)
}
blockHeader, err := ds.l1Reader.FetchBlockHeaderByNumber(firstCommitEvent.BlockNumber())
if err != nil {
return nil, fmt.Errorf("failed to get header by number, err: %w", err)
} }
codec, err := encoding.CodecFromVersion(encoding.CodecVersion(args.Version)) codec, err := encoding.CodecFromVersion(encoding.CodecVersion(args.Version))
if err != nil { if err != nil {
return nil, fmt.Errorf("unsupported codec version: %v, batch index: %v, err: %w", args.Version, commitEvent.BatchIndex().Uint64(), err) return nil, fmt.Errorf("unsupported codec version: %v, batch index: %v, err: %w", args.Version, firstCommitEvent.BatchIndex().Uint64(), err)
}
var entries Entries
var entry Entry
var previousEvent *l1.CommitBatchEvent
for i, commitEvent := range commitEvents {
// sanity check commit events from batches submitted in the same L1 transaction
if commitEvent.TxHash() != firstCommitEvent.TxHash() {
return nil, fmt.Errorf("commit events have different tx hashes, batch index: %d, tx: %s - batch index: %d, tx: %s", firstCommitEvent.BatchIndex().Uint64(), firstCommitEvent.TxHash().Hex(), commitEvent.BatchIndex().Uint64(), commitEvent.TxHash().Hex())
}
if commitEvent.BlockNumber() != firstCommitEvent.BlockNumber() {
return nil, fmt.Errorf("commit events have different block numbers, batch index: %d, block number: %d - batch index: %d, block number: %d", firstCommitEvent.BatchIndex().Uint64(), firstCommitEvent.BlockNumber(), commitEvent.BatchIndex().Uint64(), commitEvent.BlockNumber())
}
if commitEvent.BlockHash() != firstCommitEvent.BlockHash() {
return nil, fmt.Errorf("commit events have different block hashes, batch index: %d, hash: %s - batch index: %d, hash: %s", firstCommitEvent.BatchIndex().Uint64(), firstCommitEvent.BlockHash().Hex(), commitEvent.BatchIndex().Uint64(), commitEvent.BlockHash().Hex())
}
if previousEvent != nil && commitEvent.BatchIndex().Uint64() != previousEvent.BatchIndex().Uint64()+1 {
return nil, fmt.Errorf("commit events are not in sequence, batch index: %d, hash: %s - previous batch index: %d, hash: %s", commitEvent.BatchIndex().Uint64(), commitEvent.BatchHash().Hex(), previousEvent.BatchIndex().Uint64(), previousEvent.BatchHash().Hex())
} }
switch codec.Version() { switch codec.Version() {
case 0: case 0:
return NewCommitBatchDAV0(ds.db, codec, commitEvent, args.ParentBatchHeader, args.Chunks, args.SkippedL1MessageBitmap) if entry, err = NewCommitBatchDAV0(ds.db, codec, commitEvent, args.ParentBatchHeader, args.Chunks, args.SkippedL1MessageBitmap); err != nil {
case 1, 2, 3, 4: return nil, fmt.Errorf("failed to decode DA, batch index: %d, err: %w", commitEvent.BatchIndex().Uint64(), err)
return NewCommitBatchDAWithBlob(ds.ctx, ds.db, ds.l1Reader, ds.blobClient, codec, commitEvent, args.ParentBatchHeader, args.Chunks, args.SkippedL1MessageBitmap) }
default: case 1, 2, 3, 4, 5, 6:
return nil, fmt.Errorf("failed to decode DA, codec version is unknown: codec version: %d", args.Version) if entry, err = NewCommitBatchDAV1(ds.ctx, ds.db, ds.blobClient, codec, commitEvent, args.ParentBatchHeader, args.Chunks, args.SkippedL1MessageBitmap, args.BlobHashes, blockHeader.Time); err != nil {
return nil, fmt.Errorf("failed to decode DA, batch index: %d, err: %w", commitEvent.BatchIndex().Uint64(), err)
}
default: // CodecVersion 7 and above
if i >= len(args.BlobHashes) {
return nil, fmt.Errorf("not enough blob hashes for commit transaction: %s, index in tx: %d, batch index: %d, hash: %s", firstCommitEvent.TxHash(), i, commitEvent.BatchIndex().Uint64(), commitEvent.BatchHash().Hex())
}
blobHash := args.BlobHashes[i]
var parentBatchHash common.Hash
if previousEvent == nil {
parentBatchHash = common.BytesToHash(args.ParentBatchHeader)
} else {
parentBatchHash = previousEvent.BatchHash()
}
if entry, err = NewCommitBatchDAV7(ds.ctx, ds.db, ds.blobClient, codec, commitEvent, blobHash, parentBatchHash, blockHeader.Time); err != nil {
return nil, fmt.Errorf("failed to decode DA, batch index: %d, err: %w", commitEvent.BatchIndex().Uint64(), err)
} }
} }
previousEvent = commitEvent
entries = append(entries, entry)
}
return entries, nil
}

View file

@ -21,36 +21,28 @@ type CommitBatchDAV1 struct {
versionedHashes []common.Hash versionedHashes []common.Hash
} }
func NewCommitBatchDAWithBlob(ctx context.Context, db ethdb.Database, func NewCommitBatchDAV1(ctx context.Context, db ethdb.Database,
l1Reader *l1.Reader,
blobClient blob_client.BlobClient, blobClient blob_client.BlobClient,
codec encoding.Codec, codec encoding.Codec,
commitEvent *l1.CommitBatchEvent, commitEvent *l1.CommitBatchEvent,
parentBatchHeader []byte, parentBatchHeader []byte,
chunks [][]byte, chunks [][]byte,
skippedL1MessageBitmap []byte, skippedL1MessageBitmap []byte,
versionedHashes []common.Hash,
l1BlockTime uint64,
) (*CommitBatchDAV1, error) { ) (*CommitBatchDAV1, error) {
decodedChunks, err := codec.DecodeDAChunksRawTx(chunks) decodedChunks, err := codec.DecodeDAChunksRawTx(chunks)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to unpack chunks: %v, err: %w", commitEvent.BatchIndex().Uint64(), err) return nil, fmt.Errorf("failed to unpack chunks: %v, err: %w", commitEvent.BatchIndex().Uint64(), err)
} }
versionedHashes, err := l1Reader.FetchTxBlobHashes(commitEvent.TxHash(), commitEvent.BlockHash())
if err != nil {
return nil, fmt.Errorf("failed to fetch blob hash, err: %w", err)
}
// with CommitBatchDAV1 we expect only one versioned hash as we commit only one blob per batch submission // with CommitBatchDAV1 we expect only one versioned hash as we commit only one blob per batch submission
if len(versionedHashes) != 1 { if len(versionedHashes) != 1 {
return nil, fmt.Errorf("unexpected number of versioned hashes: %d", len(versionedHashes)) return nil, fmt.Errorf("unexpected number of versioned hashes: %d", len(versionedHashes))
} }
versionedHash := versionedHashes[0] versionedHash := versionedHashes[0]
header, err := l1Reader.FetchBlockHeaderByNumber(commitEvent.BlockNumber()) blob, err := blobClient.GetBlobByVersionedHashAndBlockTime(ctx, versionedHash, l1BlockTime)
if err != nil {
return nil, fmt.Errorf("failed to get header by number, err: %w", err)
}
blob, err := blobClient.GetBlobByVersionedHashAndBlockTime(ctx, versionedHash, header.Time)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch blob from blob client, err: %w", err) return nil, fmt.Errorf("failed to fetch blob from blob client, err: %w", err)
} }

View file

@ -0,0 +1,189 @@
package da
import (
"context"
"crypto/sha256"
"fmt"
"github.com/scroll-tech/da-codec/encoding"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/rollup/da_syncer/blob_client"
"github.com/scroll-tech/go-ethereum/rollup/da_syncer/serrors"
"github.com/scroll-tech/go-ethereum/rollup/l1"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
"github.com/scroll-tech/go-ethereum/ethdb"
)
type CommitBatchDAV7 struct {
version encoding.CodecVersion
batchIndex uint64
initialL1MessageIndex uint64
blocks []encoding.DABlock
transactions []types.Transactions
l1Txs []types.Transactions
versionedHashes []common.Hash
event *l1.CommitBatchEvent
}
func NewCommitBatchDAV7(ctx context.Context, db ethdb.Database,
blobClient blob_client.BlobClient,
codec encoding.Codec,
commitEvent *l1.CommitBatchEvent,
blobHash common.Hash,
parentBatchHash common.Hash,
l1BlockTime uint64,
) (*CommitBatchDAV7, error) {
calculatedBatch, err := codec.NewDABatchFromParams(commitEvent.BatchIndex().Uint64(), blobHash, parentBatchHash)
if err != nil {
return nil, fmt.Errorf("failed to create new DA batch from params, batch index: %d, err: %w", commitEvent.BatchIndex().Uint64(), err)
}
if calculatedBatch.Hash() != commitEvent.BatchHash() {
return nil, fmt.Errorf("calculated batch hash is not equal to the one from commit event: %s, calculated hash: %s", commitEvent.BatchHash().Hex(), calculatedBatch.Hash().Hex())
}
blob, err := blobClient.GetBlobByVersionedHashAndBlockTime(ctx, blobHash, l1BlockTime)
if err != nil {
return nil, fmt.Errorf("failed to fetch blob from blob client, err: %w", err)
}
if blob == nil {
return nil, fmt.Errorf("unexpected, blob == nil and err != nil, batch index: %d, versionedHash: %s, blobClient: %T", commitEvent.BatchIndex().Uint64(), blobHash.Hex(), blobClient)
}
// compute blob versioned hash and compare with one from tx
c, err := kzg4844.BlobToCommitment(blob)
if err != nil {
return nil, fmt.Errorf("failed to create blob commitment: %w", err)
}
blobVersionedHash := common.Hash(kzg4844.CalcBlobHashV1(sha256.New(), &c))
if blobVersionedHash != blobHash {
return nil, fmt.Errorf("blobVersionedHash from blob source is not equal to versionedHash from tx, correct versioned hash: %s, fetched blob hash: %s", blobHash.Hex(), blobVersionedHash.Hex())
}
blobPayload, err := codec.DecodeBlob(blob)
if err != nil {
return nil, fmt.Errorf("failed to decode blob: %w", err)
}
l1Txs, err := getL1MessagesV7(db, blobPayload.Blocks(), blobPayload.InitialL1MessageIndex())
if err != nil {
return nil, fmt.Errorf("failed to get L1 messages for v7 batch %d: %w", commitEvent.BatchIndex().Uint64(), err)
}
return &CommitBatchDAV7{
version: codec.Version(),
batchIndex: commitEvent.BatchIndex().Uint64(),
initialL1MessageIndex: blobPayload.InitialL1MessageIndex(),
blocks: blobPayload.Blocks(),
transactions: blobPayload.Transactions(),
l1Txs: l1Txs,
versionedHashes: []common.Hash{blobVersionedHash},
event: commitEvent,
}, nil
}
func (c *CommitBatchDAV7) Type() Type {
return CommitBatchWithBlobType
}
func (c *CommitBatchDAV7) BlobVersionedHashes() []common.Hash {
return c.versionedHashes
}
func (c *CommitBatchDAV7) BatchIndex() uint64 {
return c.batchIndex
}
func (c *CommitBatchDAV7) L1BlockNumber() uint64 {
return c.event.BlockNumber()
}
func (c *CommitBatchDAV7) CompareTo(other Entry) int {
if c.BatchIndex() < other.BatchIndex() {
return -1
} else if c.BatchIndex() > other.BatchIndex() {
return 1
}
return 0
}
func (c *CommitBatchDAV7) Event() l1.RollupEvent {
return c.event
}
func (c *CommitBatchDAV7) Blocks() []*PartialBlock {
var blocks []*PartialBlock
for i, daBlock := range c.blocks {
// create txs
txs := make(types.Transactions, 0, daBlock.NumTransactions())
// insert L1 messages
txs = append(txs, c.l1Txs[i]...)
// insert L2 txs
txs = append(txs, c.transactions[i]...)
block := NewPartialBlock(
&PartialHeader{
Number: daBlock.Number(),
Time: daBlock.Timestamp(),
BaseFee: daBlock.BaseFee(),
GasLimit: daBlock.GasLimit(),
Difficulty: 1, // difficulty is enforced to be 1
ExtraData: []byte{}, // extra data is enforced to be empty or at least excluded from the block hash
},
txs)
blocks = append(blocks, block)
}
return blocks
}
func (c *CommitBatchDAV7) Version() encoding.CodecVersion {
return c.version
}
func (c *CommitBatchDAV7) Chunks() []*encoding.DAChunkRawTx {
return []*encoding.DAChunkRawTx{
{
Blocks: c.blocks,
Transactions: c.transactions,
},
}
}
func getL1MessagesV7(db ethdb.Database, blocks []encoding.DABlock, initialL1MessageIndex uint64) ([]types.Transactions, error) {
allTxs := make([]types.Transactions, 0, len(blocks))
messageIndex := initialL1MessageIndex
totalL1Messages := 0
for _, block := range blocks {
var txsPerBlock types.Transactions
for i := messageIndex; i < messageIndex+uint64(block.NumL1Messages()); i++ {
l1Tx := rawdb.ReadL1Message(db, i)
if l1Tx == nil {
// message not yet available
// we return serrors.EOFError as this will be handled in the syncing pipeline with a backoff and retry
return nil, serrors.EOFError
}
txsPerBlock = append(txsPerBlock, types.NewTx(l1Tx))
}
totalL1Messages += int(block.NumL1Messages())
messageIndex += uint64(block.NumL1Messages())
allTxs = append(allTxs, txsPerBlock)
}
if messageIndex != initialL1MessageIndex+uint64(totalL1Messages) {
return nil, fmt.Errorf("unexpected message index: %d, expected: %d", messageIndex, initialL1MessageIndex+uint64(totalL1Messages))
}
return allTxs, nil
}

View file

@ -234,6 +234,7 @@ type CommitBatchArgs struct {
ParentBatchHeader []byte ParentBatchHeader []byte
Chunks [][]byte Chunks [][]byte
SkippedL1MessageBitmap []byte SkippedL1MessageBitmap []byte
BlobHashes []common.Hash
} }
func newCommitBatchArgs(method *abi.Method, values []interface{}) (*CommitBatchArgs, error) { func newCommitBatchArgs(method *abi.Method, values []interface{}) (*CommitBatchArgs, error) {

View file

@ -379,5 +379,7 @@ func (r *Reader) FetchCommitTxData(commitEvent *CommitBatchEvent) (*CommitBatchA
return nil, fmt.Errorf("unknown method name for commit transaction: %s", method.Name) return nil, fmt.Errorf("unknown method name for commit transaction: %s", method.Name)
} }
args.BlobHashes = tx.BlobHashes()
return args, nil return args, nil
} }

View file

@ -11,6 +11,7 @@ import (
"github.com/scroll-tech/da-codec/encoding" "github.com/scroll-tech/da-codec/encoding"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core" "github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/ethdb"
@ -145,6 +146,13 @@ func (s *RollupSyncService) Start() {
case <-syncTicker.C: case <-syncTicker.C:
err := s.fetchRollupEvents() err := s.fetchRollupEvents()
if err != nil { if err != nil {
// Do not log the error if the context is canceled.
select {
case <-s.ctx.Done():
return
default:
}
log.Error("failed to fetch rollup events", "err", err) log.Error("failed to fetch rollup events", "err", err)
} }
case <-logTicker.C: case <-logTicker.C:
@ -265,14 +273,24 @@ func (s *RollupSyncService) updateRollupEvents(daEntries da.Entries) error {
var highestFinalizedBlockNumber uint64 var highestFinalizedBlockNumber uint64
batchWriter := s.db.NewBatch() batchWriter := s.db.NewBatch()
for index := startBatchIndex; index <= batchIndex; index++ { for index := startBatchIndex; index <= batchIndex; index++ {
committedBatchMeta := rawdb.ReadCommittedBatchMeta(s.db, index) var parentCommittedBatchMeta *rawdb.CommittedBatchMeta
var err error
if index > 0 {
if parentCommittedBatchMeta, err = rawdb.ReadCommittedBatchMeta(s.db, index-1); err != nil {
return fmt.Errorf("failed to read parent committed batch meta, batch index: %v, err: %w", index-1, err)
}
}
committedBatchMeta, err := rawdb.ReadCommittedBatchMeta(s.db, index)
if err != nil {
return fmt.Errorf("failed to read committed batch meta, batch index: %v, err: %w", index, err)
}
chunks, err := s.getLocalChunksForBatch(committedBatchMeta.ChunkBlockRanges) chunks, err := s.getLocalChunksForBatch(committedBatchMeta.ChunkBlockRanges)
if err != nil { if err != nil {
return fmt.Errorf("failed to get local node info, batch index: %v, err: %w", index, err) return fmt.Errorf("failed to get local node info, batch index: %v, err: %w", index, err)
} }
endBlock, finalizedBatchMeta, err := validateBatch(index, event, parentFinalizedBatchMeta, committedBatchMeta, chunks, s.stack) endBlock, finalizedBatchMeta, err := validateBatch(index, event, parentFinalizedBatchMeta, parentCommittedBatchMeta, committedBatchMeta, chunks, s.stack)
if err != nil { if err != nil {
return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err) return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err)
} }
@ -358,8 +376,8 @@ func (s *RollupSyncService) getCommittedBatchMeta(commitedBatch da.EntryWithBloc
if commitedBatch.BatchIndex() == 0 { if commitedBatch.BatchIndex() == 0 {
return &rawdb.CommittedBatchMeta{ return &rawdb.CommittedBatchMeta{
Version: 0, Version: 0,
BlobVersionedHashes: nil,
ChunkBlockRanges: []*rawdb.ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 0}}, ChunkBlockRanges: []*rawdb.ChunkBlockRange{{StartBlockNumber: 0, EndBlockNumber: 0}},
LastL1MessageQueueHash: common.Hash{},
}, nil }, nil
} }
@ -368,10 +386,49 @@ func (s *RollupSyncService) getCommittedBatchMeta(commitedBatch da.EntryWithBloc
return nil, fmt.Errorf("failed to decode block ranges from chunks, batch index: %v, err: %w", commitedBatch.BatchIndex(), err) return nil, fmt.Errorf("failed to decode block ranges from chunks, batch index: %v, err: %w", commitedBatch.BatchIndex(), err)
} }
// With CodecV7 the batch creation changed. We need to compute and store LastL1MessageQueueHash.
// InitialL1MessageQueueHash of a batch == LastL1MessageQueueHash of the previous batch.
// We need to do this for every committed batch (instead of finalized batch) because the L1MessageQueueHash
// is a continuous hash of all L1 messages over all batches. With bundles we only receive the finalize event
// for the last batch of the bundle.
var lastL1MessageQueueHash common.Hash
if commitedBatch.Version() == encoding.CodecV7 {
parentCommittedBatchMeta, err := rawdb.ReadCommittedBatchMeta(s.db, commitedBatch.BatchIndex()-1)
if err != nil {
return nil, fmt.Errorf("failed to read parent committed batch meta, batch index: %v, err: %w", commitedBatch.BatchIndex()-1, err)
}
// If parent batch has a lower version this means this is the first batch of CodecV7.
// In this case we need to compute the InitialL1MessageQueueHash from the empty hash.
var initialL1MessageQueueHash common.Hash
if encoding.CodecVersion(parentCommittedBatchMeta.Version) < commitedBatch.Version() {
initialL1MessageQueueHash = common.Hash{}
} else {
initialL1MessageQueueHash = parentCommittedBatchMeta.LastL1MessageQueueHash
}
chunks, err := s.getLocalChunksForBatch(chunkRanges)
if err != nil {
return nil, fmt.Errorf("failed to get local node info, batch index: %v, err: %w", commitedBatch.BatchIndex(), err)
}
// There is no chunks encoded in a batch anymore with CodecV7.
// For compatibility reason here we still use a single chunk to store the block ranges of the batch.
// We make sure that there is really only one chunk which contains all blocks of the batch.
if len(chunks) != 1 {
return nil, fmt.Errorf("invalid argument: chunk count is not 1 for CodecV7, batch index: %v", commitedBatch.BatchIndex())
}
lastL1MessageQueueHash, err = encoding.MessageQueueV2ApplyL1MessagesFromBlocks(initialL1MessageQueueHash, chunks[0].Blocks)
if err != nil {
return nil, fmt.Errorf("failed to apply L1 messages from blocks, batch index: %v, err: %w", chunks[0], err)
}
}
return &rawdb.CommittedBatchMeta{ return &rawdb.CommittedBatchMeta{
Version: uint8(commitedBatch.Version()), Version: uint8(commitedBatch.Version()),
ChunkBlockRanges: chunkRanges, ChunkBlockRanges: chunkRanges,
BlobVersionedHashes: commitedBatch.BlobVersionedHashes(), LastL1MessageQueueHash: lastL1MessageQueueHash,
}, nil }, nil
} }
@ -398,7 +455,7 @@ func (s *RollupSyncService) getCommittedBatchMeta(commitedBatch da.EntryWithBloc
// Note: This function is compatible with both "finalize by batch" and "finalize by bundle" methods. // Note: This function is compatible with both "finalize by batch" and "finalize by bundle" methods.
// In "finalize by bundle", only the last batch of each bundle is fully verified. // In "finalize by bundle", only the last batch of each bundle is fully verified.
// This check still ensures the correctness of all batch hashes in the bundle due to the parent-child relationship between batch hashes. // This check still ensures the correctness of all batch hashes in the bundle due to the parent-child relationship between batch hashes.
func validateBatch(batchIndex uint64, event *l1.FinalizeBatchEvent, parentFinalizedBatchMeta *rawdb.FinalizedBatchMeta, committedBatchMeta *rawdb.CommittedBatchMeta, chunks []*encoding.Chunk, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) { func validateBatch(batchIndex uint64, event *l1.FinalizeBatchEvent, parentFinalizedBatchMeta *rawdb.FinalizedBatchMeta, parentCommittedBatchMeta *rawdb.CommittedBatchMeta, committedBatchMeta *rawdb.CommittedBatchMeta, chunks []*encoding.Chunk, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) {
if len(chunks) == 0 { if len(chunks) == 0 {
return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", batchIndex) return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", batchIndex)
} }
@ -416,12 +473,31 @@ func validateBatch(batchIndex uint64, event *l1.FinalizeBatchEvent, parentFinali
endBlock := endChunk.Blocks[len(endChunk.Blocks)-1] endBlock := endChunk.Blocks[len(endChunk.Blocks)-1]
// Note: All params of batch are calculated locally based on the block data. // Note: All params of batch are calculated locally based on the block data.
batch := &encoding.Batch{ var batch *encoding.Batch
if encoding.CodecVersion(committedBatchMeta.Version) < encoding.CodecV7 {
batch = &encoding.Batch{
Index: batchIndex, Index: batchIndex,
TotalL1MessagePoppedBefore: parentFinalizedBatchMeta.TotalL1MessagePopped, TotalL1MessagePoppedBefore: parentFinalizedBatchMeta.TotalL1MessagePopped,
ParentBatchHash: parentFinalizedBatchMeta.BatchHash, ParentBatchHash: parentFinalizedBatchMeta.BatchHash,
Chunks: chunks, Chunks: chunks,
} }
} else {
// With CodecV7 the batch creation changed. There is no chunks encoded in a batch anymore.
// For compatibility reason here we still use a single chunk to store the block ranges of the batch.
// We make sure that there is really only one chunk which contains all blocks of the batch.
if len(chunks) != 1 {
return 0, nil, fmt.Errorf("invalid argument: chunk count is not 1 for CodecV7, batch index: %v", batchIndex)
}
batch = &encoding.Batch{
Index: batchIndex,
ParentBatchHash: parentFinalizedBatchMeta.BatchHash,
InitialL1MessageIndex: parentFinalizedBatchMeta.TotalL1MessagePopped,
Blocks: startChunk.Blocks,
InitialL1MessageQueueHash: parentCommittedBatchMeta.LastL1MessageQueueHash,
LastL1MessageQueueHash: committedBatchMeta.LastL1MessageQueueHash,
}
}
codecVersion := encoding.CodecVersion(committedBatchMeta.Version) codecVersion := encoding.CodecVersion(committedBatchMeta.Version)
codec, err := encoding.CodecFromVersion(codecVersion) codec, err := encoding.CodecFromVersion(codecVersion)
@ -431,7 +507,7 @@ func validateBatch(batchIndex uint64, event *l1.FinalizeBatchEvent, parentFinali
daBatch, err := codec.NewDABatch(batch) daBatch, err := codec.NewDABatch(batch)
if err != nil { if err != nil {
return 0, nil, fmt.Errorf("failed to create DA batch, batch index: %v, codec version: %v, expected blob hashes: %v, err: %w", batchIndex, codecVersion, committedBatchMeta.BlobVersionedHashes, err) return 0, nil, fmt.Errorf("failed to create DA batch, batch index: %v, codec version: %v, err: %w", batchIndex, codecVersion, err)
} }
localBatchHash := daBatch.Hash() localBatchHash := daBatch.Hash()

View file

@ -151,7 +151,6 @@ func TestGetCommittedBatchMetaCodecV1(t *testing.T) {
require.Equal(t, encoding.CodecV1, encoding.CodecVersion(metadata.Version)) require.Equal(t, encoding.CodecV1, encoding.CodecVersion(metadata.Version))
require.EqualValues(t, expectedRanges, metadata.ChunkBlockRanges) require.EqualValues(t, expectedRanges, metadata.ChunkBlockRanges)
require.EqualValues(t, expectedVersionedHashes, metadata.BlobVersionedHashes)
} }
type mockEntryWithBlocks struct { type mockEntryWithBlocks struct {
@ -255,10 +254,9 @@ func TestValidateBatchCodecV0(t *testing.T) {
) )
committedBatchMeta1 := &rawdb.CommittedBatchMeta{ committedBatchMeta1 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV0), Version: uint8(encoding.CodecV0),
BlobVersionedHashes: nil,
} }
endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil) endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(13), endBlock1) assert.Equal(t, uint64(13), endBlock1)
@ -284,10 +282,9 @@ func TestValidateBatchCodecV0(t *testing.T) {
) )
committedBatchMeta2 := &rawdb.CommittedBatchMeta{ committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV0), Version: uint8(encoding.CodecV0),
BlobVersionedHashes: nil,
} }
endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil) endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta2, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(17), endBlock2) assert.Equal(t, uint64(17), endBlock2)
@ -322,10 +319,9 @@ func TestValidateBatchCodecV1(t *testing.T) {
) )
committedBatchMeta1 := &rawdb.CommittedBatchMeta{ committedBatchMeta1 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV1), Version: uint8(encoding.CodecV1),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x0129554070e4323800ca0e5ddd17bc447854601b306a70870002a058741214b3")},
} }
endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil) endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(13), endBlock1) assert.Equal(t, uint64(13), endBlock1)
@ -350,9 +346,8 @@ func TestValidateBatchCodecV1(t *testing.T) {
) )
committedBatchMeta2 := &rawdb.CommittedBatchMeta{ committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV1), Version: uint8(encoding.CodecV1),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x01a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a6")},
} }
endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil) endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(17), endBlock2) assert.Equal(t, uint64(17), endBlock2)
@ -387,10 +382,9 @@ func TestValidateBatchCodecV2(t *testing.T) {
) )
committedBatchMeta1 := &rawdb.CommittedBatchMeta{ committedBatchMeta1 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV2), Version: uint8(encoding.CodecV2),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x018d99636f4b20ccdc1dd11c289eb2a470e2c4dd631b1a7b48a6978805f49d18")},
} }
endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil) endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(13), endBlock1) assert.Equal(t, uint64(13), endBlock1)
@ -415,9 +409,8 @@ func TestValidateBatchCodecV2(t *testing.T) {
) )
committedBatchMeta2 := &rawdb.CommittedBatchMeta{ committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV2), Version: uint8(encoding.CodecV2),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x015b4e3d3dcd64cc0eb6a5ad535d7a1844a8c4cdad366ec73557bcc533941370")},
} }
endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil) endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(17), endBlock2) assert.Equal(t, uint64(17), endBlock2)
@ -453,10 +446,9 @@ func TestValidateBatchCodecV3(t *testing.T) {
committedBatchMeta1 := &rawdb.CommittedBatchMeta{ committedBatchMeta1 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x018d99636f4b20ccdc1dd11c289eb2a470e2c4dd631b1a7b48a6978805f49d18")},
} }
endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil) endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(13), endBlock1) assert.Equal(t, uint64(13), endBlock1)
@ -481,9 +473,8 @@ func TestValidateBatchCodecV3(t *testing.T) {
) )
committedBatchMeta2 := &rawdb.CommittedBatchMeta{ committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x015b4e3d3dcd64cc0eb6a5ad535d7a1844a8c4cdad366ec73557bcc533941370")},
} }
endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil) endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{chunk4}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(17), endBlock2) assert.Equal(t, uint64(17), endBlock2)
@ -513,10 +504,9 @@ func TestValidateBatchUpgrades(t *testing.T) {
committedBatchMeta1 := &rawdb.CommittedBatchMeta{ committedBatchMeta1 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV0), Version: uint8(encoding.CodecV0),
BlobVersionedHashes: nil,
} }
endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, committedBatchMeta1, []*encoding.Chunk{chunk1}, nil) endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex().Uint64(), event1, parentFinalizedBatchMeta1, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(2), endBlock1) assert.Equal(t, uint64(2), endBlock1)
@ -541,9 +531,8 @@ func TestValidateBatchUpgrades(t *testing.T) {
) )
committedBatchMeta2 := &rawdb.CommittedBatchMeta{ committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV1), Version: uint8(encoding.CodecV1),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x01a688c6e137310df38a62f5ad1e5119b8cb0455c386a9a4079b14fe92a239aa")},
} }
endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta2, []*encoding.Chunk{chunk2}, nil) endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex().Uint64(), event2, parentFinalizedBatchMeta2, committedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{chunk2}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(3), endBlock2) assert.Equal(t, uint64(3), endBlock2)
@ -568,9 +557,8 @@ func TestValidateBatchUpgrades(t *testing.T) {
) )
committedBatchMeta3 := &rawdb.CommittedBatchMeta{ committedBatchMeta3 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV1), Version: uint8(encoding.CodecV1),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x01ea66c4de196d36e2c3a5d7c0045100b9e46ef65be8f7a921ef20e6f2e99ebd")},
} }
endBlock3, finalizedBatchMeta3, err := validateBatch(event3.BatchIndex().Uint64(), event3, parentFinalizedBatchMeta3, committedBatchMeta3, []*encoding.Chunk{chunk3}, nil) endBlock3, finalizedBatchMeta3, err := validateBatch(event3.BatchIndex().Uint64(), event3, parentFinalizedBatchMeta3, committedBatchMeta2, committedBatchMeta3, []*encoding.Chunk{chunk3}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(13), endBlock3) assert.Equal(t, uint64(13), endBlock3)
@ -595,9 +583,8 @@ func TestValidateBatchUpgrades(t *testing.T) {
) )
committedBatchMeta4 := &rawdb.CommittedBatchMeta{ committedBatchMeta4 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x015b4e3d3dcd64cc0eb6a5ad535d7a1844a8c4cdad366ec73557bcc533941370")},
} }
endBlock4, finalizedBatchMeta4, err := validateBatch(event4.BatchIndex().Uint64(), event4, parentFinalizedBatchMeta4, committedBatchMeta4, []*encoding.Chunk{chunk4}, nil) endBlock4, finalizedBatchMeta4, err := validateBatch(event4.BatchIndex().Uint64(), event4, parentFinalizedBatchMeta4, committedBatchMeta3, committedBatchMeta4, []*encoding.Chunk{chunk4}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(17), endBlock4) assert.Equal(t, uint64(17), endBlock4)
@ -632,37 +619,33 @@ func TestValidateBatchInFinalizeByBundle(t *testing.T) {
committedBatchMeta1 := &rawdb.CommittedBatchMeta{ committedBatchMeta1 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x01bbc6b98d7d3783730b6208afac839ad37dcf211b9d9e7c83a5f9d02125ddd7")},
} }
committedBatchMeta2 := &rawdb.CommittedBatchMeta{ committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x01c81e5696e00f1e6e7d76c197f74ed51650147c49c4e6e5b0b702cdcc54352a")},
} }
committedBatchMeta3 := &rawdb.CommittedBatchMeta{ committedBatchMeta3 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x012e15203534ae3f4cbe1b0f58fe6db6e5c29432115a8ece6ef5550bf2ffce4c")},
} }
committedBatchMeta4 := &rawdb.CommittedBatchMeta{ committedBatchMeta4 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV3), Version: uint8(encoding.CodecV3),
BlobVersionedHashes: []common.Hash{common.HexToHash("0x015b4e3d3dcd64cc0eb6a5ad535d7a1844a8c4cdad366ec73557bcc533941370")},
} }
endBlock1, finalizedBatchMeta1, err := validateBatch(0, event, &rawdb.FinalizedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1}, nil) endBlock1, finalizedBatchMeta1, err := validateBatch(0, event, &rawdb.FinalizedBatchMeta{}, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{chunk1}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(2), endBlock1) assert.Equal(t, uint64(2), endBlock1)
endBlock2, finalizedBatchMeta2, err := validateBatch(1, event, finalizedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{chunk2}, nil) endBlock2, finalizedBatchMeta2, err := validateBatch(1, event, finalizedBatchMeta1, committedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{chunk2}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(3), endBlock2) assert.Equal(t, uint64(3), endBlock2)
endBlock3, finalizedBatchMeta3, err := validateBatch(2, event, finalizedBatchMeta2, committedBatchMeta3, []*encoding.Chunk{chunk3}, nil) endBlock3, finalizedBatchMeta3, err := validateBatch(2, event, finalizedBatchMeta2, committedBatchMeta2, committedBatchMeta3, []*encoding.Chunk{chunk3}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(13), endBlock3) assert.Equal(t, uint64(13), endBlock3)
endBlock4, finalizedBatchMeta4, err := validateBatch(3, event, finalizedBatchMeta3, committedBatchMeta4, []*encoding.Chunk{chunk4}, nil) endBlock4, finalizedBatchMeta4, err := validateBatch(3, event, finalizedBatchMeta3, committedBatchMeta3, committedBatchMeta4, []*encoding.Chunk{chunk4}, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, uint64(17), endBlock4) assert.Equal(t, uint64(17), endBlock4)
@ -675,6 +658,155 @@ func TestValidateBatchInFinalizeByBundle(t *testing.T) {
assert.Equal(t, parentFinalizedBatchMeta5, finalizedBatchMeta4) assert.Equal(t, parentFinalizedBatchMeta5, finalizedBatchMeta4)
} }
func TestValidateBatchCodecV7(t *testing.T) {
codecV7 := encoding.DACodecV7{}
var finalizedBatchMeta1 *rawdb.FinalizedBatchMeta
var committedBatchMeta1 *rawdb.CommittedBatchMeta
{
block1 := replaceBlockNumber(readBlockFromJSON(t, "./testdata/blockTrace_02.json"), 1)
batch1 := &encoding.Batch{
Index: 1,
InitialL1MessageIndex: 0,
InitialL1MessageQueueHash: common.Hash{},
LastL1MessageQueueHash: common.Hash{},
Blocks: []*encoding.Block{block1},
}
batch1LastBlock := batch1.Blocks[len(batch1.Blocks)-1]
daBatch1, err := codecV7.NewDABatch(batch1)
require.NoError(t, err)
event1 := l1.NewFinalizeBatchEvent(
new(big.Int).SetUint64(batch1.Index),
daBatch1.Hash(),
batch1LastBlock.Header.Root,
batch1LastBlock.WithdrawRoot,
common.HexToHash("0x1"),
common.HexToHash("0x1"),
1,
)
committedBatchMeta1 = &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV7),
LastL1MessageQueueHash: common.Hash{},
}
var endBlock1 uint64
endBlock1, finalizedBatchMeta1, err = validateBatch(event1.BatchIndex().Uint64(), event1, &rawdb.FinalizedBatchMeta{}, &rawdb.CommittedBatchMeta{}, committedBatchMeta1, []*encoding.Chunk{{Blocks: batch1.Blocks}}, nil)
require.NoError(t, err)
require.EqualValues(t, 1, endBlock1)
require.Equal(t, &rawdb.FinalizedBatchMeta{
BatchHash: daBatch1.Hash(),
TotalL1MessagePopped: 0,
StateRoot: batch1LastBlock.Header.Root,
WithdrawRoot: batch1LastBlock.WithdrawRoot,
}, finalizedBatchMeta1)
}
// finalize 3 batches with CodecV7 at once
block2 := replaceBlockNumber(readBlockFromJSON(t, "./testdata/blockTrace_03.json"), 2)
batch2 := &encoding.Batch{
Index: 2,
ParentBatchHash: finalizedBatchMeta1.BatchHash,
InitialL1MessageIndex: 0,
InitialL1MessageQueueHash: common.Hash{},
LastL1MessageQueueHash: common.Hash{},
Blocks: []*encoding.Block{block2},
}
batch2LastBlock := batch2.Blocks[len(batch2.Blocks)-1]
daBatch2, err := codecV7.NewDABatch(batch2)
require.NoError(t, err)
block3 := replaceBlockNumber(readBlockFromJSON(t, "./testdata/blockTrace_06.json"), 3)
LastL1MessageQueueHashBatch3, err := encoding.MessageQueueV2ApplyL1MessagesFromBlocks(common.Hash{}, []*encoding.Block{block3})
require.NoError(t, err)
batch3 := &encoding.Batch{
Index: 3,
ParentBatchHash: daBatch2.Hash(),
InitialL1MessageIndex: 0,
InitialL1MessageQueueHash: common.Hash{},
LastL1MessageQueueHash: LastL1MessageQueueHashBatch3,
Blocks: []*encoding.Block{block3},
}
batch3LastBlock := batch3.Blocks[len(batch3.Blocks)-1]
daBatch3, err := codecV7.NewDABatch(batch3)
require.NoError(t, err)
block4 := replaceBlockNumber(readBlockFromJSON(t, "./testdata/blockTrace_07.json"), 4)
LastL1MessageQueueHashBatch4, err := encoding.MessageQueueV2ApplyL1MessagesFromBlocks(LastL1MessageQueueHashBatch3, []*encoding.Block{block4})
require.NoError(t, err)
batch4 := &encoding.Batch{
Index: 4,
ParentBatchHash: daBatch3.Hash(),
InitialL1MessageIndex: 1,
InitialL1MessageQueueHash: LastL1MessageQueueHashBatch3,
LastL1MessageQueueHash: LastL1MessageQueueHashBatch4,
Blocks: []*encoding.Block{block4},
}
batch4LastBlock := batch4.Blocks[len(batch4.Blocks)-1]
daBatch4, err := codecV7.NewDABatch(batch4)
require.NoError(t, err)
event2 := l1.NewFinalizeBatchEvent(
new(big.Int).SetUint64(batch4.Index),
daBatch4.Hash(),
batch4LastBlock.Header.Root,
batch4LastBlock.WithdrawRoot,
common.HexToHash("0x1"),
common.HexToHash("0x1"),
1,
)
committedBatchMeta2 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV7),
LastL1MessageQueueHash: common.Hash{},
}
committedBatchMeta3 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV7),
LastL1MessageQueueHash: LastL1MessageQueueHashBatch3,
}
committedBatchMeta4 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV7),
LastL1MessageQueueHash: LastL1MessageQueueHashBatch4,
}
endBlock2, finalizedBatchMeta2, err := validateBatch(2, event2, finalizedBatchMeta1, committedBatchMeta1, committedBatchMeta2, []*encoding.Chunk{{Blocks: batch2.Blocks}}, nil)
require.NoError(t, err)
require.EqualValues(t, 2, endBlock2)
require.Equal(t, &rawdb.FinalizedBatchMeta{
BatchHash: daBatch2.Hash(),
TotalL1MessagePopped: 0,
StateRoot: batch2LastBlock.Header.Root,
WithdrawRoot: batch2LastBlock.WithdrawRoot,
}, finalizedBatchMeta2)
endBlock3, finalizedBatchMeta3, err := validateBatch(3, event2, finalizedBatchMeta2, committedBatchMeta2, committedBatchMeta3, []*encoding.Chunk{{Blocks: batch3.Blocks}}, nil)
require.NoError(t, err)
require.EqualValues(t, 3, endBlock3)
require.Equal(t, &rawdb.FinalizedBatchMeta{
BatchHash: daBatch3.Hash(),
TotalL1MessagePopped: 1,
StateRoot: batch3LastBlock.Header.Root,
WithdrawRoot: batch3LastBlock.WithdrawRoot,
}, finalizedBatchMeta3)
endBlock4, finalizedBatchMeta4, err := validateBatch(4, event2, finalizedBatchMeta3, committedBatchMeta3, committedBatchMeta4, []*encoding.Chunk{{Blocks: batch4.Blocks}}, nil)
require.NoError(t, err)
require.EqualValues(t, 4, endBlock4)
require.Equal(t, &rawdb.FinalizedBatchMeta{
BatchHash: daBatch4.Hash(),
TotalL1MessagePopped: 6,
StateRoot: batch4LastBlock.Header.Root,
WithdrawRoot: batch4LastBlock.WithdrawRoot,
}, finalizedBatchMeta4)
}
func readBlockFromJSON(t *testing.T, filename string) *encoding.Block { func readBlockFromJSON(t *testing.T, filename string) *encoding.Block {
data, err := os.ReadFile(filename) data, err := os.ReadFile(filename)
assert.NoError(t, err) assert.NoError(t, err)
@ -683,3 +815,8 @@ func readBlockFromJSON(t *testing.T, filename string) *encoding.Block {
assert.NoError(t, json.Unmarshal(data, block)) assert.NoError(t, json.Unmarshal(data, block))
return block return block
} }
func replaceBlockNumber(block *encoding.Block, newNumber uint64) *encoding.Block {
block.Header.Number = new(big.Int).SetUint64(newNumber)
return block
}

View 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": 0,
"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"
}

File diff suppressed because it is too large Load diff