Skip to content

feat(L1 follower): adjust to recent CodecV7 and contract changes #1120

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 85 commits into from
Mar 3, 2025

Conversation

jonastheis
Copy link

@jonastheis jonastheis commented Feb 21, 2025

1. Purpose or design rationale of this PR

This PR is a collection of changes to adjust to recent changes in CodecV7 and contracts.

  • renaming of initialL1MessageQueueHash -> prevL1MessageQueueHash and lastL1MessageQueueHash -> postL1MessageQueueHash
  • removing InitialMessageQueueIndex from blob payload: in normal operation of the L1 follower mode we assume a sync from genesis. Therefore, we can carry over the parent's total popped L1 messages recursively.
  • add new RevertEvent(startBatchIndex,endBatchIndex) to revert a range of batches
  • add recovery mode without InitialMessageQueueIndex: implement L1MessageQueueHeightFinder to determine the L1 message queue height for a given target batch from its finalized bundle
  • update ScrollChain ABI
  • add support for new commitBatches function in l1.Reader to be able to read calldata from new commit functions

2. PR title

Your PR title must follow conventional commits (as we are doing squash merge for each PR), so it must start with one of the following types:

  • feat: A new feature

3. Deployment tag versioning

Has the version in params/version.go been updated?

  • Yes

4. Breaking change label

Does this PR have the breaking-change label?

  • This PR is not a breaking change

Summary by CodeRabbit

  • New Features

    • Enhanced batch processing with improved metadata tracking and reversion event handling.
    • Upgraded contract interface with new event types for more robust batch finalization and rollback.
    • Introduced a new L1MessageQueueHeightFinder for calculating L1 message queue height.
  • Improvements

    • Streamlined state recovery and message queue tracking for increased reliability.
    • Revised error handling throughout the syncing pipeline for smoother operation.
    • Simplified handling of queue indices through direct byte manipulation.
  • Chores

    • Updated dependency versions and incremented the patch release.
    • Refined the Docker build process for more efficient dependency management.
    • Added a new entry to .dockerignore to exclude the tmp/ directory.
  • Tests

    • Adjusted test cases to validate the new event signatures and batch handling logic.

jonastheis and others added 30 commits December 10, 2024 11:24
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
rollup/da_syncer/syncing_pipeline.go (1)

283-302: Enhanced reset functionality with metadata persistence

The reset method has been properly updated to work with the new metadata structure. It reads the current state from the database, adjusts the L1 block number based on the reset counter, and persists the changes back to the database.

Consider extracting the magic number 100 in amount := 100 * uint64(resetCounter) to a named constant for better readability and maintainability.

+const resetBlockNumberStep = 100
 func (s *SyncingPipeline) reset(resetCounter int) {
-	amount := 100 * uint64(resetCounter)
+	amount := resetBlockNumberStep * uint64(resetCounter)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 973bd91 and 22215e8.

📒 Files selected for processing (2)
  • rollup/da_syncer/da/calldata_blob_source.go (3 hunks)
  • rollup/da_syncer/syncing_pipeline.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • rollup/da_syncer/da/calldata_blob_source.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (4)
rollup/da_syncer/syncing_pipeline.go (4)

82-82: Improved state tracking with more comprehensive metadata

The change from a simple initialL1Block to a more structured lastProcessedBatchMeta provides better context and tracking of the syncing state, including batch index, L1 block number, and total L1 messages popped.


91-105: Well-structured recovery mode with L1MessageQueueHeightFinder

The implementation correctly handles the recovery mode by using the L1MessageQueueHeightFinder to determine the L1 message queue height before the initial batch. This aligns with the PR objective of operating without InitialMessageQueueIndex by recursively carrying over the parent's total popped L1 messages.


109-122: Robust initialization in non-recovery mode

The code properly handles the initialization in non-recovery mode by reading the existing metadata from the database or creating a default entry with appropriate values. The approach ensures continuity of operation and persistence of state across restarts.


125-126: Updated queue initialization with metadata

The DAQueue and BatchQueue are now correctly initialized with the fields from lastProcessedBatchMeta, providing them with the necessary context about the batch processing state.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (6)
rollup/da_syncer/batch_queue.go (6)

10-10: Consider documenting import usage
The newly added imports for log and l1 are clear in context. However, adding a brief comment or docstring where these are used may help future maintainers locate their usage more quickly, especially given the multiple logging approaches and event definitions in the codebase.

Also applies to: 12-12


38-39: Clarify the return of da.EntryWithBlocks
The method signature of NextBatch now returns da.EntryWithBlocks instead of da.Entry. Consider updating the method doc comment (line 37) to reflect the new return type and its implications.


66-67: Add final batch check logs
After processing a FinalizeBatchType, you check for a newly finalized batch. Logging a short message here could help operators see that finalization triggered an immediate return of a new batch.


75-76: Loop over potentially multiple finalized batches
nextFinalizedBatch currently returns on the first batch in the heap if it meets the finalized index condition. If multiple batches in the heap fall under that condition, you may need a loop to process them all. Confirm whether partial processing is intended.

Also applies to: 82-83, 85-85


96-120: Enhance logging in handleRevertEvent
The revert event logic is sound. However, adding a log statement for each revert action would help diagnose unexpected revert ranges or repeated reverts. You may also want to confirm that StartBatchIndex <= FinishBatchIndex before looping to avoid potential no-op or invalid range errors.


134-167: Clarify batch metadata write order
In processAndDeleteBatch, the code writes the old previousBatch to disk before assigning the new batch to previousBatch. This design might be intentional, but it can be confusing since the new batch is the one being processed. Documenting why the old metadata is persisted just before overwriting would help avoid confusion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22215e8 and 5935e62.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • go.mod (1 hunks)
  • rollup/da_syncer/batch_queue.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • go.mod
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (4)
rollup/da_syncer/batch_queue.go (4)

22-24: Validate or document previousBatch initialization
Declaring previousBatch in the struct is a good approach for maintaining state. However, ensure that callers never pass nil for lastProcessedBatch in NewBatchQueue, or handle that case gracefully. Otherwise, accessing BatchIndex on a nil struct could cause a runtime panic.


58-60: Approach revert events with caution
When a revert event is encountered, the logic delegates handling to handleRevertEvent. Make sure there's no concurrency gap that could cause new finalizations or commits to slip in during revert processing. If concurrency is possible, consider adding synchronization or queue pausing around this call.


122-132: Check references when deleting the current batch
The deleteBatch method cleanly removes a batch from both batches and batchesMap. However, consider verifying that if the current peek or last accessed batch is removed, no stale references remain.


170-175: Confirm expected workflow after Reset
The Reset method resets the queue and updates previousBatch to the provided metadata. If there's any need to re-queue items based on the new state, ensure that's handled elsewhere. Documenting the Reset workflow can prevent misunderstandings about system state post-reset.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
rollup/da_syncer/l1_message_queue_height_finder.go (1)

70-105: Consider adding a timeout or maximum iteration limit to prevent potential infinite loops.

The findFinalizedBundle method iteratively processes data entries until it finds the bundle containing the target batch. While the implementation is correct, there is no timeout or limit on the number of iterations, which could potentially lead to an infinite loop if the target batch is never found (e.g., due to data corruption or if the target batch was reverted).

Consider adding a timeout or maximum iteration limit:

func (f *L1MessageQueueHeightFinder) findFinalizedBundle(targetBatch uint64, batches map[uint64]da.EntryWithBlocks) (*da.FinalizeBatch, error) {
+   maxIterations := 10000 // Adjust as needed
+   iterCount := 0
    for {
+       if iterCount >= maxIterations {
+           return nil, fmt.Errorf("exceeded maximum iterations (%d) while searching for batch %d", maxIterations, targetBatch)
+       }
+       iterCount++
        
        // Rest of the method remains unchanged
        
    }
}

Alternatively, you could use a context with timeout:

func (f *L1MessageQueueHeightFinder) findFinalizedBundle(targetBatch uint64, batches map[uint64]da.EntryWithBlocks) (*da.FinalizeBatch, error) {
+   ctx, cancel := context.WithTimeout(f.ctx, 5*time.Minute) // Adjust timeout as needed
+   defer cancel()
    for {
+       select {
+       case <-ctx.Done():
+           return nil, fmt.Errorf("timeout while searching for batch %d: %w", targetBatch, ctx.Err())
+       default:
+       }
        
        // Rest of the method remains unchanged
        
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5935e62 and bd6f89e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (4)
  • core/rawdb/accessors_l1_message.go (2 hunks)
  • params/version.go (1 hunks)
  • rollup/da_syncer/l1_message_queue_height_finder.go (1 hunks)
  • rollup/da_syncer/syncing_pipeline.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • params/version.go
🔇 Additional comments (9)
core/rawdb/accessors_l1_message.go (2)

386-389: Improved efficiency by using direct binary encoding

Good optimization by switching from big.Int conversion to direct binary encoding for storing uint64 values. This approach:

  1. Reduces memory allocations
  2. Ensures consistent 8-byte representation
  3. Makes the code more straightforward

406-409: Improved uint64 retrieval with direct binary decoding

Good simplification of the data validation and conversion process. The new approach:

  1. Simply checks for the expected 8-byte length
  2. Uses direct binary decoding instead of big.Int conversion
  3. Maintains backward compatibility by returning nil for invalid lengths
rollup/da_syncer/syncing_pipeline.go (4)

82-107: Well-structured recovery mode implementation with good error handling.

The implementation has been updated to use a comprehensive DAProcessedBatchMeta structure instead of simple block numbers, which provides better tracking of the syncing state. The code properly validates inputs (checking for zero values in lines 84-89) and uses the new L1MessageQueueHeightFinder to determine the L1 message queue height before the initial batch.

The error handling is thorough, with descriptive error messages that will help with debugging if issues arise.


109-122: Good implementation of non-recovery mode initialization.

The code appropriately reads the last processed batch metadata from the database or initializes it with default values if not found. The initialization logic for the L1 block number is sensible, using the deployment block minus one when available.

The persistence handling with rawdb.WriteDAProcessedBatchMeta ensures data consistency between runs.


125-127: Clean initialization of queue components with metadata.

The initialization of daQueue and batchQueue now properly uses the comprehensive lastProcessedBatchMeta instead of individual parameters, which maintains consistency in the syncing state.


283-302: Reset logic properly handles state regression.

The reset method now correctly reads the batch metadata from the database, updates the L1 block number based on the reset counter, and persists the changes. The incremental backing up strategy (using 100 * uint64(resetCounter)) provides a good balance between responsiveness and recovery capacity.

One thing to consider: if InitialL1Block is less than amount, the subtraction on line 290 could underflow. However, this should be rare in practice since the initial L1 block is typically large and reset counts are small.

rollup/da_syncer/l1_message_queue_height_finder.go (3)

13-30: Well-structured implementation of L1MessageQueueHeightFinder.

The struct and its constructor are well-designed with appropriate error handling. The constructor properly initializes the calldata blob source and returns meaningful errors if initialization fails.


32-68: Solid implementation of L1 message height calculation logic.

The TotalL1MessagesPoppedBefore method implements a clear algorithm for finding the L1 message queue height before a target batch. The code:

  1. Finds the finalized bundle containing the target batch
  2. Fetches transaction data to get the message queue height after the bundle
  3. Calculates backwards to determine the height before the target batch

Error handling is thorough, with checks for missing batches and potential underflows.


107-131: Good implementation of revert event handling with support for batch ranges.

The handleRevertEvent method properly handles different types of revert events, including the new V7 type that supports reverting a range of batches. The error handling is thorough with descriptive error messages.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
Dockerfile.mockccc (2)

14-15: Recommendation: Use COPY Instead of ADD
Static analysis (Hadolint DL3020) suggests using COPY in place of ADD when merely copying files or directories. Since there is no need for archive extraction or remote URL retrieval in this context, replacing ADD . ./ with COPY . ./ would improve clarity and adhere to best practices. Consider applying the following diff:

-ADD . ./
+COPY . ./
🧰 Tools
🪛 Hadolint (2.12.0)

[error] 14-14: Use COPY instead of ADD for files and folders

(DL3020)


20-21: Clarify Commented Package Installation Command
The previously active apt-get command is now fully commented out. If this command is no longer needed, consider removing it altogether to clean up the Dockerfile. Otherwise, add a clarifying comment explaining why it remains commented (e.g., documentation on dependency requirements for future reference).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd6f89e and 6c2b57c.

📒 Files selected for processing (2)
  • .dockerignore (1 hunks)
  • Dockerfile.mockccc (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .dockerignore
🧰 Additional context used
🪛 Hadolint (2.12.0)
Dockerfile.mockccc

[error] 14-14: Use COPY instead of ADD for files and folders

(DL3020)

🔇 Additional comments (1)
Dockerfile.mockccc (1)

10-12: Approval of Dependency Caching Setup
The modifications setting the working directory (WORKDIR /go-ethereum) and copying the go.mod and go.sum files followed by running go mod download -x are well implemented. This change improves dependency caching and build efficiency.

colinlyguo
colinlyguo previously approved these changes Mar 3, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
rollup/da_syncer/batch_queue.go (1)

26-35: ⚠️ Potential issue

Check for potential nil pointer dereference.
lastProcessedBatch.BatchIndex is accessed without a defensive check. If lastProcessedBatch can be nil, a panic could occur.

 func NewBatchQueue(DAQueue *DAQueue, db ethdb.Database, lastProcessedBatch *rawdb.DAProcessedBatchMeta) *BatchQueue {
+   if lastProcessedBatch == nil {
+       log.Crit("lastProcessedBatch cannot be nil in NewBatchQueue")
+   }
    return &BatchQueue{
        ...
    }
 }
🧹 Nitpick comments (4)
rollup/da_syncer/batch_queue.go (2)

22-23: Consider documenting the purpose of previousBatch.
A brief comment on how previousBatch is used (e.g., storing the last processed batch metadata) would improve clarity.


96-123: Consider efficiency for large revert ranges.
Looping from StartBatchIndex to FinishBatchIndex might be slow if the range is large. If performance becomes critical, consider more efficient ways to handle extensive batch reverts.

rollup/da_syncer/l1_message_queue_height_finder.go (2)

13-17: Add struct-level comments for clarity.
A short description of how L1MessageQueueHeightFinder determines the queue height would be helpful.


112-136: Potential duplication of revert handling logic.
This revert event loop mirrors handleRevertEvent logic in batch_queue.go. Consider refactoring into a shared helper if feasible to avoid maintenance overhead.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3418fc and cef1118.

📒 Files selected for processing (3)
  • rollup/da_syncer/batch_queue.go (5 hunks)
  • rollup/da_syncer/l1_message_queue_height_finder.go (1 hunks)
  • rollup/l1/abi.go (5 hunks)
🔇 Additional comments (24)
rollup/l1/abi.go (14)

27-27: Updated ScrollChain ABI with new functionalities

The ABI definition has been significantly updated with new functions, events, and error types, which is consistent with the PR objective to adjust to recent CodecV7 and contract changes.


38-41: Improved RevertEvent type handling

Good refactoring of the RevertEvent types to support both legacy (V0-V6) and new V7 (EuclidV2) format. This change allows the system to properly handle batch reversions in both formats, with V7 introducing the ability to revert a range of batches.


47-49: Added new method names for V7 compatibility

The addition of commitBatchesV7MethodName and finalizeBundlePostEuclidV2MethodName properly supports the new contract functions introduced in the ScrollChain update.


110-113: LGTM: Renamed RevertBatch event unpacked struct

The RevertBatchEventV0Unpacked struct properly maintains the original structure for backward compatibility with V0-V6 events.


115-122: Clear type differentiation for RevertBatch events

Good approach to explicitly differentiate the V0 and V7 versions of the RevertBatch event by renaming the original to RevertBatchEventV0 and clearly documenting its applicable version range.


136-138: Correct implementation of event type identification

The Type() method correctly returns the newly defined RevertEventV0Type constant, ensuring proper event type identification.


148-151: Added support for batch range reversion

The RevertBatchEventV7Unpacked struct correctly implements the new event structure that allows reverting a range of batches through start and finish indices.


153-162: Well-structured implementation of V7 revert event

The RevertBatchEventV7 struct implementation is well-documented and properly handles the new event format that supports reverting a range of batches, which is a key feature introduced in V7 (EuclidV2).


190-198: LGTM: Clear accessor methods for batch range

The StartBatchIndex() and FinishBatchIndex() accessors provide a clear API for retrieving the range boundaries of the reverted batches, which is essential for properly handling the new V7 revert events.


295-299: Added new batch hash fields to support V7

The CommitBatchArgs struct has been updated with ParentBatchHash and LastBatchHash fields to support the new relationships between batches in CodecV7, aligning with the PR objectives.


321-333: Well-implemented argument parsing for CommitBatchesV7

The newCommitBatchArgsFromCommitBatchesV7 function correctly handles the new argument structure for V7 batch commits, extracting the necessary hash references (ParentBatchHash and LastBatchHash) needed for the updated contract interface.


343-347: LGTM: Clean V7 commit arguments structure

The commitBatchesV7Args struct cleanly defines the parameters needed for the new commitBatches method, focusing on the batch hashes instead of the more verbose structures used in earlier versions.


349-355: Comprehensive finalization arguments structure

The FinalizeBatchArgs struct properly captures all the parameters needed for batch finalization, including the important TotalL1MessagesPoppedOverall field that replaces the deprecated InitialMessageQueueIndex mentioned in the PR objectives.


357-364: LGTM: Helper function for finalization arguments

The newFinalizeBatchArgs function provides a clean interface for parsing finalization arguments from ABI-encoded values, maintaining consistent error handling with the other argument parsing functions.

rollup/da_syncer/batch_queue.go (7)

58-60: Good error handling for revert events.
It’s good to see the revert handling logic returning the error immediately for proper upstream handling.


66-66: Finalized batch retrieval logic seems sound.
This early return pattern is consistent with the pipeline-based approach.


75-89: Incremental finalization logic approved.
Returning only one finalized batch at a time is a common and straightforward design for pipelines.


125-135: Deletion mechanism looks clean.
This is a straightforward way to remove entries from both the heap and map, returning whether a deletion occurred.


137-171: Verify the logic for persisting the “previousBatch” vs. the newly processed batch.
The code writes bq.previousBatch to the database but then reassigns bq.previousBatch to the freshly processed batch. Double-check that this correctly persists the state you intend, especially if the final step fails.


173-179: Reset method implementation is straightforward.
Clearing queued batches and resetting counters aligns with re-initialization requirements.


38-39:

✅ Verification successful

Verify all callers of NextBatch use the new return type.
NextBatch now returns da.EntryWithBlocks instead of da.Entry. Ensure all consumers handle this updated type.


🏁 Script executed:

#!/bin/bash
# Search references to NextBatch across the repository to confirm updated usage
rg -A 3 'NextBatch\s*\('

Length of output: 531


All callers are correctly updated to handle the new return type from NextBatch.
Verified that the method now returns da.EntryWithBlocks and its usage in rollup/da_syncer/block_queue.go is correctly adjusted (assigning the result to entryWithBlocks, followed by appropriate error handling).
rollup/da_syncer/batch_queue.go – Method signature updated to (da.EntryWithBlocks, error).
rollup/da_syncer/block_queue.go – Caller now correctly assigns to entryWithBlocks and handles errors.

rollup/da_syncer/l1_message_queue_height_finder.go (3)

19-30: Initialization and error handling look good.
This constructor’s approach of returning an error upon calldata source creation failure is good defensive coding.


55-58: Double-check subtracting 1 from args.TotalL1MessagesPoppedOverall.
Confirm this aligns with the intended semantics: if the value is zero, we skip, if it’s > 0, we decrement by 1.


75-110: Consider adding timeout or break conditions.
The loop continues fetching data until a finalize event for targetBatch is found. If it never arrives, this may block indefinitely.

@Thegaram Thegaram merged commit 40ebbd6 into develop Mar 3, 2025
1 check passed
@Thegaram Thegaram deleted the jt/adjust-to-codecv7-changes branch March 3, 2025 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants