Skip to content

feat(feynman): support codecv8 in rollup-verifier #1206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 26, 2025
Merged
2 changes: 1 addition & 1 deletion params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
const (
VersionMajor = 5 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release
VersionPatch = 61 // Patch version component of the current release
VersionPatch = 62 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string
)

Expand Down
12 changes: 6 additions & 6 deletions rollup/rollup_sync_service/rollup_sync_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,13 +464,13 @@ 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)
}

// With CodecV7 the batch creation changed. We need to compute and store PostL1MessageQueueHash.
// With >= CodecV7 the batch creation changed. We need to compute and store PostL1MessageQueueHash.
// PrevL1MessageQueueHash of a batch == PostL1MessageQueueHash 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 {
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, errors.Join(ErrMissingBatchEvent, err))
Expand All @@ -493,11 +493,11 @@ func (s *RollupSyncService) getCommittedBatchMeta(commitedBatch da.EntryWithBloc
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.
// 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())
return nil, fmt.Errorf("invalid argument: chunk count is not 1 for CodecV%v, batch index: %v", commitedBatch.Version(), commitedBatch.BatchIndex())
}

lastL1MessageQueueHash, err = encoding.MessageQueueV2ApplyL1MessagesFromBlocks(prevL1MessageQueueHash, chunks[0].Blocks)
Expand Down Expand Up @@ -563,11 +563,11 @@ func validateBatch(batchIndex uint64, event *l1.FinalizeBatchEvent, parentFinali
Chunks: chunks,
}
} else {
// With CodecV7 the batch creation changed. There is no chunks encoded in a batch anymore.
// 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)
return 0, nil, fmt.Errorf("invalid argument: chunk count is not 1 for CodecV%v, batch index: %v", committedBatchMeta.Version, batchIndex)
}

batch = &encoding.Batch{
Expand Down
145 changes: 145 additions & 0 deletions rollup/rollup_sync_service/rollup_sync_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,151 @@ func TestValidateBatchCodecV7(t *testing.T) {
}, finalizedBatchMeta4)
}

func TestValidateBatchCodecV8(t *testing.T) {
codecV8 := encoding.NewDACodecV8()

var finalizedBatchMeta1 *rawdb.FinalizedBatchMeta
var committedBatchMeta1 *rawdb.CommittedBatchMeta
{
block1 := replaceBlockNumber(readBlockFromJSON(t, "./testdata/blockTrace_02.json"), 1)
batch1 := &encoding.Batch{
Index: 1,
PrevL1MessageQueueHash: common.Hash{},
PostL1MessageQueueHash: common.Hash{},
Blocks: []*encoding.Block{block1},
}
batch1LastBlock := batch1.Blocks[len(batch1.Blocks)-1]

daBatch1, err := codecV8.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.CodecV8),
PostL1MessageQueueHash: 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 CodecV8 at once
block2 := replaceBlockNumber(readBlockFromJSON(t, "./testdata/blockTrace_03.json"), 2)
batch2 := &encoding.Batch{
Index: 2,
ParentBatchHash: finalizedBatchMeta1.BatchHash,
PrevL1MessageQueueHash: common.Hash{},
PostL1MessageQueueHash: common.Hash{},
Blocks: []*encoding.Block{block2},
}
batch2LastBlock := batch2.Blocks[len(batch2.Blocks)-1]

daBatch2, err := codecV8.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(),
PrevL1MessageQueueHash: common.Hash{},
PostL1MessageQueueHash: LastL1MessageQueueHashBatch3,
Blocks: []*encoding.Block{block3},
}
batch3LastBlock := batch3.Blocks[len(batch3.Blocks)-1]

daBatch3, err := codecV8.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(),
PrevL1MessageQueueHash: LastL1MessageQueueHashBatch3,
PostL1MessageQueueHash: LastL1MessageQueueHashBatch4,
Blocks: []*encoding.Block{block4},
}
batch4LastBlock := batch4.Blocks[len(batch4.Blocks)-1]

daBatch4, err := codecV8.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.CodecV8),
PostL1MessageQueueHash: common.Hash{},
}

committedBatchMeta3 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV8),
PostL1MessageQueueHash: LastL1MessageQueueHashBatch3,
}

committedBatchMeta4 := &rawdb.CommittedBatchMeta{
Version: uint8(encoding.CodecV8),
PostL1MessageQueueHash: 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 {
data, err := os.ReadFile(filename)
assert.NoError(t, err)
Expand Down
Loading