@@ -446,31 +446,22 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun
446
446
// In "finalize by bundle", only the last batch of each bundle is fully verified.
447
447
func validateBatch (batchIndex uint64 , event * L1FinalizeBatchEvent , parentBatchMeta * rawdb.FinalizedBatchMeta , chunks []* encoding.Chunk , chainCfg * params.ChainConfig , stack * node.Node ) (uint64 , * rawdb.FinalizedBatchMeta , error ) {
448
448
if len (chunks ) == 0 {
449
- log .Error ("Invalid argument: length of chunks is 0" , "batchIndex" , batchIndex )
450
449
return 0 , nil , fmt .Errorf ("invalid argument: length of chunks is 0, batch index: %v" , batchIndex )
451
450
}
452
451
453
452
startChunk := chunks [0 ]
454
453
if len (startChunk .Blocks ) == 0 {
455
- log .Error ("Invalid argument: block count of start chunk is 0" , "batchIndex" , batchIndex )
456
454
return 0 , nil , fmt .Errorf ("invalid argument: block count of start chunk is 0, batch index: %v" , batchIndex )
457
455
}
458
456
startBlock := startChunk .Blocks [0 ]
459
457
460
458
endChunk := chunks [len (chunks )- 1 ]
461
459
if len (endChunk .Blocks ) == 0 {
462
- log .Error ("Invalid argument: block count of end chunk is 0" , "batchIndex" , batchIndex )
463
460
return 0 , nil , fmt .Errorf ("invalid argument: block count of end chunk is 0, batch index: %v" , batchIndex )
464
461
}
465
462
endBlock := endChunk .Blocks [len (endChunk .Blocks )- 1 ]
466
463
467
- log .Info ("Batch details" ,
468
- "batchIndex" , batchIndex ,
469
- "startBlockNumber" , startBlock .Header .Number .Uint64 (),
470
- "endBlockNumber" , endBlock .Header .Number .Uint64 (),
471
- "parentBatchHash" , parentBatchMeta .BatchHash .Hex (),
472
- "parentTotalL1MessagePopped" , parentBatchMeta .TotalL1MessagePopped )
473
-
464
+ // Note: All params of batch are calculated locally based on the block data.
474
465
batch := & encoding.Batch {
475
466
Index : batchIndex ,
476
467
TotalL1MessagePoppedBefore : parentBatchMeta .TotalL1MessagePopped ,
@@ -479,130 +470,79 @@ func validateBatch(batchIndex uint64, event *L1FinalizeBatchEvent, parentBatchMe
479
470
}
480
471
481
472
var localBatchHash common.Hash
482
- var codecVersion string
483
-
484
- if startBlock .Header .Number .Uint64 () == 0 || ! chainCfg .IsBernoulli (startBlock .Header .Number ) {
485
- codecVersion = "codecv0"
473
+ if startBlock .Header .Number .Uint64 () == 0 || ! chainCfg .IsBernoulli (startBlock .Header .Number ) { // codecv0: genesis batch or batches before Bernoulli
486
474
daBatch , err := codecv0 .NewDABatch (batch )
487
475
if err != nil {
488
- log .Error ("Failed to create codecv0 DA batch" , "batchIndex" , batchIndex , "error" , err )
489
476
return 0 , nil , fmt .Errorf ("failed to create codecv0 DA batch, batch index: %v, err: %w" , batchIndex , err )
490
477
}
491
478
localBatchHash = daBatch .Hash ()
492
- } else if ! chainCfg .IsCurie (startBlock .Header .Number ) {
493
- codecVersion = "codecv1"
479
+ } else if ! chainCfg .IsCurie (startBlock .Header .Number ) { // codecv1: batches after Bernoulli and before Curie
494
480
daBatch , err := codecv1 .NewDABatch (batch )
495
481
if err != nil {
496
- log .Error ("Failed to create codecv1 DA batch" , "batchIndex" , batchIndex , "error" , err )
497
482
return 0 , nil , fmt .Errorf ("failed to create codecv1 DA batch, batch index: %v, err: %w" , batchIndex , err )
498
483
}
499
484
localBatchHash = daBatch .Hash ()
500
- } else if ! chainCfg .IsDarwin (startBlock .Header .Time ) {
501
- codecVersion = "codecv2"
485
+ } else if ! chainCfg .IsDarwin (startBlock .Header .Time ) { // codecv2: batches after Curie and before Darwin
502
486
daBatch , err := codecv2 .NewDABatch (batch )
503
487
if err != nil {
504
- log .Error ("Failed to create codecv2 DA batch" , "batchIndex" , batchIndex , "error" , err )
505
488
return 0 , nil , fmt .Errorf ("failed to create codecv2 DA batch, batch index: %v, err: %w" , batchIndex , err )
506
489
}
507
490
localBatchHash = daBatch .Hash ()
508
- } else {
509
- codecVersion = "codecv3"
491
+ } else { // codecv3: batches after Darwin
510
492
daBatch , err := codecv3 .NewDABatch (batch )
511
493
if err != nil {
512
- log .Error ("Failed to create codecv3 DA batch" , "batchIndex" , batchIndex , "error" , err )
513
494
return 0 , nil , fmt .Errorf ("failed to create codecv3 DA batch, batch index: %v, err: %w" , batchIndex , err )
514
495
}
515
496
localBatchHash = daBatch .Hash ()
516
497
}
517
498
518
- log .Info ("Batch hash calculated" ,
519
- "batchIndex" , batchIndex ,
520
- "codecVersion" , codecVersion ,
521
- "localBatchHash" , localBatchHash .Hex ())
522
-
523
499
localStateRoot := endBlock .Header .Root
524
500
localWithdrawRoot := endBlock .WithdrawRoot
525
501
526
- log . Info ( "Local roots calculated" ,
527
- "batchIndex" , batchIndex ,
528
- "localStateRoot" , localStateRoot . Hex (),
529
- "localWithdrawRoot" , localWithdrawRoot . Hex ())
530
-
531
- // if this is the last batch in a bundle.
502
+ // Note: If the state root, withdraw root, and batch headers match, this ensures the consistency of blocks and transactions
503
+ // (including skipped transactions) between L1 and L2.
504
+ //
505
+ // Only check when batch index matches the index of the event. This is compatible with both "finalize by batch" and "finalize by bundle":
506
+ // - finalize by batch: check all batches
507
+ // - finalize by bundle: check the last batch, because only one event (containing the info of the last batch) is emitted per bundle
532
508
if batchIndex == event .BatchIndex .Uint64 () {
533
- log .Info ("Verifying last batch" , "batchIndex" , event .BatchIndex .Uint64 ())
534
-
535
509
if localStateRoot != event .StateRoot {
536
- log .Error ("State root mismatch" ,
537
- "batchIndex" , batchIndex ,
538
- "startBlock" , startBlock .Header .Number .Uint64 (),
539
- "endBlock" , endBlock .Header .Number .Uint64 (),
540
- "parentBatchHash" , parentBatchMeta .BatchHash .Hex (),
541
- "l1FinalizedStateRoot" , event .StateRoot .Hex (),
542
- "l2StateRoot" , localStateRoot .Hex ())
510
+ 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 ())
543
511
stack .Close ()
544
512
os .Exit (1 )
545
513
}
546
514
547
515
if localWithdrawRoot != event .WithdrawRoot {
548
- log .Error ("Withdraw root mismatch" ,
549
- "batchIndex" , batchIndex ,
550
- "startBlock" , startBlock .Header .Number .Uint64 (),
551
- "endBlock" , endBlock .Header .Number .Uint64 (),
552
- "parentBatchHash" , parentBatchMeta .BatchHash .Hex (),
553
- "l1FinalizedWithdrawRoot" , event .WithdrawRoot .Hex (),
554
- "l2WithdrawRoot" , localWithdrawRoot .Hex ())
516
+ 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 ())
555
517
stack .Close ()
556
518
os .Exit (1 )
557
519
}
558
520
521
+ // Verify batch hash
522
+ // This check ensures the correctness of all batch hashes in the bundle
523
+ // due to the parent-child relationship between batch hashes
559
524
if localBatchHash != event .BatchHash {
560
- log .Error ("Batch hash mismatch" ,
561
- "batchIndex" , batchIndex ,
562
- "startBlock" , startBlock .Header .Number .Uint64 (),
563
- "endBlock" , endBlock .Header .Number .Uint64 (),
564
- "parentBatchHash" , parentBatchMeta .BatchHash .Hex (),
565
- "parentTotalL1MessagePopped" , parentBatchMeta .TotalL1MessagePopped ,
566
- "l1FinalizedBatchHash" , event .BatchHash .Hex (),
567
- "l2BatchHash" , localBatchHash .Hex ())
525
+ 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 ())
568
526
chunksJson , err := json .Marshal (chunks )
569
527
if err != nil {
570
- log .Error ("Marshal chunks failed" , "error " , err )
528
+ log .Error ("marshal chunks failed" , "err " , err )
571
529
}
572
530
log .Error ("Chunks" , "chunks" , string (chunksJson ))
573
531
stack .Close ()
574
532
os .Exit (1 )
575
533
}
576
-
577
- log .Info ("Last batch verified successfully" , "batchIndex" , batchIndex )
578
534
}
579
535
580
536
totalL1MessagePopped := parentBatchMeta .TotalL1MessagePopped
581
- for i , chunk := range chunks {
582
- chunkL1Messages := chunk .NumL1Messages (totalL1MessagePopped )
583
- totalL1MessagePopped += chunkL1Messages
584
- log .Info ("Chunk L1 messages" ,
585
- "batchIndex" , batchIndex ,
586
- "chunkIndex" , i ,
587
- "chunkL1Messages" , chunkL1Messages ,
588
- "totalL1MessagePopped" , totalL1MessagePopped )
537
+ for _ , chunk := range chunks {
538
+ totalL1MessagePopped += chunk .NumL1Messages (totalL1MessagePopped )
589
539
}
590
-
591
540
finalizedBatchMeta := & rawdb.FinalizedBatchMeta {
592
541
BatchHash : localBatchHash ,
593
542
TotalL1MessagePopped : totalL1MessagePopped ,
594
543
StateRoot : localStateRoot ,
595
544
WithdrawRoot : localWithdrawRoot ,
596
545
}
597
-
598
- log .Info ("Batch validation completed" ,
599
- "batchIndex" , event .BatchIndex .Uint64 (),
600
- "endBlockNumber" , endBlock .Header .Number .Uint64 (),
601
- "finalBatchHash" , finalizedBatchMeta .BatchHash .Hex (),
602
- "finalTotalL1MessagePopped" , finalizedBatchMeta .TotalL1MessagePopped ,
603
- "finalStateRoot" , finalizedBatchMeta .StateRoot .Hex (),
604
- "finalWithdrawRoot" , finalizedBatchMeta .WithdrawRoot .Hex ())
605
-
606
546
return endBlock .Header .Number .Uint64 (), finalizedBatchMeta , nil
607
547
}
608
548
0 commit comments