From 600ea40ff5f8e8aa24133dcaf721e88280bc52e3 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 00:05:54 +0800 Subject: [PATCH 01/11] fix(l2geth-verifier): only check the last batch of each bundle --- params/version.go | 2 +- .../rollup_sync_service.go | 60 +++++++++++-------- .../rollup_sync_service_test.go | 24 ++++---- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/params/version.go b/params/version.go index a536231d375d..efa00cbde508 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 5 // Major version component of the current release VersionMinor = 5 // Minor version component of the current release - VersionPatch = 12 // Patch version component of the current release + VersionPatch = 13 // Patch version component of the current release VersionMeta = "mainnet" // Version metadata to append to the version string ) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index c94e55d0b703..a02b9d2a0f8b 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -248,7 +248,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB return fmt.Errorf("failed to get local node info, batch index: %v, err: %w", index, err) } - endBlock, finalizedBatchMeta, err := validateBatch(event, parentBatchMeta, chunks, s.bc.Config(), s.stack) + endBlock, finalizedBatchMeta, err := validateBatch(event, parentBatchMeta, chunks, s.bc.Config(), s.stack, index == batchIndex) if err != nil { return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err) } @@ -425,7 +425,7 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // validateBatch verifies the consistency between the L1 contract and L2 node data. // The function will terminate the node and exit if any consistency check fails. // It returns the number of the end block, a finalized batch meta data, and an error if any. -func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) { +func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node, lastBatch bool) (uint64, *rawdb.FinalizedBatchMeta, error) { if len(chunks) == 0 { return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64()) } @@ -442,20 +442,6 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized } endBlock := endChunk.Blocks[len(endChunk.Blocks)-1] - localStateRoot := endBlock.Header.Root - if localStateRoot != event.StateRoot { - log.Error("State root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized state root", event.StateRoot.Hex(), "l2 state root", localStateRoot.Hex()) - stack.Close() - os.Exit(1) - } - - localWithdrawRoot := endBlock.WithdrawRoot - if localWithdrawRoot != event.WithdrawRoot { - log.Error("Withdraw root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized withdraw root", event.WithdrawRoot.Hex(), "l2 withdraw root", localWithdrawRoot.Hex()) - stack.Close() - os.Exit(1) - } - // Note: All params of batch are calculated locally based on the block data. batch := &encoding.Batch{ Index: event.BatchIndex.Uint64(), @@ -491,17 +477,41 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized localBatchHash = daBatch.Hash() } - // Note: If the batch headers match, this ensures the consistency of blocks and transactions + localStateRoot := endBlock.Header.Root + localWithdrawRoot := endBlock.WithdrawRoot + + // Note: If the state root, withdraw root, and batch headers match, this ensures the consistency of blocks and transactions // (including skipped transactions) between L1 and L2. - if localBatchHash != event.BatchHash { - log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex()) - chunksJson, err := json.Marshal(chunks) - if err != nil { - log.Error("marshal chunks failed", "err", err) + // + // Only check when it's the last batch. This is compatible with both "finalize by batch" and "finalize by bundle": + // - finalize by batch: check all batches + // - finalize by bundle: check the last batch, because only one event (containing the info of the last batch) is emitted per bundle + if lastBatch { + if localStateRoot != event.StateRoot { + log.Error("State root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized state root", event.StateRoot.Hex(), "l2 state root", localStateRoot.Hex()) + stack.Close() + os.Exit(1) + } + + if localWithdrawRoot != event.WithdrawRoot { + log.Error("Withdraw root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized withdraw root", event.WithdrawRoot.Hex(), "l2 withdraw root", localWithdrawRoot.Hex()) + stack.Close() + os.Exit(1) + } + + // The rollup verifier recalculates all batch hashes locally. + // Each batch hash depends on the parent hash, so checking the last batch hash of each bundle when "finalize by bundle" + // still ensures all batch hashes are correct. + if localBatchHash != event.BatchHash { + log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex()) + chunksJson, err := json.Marshal(chunks) + if err != nil { + log.Error("marshal chunks failed", "err", err) + } + log.Error("Chunks", "chunks", string(chunksJson)) + stack.Close() + os.Exit(1) } - log.Error("Chunks", "chunks", string(chunksJson)) - stack.Close() - os.Exit(1) } totalL1MessagePopped := parentBatchMeta.TotalL1MessagePopped diff --git a/rollup/rollup_sync_service/rollup_sync_service_test.go b/rollup/rollup_sync_service/rollup_sync_service_test.go index 1ed258780f35..616f008b21a7 100644 --- a/rollup/rollup_sync_service/rollup_sync_service_test.go +++ b/rollup/rollup_sync_service/rollup_sync_service_test.go @@ -552,7 +552,7 @@ func TestValidateBatchCodecv0(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -572,7 +572,7 @@ func TestValidateBatchCodecv0(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -605,7 +605,7 @@ func TestValidateBatchCodecv1(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -625,7 +625,7 @@ func TestValidateBatchCodecv1(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -658,7 +658,7 @@ func TestValidateBatchCodecv2(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -678,7 +678,7 @@ func TestValidateBatchCodecv2(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -711,7 +711,7 @@ func TestValidateBatchCodecv3(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -731,7 +731,7 @@ func TestValidateBatchCodecv3(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -758,7 +758,7 @@ func TestValidateBatchUpgrades(t *testing.T) { WithdrawRoot: chunk1.Blocks[len(chunk1.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1}, chainConfig, nil) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(2), endBlock1) @@ -778,7 +778,7 @@ func TestValidateBatchUpgrades(t *testing.T) { StateRoot: chunk2.Blocks[len(chunk2.Blocks)-1].Header.Root, WithdrawRoot: chunk2.Blocks[len(chunk2.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk2}, chainConfig, nil) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk2}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(3), endBlock2) @@ -798,7 +798,7 @@ func TestValidateBatchUpgrades(t *testing.T) { StateRoot: chunk3.Blocks[len(chunk3.Blocks)-1].Header.Root, WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock3, finalizedBatchMeta3, err := validateBatch(event3, parentBatchMeta3, []*encoding.Chunk{chunk3}, chainConfig, nil) + endBlock3, finalizedBatchMeta3, err := validateBatch(event3, parentBatchMeta3, []*encoding.Chunk{chunk3}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock3) @@ -818,7 +818,7 @@ func TestValidateBatchUpgrades(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock4, finalizedBatchMeta4, err := validateBatch(event4, parentBatchMeta4, []*encoding.Chunk{chunk4}, chainConfig, nil) + endBlock4, finalizedBatchMeta4, err := validateBatch(event4, parentBatchMeta4, []*encoding.Chunk{chunk4}, chainConfig, nil, true) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock4) From aa76eb7e495f9160a9f8e0fdc944ca3b99c301de Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 00:20:41 +0800 Subject: [PATCH 02/11] refactor function comments --- .../rollup_sync_service.go | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index a02b9d2a0f8b..8ba7ce808779 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -422,9 +422,28 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun return nil, fmt.Errorf("unexpected method name: %v", method.Name) } -// validateBatch verifies the consistency between the L1 contract and L2 node data. +// validateBatch verifies the consistency between L1 contract and L2 node data. +// It performs the following checks: +// 1. Recalculates the batch hash locally +// 2. Compares local state root, withdraw root, and batch hash with L1 data (for the last batch only when "finalize by bundle") +// // The function will terminate the node and exit if any consistency check fails. -// It returns the number of the end block, a finalized batch meta data, and an error if any. +// +// Parameters: +// - event: L1 finalize batch event data +// - parentBatchMeta: metadata of the parent batch +// - chunks: slice of chunk data for the current batch +// - chainCfg: chain configuration to identify the codec version +// - stack: node stack to terminate the node in case of inconsistency +// - lastBatch: boolean indicating if this is the last batch in a bundle +// +// Returns: +// - uint64: the end block height of the batch +// - *rawdb.FinalizedBatchMeta: finalized batch metadata +// - error: any error encountered during validation +// +// 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. func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node, lastBatch bool) (uint64, *rawdb.FinalizedBatchMeta, error) { if len(chunks) == 0 { return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64()) @@ -499,9 +518,9 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized os.Exit(1) } - // The rollup verifier recalculates all batch hashes locally. - // Each batch hash depends on the parent hash, so checking the last batch hash of each bundle when "finalize by bundle" - // still ensures all batch hashes are correct. + // Verify batch hash + // This check ensures the correctness of all batch hashes in the bundle + // due to the parent-child relationship between batch hashes if localBatchHash != event.BatchHash { log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex()) chunksJson, err := json.Marshal(chunks) From 4befe9fe739275988b4bf34999bd1aad4d7a1d0e Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 13:35:13 +0800 Subject: [PATCH 03/11] add more logs to debug --- .../rollup_sync_service.go | 101 ++++++++++++++---- 1 file changed, 81 insertions(+), 20 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index 8ba7ce808779..06ad2b41f4bf 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -445,23 +445,34 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // 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. func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node, lastBatch bool) (uint64, *rawdb.FinalizedBatchMeta, error) { + log.Info("Starting validateBatch", "batchIndex", event.BatchIndex.Uint64(), "lastBatch", lastBatch) + if len(chunks) == 0 { + log.Error("Invalid argument: length of chunks is 0", "batchIndex", event.BatchIndex.Uint64()) return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64()) } startChunk := chunks[0] if len(startChunk.Blocks) == 0 { + log.Error("Invalid argument: block count of start chunk is 0", "batchIndex", event.BatchIndex.Uint64()) return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0, batch index: %v", event.BatchIndex.Uint64()) } startBlock := startChunk.Blocks[0] endChunk := chunks[len(chunks)-1] if len(endChunk.Blocks) == 0 { + log.Error("Invalid argument: block count of end chunk is 0", "batchIndex", event.BatchIndex.Uint64()) return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0, batch index: %v", event.BatchIndex.Uint64()) } endBlock := endChunk.Blocks[len(endChunk.Blocks)-1] - // Note: All params of batch are calculated locally based on the block data. + log.Info("Batch details", + "batchIndex", event.BatchIndex.Uint64(), + "startBlockNumber", startBlock.Header.Number.Uint64(), + "endBlockNumber", endBlock.Header.Number.Uint64(), + "parentBatchHash", parentBatchMeta.BatchHash.Hex(), + "parentTotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped) + batch := &encoding.Batch{ Index: event.BatchIndex.Uint64(), TotalL1MessagePoppedBefore: parentBatchMeta.TotalL1MessagePopped, @@ -470,79 +481,129 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized } var localBatchHash common.Hash - if startBlock.Header.Number.Uint64() == 0 || !chainCfg.IsBernoulli(startBlock.Header.Number) { // codecv0: genesis batch or batches before Bernoulli + var codecVersion string + + if startBlock.Header.Number.Uint64() == 0 || !chainCfg.IsBernoulli(startBlock.Header.Number) { + codecVersion = "codecv0" daBatch, err := codecv0.NewDABatch(batch) if err != nil { + log.Error("Failed to create codecv0 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) return 0, nil, fmt.Errorf("failed to create codecv0 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) } localBatchHash = daBatch.Hash() - } else if !chainCfg.IsCurie(startBlock.Header.Number) { // codecv1: batches after Bernoulli and before Curie + } else if !chainCfg.IsCurie(startBlock.Header.Number) { + codecVersion = "codecv1" daBatch, err := codecv1.NewDABatch(batch) if err != nil { + log.Error("Failed to create codecv1 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) return 0, nil, fmt.Errorf("failed to create codecv1 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) } localBatchHash = daBatch.Hash() - } else if !chainCfg.IsDarwin(startBlock.Header.Time) { // codecv2: batches after Curie and before Darwin + } else if !chainCfg.IsDarwin(startBlock.Header.Time) { + codecVersion = "codecv2" daBatch, err := codecv2.NewDABatch(batch) if err != nil { + log.Error("Failed to create codecv2 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) return 0, nil, fmt.Errorf("failed to create codecv2 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) } localBatchHash = daBatch.Hash() - } else { // codecv3: batches after Darwin + } else { + codecVersion = "codecv3" daBatch, err := codecv3.NewDABatch(batch) if err != nil { + log.Error("Failed to create codecv3 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) return 0, nil, fmt.Errorf("failed to create codecv3 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) } localBatchHash = daBatch.Hash() } + log.Info("Batch hash calculated", + "batchIndex", event.BatchIndex.Uint64(), + "codecVersion", codecVersion, + "localBatchHash", localBatchHash.Hex()) + localStateRoot := endBlock.Header.Root localWithdrawRoot := endBlock.WithdrawRoot - // Note: If the state root, withdraw root, and batch headers match, this ensures the consistency of blocks and transactions - // (including skipped transactions) between L1 and L2. - // - // Only check when it's the last batch. This is compatible with both "finalize by batch" and "finalize by bundle": - // - finalize by batch: check all batches - // - finalize by bundle: check the last batch, because only one event (containing the info of the last batch) is emitted per bundle + log.Info("Local roots calculated", + "batchIndex", event.BatchIndex.Uint64(), + "localStateRoot", localStateRoot.Hex(), + "localWithdrawRoot", localWithdrawRoot.Hex()) + if lastBatch { + log.Info("Verifying last batch", "batchIndex", event.BatchIndex.Uint64()) + if localStateRoot != event.StateRoot { - log.Error("State root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized state root", event.StateRoot.Hex(), "l2 state root", localStateRoot.Hex()) + log.Error("State root mismatch", + "batchIndex", event.BatchIndex.Uint64(), + "startBlock", startBlock.Header.Number.Uint64(), + "endBlock", endBlock.Header.Number.Uint64(), + "parentBatchHash", parentBatchMeta.BatchHash.Hex(), + "l1FinalizedStateRoot", event.StateRoot.Hex(), + "l2StateRoot", localStateRoot.Hex()) stack.Close() os.Exit(1) } if localWithdrawRoot != event.WithdrawRoot { - log.Error("Withdraw root mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "l1 finalized withdraw root", event.WithdrawRoot.Hex(), "l2 withdraw root", localWithdrawRoot.Hex()) + log.Error("Withdraw root mismatch", + "batchIndex", event.BatchIndex.Uint64(), + "startBlock", startBlock.Header.Number.Uint64(), + "endBlock", endBlock.Header.Number.Uint64(), + "parentBatchHash", parentBatchMeta.BatchHash.Hex(), + "l1FinalizedWithdrawRoot", event.WithdrawRoot.Hex(), + "l2WithdrawRoot", localWithdrawRoot.Hex()) stack.Close() os.Exit(1) } - // Verify batch hash - // This check ensures the correctness of all batch hashes in the bundle - // due to the parent-child relationship between batch hashes if localBatchHash != event.BatchHash { - log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex()) + log.Error("Batch hash mismatch", + "batchIndex", event.BatchIndex.Uint64(), + "startBlock", startBlock.Header.Number.Uint64(), + "endBlock", endBlock.Header.Number.Uint64(), + "parentBatchHash", parentBatchMeta.BatchHash.Hex(), + "parentTotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, + "l1FinalizedBatchHash", event.BatchHash.Hex(), + "l2BatchHash", localBatchHash.Hex()) chunksJson, err := json.Marshal(chunks) if err != nil { - log.Error("marshal chunks failed", "err", err) + log.Error("Marshal chunks failed", "error", err) } log.Error("Chunks", "chunks", string(chunksJson)) stack.Close() os.Exit(1) } + + log.Info("Last batch verified successfully", "batchIndex", event.BatchIndex.Uint64()) } totalL1MessagePopped := parentBatchMeta.TotalL1MessagePopped - for _, chunk := range chunks { - totalL1MessagePopped += chunk.NumL1Messages(totalL1MessagePopped) + for i, chunk := range chunks { + chunkL1Messages := chunk.NumL1Messages(totalL1MessagePopped) + totalL1MessagePopped += chunkL1Messages + log.Info("Chunk L1 messages", + "batchIndex", event.BatchIndex.Uint64(), + "chunkIndex", i, + "chunkL1Messages", chunkL1Messages, + "totalL1MessagePopped", totalL1MessagePopped) } + finalizedBatchMeta := &rawdb.FinalizedBatchMeta{ BatchHash: localBatchHash, TotalL1MessagePopped: totalL1MessagePopped, StateRoot: localStateRoot, WithdrawRoot: localWithdrawRoot, } + + log.Info("Batch validation completed", + "batchIndex", event.BatchIndex.Uint64(), + "endBlockNumber", endBlock.Header.Number.Uint64(), + "finalBatchHash", finalizedBatchMeta.BatchHash.Hex(), + "finalTotalL1MessagePopped", finalizedBatchMeta.TotalL1MessagePopped, + "finalStateRoot", finalizedBatchMeta.StateRoot.Hex(), + "finalWithdrawRoot", finalizedBatchMeta.WithdrawRoot.Hex()) + return endBlock.Header.Number.Uint64(), finalizedBatchMeta, nil } From df6a93ee70cd4ba534a9ca4ed78a0757498929a8 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 14:36:40 +0800 Subject: [PATCH 04/11] fix the bug --- .../rollup_sync_service.go | 57 +++++++++---------- .../rollup_sync_service_test.go | 24 ++++---- 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index 06ad2b41f4bf..d0d461049770 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -248,7 +248,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB return fmt.Errorf("failed to get local node info, batch index: %v, err: %w", index, err) } - endBlock, finalizedBatchMeta, err := validateBatch(event, parentBatchMeta, chunks, s.bc.Config(), s.stack, index == batchIndex) + endBlock, finalizedBatchMeta, err := validateBatch(index, event, parentBatchMeta, chunks, s.bc.Config(), s.stack) if err != nil { return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err) } @@ -430,12 +430,12 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // The function will terminate the node and exit if any consistency check fails. // // Parameters: +// - batchIndex: batch index of the validated batch // - event: L1 finalize batch event data // - parentBatchMeta: metadata of the parent batch // - chunks: slice of chunk data for the current batch // - chainCfg: chain configuration to identify the codec version // - stack: node stack to terminate the node in case of inconsistency -// - lastBatch: boolean indicating if this is the last batch in a bundle // // Returns: // - uint64: the end block height of the batch @@ -444,37 +444,35 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // // 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. -func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node, lastBatch bool) (uint64, *rawdb.FinalizedBatchMeta, error) { - log.Info("Starting validateBatch", "batchIndex", event.BatchIndex.Uint64(), "lastBatch", lastBatch) - +func validateBatch(batchIndex uint64, event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) { if len(chunks) == 0 { - log.Error("Invalid argument: length of chunks is 0", "batchIndex", event.BatchIndex.Uint64()) - return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", event.BatchIndex.Uint64()) + log.Error("Invalid argument: length of chunks is 0", "batchIndex", batchIndex) + return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", batchIndex) } startChunk := chunks[0] if len(startChunk.Blocks) == 0 { - log.Error("Invalid argument: block count of start chunk is 0", "batchIndex", event.BatchIndex.Uint64()) - return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0, batch index: %v", event.BatchIndex.Uint64()) + log.Error("Invalid argument: block count of start chunk is 0", "batchIndex", batchIndex) + return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0, batch index: %v", batchIndex) } startBlock := startChunk.Blocks[0] endChunk := chunks[len(chunks)-1] if len(endChunk.Blocks) == 0 { - log.Error("Invalid argument: block count of end chunk is 0", "batchIndex", event.BatchIndex.Uint64()) - return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0, batch index: %v", event.BatchIndex.Uint64()) + log.Error("Invalid argument: block count of end chunk is 0", "batchIndex", batchIndex) + return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0, batch index: %v", batchIndex) } endBlock := endChunk.Blocks[len(endChunk.Blocks)-1] log.Info("Batch details", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "startBlockNumber", startBlock.Header.Number.Uint64(), "endBlockNumber", endBlock.Header.Number.Uint64(), "parentBatchHash", parentBatchMeta.BatchHash.Hex(), "parentTotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped) batch := &encoding.Batch{ - Index: event.BatchIndex.Uint64(), + Index: batchIndex, TotalL1MessagePoppedBefore: parentBatchMeta.TotalL1MessagePopped, ParentBatchHash: parentBatchMeta.BatchHash, Chunks: chunks, @@ -487,38 +485,38 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized codecVersion = "codecv0" daBatch, err := codecv0.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv0 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) - return 0, nil, fmt.Errorf("failed to create codecv0 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) + log.Error("Failed to create codecv0 DA batch", "batchIndex", batchIndex, "error", err) + return 0, nil, fmt.Errorf("failed to create codecv0 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() } else if !chainCfg.IsCurie(startBlock.Header.Number) { codecVersion = "codecv1" daBatch, err := codecv1.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv1 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) - return 0, nil, fmt.Errorf("failed to create codecv1 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) + log.Error("Failed to create codecv1 DA batch", "batchIndex", batchIndex, "error", err) + return 0, nil, fmt.Errorf("failed to create codecv1 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() } else if !chainCfg.IsDarwin(startBlock.Header.Time) { codecVersion = "codecv2" daBatch, err := codecv2.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv2 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) - return 0, nil, fmt.Errorf("failed to create codecv2 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) + log.Error("Failed to create codecv2 DA batch", "batchIndex", batchIndex, "error", err) + return 0, nil, fmt.Errorf("failed to create codecv2 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() } else { codecVersion = "codecv3" daBatch, err := codecv3.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv3 DA batch", "batchIndex", event.BatchIndex.Uint64(), "error", err) - return 0, nil, fmt.Errorf("failed to create codecv3 DA batch, batch index: %v, err: %w", event.BatchIndex.Uint64(), err) + log.Error("Failed to create codecv3 DA batch", "batchIndex", batchIndex, "error", err) + return 0, nil, fmt.Errorf("failed to create codecv3 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() } log.Info("Batch hash calculated", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "codecVersion", codecVersion, "localBatchHash", localBatchHash.Hex()) @@ -526,16 +524,17 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized localWithdrawRoot := endBlock.WithdrawRoot log.Info("Local roots calculated", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "localStateRoot", localStateRoot.Hex(), "localWithdrawRoot", localWithdrawRoot.Hex()) - if lastBatch { + // if this is the last batch in a bundle. + if batchIndex == event.BatchIndex.Uint64() { log.Info("Verifying last batch", "batchIndex", event.BatchIndex.Uint64()) if localStateRoot != event.StateRoot { log.Error("State root mismatch", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "startBlock", startBlock.Header.Number.Uint64(), "endBlock", endBlock.Header.Number.Uint64(), "parentBatchHash", parentBatchMeta.BatchHash.Hex(), @@ -547,7 +546,7 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized if localWithdrawRoot != event.WithdrawRoot { log.Error("Withdraw root mismatch", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "startBlock", startBlock.Header.Number.Uint64(), "endBlock", endBlock.Header.Number.Uint64(), "parentBatchHash", parentBatchMeta.BatchHash.Hex(), @@ -559,7 +558,7 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized if localBatchHash != event.BatchHash { log.Error("Batch hash mismatch", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "startBlock", startBlock.Header.Number.Uint64(), "endBlock", endBlock.Header.Number.Uint64(), "parentBatchHash", parentBatchMeta.BatchHash.Hex(), @@ -575,7 +574,7 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized os.Exit(1) } - log.Info("Last batch verified successfully", "batchIndex", event.BatchIndex.Uint64()) + log.Info("Last batch verified successfully", "batchIndex", batchIndex) } totalL1MessagePopped := parentBatchMeta.TotalL1MessagePopped @@ -583,7 +582,7 @@ func validateBatch(event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.Finalized chunkL1Messages := chunk.NumL1Messages(totalL1MessagePopped) totalL1MessagePopped += chunkL1Messages log.Info("Chunk L1 messages", - "batchIndex", event.BatchIndex.Uint64(), + "batchIndex", batchIndex, "chunkIndex", i, "chunkL1Messages", chunkL1Messages, "totalL1MessagePopped", totalL1MessagePopped) diff --git a/rollup/rollup_sync_service/rollup_sync_service_test.go b/rollup/rollup_sync_service/rollup_sync_service_test.go index 616f008b21a7..caac9bc39dd4 100644 --- a/rollup/rollup_sync_service/rollup_sync_service_test.go +++ b/rollup/rollup_sync_service/rollup_sync_service_test.go @@ -552,7 +552,7 @@ func TestValidateBatchCodecv0(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex.Uint64(), event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -572,7 +572,7 @@ func TestValidateBatchCodecv0(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex.Uint64(), event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -605,7 +605,7 @@ func TestValidateBatchCodecv1(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex.Uint64(), event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -625,7 +625,7 @@ func TestValidateBatchCodecv1(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex.Uint64(), event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -658,7 +658,7 @@ func TestValidateBatchCodecv2(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex.Uint64(), event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -678,7 +678,7 @@ func TestValidateBatchCodecv2(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex.Uint64(), event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -711,7 +711,7 @@ func TestValidateBatchCodecv3(t *testing.T) { WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil, true) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex.Uint64(), event1, parentBatchMeta1, []*encoding.Chunk{chunk1, chunk2, chunk3}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock1) @@ -731,7 +731,7 @@ func TestValidateBatchCodecv3(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil, true) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex.Uint64(), event2, parentBatchMeta2, []*encoding.Chunk{chunk4}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock2) @@ -758,7 +758,7 @@ func TestValidateBatchUpgrades(t *testing.T) { WithdrawRoot: chunk1.Blocks[len(chunk1.Blocks)-1].WithdrawRoot, } - endBlock1, finalizedBatchMeta1, err := validateBatch(event1, parentBatchMeta1, []*encoding.Chunk{chunk1}, chainConfig, nil, true) + endBlock1, finalizedBatchMeta1, err := validateBatch(event1.BatchIndex.Uint64(), event1, parentBatchMeta1, []*encoding.Chunk{chunk1}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(2), endBlock1) @@ -778,7 +778,7 @@ func TestValidateBatchUpgrades(t *testing.T) { StateRoot: chunk2.Blocks[len(chunk2.Blocks)-1].Header.Root, WithdrawRoot: chunk2.Blocks[len(chunk2.Blocks)-1].WithdrawRoot, } - endBlock2, finalizedBatchMeta2, err := validateBatch(event2, parentBatchMeta2, []*encoding.Chunk{chunk2}, chainConfig, nil, true) + endBlock2, finalizedBatchMeta2, err := validateBatch(event2.BatchIndex.Uint64(), event2, parentBatchMeta2, []*encoding.Chunk{chunk2}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(3), endBlock2) @@ -798,7 +798,7 @@ func TestValidateBatchUpgrades(t *testing.T) { StateRoot: chunk3.Blocks[len(chunk3.Blocks)-1].Header.Root, WithdrawRoot: chunk3.Blocks[len(chunk3.Blocks)-1].WithdrawRoot, } - endBlock3, finalizedBatchMeta3, err := validateBatch(event3, parentBatchMeta3, []*encoding.Chunk{chunk3}, chainConfig, nil, true) + endBlock3, finalizedBatchMeta3, err := validateBatch(event3.BatchIndex.Uint64(), event3, parentBatchMeta3, []*encoding.Chunk{chunk3}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(13), endBlock3) @@ -818,7 +818,7 @@ func TestValidateBatchUpgrades(t *testing.T) { StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, } - endBlock4, finalizedBatchMeta4, err := validateBatch(event4, parentBatchMeta4, []*encoding.Chunk{chunk4}, chainConfig, nil, true) + endBlock4, finalizedBatchMeta4, err := validateBatch(event4.BatchIndex.Uint64(), event4, parentBatchMeta4, []*encoding.Chunk{chunk4}, chainConfig, nil) assert.NoError(t, err) assert.Equal(t, uint64(17), endBlock4) From 15e7f332173984d042f21183d0d73b9e1381465b Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 14:50:38 +0800 Subject: [PATCH 05/11] Revert "add more logs to debug" This reverts commit 4befe9fe739275988b4bf34999bd1aad4d7a1d0e. --- .../rollup_sync_service.go | 100 ++++-------------- 1 file changed, 20 insertions(+), 80 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index d0d461049770..9517b45cc49a 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -446,31 +446,22 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // In "finalize by bundle", only the last batch of each bundle is fully verified. func validateBatch(batchIndex uint64, event *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) { if len(chunks) == 0 { - log.Error("Invalid argument: length of chunks is 0", "batchIndex", batchIndex) return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", batchIndex) } startChunk := chunks[0] if len(startChunk.Blocks) == 0 { - log.Error("Invalid argument: block count of start chunk is 0", "batchIndex", batchIndex) return 0, nil, fmt.Errorf("invalid argument: block count of start chunk is 0, batch index: %v", batchIndex) } startBlock := startChunk.Blocks[0] endChunk := chunks[len(chunks)-1] if len(endChunk.Blocks) == 0 { - log.Error("Invalid argument: block count of end chunk is 0", "batchIndex", batchIndex) return 0, nil, fmt.Errorf("invalid argument: block count of end chunk is 0, batch index: %v", batchIndex) } endBlock := endChunk.Blocks[len(endChunk.Blocks)-1] - log.Info("Batch details", - "batchIndex", batchIndex, - "startBlockNumber", startBlock.Header.Number.Uint64(), - "endBlockNumber", endBlock.Header.Number.Uint64(), - "parentBatchHash", parentBatchMeta.BatchHash.Hex(), - "parentTotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped) - + // Note: All params of batch are calculated locally based on the block data. batch := &encoding.Batch{ Index: batchIndex, TotalL1MessagePoppedBefore: parentBatchMeta.TotalL1MessagePopped, @@ -479,130 +470,79 @@ func validateBatch(batchIndex uint64, event *L1FinalizeBatchEvent, parentBatchMe } var localBatchHash common.Hash - var codecVersion string - - if startBlock.Header.Number.Uint64() == 0 || !chainCfg.IsBernoulli(startBlock.Header.Number) { - codecVersion = "codecv0" + if startBlock.Header.Number.Uint64() == 0 || !chainCfg.IsBernoulli(startBlock.Header.Number) { // codecv0: genesis batch or batches before Bernoulli daBatch, err := codecv0.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv0 DA batch", "batchIndex", batchIndex, "error", err) return 0, nil, fmt.Errorf("failed to create codecv0 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() - } else if !chainCfg.IsCurie(startBlock.Header.Number) { - codecVersion = "codecv1" + } else if !chainCfg.IsCurie(startBlock.Header.Number) { // codecv1: batches after Bernoulli and before Curie daBatch, err := codecv1.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv1 DA batch", "batchIndex", batchIndex, "error", err) return 0, nil, fmt.Errorf("failed to create codecv1 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() - } else if !chainCfg.IsDarwin(startBlock.Header.Time) { - codecVersion = "codecv2" + } else if !chainCfg.IsDarwin(startBlock.Header.Time) { // codecv2: batches after Curie and before Darwin daBatch, err := codecv2.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv2 DA batch", "batchIndex", batchIndex, "error", err) return 0, nil, fmt.Errorf("failed to create codecv2 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() - } else { - codecVersion = "codecv3" + } else { // codecv3: batches after Darwin daBatch, err := codecv3.NewDABatch(batch) if err != nil { - log.Error("Failed to create codecv3 DA batch", "batchIndex", batchIndex, "error", err) return 0, nil, fmt.Errorf("failed to create codecv3 DA batch, batch index: %v, err: %w", batchIndex, err) } localBatchHash = daBatch.Hash() } - log.Info("Batch hash calculated", - "batchIndex", batchIndex, - "codecVersion", codecVersion, - "localBatchHash", localBatchHash.Hex()) - localStateRoot := endBlock.Header.Root localWithdrawRoot := endBlock.WithdrawRoot - log.Info("Local roots calculated", - "batchIndex", batchIndex, - "localStateRoot", localStateRoot.Hex(), - "localWithdrawRoot", localWithdrawRoot.Hex()) - - // if this is the last batch in a bundle. + // Note: If the state root, withdraw root, and batch headers match, this ensures the consistency of blocks and transactions + // (including skipped transactions) between L1 and L2. + // + // Only check when batch index matches the index of the event. This is compatible with both "finalize by batch" and "finalize by bundle": + // - finalize by batch: check all batches + // - finalize by bundle: check the last batch, because only one event (containing the info of the last batch) is emitted per bundle if batchIndex == event.BatchIndex.Uint64() { - log.Info("Verifying last batch", "batchIndex", event.BatchIndex.Uint64()) - if localStateRoot != event.StateRoot { - log.Error("State root mismatch", - "batchIndex", batchIndex, - "startBlock", startBlock.Header.Number.Uint64(), - "endBlock", endBlock.Header.Number.Uint64(), - "parentBatchHash", parentBatchMeta.BatchHash.Hex(), - "l1FinalizedStateRoot", event.StateRoot.Hex(), - "l2StateRoot", localStateRoot.Hex()) + 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()) stack.Close() os.Exit(1) } if localWithdrawRoot != event.WithdrawRoot { - log.Error("Withdraw root mismatch", - "batchIndex", batchIndex, - "startBlock", startBlock.Header.Number.Uint64(), - "endBlock", endBlock.Header.Number.Uint64(), - "parentBatchHash", parentBatchMeta.BatchHash.Hex(), - "l1FinalizedWithdrawRoot", event.WithdrawRoot.Hex(), - "l2WithdrawRoot", localWithdrawRoot.Hex()) + 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()) stack.Close() os.Exit(1) } + // Verify batch hash + // This check ensures the correctness of all batch hashes in the bundle + // due to the parent-child relationship between batch hashes if localBatchHash != event.BatchHash { - log.Error("Batch hash mismatch", - "batchIndex", batchIndex, - "startBlock", startBlock.Header.Number.Uint64(), - "endBlock", endBlock.Header.Number.Uint64(), - "parentBatchHash", parentBatchMeta.BatchHash.Hex(), - "parentTotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, - "l1FinalizedBatchHash", event.BatchHash.Hex(), - "l2BatchHash", localBatchHash.Hex()) + log.Error("Batch hash mismatch", "batch index", event.BatchIndex.Uint64(), "start block", startBlock.Header.Number.Uint64(), "end block", endBlock.Header.Number.Uint64(), "parent batch hash", parentBatchMeta.BatchHash.Hex(), "parent TotalL1MessagePopped", parentBatchMeta.TotalL1MessagePopped, "l1 finalized batch hash", event.BatchHash.Hex(), "l2 batch hash", localBatchHash.Hex()) chunksJson, err := json.Marshal(chunks) if err != nil { - log.Error("Marshal chunks failed", "error", err) + log.Error("marshal chunks failed", "err", err) } log.Error("Chunks", "chunks", string(chunksJson)) stack.Close() os.Exit(1) } - - log.Info("Last batch verified successfully", "batchIndex", batchIndex) } totalL1MessagePopped := parentBatchMeta.TotalL1MessagePopped - for i, chunk := range chunks { - chunkL1Messages := chunk.NumL1Messages(totalL1MessagePopped) - totalL1MessagePopped += chunkL1Messages - log.Info("Chunk L1 messages", - "batchIndex", batchIndex, - "chunkIndex", i, - "chunkL1Messages", chunkL1Messages, - "totalL1MessagePopped", totalL1MessagePopped) + for _, chunk := range chunks { + totalL1MessagePopped += chunk.NumL1Messages(totalL1MessagePopped) } - finalizedBatchMeta := &rawdb.FinalizedBatchMeta{ BatchHash: localBatchHash, TotalL1MessagePopped: totalL1MessagePopped, StateRoot: localStateRoot, WithdrawRoot: localWithdrawRoot, } - - log.Info("Batch validation completed", - "batchIndex", event.BatchIndex.Uint64(), - "endBlockNumber", endBlock.Header.Number.Uint64(), - "finalBatchHash", finalizedBatchMeta.BatchHash.Hex(), - "finalTotalL1MessagePopped", finalizedBatchMeta.TotalL1MessagePopped, - "finalStateRoot", finalizedBatchMeta.StateRoot.Hex(), - "finalWithdrawRoot", finalizedBatchMeta.WithdrawRoot.Hex()) - return endBlock.Header.Number.Uint64(), finalizedBatchMeta, nil } From 827ce3ced583b8ce8a5d94c18129b9d41190805b Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 14:55:48 +0800 Subject: [PATCH 06/11] tweak --- rollup/rollup_sync_service/rollup_sync_service.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index 9517b45cc49a..dbe12edaa5a4 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -422,10 +422,10 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun return nil, fmt.Errorf("unexpected method name: %v", method.Name) } -// validateBatch verifies the consistency between L1 contract and L2 node data. +// validateBatch verifies the consistency between the L1 contract and L2 node data. // It performs the following checks: // 1. Recalculates the batch hash locally -// 2. Compares local state root, withdraw root, and batch hash with L1 data (for the last batch only when "finalize by bundle") +// 2. Compares local state root, local withdraw root, and locally calculated batch hash with L1 data (for the last batch only when "finalize by bundle") // // The function will terminate the node and exit if any consistency check fails. // @@ -444,6 +444,7 @@ func (s *RollupSyncService) decodeChunkBlockRanges(txData []byte) ([]*rawdb.Chun // // 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. +// 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 *L1FinalizeBatchEvent, parentBatchMeta *rawdb.FinalizedBatchMeta, chunks []*encoding.Chunk, chainCfg *params.ChainConfig, stack *node.Node) (uint64, *rawdb.FinalizedBatchMeta, error) { if len(chunks) == 0 { return 0, nil, fmt.Errorf("invalid argument: length of chunks is 0, batch index: %v", batchIndex) From 194395069b9dfebb9394109df970357686fd5d3a Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Tue, 16 Jul 2024 15:15:28 +0800 Subject: [PATCH 07/11] TestValidateBatchInFinalizeByBundle --- .../rollup_sync_service_test.go | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/rollup/rollup_sync_service/rollup_sync_service_test.go b/rollup/rollup_sync_service/rollup_sync_service_test.go index caac9bc39dd4..dea97613fb96 100644 --- a/rollup/rollup_sync_service/rollup_sync_service_test.go +++ b/rollup/rollup_sync_service/rollup_sync_service_test.go @@ -831,6 +831,51 @@ func TestValidateBatchUpgrades(t *testing.T) { assert.Equal(t, parentBatchMeta5, finalizedBatchMeta4) } +func TestValidateBatchInFinalizeByBundle(t *testing.T) { + chainConfig := ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0), CurieBlock: big.NewInt(0), DarwinTime: func() *uint64 { t := uint64(0); return &t }()} + + block1 := readBlockFromJSON(t, "./testdata/blockTrace_02.json") + block2 := readBlockFromJSON(t, "./testdata/blockTrace_03.json") + block3 := readBlockFromJSON(t, "./testdata/blockTrace_04.json") + block4 := readBlockFromJSON(t, "./testdata/blockTrace_05.json") + + chunk1 := &encoding.Chunk{Blocks: []*encoding.Block{block1}} + chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{block2}} + chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{block3}} + chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{block4}} + + event := &L1FinalizeBatchEvent{ + BatchIndex: big.NewInt(3), + BatchHash: common.HexToHash("0xaa6dc7cc432c8d46a9373e1e96d829a1e24e52fe0468012ff062793ea8f5b55e"), + StateRoot: chunk4.Blocks[len(chunk4.Blocks)-1].Header.Root, + WithdrawRoot: chunk4.Blocks[len(chunk4.Blocks)-1].WithdrawRoot, + } + + endBlock1, finalizedBatchMeta1, err := validateBatch(0, event, &rawdb.FinalizedBatchMeta{}, []*encoding.Chunk{chunk1}, chainConfig, nil) + assert.NoError(t, err) + assert.Equal(t, uint64(2), endBlock1) + + endBlock2, finalizedBatchMeta2, err := validateBatch(1, event, finalizedBatchMeta1, []*encoding.Chunk{chunk2}, chainConfig, nil) + assert.NoError(t, err) + assert.Equal(t, uint64(3), endBlock2) + + endBlock3, finalizedBatchMeta3, err := validateBatch(2, event, finalizedBatchMeta2, []*encoding.Chunk{chunk3}, chainConfig, nil) + assert.NoError(t, err) + assert.Equal(t, uint64(13), endBlock3) + + endBlock4, finalizedBatchMeta4, err := validateBatch(3, event, finalizedBatchMeta3, []*encoding.Chunk{chunk4}, chainConfig, nil) + assert.NoError(t, err) + assert.Equal(t, uint64(17), endBlock4) + + parentBatchMeta5 := &rawdb.FinalizedBatchMeta{ + BatchHash: event.BatchHash, + TotalL1MessagePopped: 42, + StateRoot: event.StateRoot, + WithdrawRoot: event.WithdrawRoot, + } + assert.Equal(t, parentBatchMeta5, finalizedBatchMeta4) +} + func readBlockFromJSON(t *testing.T, filename string) *encoding.Block { data, err := os.ReadFile(filename) assert.NoError(t, err) From 6cb8a764fe89d824dd79e9120a47829468b57be0 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 17 Jul 2024 13:42:12 +0800 Subject: [PATCH 08/11] update da-codec dependency --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c37ecdda836a..61a8a699b2f5 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/scroll-tech/da-codec v0.1.1-0.20240703091800-5b6cded48ab7 + github.com/scroll-tech/da-codec v0.1.1-0.20240716101216-c55ed9455cf4 github.com/scroll-tech/zktrie v0.8.4 github.com/shirou/gopsutil v3.21.11+incompatible github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 diff --git a/go.sum b/go.sum index 00258e3e5bbc..7f62294b4a77 100644 --- a/go.sum +++ b/go.sum @@ -392,8 +392,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/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scroll-tech/da-codec v0.1.1-0.20240703091800-5b6cded48ab7 h1:UfiLBLCAMBk9bsTP3fc1fETpNVFSQapQVdLcZveyV0M= -github.com/scroll-tech/da-codec v0.1.1-0.20240703091800-5b6cded48ab7/go.mod h1:D6XEESeNVJkQJlv3eK+FyR+ufPkgVQbJzERylQi53Bs= +github.com/scroll-tech/da-codec v0.1.1-0.20240716101216-c55ed9455cf4 h1:40Lby3huKNFZ2EXzxqVpADB+caepDRrNRoUgTsCKN88= +github.com/scroll-tech/da-codec v0.1.1-0.20240716101216-c55ed9455cf4/go.mod h1:D6XEESeNVJkQJlv3eK+FyR+ufPkgVQbJzERylQi53Bs= 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/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= From 7e263b4cecfdc8c854c88648dc54108a3c69638f Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 17 Jul 2024 15:56:57 +0800 Subject: [PATCH 09/11] move rawdb.WriteFinalizedBatchMeta outside the loop --- rollup/rollup_sync_service/rollup_sync_service.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index dbe12edaa5a4..1e8f78894c64 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -242,6 +242,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB } var highestFinalizedBlockNumber uint64 + var finalizedBatchMetas []*rawdb.FinalizedBatchMeta for index := startBatchIndex; index <= batchIndex; index++ { parentBatchMeta, chunks, err := s.getLocalInfoForBatch(index) if err != nil { @@ -253,15 +254,17 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err) } - rawdb.WriteFinalizedBatchMeta(s.db, index, finalizedBatchMeta) + finalizedBatchMetas = append(finalizedBatchMetas, finalizedBatchMeta) + highestFinalizedBlockNumber = endBlock if index%100 == 0 { log.Info("finalized batch progress", "batch index", index, "finalized l2 block height", endBlock) } - - highestFinalizedBlockNumber = endBlock } + for index, finalizedBatchMeta := range finalizedBatchMetas { + rawdb.WriteFinalizedBatchMeta(s.db, startBatchIndex+uint64(index), finalizedBatchMeta) + } rawdb.WriteFinalizedL2BlockNumber(s.db, highestFinalizedBlockNumber) rawdb.WriteLastFinalizedBatchIndex(s.db, batchIndex) log.Debug("write finalized l2 block number", "batch index", batchIndex, "finalized l2 block height", highestFinalizedBlockNumber) From f30cc338adc68ae154e1ae5b20c68ab97ed8ad03 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 17 Jul 2024 16:18:46 +0800 Subject: [PATCH 10/11] use batch writer --- rollup/rollup_sync_service/rollup_sync_service.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index 1e8f78894c64..91b22fd90e1c 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -242,7 +242,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB } var highestFinalizedBlockNumber uint64 - var finalizedBatchMetas []*rawdb.FinalizedBatchMeta + batchWriter := s.db.NewBatch() for index := startBatchIndex; index <= batchIndex; index++ { parentBatchMeta, chunks, err := s.getLocalInfoForBatch(index) if err != nil { @@ -254,7 +254,7 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB return fmt.Errorf("fatal: validateBatch failed: finalize event: %v, err: %w", event, err) } - finalizedBatchMetas = append(finalizedBatchMetas, finalizedBatchMeta) + rawdb.WriteFinalizedBatchMeta(batchWriter, index, finalizedBatchMeta) highestFinalizedBlockNumber = endBlock if index%100 == 0 { @@ -262,8 +262,8 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB } } - for index, finalizedBatchMeta := range finalizedBatchMetas { - rawdb.WriteFinalizedBatchMeta(s.db, startBatchIndex+uint64(index), finalizedBatchMeta) + if err := batchWriter.Write(); err != nil { + log.Crit("Failed to write finalized batch meta to database", "err", err) } rawdb.WriteFinalizedL2BlockNumber(s.db, highestFinalizedBlockNumber) rawdb.WriteLastFinalizedBatchIndex(s.db, batchIndex) From 18cc8d7a74fa97375e20bd8a214c0c19fd97bc61 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 17 Jul 2024 17:55:00 +0800 Subject: [PATCH 11/11] change log.Crit to log.Error --- rollup/rollup_sync_service/rollup_sync_service.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rollup/rollup_sync_service/rollup_sync_service.go b/rollup/rollup_sync_service/rollup_sync_service.go index 91b22fd90e1c..5e69190a0d1f 100644 --- a/rollup/rollup_sync_service/rollup_sync_service.go +++ b/rollup/rollup_sync_service/rollup_sync_service.go @@ -263,7 +263,9 @@ func (s *RollupSyncService) parseAndUpdateRollupEventLogs(logs []types.Log, endB } if err := batchWriter.Write(); err != nil { - log.Crit("Failed to write finalized batch meta to database", "err", err) + log.Error("fatal: failed to batch write finalized batch meta to database", "startBatchIndex", startBatchIndex, "endBatchIndex", batchIndex, + "batchCount", batchIndex-startBatchIndex+1, "highestFinalizedBlockNumber", highestFinalizedBlockNumber, "err", err) + return fmt.Errorf("failed to batch write finalized batch meta to database: %w", err) } rawdb.WriteFinalizedL2BlockNumber(s.db, highestFinalizedBlockNumber) rawdb.WriteLastFinalizedBatchIndex(s.db, batchIndex)