Skip to content
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

Move block context to blob #649

Merged
merged 39 commits into from
Feb 14, 2025
Merged

Move block context to blob #649

merged 39 commits into from
Feb 14, 2025

Conversation

chengwenxi
Copy link
Collaborator

@chengwenxi chengwenxi commented Nov 26, 2024

Summary by CodeRabbit

  • New Features

    • Introduced enhanced batch processing with support for a new version format and integrated Layer 2 provider into batch synchronization for improved network responsiveness.
  • Refactor

    • Standardized smart contract compiler versions and streamlined batch data structures and commit operations for increased consistency and reliability.
  • Chores

    • Upgraded key dependencies and modules, updated deployment configuration keys, and refreshed Docker base images to improve build and deployment stability.
  • Tests

    • Adjusted test routines and metrics to align with the refined batch and contract processing logic.

@chengwenxi chengwenxi marked this pull request as ready for review January 20, 2025 04:34
@chengwenxi chengwenxi requested a review from a team as a code owner January 20, 2025 04:34
@chengwenxi chengwenxi requested review from yunxu1 and removed request for a team January 20, 2025 04:34
@ET-xu ET-xu removed the request for review from yunxu1 February 12, 2025 12:19
Copy link

coderabbitai bot commented Feb 13, 2025

Walkthrough

This pull request standardizes dependencies and updates submodules to reference newer commits. It revises multiple smart contract files by fixing Solidity version pragmas to =0.8.24, and alters the batch processing logic in both contracts and node/executor components to use new parameters (lastBlockNumber and numL1Messages) instead of the deprecated blockContexts. In addition, the changes improve batch header encoding via new codec libraries, adjust deployment configuration and Docker base images, and modify prover and tx-submitter modules by refining error handling, metric registration, and utility functions.

Changes

File(s) Change Summary
.gitmodules, Makefile, .../go.mod (bindings, contracts, node, oracle, tx-submitter, ops/tools) Updated dependency versions and submodule branch; newer commits for go-ethereum and tendermint are referenced.
contracts/contracts/**/*.sol, bindings/bin/*, bindings/bindings/*.go Updated Solidity pragmas to =0.8.24; modified commitBatch in Rollup and updated ABI/bytecode for l2staking and rollup contracts.
contracts/libraries/codec/*, contracts/test/*, node/core/batch*.go, node/derivation/*, node/types/batch*.go, tx-submitter/services/rollup.go Introduced BatchHeaderCodecV1, refactored batch commitment, sealing, and header parsing logic; replaced blockContexts with lastBlockNumber/numL1Messages.
prover/bin/challenge/*, prover/bin/shadow-prove/*, prover/crates/*, prover/bin/server/src/queue.rs, prover/bin/host/src/lib.rs Modified error handling and BatchInfo structures, updated metric registrations, and adjusted BlobVerifier calls with additional parameters.
contracts/src/deploy-config/*, ops/docker/*, ops/l2-genesis/* Updated program verification keys; Dockerfiles now use ghcr.io/morph-l2/go-ubuntu-builder:go-1.22-ubuntu, and deployment scripts add --no-recreate in docker-compose commands.
tx-submitter/utils/utils.go Simplified batch index parsing by replacing intermediate decoding with direct retrieval via BatchHeaderBytes().BatchIndex().

Sequence Diagram(s)

sequenceDiagram
    participant Executor
    participant BatchCache
    participant L2Client
    participant RollupContract
    Executor->>BatchCache: Retrieve current block bytes & txs
    BatchCache-->>Executor: Return batch data (including lastBlockNumber, numL1Messages)
    Executor->>L2Client: Call commitBatch(lastBlockNumber, numL1Messages, signatures)
    L2Client-->>Executor: Batch commit confirmation
    Executor->>RollupContract: Update state & metrics
Loading

Poem

I’m a rabbit with a code-hopping beat,
Skipping through changes so crisp and neat.
New batch headers and smart contracts shine,
Like fresh carrots in a digital line.
With updated keys and Docker’s bright hue,
I celebrate each change—hip, hop, woo!
Code leaps ahead as I gently chew!

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

level=warning msg="[runner] Can't run linter goanalysis_metalinter: buildir: failed to load package zstd: could not load export data: no export data for "morph-l2/node/zstd""
level=error msg="Running error: can't run linter goanalysis_metalinter\nbuildir: failed to load package zstd: could not load export data: no export data for "morph-l2/node/zstd""

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 13

🔭 Outside diff range comments (4)
contracts/contracts/mock/TestUpgrade.sol (1)

51-53: ⚠️ Potential issue

Fix incorrect variable update.

The function setOtherVersion updates version instead of otherVersion.

Apply this diff to fix the bug:

 function setOtherVersion(uint256 _version) public {
-    version = _version;
+    otherVersion = _version;
 }
prover/crates/core/src/batch.rs (1)

81-82: ⚠️ Potential issue

Critical: Unwrapping Optional values could cause panic.

The unwrap() calls on withdraw_root and sequencer_root will panic if these values are None. Consider:

  1. Using expect() with descriptive messages
  2. Handling the None case gracefully
  3. Adding documentation to clarify that these fields must be set before calling this method

Apply this diff to improve error handling:

-hasher.update(self.withdraw_root.unwrap().as_slice());
-hasher.update(self.sequencer_root.unwrap().as_slice());
+hasher.update(self.withdraw_root.expect("withdraw_root must be set before computing hash").as_slice());
+hasher.update(self.sequencer_root.expect("sequencer_root must be set before computing hash").as_slice());
tx-submitter/services/rollup.go (1)

728-730: ⚠️ Potential issue

Critical: Update gas estimation to use new batch structure.

The gas estimation logic still uses the removed BlockContexts field, which will cause runtime errors. This needs to be updated to use the new batch structure.

Apply this diff to fix the gas estimation:

-            msgcnt := utils.ParseL1MessageCnt(batch.BlockContexts)
+            msgcnt := batch.NumL1Messages
             gas = r.RoughRollupGasEstimate(msgcnt)
             log.Info("rough estimate rollup tx gas", "gas", gas, "msgcnt", msgcnt)
bindings/bindings/l2staking.go (1)

60-75: 💡 Verification agent

❓ Verification inconclusive

Verify error handling in deployment function.

The DeployL2Staking function has good error handling but should verify the contract deployment transaction receipt.


🏁 Script executed:

#!/bin/bash
# Description: Check for deployment verification patterns in other contracts
ast-grep --pattern 'if tx := $_ err != nil {
  $$$
  receipt, err := bind.WaitMined($_, tx)
  $$$
}'

Length of output: 102


Action Required: Add transaction receipt verification in the DeployL2Staking function.

While the function handles ABI retrieval and deployment errors adequately, it does not verify that the deployment transaction has actually been mined. To ensure robust error handling, please add a verification step—such as calling bind.WaitMined on the deployment transaction—to confirm that the contract has been successfully deployed.

  • Location: bindings/bindings/l2staking.go, within the DeployL2Staking function.
  • Suggested Change: After a successful call to bind.DeployContract and prior to returning the contract instance, add a check like:
    receipt, err := bind.WaitMined(backend, tx)
    if err != nil {
        return common.Address{}, nil, nil, err
    }
    // Optionally: verify receipt.Status to confirm successful mining.

Implementing this step will help ensure the deployed contract has been confirmed on-chain.

🧹 Nitpick comments (33)
node/core/batch_commit.go (1)

70-85: Use a cancellable context
Replacing context.Background() in the call to CommitBatch with a passed-in or cancellable context can improve flexibility and allow graceful cancellations or timeouts.

- if err = e.l2Client.CommitBatch(context.Background(), &eth.RollupBatch{...
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ if err = e.l2Client.CommitBatch(ctx, &eth.RollupBatch{...
node/core/batch_seal.go (2)

28-33: Log fallback to old batch version
When the upgraded path is skipped due to oversized payload (line 78), the code falls back to the old version without logging this decision. For transparency, add a log statement indicating fallback to version 0.

+ e.logger.Info("Upgraded payload size too large, falling back to version 0.")

16-20: Finalize batch usage
Sealing a batch when the cache is empty understandably returns an error. Ensure external callers handle this condition gracefully to avoid silent failures in any scheduling or state machine logic.

node/types/batch_header.go (1)

31-49: Confirm length vs. version checks
The validate() method ensures batch headers match the expected length of each version. If future expansions require more dynamic handling of lengths, consider version-specific decoders for added flexibility.

gas-oracle/app/src/da_scalar/calculate.rs (1)

83-109: Caution with underflow and range checks.

  1. let block_count = last_block_num - first_block_num + 1; can overflow if last_block_num < first_block_num.
  2. origin_batch.len() < 60 * block_count as usize is properly checked, but consider explicit handling if block_count becomes unexpectedly large or zero.
  3. Logging and returning None upon mismatches is valid; ensure upstream callers handle None gracefully.
node/core/batch.go (2)

105-109: Error handling is solid, but consider more context.

When retrieving totalL1MessagePopped fails, an error is logged and returned. Providing additional context about the parent batch or block index might ease debugging.


158-159: Ignoring error from BatchIndex().

Using index, _ := e.batchingCache.parentBatchHeader.BatchIndex() suppresses potential errors. If this index can actually fail, consider handling or logging the error to avoid silent fallback to the zero value.

prover/bin/shadow-prove/src/shadow_rollup.rs (7)

23-23: New l2_provider field added to BatchSyncer
This extension to handle a Layer 2 provider makes sense to support full batch synchronization across L1 and L2. Ensure that all necessary error handling is present when making calls via this new provider.


80-81: Comment referencing BatchHeader V1 additions
You added a comment describing new fields such as lastBlockNumber. This is a good addition for clarity. Recommend referencing the actual struct or spec as needed for easier maintenance.


192-192: Shifting the batch_index extraction
Skipping to the second-to-last log might be fragile if certain logs are out of order or incomplete. Confirm the ordering assumption.


205-209: Refactored call to batch_blocks_inspect
Using match to check for None is good, but add logs or more context if you suspect frequent errors.

Would you like a script to scan for all None returns from this function for correlation or debugging?


215-215: Limit check on blocks
Rejecting large block ranges is sensible for performance reasons. However, consider logging how large the block range was to aid investigation.


225-236: Populating batch_info and retrieving next transaction hash
Bundling lines 225-236 streamlines the retrieval of batch_index, start_block, end_block, and the final TX hash. No immediate issues seen. Consider adding logs for debugging.


279-323: Refactor batch_blocks_inspect to also gather L2 transaction counts
This large chunk integrates L2 calls for block inspection.

  • Check if partial errors on any block might cause partial data.
  • If the provider is busy or times out, ensure you handle the error gracefully.
node/derivation/derivation.go (2)

100-102: Error handling when loading beforeMoveBlockCtxABI
The code returns an error immediately if the ABI load fails. This is correct, but consider more explicit user logs if the ABI file or resource is missing.


364-366: Handling legacy commit batch in newly extended UnPackData
Ensure the logic difference between legacyRollupABI commitBatch vs. beforeMoveBlockCtxABI or rollupABI is correct. Also confirm that older skipping logic (like skippedL1MessageBitmap) is still relevant if needed.

contracts/contracts/test/Rollup.t.sol (3)

109-117: Revised commit with batchDataInput
Lines 109-117 incorporate the enlarged BatchDataInput, referencing lastBlockNumber, numL1Messages, etc. Validate none of these fields remain uninitialized or cause future reverts.


181-189: Second batch references the updated batch header
Lines 181-189 show constructing the new batchDataInput. Check you always pass the correct “parent batch header” to maintain consistency.


330-330: batch header length too small revert (another check)
Repetitive checks might be consolidated if you desire simpler code, but it’s not a big issue.

oracle/oracle/batch.go (1)

13-13: Use explicit local alias or revert to standard naming convention.

Replacing the alias nodetypes with a simpler or more descriptive import alias (or none) can improve clarity, especially since the file already imports multiple packages.

contracts/contracts/l1/rollup/Rollup.sol (4)

255-255: Use of unchecked block.

Adding subsequent messages within an unchecked block is ok if all arithmetic is guaranteed safe. Confirm that any potential overflow from batchDataInput.numL1Messages is validated elsewhere.


262-266: Dynamic header length adjustment for version 1.

The _headerLength logic sets up flexible loading. Ensure that the system gracefully handles or logs unexpected lengths from external calls.


480-480: Restrict proveState call to active stakers.

This is an important security improvement. Ensure that legitimate non-staker roles (like watchers or challengers) are not unintentionally blocked from relevant calls.


741-742: Refactor _commitBatch signature for versioning.

  1. Clear parameter naming (_lastBlockNumber, _numL1Messages) is beneficial.
  2. If future versions add further data, consider an extensible approach or a separate function to avoid large param expansions.

Also applies to: 747-747

node/types/batch.go (2)

128-131: Potential high memory usage when building a combined payload

TxsPayloadV2 appends blockContexts and txsPayload into a single slice. Consider checking the length or possible memory constraints if large data sets are appended.


157-170: Ensure repeated compression calls won’t degrade performance

WillExceedCompressedSizeLimit repeatedly combines payloads and compresses them as new data arrives. This can become a performance bottleneck under heavy load. Consider caching or incremental compression strategies if needed.

prover/bin/shadow-prove/src/lib.rs (1)

12-13: Revisit the block range design

Replacing Vec<u64> with start_block and end_block is simpler, but ensure you don’t need the flexibility of multiple non-sequential blocks. If partial or disjoint ranges are anticipated, reconsider the original approach.

prover/crates/morph-executor/client/src/lib.rs (2)

14-26: Optimize memory allocation for block context.

The block context building could be more efficient:

  1. Pre-calculate exact capacity
  2. Use a single allocation
-    let mut block_ctx: Vec<u8> = Vec::with_capacity(60);
+    const BLOCK_CTX_SIZE: usize = 8 + 8 + 32 + 8 + 2 + 2; // 60 bytes
+    let mut block_ctx: Vec<u8> = vec![0u8; BLOCK_CTX_SIZE];

40-40: Add detailed error message for batch data mismatch.

The assertion should provide more context about the mismatch.

-    assert_eq!(batch_data, batch_from_trace, "blob data mismatch!");
+    assert_eq!(
+        batch_data,
+        batch_from_trace,
+        "Blob data mismatch! Expected length: {}, actual length: {}",
+        batch_data.len(),
+        batch_from_trace.len()
+    );
node/types/batch_test.go (1)

62-71: Consider adding more test cases for BatchHeaderV1.

While the basic functionality is tested, consider adding edge cases such as:

  • Maximum block number
  • Zero block number
  • Invalid version transitions
prover/crates/morph-executor/host/src/lib.rs (1)

58-68: Consider pre-allocating tx_bytes vector.

For better performance, consider pre-allocating the tx_bytes vector based on the number of transactions.

-let mut tx_bytes: Vec<u8> = vec![];
+let total_txs: usize = block_trace.iter().map(|trace| trace.transactions.len()).sum();
+let mut tx_bytes: Vec<u8> = Vec::with_capacity(total_txs * 256); // Assuming average tx size
prover/bin/host/src/lib.rs (1)

148-148: Consider parameterizing the hardcoded value.

The hardcoded value 1 passed to BlobVerifier::verify might be specific to test data. Consider:

  1. Making it a test parameter
  2. Adding a comment explaining its significance
  3. Using a named constant for better readability
-let (versioned_hash, batch_data) = BlobVerifier::verify(&blob_info, 1).unwrap();
+const TEST_NUM_BLOCKS: usize = 1;  // Number of blocks in test blob
+let (versioned_hash, batch_data) = BlobVerifier::verify(&blob_info, TEST_NUM_BLOCKS).unwrap();
tx-submitter/services/rollup.go (1)

1154-1169: Consider extracting fee calculation logic into a helper function.

The fee calculation logic is duplicated between blob and non-blob transactions. Consider extracting this into a helper function to improve maintainability and reduce duplication.

Consider refactoring like this:

+func calculateTxFee(tx *ethtypes.Transaction) uint64 {
+    if tx.Type() == ethtypes.BlobTxType {
+        // blob fee
+        fee := tx.BlobGasFeeCap().Uint64() * tx.BlobGas()
+        // tx fee
+        fee += tx.GasPrice().Uint64() * tx.Gas()
+        return fee
+    }
+    return tx.GasPrice().Uint64() * tx.Gas()
+}
+
 func sendTx(client iface.Client, txFeeLimit uint64, tx *ethtypes.Transaction) error {
     // fee limit
     if txFeeLimit > 0 {
-        var fee uint64
-        // calc tx gas fee
-        if tx.Type() == ethtypes.BlobTxType {
-            // blob fee
-            fee = tx.BlobGasFeeCap().Uint64() * tx.BlobGas()
-            // tx fee
-            fee += tx.GasPrice().Uint64() * tx.Gas()
-        } else {
-            fee = tx.GasPrice().Uint64() * tx.Gas()
-        }
+        fee := calculateTxFee(tx)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1f705d5 and 1615b8d.

⛔ Files ignored due to path filters (8)
  • bindings/go.sum is excluded by !**/*.sum
  • contracts/go.sum is excluded by !**/*.sum
  • node/go.sum is excluded by !**/*.sum
  • ops/l2-genesis/go.sum is excluded by !**/*.sum
  • ops/tools/go.sum is excluded by !**/*.sum
  • oracle/go.sum is excluded by !**/*.sum
  • prover/bin/shadow-prove/Cargo.lock is excluded by !**/*.lock
  • tx-submitter/go.sum is excluded by !**/*.sum
📒 Files selected for processing (96)
  • .gitmodules (1 hunks)
  • Makefile (1 hunks)
  • bindings/bin/l2staking_deployed.hex (1 hunks)
  • bindings/bin/rollup_deployed.hex (1 hunks)
  • bindings/bindings/l2staking.go (1 hunks)
  • bindings/bindings/l2staking_more.go (1 hunks)
  • bindings/bindings/rollup_more.go (1 hunks)
  • bindings/go.mod (1 hunks)
  • contracts/contracts/l1/rollup/IL1MessageQueue.sol (1 hunks)
  • contracts/contracts/l1/rollup/IL1MessageQueueWithGasPriceOracle.sol (1 hunks)
  • contracts/contracts/l1/rollup/IRollup.sol (1 hunks)
  • contracts/contracts/l1/rollup/Rollup.sol (6 hunks)
  • contracts/contracts/l2/staking/IDistribute.sol (1 hunks)
  • contracts/contracts/l2/system/IMorphToken.sol (1 hunks)
  • contracts/contracts/l2/system/MorphToken.sol (1 hunks)
  • contracts/contracts/l2/system/WrappedEther.sol (1 hunks)
  • contracts/contracts/libraries/ICrossDomainMessenger.sol (1 hunks)
  • contracts/contracts/libraries/callbacks/IERC677Receiver.sol (1 hunks)
  • contracts/contracts/libraries/callbacks/IGatewayCallback.sol (1 hunks)
  • contracts/contracts/libraries/callbacks/IMessageDropCallback.sol (1 hunks)
  • contracts/contracts/libraries/codec/BatchCodecV0.sol (0 hunks)
  • contracts/contracts/libraries/codec/BatchHeaderCodecV0.sol (1 hunks)
  • contracts/contracts/libraries/codec/BatchHeaderCodecV1.sol (1 hunks)
  • contracts/contracts/libraries/common/IWhitelist.sol (1 hunks)
  • contracts/contracts/libraries/token/IMorphERC1155Extension.sol (1 hunks)
  • contracts/contracts/libraries/token/IMorphERC20Extension.sol (1 hunks)
  • contracts/contracts/libraries/token/IMorphERC721Extension.sol (1 hunks)
  • contracts/contracts/libraries/verifier/IRollupVerifier.sol (1 hunks)
  • contracts/contracts/libraries/verifier/ISP1Verifier.sol (1 hunks)
  • contracts/contracts/libraries/verifier/IZkEvmVerifier.sol (1 hunks)
  • contracts/contracts/libraries/verifier/PlonkVerifier.sol (1 hunks)
  • contracts/contracts/libraries/verifier/RollupVerifier.sol (1 hunks)
  • contracts/contracts/libraries/verifier/SP1VerifierPlonk.sol (1 hunks)
  • contracts/contracts/mock/TestUpgrade.sol (1 hunks)
  • contracts/contracts/test/Rollup.t.sol (17 hunks)
  • contracts/contracts/test/ZkEvmVerifierV1.t.sol (1 hunks)
  • contracts/deploy/016-RollupInit.ts (1 hunks)
  • contracts/go.mod (1 hunks)
  • contracts/hardhat.config.ts (1 hunks)
  • contracts/src/deploy-config/holesky.ts (1 hunks)
  • contracts/src/deploy-config/l1.ts (1 hunks)
  • contracts/src/deploy-config/qanetl1.ts (1 hunks)
  • contracts/src/deploy-config/sepolia.ts (1 hunks)
  • contracts/src/deploy-config/testnetl1.ts (1 hunks)
  • gas-oracle/app/src/abi/Rollup.json (1 hunks)
  • gas-oracle/app/src/da_scalar/calculate.rs (2 hunks)
  • gas-oracle/app/src/da_scalar/l1_scalar.rs (7 hunks)
  • go-ethereum (1 hunks)
  • node/core/batch.go (13 hunks)
  • node/core/batch_commit.go (1 hunks)
  • node/core/batch_seal.go (1 hunks)
  • node/db/keys.go (2 hunks)
  • node/db/store.go (0 hunks)
  • node/derivation/batch_info.go (3 hunks)
  • node/derivation/derivation.go (6 hunks)
  • node/derivation/derivation_test.go (2 hunks)
  • node/go.mod (1 hunks)
  • node/types/batch.go (4 hunks)
  • node/types/batch_header.go (1 hunks)
  • node/types/batch_test.go (2 hunks)
  • node/types/blob.go (2 hunks)
  • node/types/consensus_message.go (2 hunks)
  • node/types/retryable_client.go (4 hunks)
  • ops/devnet-morph/devnet/__init__.py (1 hunks)
  • ops/docker/Dockerfile.l2-node (2 hunks)
  • ops/docker/Dockerfile.l2-node-1 (1 hunks)
  • ops/docker/Dockerfile.l2-node-4 (1 hunks)
  • ops/docker/Dockerfile.staking-oracle (1 hunks)
  • ops/docker/Dockerfile.submitter (2 hunks)
  • ops/l2-genesis/cmd/genesis/cmd.go (1 hunks)
  • ops/l2-genesis/go.mod (1 hunks)
  • ops/l2-genesis/morph-chain-ops/genesis/layer_two_test.go (1 hunks)
  • ops/tools/batchparse/main.go (1 hunks)
  • ops/tools/go.mod (1 hunks)
  • ops/tools/multisend/main.go (1 hunks)
  • oracle/go.mod (1 hunks)
  • oracle/oracle/batch.go (2 hunks)
  • prover/bin/challenge/src/abi/Rollup.json (1 hunks)
  • prover/bin/challenge/src/handler.rs (10 hunks)
  • prover/bin/challenge/src/main.rs (1 hunks)
  • prover/bin/challenge/src/metrics.rs (0 hunks)
  • prover/bin/host/src/lib.rs (1 hunks)
  • prover/bin/server/src/queue.rs (1 hunks)
  • prover/bin/shadow-prove/Cargo.toml (1 hunks)
  • prover/bin/shadow-prove/abi/Rollup.json (1 hunks)
  • prover/bin/shadow-prove/src/lib.rs (1 hunks)
  • prover/bin/shadow-prove/src/main.rs (4 hunks)
  • prover/bin/shadow-prove/src/shadow_prove.rs (4 hunks)
  • prover/bin/shadow-prove/src/shadow_rollup.rs (14 hunks)
  • prover/crates/core/src/batch.rs (1 hunks)
  • prover/crates/morph-executor/client/src/lib.rs (2 hunks)
  • prover/crates/morph-executor/client/src/verifier/blob_verifier.rs (1 hunks)
  • prover/crates/morph-executor/host/src/lib.rs (3 hunks)
  • tx-submitter/go.mod (1 hunks)
  • tx-submitter/services/rollup.go (1 hunks)
  • tx-submitter/utils/utils.go (2 hunks)
💤 Files with no reviewable changes (3)
  • node/db/store.go
  • prover/bin/challenge/src/metrics.rs
  • contracts/contracts/libraries/codec/BatchCodecV0.sol
✅ Files skipped from review due to trivial changes (31)
  • contracts/contracts/libraries/callbacks/IMessageDropCallback.sol
  • contracts/contracts/l2/staking/IDistribute.sol
  • .gitmodules
  • contracts/contracts/libraries/callbacks/IGatewayCallback.sol
  • contracts/contracts/l2/system/IMorphToken.sol
  • ops/docker/Dockerfile.l2-node-1
  • contracts/contracts/libraries/callbacks/IERC677Receiver.sol
  • contracts/contracts/libraries/codec/BatchHeaderCodecV0.sol
  • contracts/contracts/libraries/token/IMorphERC20Extension.sol
  • contracts/contracts/libraries/verifier/IRollupVerifier.sol
  • ops/docker/Dockerfile.l2-node
  • ops/l2-genesis/morph-chain-ops/genesis/layer_two_test.go
  • contracts/contracts/libraries/token/IMorphERC721Extension.sol
  • ops/docker/Dockerfile.staking-oracle
  • contracts/contracts/libraries/verifier/ISP1Verifier.sol
  • ops/docker/Dockerfile.submitter
  • contracts/contracts/libraries/verifier/PlonkVerifier.sol
  • ops/tools/multisend/main.go
  • contracts/contracts/libraries/common/IWhitelist.sol
  • ops/docker/Dockerfile.l2-node-4
  • contracts/contracts/l2/system/MorphToken.sol
  • go-ethereum
  • contracts/contracts/l1/rollup/IL1MessageQueueWithGasPriceOracle.sol
  • bindings/bindings/l2staking_more.go
  • ops/tools/batchparse/main.go
  • contracts/contracts/libraries/verifier/SP1VerifierPlonk.sol
  • contracts/contracts/libraries/verifier/IZkEvmVerifier.sol
  • ops/tools/go.mod
  • contracts/contracts/libraries/token/IMorphERC1155Extension.sol
  • contracts/contracts/libraries/verifier/RollupVerifier.sol
  • bindings/bindings/rollup_more.go
🧰 Additional context used
🪛 golangci-lint (1.62.2)
node/derivation/batch_info.go

17-17: could not import morph-l2/node/zstd (-: build constraints exclude all Go files in zstd)

(typecheck)

🔇 Additional comments (138)
contracts/src/deploy-config/testnetl1.ts (1)

16-16: Verify the new program verification key.

The program verification key has been updated consistently across all deployment configurations (testnet, qanet, mainnet, and holesky). Please verify:

  1. The origin and validity of the new key.
  2. Whether this change is related to the architectural change of moving block context to blob.

Could you provide documentation or context about why this verification key needed to be updated? This will help future maintainers understand the change.

contracts/src/deploy-config/qanetl1.ts (1)

19-19: LGTM! Key matches other environments.

The program verification key matches the value used in other deployment configurations.

contracts/src/deploy-config/l1.ts (1)

20-20: LGTM! Key matches other environments.

The program verification key matches the value used in other deployment configurations.

contracts/src/deploy-config/holesky.ts (1)

17-17: LGTM! Key matches other environments.

The program verification key matches the value used in other deployment configurations.

contracts/src/deploy-config/sepolia.ts (1)

21-21:

❓ Verification inconclusive

Verify the consistency and authenticity of the new program verification key.

The programVkey has been updated to a new value. Since this is a critical cryptographic key used in program verification, we should ensure:

  1. The new key is consistent across all deployment configurations
  2. The key was properly generated and is valid for its intended use

Run the following script to verify the consistency of the programVkey across all deployment configurations:

Could you also confirm:

  1. The source and generation process of this new verification key
  2. Whether this key has been properly tested in a non-production environment

🏁 Script executed:

#!/bin/bash
# Description: Check if programVkey is consistent across all deployment configurations

# Search for programVkey in all deployment config files
echo "Checking programVkey consistency across deployment configs..."
rg --type ts "programVkey.*0x0067523b285111b45b465b927d56449351e78d802252ccbf4bcf5eae588b7356" contracts/src/deploy-config/

Length of output: 885


Ensure consistency and proper key generation for the program verification key.

The updated hexadecimal key is now consistently used across all deployment configurations, which is confirmed by the script output. However, please confirm the following:

  • The source/generation process of the new verification key.
  • That the key has been successfully tested in a non-production environment.
prover/bin/challenge/src/main.rs (2)

51-51: LGTM! Comment updated to reflect block context.

The terminology change from "chunks len." to "blocks len." aligns with the PR objective of moving block context to blob.


48-57:

❓ Verification inconclusive

Verify the impact of removing txn_len metric.

The txn_len metric has been removed from registration. Please ensure that no monitoring systems or dashboards depend on this metric.


🏁 Script executed:

#!/bin/bash
# Description: Search for any remaining references to txn_len metric in the codebase

# Search for txn_len in Rust files
rg -t rust 'txn_len' 

# Search for txn_len in monitoring configurations
rg -g '*.{yaml,yml,json}' 'txn_len'

Length of output: 544


Action Required: Verify Monitoring Dependencies for Removed txn_len Metric

The txn_len metric has been removed from registration in prover/bin/challenge/src/main.rs as intended. Our search confirmed that there are no lingering references to txn_len in the main code or configuration files. However, note that the similar metric shadow_txn_len still exists in the prover/bin/shadow-prove module. Please ensure that any dashboards or monitoring systems previously relying on txn_len are either updated or confirmed not to be affected.

node/core/batch_commit.go (2)

16-22: Validate no pending batch scenario
The early return is clear and prevents unnecessary processing when no batch is sealed. This is good for performance.


97-113: Clarify concurrency assumptions
commitSealedBatch resets shared state in batchingCache. Ensure this method is called under proper locking or single-threaded usage to avoid race conditions in multi-threaded scenarios.

node/core/batch_seal.go (1)

46-52: Check sidecar usage
Caching the sealed header and sidecar is a good approach. Consider adding test coverage to confirm that sidecar is accurately retrieved and consumed downstream without stale or missing data.

node/types/batch_header.go (1)

139-148: Guard against misuse of LastBlockNumber
Accessing LastBlockNumber() in version 0 triggers an error, which is correct. Consider logging or handling this error upstream to avoid confusion, especially if version checks are overlooked in calling code.

node/derivation/batch_info.go (3)

60-62: Struct field additions look consistent.

New fields (root, withdrawalRoot, and parentTotalL1MessagePopped) in BatchInfo appear to align with the overall refactor. Ensure any downstream usage is updated and tested to avoid inconsistencies.


83-93: Good validation of parent batch header fields.

Fetching BatchIndex() and TotalL1MessagePopped() from parentBatchHeader ensures the correct state. The error handling is appropriate. Just confirm all references to these batch header fields across the codebase remain consistent with new logic (e.g., verifying no stale references to removed fields).


118-123: Potential off-by-one or length mismatch.

You decode a fixed 60-byte chunk to populate startBlock and compute blockCount = batch.LastBlockNumber - startBlock.Number + 1. Ensure there's no scenario where the batch’s data is truncated, or the block range is zero/negative. If an unexpected length arises, consider more explicit boundary checks or user-friendly error logs.

gas-oracle/app/src/da_scalar/calculate.rs (2)

19-20: Returning a vector of byte vectors allows for clearer batching logic.

Refactoring extract_tx_payload to Result<Vec<Vec<u8>>, ScalarError> clarifies that multiple payloads can be collected and processed individually. Ensure callers are updated to handle multiple batches instead of a single concatenated payload.


66-73: Verify each origin batch is needed.

Pushing the entire origin_batch into batch_bytes is valid when all provided blobs must be processed downstream. If some blobs can be optional or filtered out, confirm the logic here. Otherwise this is good for full-batch extraction.

node/core/batch.go (5)

20-20: Updated pointers to byte-based batch headers.

Changing parentBatchHeader and sealedBatchHeader to *types.BatchHeaderBytes aligns with the new approach. Ensure all call sites that expected the older BatchHeader struct are updated to decode or read bytes as needed.

Also applies to: 31-31


83-96: Graceful fallback to genesis batch header.

Handling an empty parentBatchHeaderBytes by generating a GenesisBatchHeader makes the initial batch determination clear. Just confirm that the genesis logic aligns with your chain’s actual first block state so no unexpected mismatches happen.


297-321: Migration to BatchHeaderV0.

Returning BatchHeaderV0 in GenesisBatchHeader and populating fields like DataHash, BlobVersionedHash, etc., enforces consistency in versioned logic. Verify all references to older batch headers are updated to read from BatchHeaderV0 or converted appropriately to avoid mixing versions.


337-338: Copying 32 bytes is correct but ensure signer validation.

Storing blsData.Signer into a [32]byte is appropriate, but also confirm that external data always provides a 32-byte signer key. Any mismatch would panic on copy(signer[:], blsData.Signer).


351-353: Batch upgrade condition is straightforward.

Checking blockTime >= e.UpgradeBatchTime is a clear approach. Ensure this logic lines up with any rollout plan so that partially upgraded batches aren’t inadvertently accepted.

prover/bin/shadow-prove/src/shadow_rollup.rs (12)

3-3: New import for Transaction
This import likely provides an abstraction for transaction objects. No apparent issues.


37-38: Constructor updates
Lines 37-38 initialize the new l2_provider parameter. This is consistent with the struct extension in line 23. Check for potential misconfiguration if l2_provider is empty or points to an invalid endpoint.


41-41: Constructing l1_rollup
The cloned provider pattern is correct for concurrency. Verify that subsequent function calls do not block or race on the same provider.


44-44: Returning Self with new field
Simple addition of the l2_provider to the self-struct instantiation. Looks correct.


60-60: Passing &self.l2_provider to get_committed_batch
Exposing the L2 provider to the batch retrieval logic is coherent with the new feature. Verify the underlying calls do not break existing tests.


95-96: New parameters in BatchInfo: start_block and end_block
Storing the block range in BatchInfo is helpful for more precise batch data. Verify that future code expansions (e.g., partial batch commits) also integrate these fields properly.


186-189: Adding stricter log count check from < 2 to < 3
Increasing the minimum log requirement could reduce false positives in batch detection, but also might skip valid edge cases. Confirm that no corner case logs are now incorrectly filtered out.


195-195: Conversion to u64
Ensure no overflow for large on-chain integer values. For extremely large batch indexes, a u64 might be insufficient.


211-211: Checking blocks ordering
This error path ensures the batch block range is increasing. This prevents further calculations from going negative, which is correct.


263-263: Accessing tx.input()
Line 263 ensures data = tx.input(). If data.is_empty(), you return early. This is correct for empty commits.


364-366: #[tokio::test] for test_sync_batch
These lines finalize the function's environment variables for L2 and enhance coverage by using the new l2_provider. Looks coherent.


373-375: Injecting l2_provider into BatchSyncer constructor in test
Testing the new L2-bound code is essential. Confirm that you mock or differentiate test RPC from production.

node/derivation/derivation.go (2)

51-53: New fields: rollupABI, legacyRollupABI, beforeMoveBlockCtxABI
These fields handle different ABIs. Ensure the code path is well tested across the legacy vs. new vs. “before move block context” scenarios.


338-338: New condition for beforeMoveBlockCtxABI.Methods["commitBatch"]
The commitBatch detection for “before-move-block-ctx” scenario ensures older flows remain intact. Check that the fallback logic (further else ifs) is always reachable.

contracts/contracts/test/Rollup.t.sol (18)

8-9: Added imports for BatchHeaderCodecV0 and BatchHeaderCodecV1
This introduction references two codec libraries. It is a clean approach for versioned batch header encoding/decoding. Ensure updates in future versions do not break existing tests.


78-78: Constructing batchHeader1 with BatchHeaderCodecV0.BATCH_HEADER_LENGTH
Line 78 references BatchHeaderCodecV0. Good that you use the library’s constant to avoid mismatched sizes.


83-84: Setting mstore fields for batch header
You’re populating indexed memory offsets. Confirm each offset is correct per the spec, especially for slightly offset fields (like l1MessagePopped, totalL1MessagePopped).


95-96: Introducing lastBlockNumber and numL1Messages
These new typed parameters improve clarity over raw bytes. Ensure they match the contract’s updated BatchDataInput struct.


140-140: Comment references version 1 with multiple blocks
This explanatory comment helps new developers track the differences between version 0 and 1. Keep it updated if any new logic is introduced.


145-147: Constructing batchHeader2 with BatchHeaderCodecV1.BATCH_HEADER_LENGTH
Similar to line 78, referencing the library constant for version 1 is consistent. Keep both references aligned with real library code.


164-164: Writing lastBlockNumber at offset 249
This offset must remain consistent with the new codex. Mistakes in indexing cause silent errors in the decoding. Thorough tests or invariants recommended.


179-179: Emitting CommitBatch(2, ...)
The event signature has changed for the new batch format. Confirm external listeners still parse it correctly.


275-275: Expect revert usage
Line 275 is an example of thorough negative testing. Keep these revert checks in sync with the final contract logic.


283-283: invalid version revert test
Ensuring the contract reverts for version 2 (unsupported) is crucial. Good coverage.


289-289: batch header length too small revert
Multiple checks for invalid lengths are good for defensive coding.


300-300: incorrect batch index revert
Verifying the mismatch between the passed index and the header’s internal index is an important safety check.


313-313: incorrect parent batch hash revert
Continuing the same pattern of strict checks is consistent.


324-324: incorrect previous state root revert
Ensures the new batch can’t arbitrarily skip or replace a known state root.


337-337: Committing a batch with one chunk
Tests a success path for a single-chunk scenario. Good coverage.


345-345: batch already committed revert
This guards double-commit attempts. Make sure the contract also forbids partial overrides in unexpected ways.


399-399: Committing another batch
Line 399 modifies the second call with updated new fields. This ensures multi-batch scenarios are tested thoroughly.


405-413: Reverting batches
Lines 405-413 revolve around verifying that only unfinalized batches can be reverted, must be from the end, etc. This thorough revert logic helps ensure finalization invariants.

oracle/oracle/batch.go (1)

158-165: Successfully removed SkippedL1MessageBitmap.

Omitting the SkippedL1MessageBitmap field simplifies the struct. Ensure analogous references throughout the system are also removed to avoid runtime errors.

bindings/bin/rollup_deployed.hex (1)

1-2: Hex bytecode updated.

The entire file has been replaced with new contract bytecode. Verify that the deployed contract matches the correct build of your updated Solidity sources.

You can do this by generating and comparing the on-chain bytecode or using a reproducible build pipeline for consistency checks.

contracts/contracts/l1/rollup/Rollup.sol (6)

7-7: Good introduction of BatchHeaderCodecV1.

The new import indicates support for updated batch headers. Confirm that older references to BatchHeaderCodecV0 do not inadvertently process version 1 data.


223-223: Version check ensures backward compatibility.

Allowing both version 0 and 1 is helpful. Confirm all code paths are tested for both versions.


248-253: Storing the data hash for new batch logic.

  1. _commitBatch references batchDataInput.lastBlockNumber and batchDataInput.numL1Messages. This is a clear, more streamlined approach than the previous context-based approach.
  2. Confirm your system logs and debugging information still provide enough block context if needed.

285-287: Conditionally storing the last block number for version >= 1.

This is a good approach to maintain backward compatibility. Confirm older decoding logic does not expect the field for version 0.


299-299: Additional parameter batchDataInput.lastBlockNumber.

The new field is appended to batchDataStore. Check for usage in subsequent finalization or revert logic to confirm that side effects are properly integrated.


723-732: Flexible batch version loading.

Code cleanly defers to BatchHeaderCodecV0.loadAndValidate or BatchHeaderCodecV1.loadAndValidate. This modular approach is sound.

node/types/batch.go (4)

19-21: Validate the usage of duplicated ABIs

You've introduced BeforeMoveBlockCtxABI here while the file already references other ABIs (e.g., LegacyRollupMetaData). Please confirm that references to each ABI are consistent and that none are inadvertently overshadowed.


27-27: Confirm that uint16 suffices for l1TxNum

If there's any possibility of exceeding 65,535 L1 transactions in a single batch, consider increasing this field to uint32 (or larger) to avoid overflow.


92-122: Check correctness of DataHashV2 and calculateHash

This revised hashing logic incorporates last block height, l1TxNum, and all L1 transaction hashes. Please ensure:

  • The last 60-byte extraction is consistent with block context size.
  • The block height parsing function is tested and validated.
  • Potential edge cases (e.g., empty contexts) are properly handled.

147-155: Consider adding boundary checks in combinePayloads

While this is a straightforward concatenation approach, large or malformed inputs could risk memory strain. Confirm validity of newBlockContext and newTxPayload lengths before combining.

bindings/bin/l2staking_deployed.hex (1)

1-2: Verify the updated hex code for correctness and consistency

This file’s contents have been fully replaced with new contract bytecode. Confirm that the deployed bytecode aligns with the expected compiled output, and that no extraneous changes or corruption occurred.

node/db/keys.go (2)

8-8: LGTM!

The prefix variable follows the established naming convention and uses a unique, descriptive value.


25-28: LGTM!

The function follows the established pattern, is well-documented, and promotes code reuse by leveraging the existing encodeEnqueueIndex function.

contracts/contracts/mock/TestUpgrade.sol (3)

3-3: LGTM!

Locking to a specific Solidity version (0.8.24) improves build reproducibility and security.


37-40: Verify storage layout compatibility.

The intentional change in storage variable order could affect storage layout compatibility during upgrades. Ensure this is the intended test scenario.


42-42: LGTM!

The new variable otherVersion is appropriately initialized and complements the existing version tracking.

contracts/contracts/l2/system/WrappedEther.sol (1)

3-3: LGTM!

Locking to a specific Solidity version (0.8.24) improves build reproducibility and security.

contracts/contracts/test/ZkEvmVerifierV1.t.sol (3)

36-36: LGTM!

Removing the view modifier is correct as the function modifies state through verifyPlonk.


42-42: LGTM!

The new name testRevert_InValidProof better reflects the test's behavior of expecting a revert.


43-43: LGTM!

Adding vm.expectRevert() makes the test's expectations explicit and improves test clarity.

contracts/contracts/libraries/ICrossDomainMessenger.sol (2)

62-78: LGTM! Well-documented interface extension.

The new overloaded sendMessage function with refundAddress parameter maintains backward compatibility while adding new functionality. The documentation clearly explains all parameters.


3-3:

❓ Verification inconclusive

Verify the Solidity version compatibility.

The version has been pinned to exactly 0.8.24. Let's verify this is the latest stable version and check for any known security advisories.


🌐 Web query:

What is the latest stable version of Solidity and are there any known security issues with version 0.8.24?

💡 Result:

The latest stable version of Solidity is v0.8.28, released on October 9, 2024[1][7]. This version introduces full support for transient storage state variables of value types and includes optimizations for memory usage and JSON interface improvements[1][7].

For Solidity v0.8.24 (released January 26, 2024), there are no critical security vulnerabilities explicitly listed in the provided sources[1][3][5][6]. However:

Key Points About v0.8.24:

1️⃣ Cancun Network Upgrade Support
Added Yul-level support for EIP-1153 (transient storage), EIP-4844 (blob transactions), and new opcodes like MCOPY[1][5].

2️⃣ Bug Fixes

  • Fixed shifted native source locations in Yul AST debug info[1].
  • Addressed SELFDESTRUCT behavior changes (EIP-6780)[1].

3️⃣ Security Considerations
While no direct vulnerabilities are mentioned for v0.8.24 itself:

  • The Solidity team recommends always using the latest compiler version for security fixes[3][6].
  • Earlier versions had bugs like incorrect Keccak caching (fixed in v0.8.3) and memory corruption issues (fixed in v0.7.x)[2][9].

Recommendation

Upgrade to v0.8.28 for:

  • Full transient storage support including reference types (new in v0.8.x series)
  • Reduced memory footprint during compilation
  • Latest security patches[1][7]

For projects requiring v0.8.x compatibility, ensure you use at least v0.8.25 which includes Dencun hard-fork readiness and gas optimizations via MCOPY opcode[1][4].

Citations:


Solidity Version Verification & Upgrade Consideration

  • The pragma solidity =0.8.24; statement is confirmed to use a version that does not present any known critical security vulnerabilities.
  • Note that the latest stable release is v0.8.28, which includes further optimizations, bug fixes, and additional support (such as enhanced transient storage features).
  • If backward compatibility is a priority or if there’s a specific need to remain on v0.8.24, the current setup is acceptable. Otherwise, please review whether updating to v0.8.28 might offer added benefits for the project.
contracts/contracts/libraries/codec/BatchHeaderCodecV1.sol (1)

33-42:

❓ Verification inconclusive

Verify memory bounds in assembly block.

The assembly block correctly manages memory pointer but should include additional safety checks:

  1. Ensure memory expansion doesn't exceed available memory
  2. Validate memory pointer alignment

🏁 Script executed:

#!/bin/bash
# Search for similar memory management patterns in the codebase
ast-grep --pattern 'assembly {
  $ptr := mload(0x40)
  $$$
  mstore(0x40, add($ptr, $_))
}'

Length of output: 93


Action: Ensure correct memory pointer alignment in the assembly block.

The inline assembly block in BatchHeaderCodecV1.sol uses the standard pattern of fetching the free memory pointer via mload(0x40) and updating it with the copied data’s length. However, since the batch header length (expected to be a fixed 257 bytes) is not a multiple of 32, simply adding the length without rounding up could leave the new free memory pointer misaligned. This misalignment may lead to issues in subsequent memory allocations if those routines assume 32-byte alignment.

  • Issue Identified:
    • The free memory pointer update (mstore(0x40, add(batchPtr, length))) does not round the pointer to a multiple of 32.
    • This could cause problematic alignment if later operations expect a 32-byte aligned pointer.
  • Recommendation:
    • Consider updating the memory pointer using an expression that rounds up to the nearest multiple of 32 (for example, using something like mstore(0x40, add(batchPtr, and(add(length, 31), not(31))))).
  • Additional Note:
    • While the EVM handles memory expansion automatically, ensuring alignment is crucial for consistency with Solidity’s memory management conventions.

Please manually verify that the intended consuming parts of your codebase either account for or are unaffected by this potential misalignment.

prover/crates/morph-executor/client/src/verifier/blob_verifier.rs (1)

13-16: LGTM! Function signature updated correctly.

The addition of num_blocks parameter aligns with the changes in batch processing logic.

node/types/batch_test.go (2)

13-61: LGTM! Comprehensive test coverage for BatchHeaderV0.

The test thoroughly validates all fields of BatchHeaderV0 including version, batch index, L1 message counts, various hashes, and state roots.


74-82:

❓ Verification inconclusive

Verify ABI compatibility across versions.

The test ensures method IDs differ across versions, which is crucial for contract upgrades. However, consider adding assertions to verify specific expected method ID values.


🏁 Script executed:

#!/bin/bash
# Description: Verify method IDs across different versions of the Rollup contract

# Search for commitBatch function signatures
rg -A 2 'function commitBatch\('

Length of output: 2096


Enhance ABI Test with Expected Method ID Values

The current test in node/types/batch_test.go verifies that the commitBatch method IDs differ across ABI versions, which is a crucial check for contract upgrades. To further strengthen the test, please add assertions that compare each method ID against its expected constant (e.g., the 4-byte selector computed from the Solidity function signature). This extra validation will ensure that any inadvertent changes to the ABI are caught immediately.

  • Compute the expected method IDs using a Keccak256 hash on the appropriate commitBatch signatures.
  • Update the test to compare the computed IDs from LegacyRollupMetaData, BeforeMoveBlockCtxABI, and bindings.RollupMetaData against these expected values.
contracts/hardhat.config.ts (2)

13-22: LGTM! Well-organized task imports.

The task imports are logically grouped and follow a clear pattern for deployment, testing, and upgrade operations.


107-118:

❓ Verification inconclusive

Verify Solidity compiler configuration.

The compiler is set to version 0.8.24 with Cancun EVM and optimizations enabled. Ensure this aligns with your deployment requirements.


🌐 Web query:

What is the latest stable version of Solidity compiler and does it support the Cancun EVM?

💡 Result:

The latest stable version of the Solidity compiler is v0.8.28, released on October 8, 2024[1][4]. This version includes full support for transient storage state variables of value types and optimizations for compilation via IR[1][4].

Regarding Cancun EVM support:

  1. Cancun compatibility was first introduced in Solidity v0.8.24[2][5], with subsequent versions refining this support.
  2. As of Solidity v0.8.25 (released March 2024), Cancun became the default EVM version when compiling contracts[4][8].
  3. Current versions (including v0.8.28) maintain full Cancun support through:
    • Native integration of EIP-1153 (transient storage)
    • Built-in mcopy() opcode support
    • Automatic bytecode optimization for MCOPY operations[1][5][8]

To verify Cancun support in your environment:

solc --evm-version cancun your_contract.sol

The compiler will automatically select Cancun features unless overridden[5][8]. Note that some Layer 2 solutions like Immutable zkEVM currently cap support at v0.8.25 while aligning with Ethereum's Cancun fork[10].

Citations:


Compiler Version & EVM Setting Verification

  • The current configuration sets Solidity to v0.8.24 with Cancun EVM and optimizations enabled, which is valid since Cancun support was introduced in v0.8.24.
  • Note that the latest stable version is v0.8.28, offering additional improvements—consider whether an upgrade may better suit your deployment needs.
  • Please verify that using v0.8.24 aligns with your project requirements, or update accordingly if benefiting from the newer version is desired.
ops/l2-genesis/cmd/genesis/cmd.go (1)

118-123:

❓ Verification inconclusive

Verify backward compatibility of batch header serialization.

The change from Encode() to Bytes() might affect systems expecting the old format. Ensure all consumers of the genesis batch header are updated accordingly.


🏁 Script executed:

#!/bin/bash
# Description: Search for other uses of genesis batch header encoding

# Search for Encode() or Bytes() method calls on batch headers
rg -A 2 '(Encode|Bytes)\(\).*batch.*header'

Length of output: 45


Below is an updated review comment. Since the initial script produced no output (which might indicate that no other usages of the old serialization method were found), please verify manually that the new Bytes() output is identical in structure to what Encode() used to produce. Additionally, please review the implementation of the BatchHeader methods to ensure that the change does not affect consumers who might expect the legacy format.

  • File: ops/l2-genesis/cmd/genesis/cmd.go (lines 118–123)
  • Action Required:
    • Confirm that the switch from Encode() to Bytes() does not alter the serialized format.
    • Manually inspect the definition of the BatchHeader type (and its Bytes() and Encode() methods, if available) to check for differences.
    • Ensure that downstream systems or consumers relying on the old serialization method are either updated or compatible with the new output.

Please verify these points before merging.

tx-submitter/utils/utils.go (2)

41-42: LGTM! Simplified batch index extraction.

The change improves efficiency by directly accessing the batch index instead of decoding the entire batch header.


124-127: LGTM! Consistent with earlier changes.

The modification maintains consistency with the earlier changes in batch index extraction.

contracts/contracts/l1/rollup/IL1MessageQueue.sol (1)

3-3: LGTM! Fixed Solidity version for better stability.

Locking to a specific version (0.8.24) instead of using a range (^0.8.16) ensures consistent behavior across deployments.

contracts/deploy/016-RollupInit.ts (1)

38-38:

❓ Verification inconclusive

Verify the impact of version upgrade.

The version change from 0 to 1 aligns with the new batch data structure changes. However, ensure that:

  1. All components are compatible with version 1
  2. Migration path exists for handling version 0 data

🏁 Script executed:

#!/bin/bash
# Search for version-specific handling in the codebase
rg -A 5 "version.*0.*|version.*1.*" --type ts --type sol

Length of output: 86


Action: Verify version upgrade compatibility and migration handling

Please ensure the following regarding the version upgrade from 0 to 1:

  • Confirm that all components—both in TypeScript (e.g., deployment scripts, interfacing modules) and in Solidity contracts—are fully compatible with version = 1.
  • Verify that a proper migration path exists for handling legacy (version 0) data. Automated searches for version-specific logic were inconclusive (note the error with Solidity file type filtering), so please perform a manual check or update the search commands (e.g., using glob patterns for Solidity files).
node/types/consensus_message.go (3)

150-156: LGTM! Well-structured block deserialization.

The function provides a clean abstraction for block deserialization with proper error handling.


158-164: LGTM! Clean height extraction.

The function reuses WrappedBlockFromBytes for consistency and provides proper error propagation.


166-171: LGTM! Robust validation for block context.

The function includes proper length validation and clear error messaging.

node/types/retryable_client.go (2)

26-26: LGTM!

The new error constant follows the existing naming convention and has a clear, descriptive message.


225-234: LGTM!

The changes effectively simplify the error handling logic while maintaining clear intent through the comment. The inverted condition makes the code more maintainable by defaulting to retry for all errors except the specific case.

prover/bin/server/src/queue.rs (1)

120-120: LGTM!

The change correctly uses blocks.len() as the number of blocks parameter, maintaining consistency with the updated BlobVerifier::verify method signature.

contracts/contracts/l1/rollup/IRollup.sol (2)

11-12: LGTM! Clear and concise parameter documentation.

The documentation for the new parameters lastBlockNumber and numL1Messages is clear and accurately describes their purpose.


19-20: LGTM! Appropriate type choices for new parameters.

The type choices are well-considered:

  • uint64 for lastBlockNumber provides sufficient range for block numbers
  • uint16 for numL1Messages is a reasonable size for counting L1 messages per batch
prover/bin/shadow-prove/src/shadow_prove.rs (4)

96-96: LGTM! Clear block length calculation.

The calculation blocks_len = end_block - start_block + 1 is correct and more straightforward than using array length.


108-108: LGTM! Updated log message for clarity.

The log message now correctly references start_block instead of the old blocks array.


123-124: LGTM! Direct use of block range in ProveRequest.

The ProveRequest initialization now directly uses start_block and end_block, improving clarity and reliability.


157-157: LGTM! Proper type casting in waiting time calculation.

The explicit type cast of blocks_len to usize in the max_waiting_time calculation ensures type safety.

prover/bin/shadow-prove/src/main.rs (5)

37-37: LGTM! Added L2 RPC configuration.

Added environment variable for L2 RPC endpoint, enabling Layer 2 network interaction.


45-49: LGTM! Clear provider initialization.

Renamed provider to l1_provider and added l2_provider, improving clarity of each provider's purpose.


62-63: LGTM! Updated BatchSyncer initialization.

BatchSyncer now correctly uses both L1 and L2 providers for cross-layer synchronization.


235-235: LGTM! Updated module path.

Corrected the module path for batch_header_inspect function.


269-269: LGTM! Updated BatchInfo initialization.

BatchInfo now uses explicit block range with start_block and end_block instead of block array.

node/derivation/derivation_test.go (4)

14-16: LGTM! Well-structured test data.

Added beforeMoveBctxData test data alongside existing test cases, maintaining consistent formatting.


24-25: LGTM! Added new ABI support.

Added beforeMoveBlockCtxABI retrieval with proper error handling.


27-29: LGTM! Updated Derivation struct initialization.

The Derivation struct now includes all necessary ABIs for testing different scenarios.


42-48: LGTM! Clear test case implementation.

Updated variable names to clearly indicate their purpose in the before-move-block-context scenario.

node/types/blob.go (1)

113-122: LGTM!

The function correctly handles empty input and provides clear error messages. The use of zstd compression is appropriate for batch data.

ops/devnet-morph/devnet/__init__.py (1)

231-233: LGTM!

Adding the --no-recreate flag is a good optimization that prevents unnecessary container recreation during deployment.

gas-oracle/app/src/da_scalar/l1_scalar.rs (4)

1-8: LGTM!

The import statement is correctly updated to use the renamed function.


230-235: LGTM!

The changes improve error handling with better logging and use a more descriptive function name.


349-394: LGTM!

The changes enhance the function by:

  1. Adding validation for empty input
  2. Improving error messages
  3. Returning both total size and transaction count

400-440: LGTM!

The test case provides good coverage for the new blob data handling functionality, verifying both total size and transaction count calculations.

prover/bin/challenge/src/handler.rs (3)

407-422: LGTM!

The struct is simplified by replacing the blocks_info vector with direct start_block and end_block fields, making it more efficient and easier to understand.


424-484: LGTM!

The function is improved by:

  1. Using batch_index to compute block range
  2. Utilizing last_block_number and num_l1_messages from batch data
  3. Providing better error handling

572-573: LGTM!

The error message formatting is improved for better consistency.

tx-submitter/services/rollup.go (2)

694-701: LGTM! The batch data structure changes improve type safety.

The replacement of BlockContexts with explicit LastBlockNumber and NumL1Messages fields makes the data structure clearer and more type-safe.


715-735: LGTM! Comprehensive error handling and logging.

The code demonstrates good practices with:

  • Descriptive error messages with context
  • Structured logging with appropriate log levels
  • Graceful fallback to rough gas estimation when needed
bindings/bindings/l2staking.go (7)

1-3: LGTM! Important warning about auto-generated code.

The warning comment clearly indicates this is auto-generated code that should not be manually edited.


47-50: LGTM! Contract metadata properly defined.

The L2StakingMetaData struct contains the contract's ABI and bytecode, with deprecated variables properly marked.


78-97: LGTM! Clean separation of contract interfaces.

The L2Staking struct properly separates read-only (Caller), write-only (Transactor) and event filtering (Filterer) interfaces.


1507-1517: LGTM! Consistent event iterator implementation.

The event iterators (CommissionUpdated, Delegated, Initialized etc.) follow a consistent pattern with proper error handling and cleanup.

Also applies to: 1573-1583, 1809-1819


2802-2954: LGTM! Comprehensive event filtering capabilities.

The event filtering system provides flexible options for monitoring contract events with proper subscription cleanup.


181-217:

❓ Verification inconclusive

Verify transaction receipt handling in Call/Transfer/Transact methods.

The base contract methods should verify transaction receipts and handle revert reasons.


🏁 Script executed:

#!/bin/bash
# Description: Check for receipt verification in other contracts
ast-grep --pattern 'receipt, err := bind.WaitMined($_, tx)
if err != nil {
  return nil, fmt.Errorf("failed to get receipt: %v", err)
}
if receipt.Status == 0 {
  return nil, fmt.Errorf("transaction reverted")'

Length of output: 212


Action Required: Manually Confirm Transaction Receipt Verification in Transaction Methods

The current implementation in bindings/bindings/l2staking.go (lines 181–217) simply passes the call through to the underlying contract methods without any explicit handling of transaction receipts. In our codebase, methods like Call, Transfer, and Transact should verify the transaction receipt (using logic such as checking receipt.Status after a call to bind.WaitMined) and correctly handle revert reasons.

  • Verify that after invoking these methods, the receipt is properly fetched and checked for a success status.
  • If receipt verification is performed elsewhere or intentionally omitted, please document the reasoning.
  • Consider including receipt verification logic similar to:
    receipt, err := bind.WaitMined(ctx, tx)
    if err != nil {
        return nil, fmt.Errorf("failed to get receipt: %v", err)
    }
    if receipt.Status == 0 {
        return nil, fmt.Errorf("transaction reverted")
    }

Please manually verify that the transaction methods propagate or incorporate receipt validation as intended.


1171-1189:

❓ Verification inconclusive

Verify input validation in state-changing methods.

The contract methods that modify state (AddStaker, DelegateStake, Initialize etc.) should validate inputs before sending transactions.

Also applies to: 1254-1273, 1317-1336


🏁 Script executed:

#!/bin/bash
# Description: Check for input validation patterns
ast-grep --pattern 'if $_ == nil || $_.Sign() <= 0 {
  return nil, fmt.Errorf("invalid amount")
}'

Length of output: 100


Action Required: Verify and Enhance Input Validation in State-Changing Methods

The current implementation for the state-changing methods (e.g., AddStaker, and similarly for methods at lines 1254–1273 and 1317–1336) shows no detected input validation (e.g., checks for nil values or non-positive amounts) before sending transactions. Please verify one of the following:

  • If input validation is expected on the client side:
    Ensure that methods validate critical inputs (like ensuring a non-nil, correctly signed _nonce or other fields in TypesStakerInfo) before invoking transaction calls. An example pattern to consider is:

    if _nonce == nil || _nonce.Sign() <= 0 {
        return nil, fmt.Errorf("invalid _nonce")
    }
  • If the validations are handled within the contract logic:
    Add a comment clarifying that input integrity is enforced on-chain, so additional client-side checks are redundant.

Please update the code or provide documentation to confirm that input validation is appropriately addressed.

prover/bin/shadow-prove/Cargo.toml (1)

13-18:

❓ Verification inconclusive

Verify compatibility with the major version upgrade of alloy.

The upgrade from alloy 0.3 to 0.8 is a major version bump that could introduce breaking changes.


🌐 Web query:

What are the breaking changes between alloy 0.3 and 0.8?

💡 Result:

The breaking changes between Alloy versions 0.3 and 0.8 primarily involve API updates and structural modifications to improve functionality and compliance with newer standards:

Transaction Handling

  • Typed Transaction Requirement: Version 0.8 mandates EIP-2718-compliant typed transactions12, replacing older transaction formats12.

Consensus Layer Changes

  • Header Method Removal: Consensus-related header methods were deprecated12.
  • Forkchoice Versioning: Introduced explicit forkchoice version tracking12.

RPC Modifications

  • Block Bounds Relaxation: RPC Block type bounds were expanded for flexibility12.
  • TransactionResponse Simplification: Removed duplicate to method in TransactionResponse12.

Type System Updates

  • BlockHashOrNumber Restructuring: Swapped alias/struct naming conventions for clarity12.
  • Recovery Traits: Added Recovered and Recoverable traits for transaction handling12.

New Features with Compatibility Impact

  • EIP-7691 Implementation: Added support for new Ethereum improvement proposal12.
  • reth Pooled TX Integration: Ported transaction pool types from reth implementation12.

Build/Dependency Changes

  • Arbitrary Trait Support: Added arbitrary crate integration for fuzzing12.
  • Serde Optionality: Made serde dependencies optional in some modules12.

These changes require codebase adjustments when upgrading from 0.x versions below 0.7.x to 0.8.x12. Developers should review transaction handling patterns and consensus-layer integrations particularly closely.

Citations:


Action Required: Confirm Alloy v0.8 Integration Adjustments

The dependency upgrade from Alloy 0.3 to 0.8 introduces several breaking changes—most notably in transaction handling, consensus header handling, RPC modifications, and type system updates. Please review the following:

  • Transaction Handling: Verify that your code now properly implements EIP-2718-compliant typed transactions.
  • Consensus Layer: Ensure deprecated header methods are replaced and that any forkchoice version tracking is correctly integrated.
  • RPC Modifications: Check that adjustments like the expanded block type bounds and the simplified TransactionResponse are correctly handled.
  • Type System and New Features: Confirm that any changes in block hash handling, the addition of recovery traits, and new features (e.g., EIP-7691 support) are accommodated in your implementations.

Review all modules that use the Alloy crate features (e.g., "contract", "signer-local", "rpc-types-eth", and "json-rpc") to guarantee compatibility with these API updates. Detailed breaking changes can be found in the Alloy changelogs.

contracts/go.mod (1)

5-5:

❓ Verification inconclusive

Verify the stability of pinned dependency versions.

The updates to tendermint and go-ethereum are pinned to specific commits rather than release tags. Let's verify these commits:

Also applies to: 9-9


🏁 Script executed:

#!/bin/bash
# Description: Check commit messages and changes for the updated dependencies

# Check tendermint commit
gh api repos/morph-l2/tendermint/commits/c84dfe5c8533 --jq '.commit.message'

# Check go-ethereum commit
gh api repos/morph-l2/go-ethereum/commits/3b9465a03a8c --jq '.commit.message'

Length of output: 268


Verify Stability of Pinned Dependency Versions

The dependency update in contracts/go.mod pins specific commit hashes instead of stable release tags. We verified the commit messages:

  • Tendermint (commit: c84dfe5c8533)
    → Commit message: “skip proposing block if an error is encountered”
    This indicates a targeted change addressing a specific error handling scenario.

  • Go-ethereum (commit: 3b9465a03a8c)
    → Commit message: “Merge remote-tracking branch 'origin' into feature/block_context”
    This merge commit from a feature branch may warrant extra scrutiny to ensure it’s sufficiently stable for production.

Please confirm that these pinned commits have been reviewed and tested in your context. If possible, consider pinning to official release tags to guarantee long-term stability and easier maintenance.

bindings/go.mod (1)

5-5: LGTM! Dependency versions are consistent.

The updated versions match those in contracts/go.mod, maintaining consistency across modules.

Also applies to: 7-7

ops/l2-genesis/go.mod (1)

5-5: LGTM! Dependency versions are consistent.

The updated versions match those in other modules, maintaining consistency across the project.

Also applies to: 9-9

tx-submitter/go.mod (1)

5-5: LGTM! Dependency versions are consistent.

The updated versions match those in other modules, maintaining consistency across the project.

Also applies to: 10-10

oracle/go.mod (1)

5-5:

❓ Verification inconclusive

Verify the stability of pre-release dependencies.

The updated dependencies point to specific commits rather than stable releases:

  • tendermint: Using pre-release version v0.3.2-0.20250115141431
  • go-ethereum: Using commit from December 26, 2024

Run the following script to check for any reported issues with these versions:

Also applies to: 10-10


🏁 Script executed:

#!/bin/bash
# Description: Check for issues in the specified versions of tendermint and go-ethereum

# Check tendermint repository
echo "Checking tendermint repository..."
gh api repos/morph-l2/tendermint/commits/v0.3.2-0.20250115141431-c84dfe5c8533/check-runs

# Check go-ethereum repository
echo "Checking go-ethereum repository..."
gh api repos/morph-l2/go-ethereum/commits/v1.10.14-0.20241226065029-3b9465a03a8c/check-runs

Length of output: 876


Verify the stability of pre-release dependencies.

The current dependency replacements in oracle/go.mod reference pseudo-versions for both tendermint and go-ethereum, which point to specific commits rather than stable releases. Notably, the GitHub API check failed with errors indicating that these pseudo-version strings cannot be directly resolved to commit SHAs. This is expected behavior with pseudo-versions, so please:

  • Confirm that using these pseudo-versions (tendermint: v0.3.2-0.20250115141431-c84dfe5c8533, go-ethereum: v1.10.14-0.20241226065029-3b9465a03a8c) is intentional.
  • Verify their stability and compatibility through alternative methods (e.g., reviewing upstream changes or running comprehensive tests), as the API check isn’t conclusive for pseudo-versions.
Makefile (1)

3-4: LGTM! Version updates are consistent with go.mod changes.

The target versions in the Makefile align with the dependency updates in go.mod files, ensuring consistent versioning across modules.

node/go.mod (1)

5-5: LGTM! Version updates match other modules.

The dependency updates are consistent with changes in oracle/go.mod and the Makefile target versions.

Also applies to: 13-13

gas-oracle/app/src/abi/Rollup.json (1)

612-619: LGTM! Improved type safety in BatchDataInput struct.

The change from opaque blockContexts bytes to explicit lastBlockNumber and numL1Messages fields improves type safety and makes the interface more explicit. This aligns with the PR objective of moving block context to blob.

prover/bin/shadow-prove/abi/Rollup.json (1)

612-619: LGTM! ABI changes match gas oracle implementation.

The BatchDataInput struct changes are identical to those in gas-oracle/app/src/abi/Rollup.json, maintaining consistency across components.

prover/bin/challenge/src/abi/Rollup.json (1)

612-619: LGTM! The parameter types are well-chosen for their purposes.

The changes replace the blockContexts bytes parameter with two specific parameters:

  • lastBlockNumber as uint64: Appropriate for block numbers
  • numL1Messages as uint16: Provides a reasonable upper limit for L1 messages per batch

Footnotes

  1. GitHub Changelog v0.8 2 3 4 5 6 7 8 9 10 11 12 13

  2. GitHub Changelog v0.3 2 3 4 5 6 7 8 9 10 11 12 13

Comment on lines +70 to +85
if err = e.l2Client.CommitBatch(context.Background(), &eth.RollupBatch{
Version: uint(version),
Index: parentBatchIndex + 1,
Hash: hash,
ParentBatchHeader: *e.batchingCache.parentBatchHeader,
CurrentSequencerSetBytes: sequencerSetBytes,
BlockContexts: blockContexts,
PrevStateRoot: e.batchingCache.prevStateRoot,
PostStateRoot: e.batchingCache.postStateRoot,
WithdrawRoot: e.batchingCache.withdrawRoot,
Sidecar: e.batchingCache.sealedSidecar,
LastBlockNumber: e.batchingCache.lastPackedBlockHeight,
NumL1Messages: uint16(l1MessagePopped),
}, batchSigs); err != nil {
return fmt.Errorf("failed to commit batch to L2 client: %w", err)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential overflow when casting to uint16
Casting l1MessagePopped to uint16 (line 82) may lead to truncation if the actual value exceeds 65535. If large values are possible, consider a larger type or add overflow checks to avoid silent data loss.

- NumL1Messages: uint16(l1MessagePopped),
+ if l1MessagePopped > math.MaxUint16 {
+   return fmt.Errorf("l1MessagePopped overflow: %d", l1MessagePopped)
+ }
+ NumL1Messages: uint16(l1MessagePopped),

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +178 to +179
blockContexts := make([]*BlockContext, int(blockCount))
for i := 0; i < int(blockCount); i++ {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Integer overflow concern when creating slice.

blockCount is a uint64, but it's cast to int in make([]*BlockContext, int(blockCount)). In extremely large batch scenarios, this can overflow on 32-bit systems or if blockCount exceeds MaxInt. Consider handling this more safely:

 if blockCount > (1<<31 - 1) {
   return fmt.Errorf("blockCount too large: %d", blockCount)
 }
-blockContexts := make([]*BlockContext, int(blockCount))
+blockContexts := make([]*BlockContext, int64(blockCount)) // or handle more robustly

Also applies to: 180-186

Comment on lines +149 to +153
mstore(add(batchHeader2, 0x20), shl(248, 1)) // version
mstore(add(batchHeader2, add(0x20, 1)), shl(192, 2)) // batchIndex = 2
mstore(add(batchHeader2, add(0x20, 9)), shl(192, 264)) // l1MessagePopped = 264
mstore(add(batchHeader2, add(0x20, 17)), shl(192, 265)) // totalL1MessagePopped = 265
mstore(add(batchHeader2, add(0x20, 25)), 0x81e7e4ffa69f7496f9377a1e4140fbb16fcc81d8086b44a1316fc77cc2b9a63b) // dataHash
mstore(add(batchHeader2, add(0x20, 25)), 0x688bd49eddb8f52296974c2a243b10b91b305edd68f46190df21a83c13a6e2ec) // dataHash
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Complex mstore definitions
Manually writing memory offsets can be error-prone. If the library supports direct struct-based construction, prefer it. Otherwise, consider verifying each offset carefully.

Comment on lines +166 to +180
parentBatchHeader := nodetypes.BatchHeaderBytes(batch.ParentBatchHeader)
parentVersion, err := parentBatchHeader.Version()
if err != nil {
return fmt.Errorf("decode parent batch version error:%v", err)
}
if batch.Version == 1 && parentVersion == 0 {
parentBatchIndex, err := parentBatchHeader.BatchIndex()
if err != nil {
return fmt.Errorf("decode parent batch index error:%v", err)
}
parentBatch, err := o.l2Client.GetRollupBatchByIndex(o.ctx, parentBatchIndex)
if err != nil {
return fmt.Errorf("get parent batch error:%v", err)
}
batch.Sidecar = parentBatch.Sidecar
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate parent batch logic and error handling.

  1. Retrieving the parent batch data based on version is a good step.
  2. Verify that batch.Sidecar is always relevant and won't overshadow required data from the current batch, or become stale if parent data changes.
  3. Ensure that calls to GetRollupBatchByIndex handle both existing and non-existing parent indices correctly.

As a follow-up, consider testing edge cases:

  • If parentBatchIndex references an invalid or finalized batch.
  • If a mismatch occurs between batch.Version and parentVersion.
    Do you want me to generate a script to check references to all calls of GetRollupBatchByIndex?

@@ -121,6 +49,7 @@ func (cks *BatchData) Append(blockContext, txsPayload []byte, l1TxHashes []commo
for _, txHash := range l1TxHashes {
cks.l1TxHashes = append(cks.l1TxHashes, txHash.Bytes()...)
}
cks.l1TxNum += uint16(len(l1TxHashes))
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate potential overflow in l1TxNum accumulation

Adding uint16(len(l1TxHashes)) could overflow if the batch is already close to the limit. If large L1Tx arrays are possible, guard or switch to a larger integer type.

Comment on lines +11 to +12
let num_blocks = input.l2_traces.len();
let (versioned_hash, batch_data) = BlobVerifier::verify(&input.blob_info, num_blocks).unwrap();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for empty traces.

The num_blocks calculation should handle empty traces gracefully.

-    let num_blocks = input.l2_traces.len();
+    let num_blocks = input.l2_traces.len();
+    if num_blocks == 0 {
+        return Err(anyhow::anyhow!("No L2 traces provided"));
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let num_blocks = input.l2_traces.len();
let (versioned_hash, batch_data) = BlobVerifier::verify(&input.blob_info, num_blocks).unwrap();
let num_blocks = input.l2_traces.len();
if num_blocks == 0 {
return Err(anyhow::anyhow!("No L2 traces provided"));
}
let (versioned_hash, batch_data) = BlobVerifier::verify(&input.blob_info, num_blocks).unwrap();

Comment on lines 41 to +57
pub fn get_blob_data(block_trace: &Vec<BlockTrace>) -> [u8; BLOB_DATA_SIZE] {
// collect txns
let num_blocks = block_trace.len();
let mut batch_from_trace: Vec<u8> = Vec::with_capacity(num_blocks * 60);
let mut tx_bytes: Vec<u8> = vec![];
for trace in block_trace {
// BlockContext
// https://github.com/morph-l2/morph/blob/main/contracts/contracts/libraries/codec/BatchCodecV0.sol
let mut block_ctx: Vec<u8> = Vec::with_capacity(60);
block_ctx.extend_from_slice(&trace.number().to_be_bytes());
block_ctx.extend_from_slice(&trace.timestamp().to::<u64>().to_be_bytes());
block_ctx
.extend_from_slice(&trace.base_fee_per_gas().unwrap_or_default().to_be_bytes::<32>());
block_ctx.extend_from_slice(&trace.gas_limit().to::<u64>().to_be_bytes());
block_ctx.extend_from_slice(&(trace.transactions.len() as u16).to_be_bytes());
block_ctx.extend_from_slice(&(trace.num_l1_txs() as u16).to_be_bytes());
batch_from_trace.extend(block_ctx);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance error handling for block context processing.

While the block context collection is well-structured, consider adding error handling for:

  • Invalid block numbers
  • Timestamp conversion failures
  • Gas limit overflow scenarios
 block_ctx.extend_from_slice(&trace.number().to_be_bytes());
-block_ctx.extend_from_slice(&trace.timestamp().to::<u64>().to_be_bytes());
+block_ctx.extend_from_slice(&trace.timestamp().to::<u64>().ok_or_else(|| 
+    anyhow!("Invalid timestamp conversion"))?.to_be_bytes());

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +34 to +36
data_hasher.update(&traces.last().unwrap().number().to_be_bytes());
let num_l1_txs: u16 = traces.iter().map(|x| x.num_l1_txs()).sum::<u64>() as u16;
data_hasher.update(&num_l1_txs.to_be_bytes());
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify potential overflow in L1 transactions count.

The conversion of total L1 transactions to u16 could overflow if the sum exceeds 65535. Consider using a larger integer type or adding a validation check.


🏁 Script executed:

#!/bin/bash
# Description: Check if any batch has more than 65535 L1 transactions.

ast-grep --pattern 'fn num_l1_txs($$$) -> u64 {
  $$$
}'

Length of output: 1124


Attention: Validate L1 Transaction Count Conversion

In prover/crates/core/src/batch.rs at lines 34–36, the sum of L1 transactions (computed as a u64) is being cast to a u16. This conversion can silently truncate the value if the total exceeds 65,535, potentially causing an overflow. Please consider one of the following to mitigate this risk:

  • Use a larger integer type: Replace u16 with a larger type (such as u32 or retain u64) to safely handle broader ranges.
  • Add a validation check: Before casting, verify that the computed sum does not exceed u16::MAX to prevent overflow.

Comment on lines +324 to +394
func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) {
//if isEmptyBlob(blob) {
// return eth.Transactions{}, nil
//}
//data, err := RetrieveBlobBytes(blob)
//if err != nil {
// return nil, err
//}
//batchBytes, err := zstd.DecompressBatchBytes(data)
//if err != nil {
// return nil, err
//}
reader := bytes.NewReader(txsBytes)
txs := make(eth.Transactions, 0)
for {
var (
firstByte byte
fullTxBytes []byte
innerTx eth.TxData
err error
)
if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// if the blob byte array is completely consumed, then break the loop
if err == io.EOF {
break
}
return nil, err
}
// zero byte is found after valid tx bytes, break the loop
if firstByte == 0 {
break
}

switch firstByte {
case eth.AccessListTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.AccessListTx)
case eth.DynamicFeeTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.DynamicFeeTx)
default:
if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
return nil, fmt.Errorf("not supported tx type: %d", firstByte)
}
innerTx = new(eth.LegacyTx)
}

// we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType
//if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType {
// // the firstByte here is used to indicate tx type, so skip it
// if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// return nil, err
// }
//} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
// return nil, fmt.Errorf("not supported tx type: %d", firstByte)
//}
fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
if err != nil {
return nil, err
}
if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
return nil, err
}
txs = append(txs, eth.NewTx(innerTx))
}
return txs, nil
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract common transaction decoding logic and remove commented code.

The function has two issues:

  1. Contains unnecessary commented-out code for blob handling.

  2. Duplicates transaction decoding logic from DecodeTxsFromBlob.

  3. Remove the commented-out code:

-//if isEmptyBlob(blob) {
-//	return eth.Transactions{}, nil
-//}
-//data, err := RetrieveBlobBytes(blob)
-//if err != nil {
-//	return nil, err
-//}
-//batchBytes, err := zstd.DecompressBatchBytes(data)
-//if err != nil {
-//	return nil, err
-//}
  1. Extract the common transaction decoding logic into a shared helper function:
func decodeTxsFromReader(reader *bytes.Reader) (eth.Transactions, error) {
	txs := make(eth.Transactions, 0)
	for {
		var (
			firstByte   byte
			fullTxBytes []byte
			innerTx     eth.TxData
			err         error
		)
		if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		if firstByte == 0 {
			break
		}

		switch firstByte {
		case eth.AccessListTxType:
			if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
				return nil, err
			}
			innerTx = new(eth.AccessListTx)
		case eth.DynamicFeeTxType:
			if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
				return nil, err
			}
			innerTx = new(eth.DynamicFeeTx)
		default:
			if firstByte <= 0xf7 {
				return nil, fmt.Errorf("not supported tx type: %d", firstByte)
			}
			innerTx = new(eth.LegacyTx)
		}

		fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
		if err != nil {
			return nil, err
		}
		if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
			return nil, err
		}
		txs = append(txs, eth.NewTx(innerTx))
	}
	return txs, nil
}

Then update the functions to use the shared helper:

func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) {
	reader := bytes.NewReader(txsBytes)
	return decodeTxsFromReader(reader)
}

func DecodeTxsFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
	if isEmptyBlob(blob) {
		return eth.Transactions{}, nil
	}
	data, err := RetrieveBlobBytes(blob)
	if err != nil {
		return nil, err
	}
	batchBytes, err := zstd.DecompressBatchBytes(data)
	if err != nil {
		return nil, err
	}
	reader := bytes.NewReader(batchBytes)
	return decodeTxsFromReader(reader)
}

Comment on lines +252 to +322
func DecodeBlocksFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
if isEmptyBlob(blob) {
return eth.Transactions{}, nil
}
data, err := RetrieveBlobBytes(blob)
if err != nil {
return nil, err
}
batchBytes, err := zstd.DecompressBatchBytes(data)
if err != nil {
return nil, err
}
reader := bytes.NewReader(batchBytes)
txs := make(eth.Transactions, 0)
for {
var (
firstByte byte
fullTxBytes []byte
innerTx eth.TxData
err error
)
if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// if the blob byte array is completely consumed, then break the loop
if err == io.EOF {
break
}
return nil, err
}
// zero byte is found after valid tx bytes, break the loop
if firstByte == 0 {
break
}

switch firstByte {
case eth.AccessListTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.AccessListTx)
case eth.DynamicFeeTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.DynamicFeeTx)
default:
if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
return nil, fmt.Errorf("not supported tx type: %d", firstByte)
}
innerTx = new(eth.LegacyTx)
}

// we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType
//if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType {
// // the firstByte here is used to indicate tx type, so skip it
// if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// return nil, err
// }
//} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
// return nil, fmt.Errorf("not supported tx type: %d", firstByte)
//}
fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
if err != nil {
return nil, err
}
if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
return nil, err
}
txs = append(txs, eth.NewTx(innerTx))
}
return txs, nil
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove duplicate function.

This function is an exact duplicate of DecodeTxsFromBlob. Consider removing it to avoid code duplication and potential maintenance issues.

Apply this diff to remove the duplicate function and update any callers to use DecodeTxsFromBlob instead:

-func DecodeBlocksFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
-	if isEmptyBlob(blob) {
-		return eth.Transactions{}, nil
-	}
-	data, err := RetrieveBlobBytes(blob)
-	if err != nil {
-		return nil, err
-	}
-	batchBytes, err := zstd.DecompressBatchBytes(data)
-	if err != nil {
-		return nil, err
-	}
-	reader := bytes.NewReader(batchBytes)
-	txs := make(eth.Transactions, 0)
-	for {
-		var (
-			firstByte   byte
-			fullTxBytes []byte
-			innerTx     eth.TxData
-			err         error
-		)
-		if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
-			// if the blob byte array is completely consumed, then break the loop
-			if err == io.EOF {
-				break
-			}
-			return nil, err
-		}
-		// zero byte is found after valid tx bytes, break the loop
-		if firstByte == 0 {
-			break
-		}
-
-		switch firstByte {
-		case eth.AccessListTxType:
-			if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
-				return nil, err
-			}
-			innerTx = new(eth.AccessListTx)
-		case eth.DynamicFeeTxType:
-			if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
-				return nil, err
-			}
-			innerTx = new(eth.DynamicFeeTx)
-		default:
-			if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
-				return nil, fmt.Errorf("not supported tx type: %d", firstByte)
-			}
-			innerTx = new(eth.LegacyTx)
-		}
-
-		// we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType
-		//if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType {
-		//	// the firstByte here is used to indicate tx type, so skip it
-		//	if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
-		//		return nil, err
-		//	}
-		//} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
-		//	return nil, fmt.Errorf("not supported tx type: %d", firstByte)
-		//}
-		fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
-		if err != nil {
-			return nil, err
-		}
-		if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
-			return nil, err
-		}
-		txs = append(txs, eth.NewTx(innerTx))
-	}
-	return txs, nil
-}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func DecodeBlocksFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
if isEmptyBlob(blob) {
return eth.Transactions{}, nil
}
data, err := RetrieveBlobBytes(blob)
if err != nil {
return nil, err
}
batchBytes, err := zstd.DecompressBatchBytes(data)
if err != nil {
return nil, err
}
reader := bytes.NewReader(batchBytes)
txs := make(eth.Transactions, 0)
for {
var (
firstByte byte
fullTxBytes []byte
innerTx eth.TxData
err error
)
if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// if the blob byte array is completely consumed, then break the loop
if err == io.EOF {
break
}
return nil, err
}
// zero byte is found after valid tx bytes, break the loop
if firstByte == 0 {
break
}
switch firstByte {
case eth.AccessListTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.AccessListTx)
case eth.DynamicFeeTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.DynamicFeeTx)
default:
if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
return nil, fmt.Errorf("not supported tx type: %d", firstByte)
}
innerTx = new(eth.LegacyTx)
}
// we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType
//if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType {
// // the firstByte here is used to indicate tx type, so skip it
// if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// return nil, err
// }
//} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
// return nil, fmt.Errorf("not supported tx type: %d", firstByte)
//}
fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
if err != nil {
return nil, err
}
if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
return nil, err
}
txs = append(txs, eth.NewTx(innerTx))
}
return txs, nil
}

@FletcherMan FletcherMan merged commit a1c6c5f into main Feb 14, 2025
14 checks passed
@FletcherMan FletcherMan deleted the feature/block-context branch February 14, 2025 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants