Skip to content

Commit 600ea40

Browse files
committed
fix(l2geth-verifier): only check the last batch of each bundle
1 parent 0cecc19 commit 600ea40

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

params/version.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
const (
2525
VersionMajor = 5 // Major version component of the current release
2626
VersionMinor = 5 // Minor version component of the current release
27-
VersionPatch = 12 // Patch version component of the current release
27+
VersionPatch = 13 // Patch version component of the current release
2828
VersionMeta = "mainnet" // Version metadata to append to the version string
2929
)
3030

rollup/rollup_sync_service/rollup_sync_service.go

+35-25
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB
248248
return fmt.Errorf("failed to get local node info, batch index: %v, err: %w", index, err)
249249
}
250250

251-
endBlock, finalizedBatchMeta, err := validateBatch(event, parentBatchMeta, chunks, s.bc.Config(), s.stack)
251+
endBlock, finalizedBatchMeta, err := validateBatch(event, parentBatchMeta, chunks, s.bc.Config(), s.stack, index == batchIndex)
252252
if err != nil {
253253
return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err)
254254
}
@@ -425,7 +425,7 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun
425425
// validateBatch verifies the consistency between the L1 contract and L2 node data.
426426
// The function will terminate the node and exit if any consistency check fails.
427427
// It returns the number of the end block, a finalized batch meta data, and an error if any.
428-
func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) {
428+
func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node, lastBatch bool) (uint64, *rawdb.FinalizedBatchMeta, error) {
429429
if len(chunks) == 0 {
430430
return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64())
431431
}
@@ -442,20 +442,6 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized
442442
}
443443
endBlock := endChunk.Blocks[len(endChunk.Blocks)-1]
444444

445-
localStateRoot := endBlock.Header.Root
446-
if localStateRoot != event.StateRoot {
447-
log.Error("State root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized state root", event.StateRoot.Hex(), "l2 state root", localStateRoot.Hex())
448-
stack.Close()
449-
os.Exit(1)
450-
}
451-
452-
localWithdrawRoot := endBlock.WithdrawRoot
453-
if localWithdrawRoot != event.WithdrawRoot {
454-
log.Error("Withdraw root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized withdraw root", event.WithdrawRoot.Hex(), "l2 withdraw root", localWithdrawRoot.Hex())
455-
stack.Close()
456-
os.Exit(1)
457-
}
458-
459445
// Note: All params of batch are calculated locally based on the block data.
460446
batch := &encoding.Batch{
461447
Index: event.BatchIndex.Uint64(),
@@ -491,17 +477,41 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized
491477
localBatchHash = daBatch.Hash()
492478
}
493479

494-
// Note: If the batch headers match, this ensures the consistency of blocks and transactions
480+
localStateRoot := endBlock.Header.Root
481+
localWithdrawRoot := endBlock.WithdrawRoot
482+
483+
// Note: If the state root, withdraw root, and batch headers match, this ensures the consistency of blocks and transactions
495484
// (including skipped transactions) between L1 and L2.
496-
if localBatchHash != event.BatchHash {
497-
log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex())
498-
chunksJson, err := json.Marshal(chunks)
499-
if err != nil {
500-
log.Error("marshal chunks failed", "err", err)
485+
//
486+
// Only check when it's the last batch. This is compatible with both "finalize by batch" and "finalize by bundle":
487+
// - finalize by batch: check all batches
488+
// - finalize by bundle: check the last batch, because only one event (containing the info of the last batch) is emitted per bundle
489+
if lastBatch {
490+
if localStateRoot != event.StateRoot {
491+
log.Error("State root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized state root", event.StateRoot.Hex(), "l2 state root", localStateRoot.Hex())
492+
stack.Close()
493+
os.Exit(1)
494+
}
495+
496+
if localWithdrawRoot != event.WithdrawRoot {
497+
log.Error("Withdraw root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized withdraw root", event.WithdrawRoot.Hex(), "l2 withdraw root", localWithdrawRoot.Hex())
498+
stack.Close()
499+
os.Exit(1)
500+
}
501+
502+
// The rollup verifier recalculates all batch hashes locally.
503+
// Each batch hash depends on the parent hash, so checking the last batch hash of each bundle when "finalize by bundle"
504+
// still ensures all batch hashes are correct.
505+
if localBatchHash != event.BatchHash {
506+
log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex())
507+
chunksJson, err := json.Marshal(chunks)
508+
if err != nil {
509+
log.Error("marshal chunks failed", "err", err)
510+
}
511+
log.Error("Chunks", "chunks", string(chunksJson))
512+
stack.Close()
513+
os.Exit(1)
501514
}
502-
log.Error("Chunks", "chunks", string(chunksJson))
503-
stack.Close()
504-
os.Exit(1)
505515
}
506516

507517
totalL1MessagePopped := parentBatchMeta.TotalL1MessagePopped

rollup/rollup_sync_service/rollup_sync_service_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ func TestValidateBatchCodecv0(t *testing.T) {
552552
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
553553
}
554554

555-
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil)
555+
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true)
556556
assert.NoError(t, err)
557557
assert.Equal(t, uint64(13), endBlock1)
558558

@@ -572,7 +572,7 @@ func TestValidateBatchCodecv0(t *testing.T) {
572572
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
573573
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
574574
}
575-
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil)
575+
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true)
576576
assert.NoError(t, err)
577577
assert.Equal(t, uint64(17), endBlock2)
578578

@@ -605,7 +605,7 @@ func TestValidateBatchCodecv1(t *testing.T) {
605605
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
606606
}
607607

608-
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil)
608+
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true)
609609
assert.NoError(t, err)
610610
assert.Equal(t, uint64(13), endBlock1)
611611

@@ -625,7 +625,7 @@ func TestValidateBatchCodecv1(t *testing.T) {
625625
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
626626
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
627627
}
628-
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil)
628+
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true)
629629
assert.NoError(t, err)
630630
assert.Equal(t, uint64(17), endBlock2)
631631

@@ -658,7 +658,7 @@ func TestValidateBatchCodecv2(t *testing.T) {
658658
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
659659
}
660660

661-
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil)
661+
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true)
662662
assert.NoError(t, err)
663663
assert.Equal(t, uint64(13), endBlock1)
664664

@@ -678,7 +678,7 @@ func TestValidateBatchCodecv2(t *testing.T) {
678678
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
679679
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
680680
}
681-
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil)
681+
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true)
682682
assert.NoError(t, err)
683683
assert.Equal(t, uint64(17), endBlock2)
684684

@@ -711,7 +711,7 @@ func TestValidateBatchCodecv3(t *testing.T) {
711711
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
712712
}
713713

714-
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil)
714+
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true)
715715
assert.NoError(t, err)
716716
assert.Equal(t, uint64(13), endBlock1)
717717

@@ -731,7 +731,7 @@ func TestValidateBatchCodecv3(t *testing.T) {
731731
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
732732
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
733733
}
734-
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil)
734+
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true)
735735
assert.NoError(t, err)
736736
assert.Equal(t, uint64(17), endBlock2)
737737

@@ -758,7 +758,7 @@ func TestValidateBatchUpgrades(t *testing.T) {
758758
WithdrawRoot: chunk1.Blocks[len(chunk1.Blocks)-1].WithdrawRoot,
759759
}
760760

761-
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1}, chainConfig, nil)
761+
endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1}, chainConfig, nil, true)
762762
assert.NoError(t, err)
763763
assert.Equal(t, uint64(2), endBlock1)
764764

@@ -778,7 +778,7 @@ func TestValidateBatchUpgrades(t *testing.T) {
778778
StateRoot: chunk2.Blocks[len(chunk2.Blocks)-1].Header.Root,
779779
WithdrawRoot: chunk2.Blocks[len(chunk2.Blocks)-1].WithdrawRoot,
780780
}
781-
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk2}, chainConfig, nil)
781+
endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk2}, chainConfig, nil, true)
782782
assert.NoError(t, err)
783783
assert.Equal(t, uint64(3), endBlock2)
784784

@@ -798,7 +798,7 @@ func TestValidateBatchUpgrades(t *testing.T) {
798798
StateRoot: chunk3.Blocks[len(chunk3.Blocks)-1].Header.Root,
799799
WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot,
800800
}
801-
endBlock3, finalizedBatchMeta3, err := validateBatch(event3, parentBatchMeta3, []*encoding.Chunk{chunk3}, chainConfig, nil)
801+
endBlock3, finalizedBatchMeta3, err := validateBatch(event3, parentBatchMeta3, []*encoding.Chunk{chunk3}, chainConfig, nil, true)
802802
assert.NoError(t, err)
803803
assert.Equal(t, uint64(13), endBlock3)
804804

@@ -818,7 +818,7 @@ func TestValidateBatchUpgrades(t *testing.T) {
818818
StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root,
819819
WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot,
820820
}
821-
endBlock4, finalizedBatchMeta4, err := validateBatch(event4, parentBatchMeta4, []*encoding.Chunk{chunk4}, chainConfig, nil)
821+
endBlock4, finalizedBatchMeta4, err := validateBatch(event4, parentBatchMeta4, []*encoding.Chunk{chunk4}, chainConfig, nil, true)
822822
assert.NoError(t, err)
823823
assert.Equal(t, uint64(17), endBlock4)
824824

0 commit comments

Comments
 (0)