Skip to content

feat(l2): shared bridge forced inclusion#5477

Merged
ilitteri merged 240 commits intomainfrom
feat/l2/shared_bridge_forced_inclusion
Dec 16, 2025
Merged

feat(l2): shared bridge forced inclusion#5477
ilitteri merged 240 commits intomainfrom
feat/l2/shared_bridge_forced_inclusion

Conversation

@avilagaston9
Copy link
Contributor

@avilagaston9 avilagaston9 commented Dec 1, 2025

Motivation

In a shared bridge environment, we need a way to enforce L2s to include messages from other L2s.
We take the same approach as with deposits:

  • After some time, a message is considered expired if it has not yet been included in a batch.
  • When this happens, the sequencer is prevented from including non-privileged transactions until all expired messages are included.

Description

  • Adds the forced inclusion mechanism to the documentation.
  • Modifies l1_committer to commit the l2_out_message_hashes and the rolling hash of received processed messages in the batch.
  • Modifies the Batch struct:
    • Adds the l2_in_message_rolling_hashes field.
    • Removes l2_message_hashes, since they are now included in the BalanceDiff struct.
  • Removes all l2_messages_merkle_root related logic. Since we now send all message hashes, the Merkle root is no longer needed.
  • Renames privileged transactions | deposits to l1_in_messages throughout the codebase. A privileged transaction represents a message from another chain (L1 or L2). deposits was also being used to refer to L1 inbound messages, but messages can be more than simple deposits.
  • Updates the prover to output L2RollingHashes.
  • Restores blobs due to changes in the L2 genesis.

@avilagaston9 avilagaston9 marked this pull request as ready for review December 10, 2025 18:12
Copilot AI review requested due to automatic review settings December 10, 2025 18:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements forced inclusion of cross-chain messages for shared bridge environments. The core change ensures L2s cannot avoid processing messages from other L2s by preventing commitment of batches with non-privileged transactions until all expired messages are included. The implementation tracks message hashes per source chain and validates their inclusion through rolling hashes computed by the prover.

Key changes:

  • Introduces forced inclusion mechanism where expired messages block non-privileged transaction inclusion
  • Replaces merkle root verification with direct message hash tracking and rolling hash validation
  • Renames privileged transaction terminology from "deposits" to "l1_in_messages" and "l2_in_messages" for clarity

Reviewed changes

Copilot reviewed 43 out of 50 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
docs/l2/fundamentals/shared_bridge.md Documents forced inclusion mechanism and updated cross-chain message flow
crates/networking/p2p/rlpx/l2/messages.rs Updates Batch serialization to include rolling hashes and remove merkle roots
crates/l2/utils/state_reconstruct.rs Refactors batch reconstruction to compute rolling hashes for L1/L2 inbound messages
crates/l2/utils/error.rs Adds error variants for privileged transaction and integer conversion failures
crates/l2/tests/shared_bridge.rs Adds test verifying forced inclusion prevents batch verification
crates/l2/storage/src/store_db/sql.rs Updates database schema to store rolling hashes and non-privileged transaction counts
crates/l2/storage/src/store_db/in_memory.rs Updates in-memory storage to match SQL store changes
crates/l2/storage/src/store.rs Updates store API to retrieve rolling hashes instead of message lists
crates/l2/storage/src/api.rs Updates storage API signatures for rolling hash access
crates/l2/sequencer/l1_watcher.rs Changes message verification from merkle proofs to pending message hash checks
crates/l2/sequencer/l1_committer.rs Updates batch commitment to include rolling hashes and message hash lists
crates/l2/sequencer/errors.rs Adds error for invalid privileged transactions
crates/l2/sequencer/block_producer/payload_builder.rs Removes chain-specific privileged transaction filtering
crates/l2/sdk/src/sdk.rs Adds functions to query pending L2 messages and removes message verification
crates/l2/sdk/contract_utils/src/compile.rs Enables Solidity optimizer to manage bytecode size
crates/l2/prover/src/guest_program/src/output.rs Updates prover output to include rolling hashes instead of merkle roots
crates/l2/prover/src/guest_program/src/execution.rs Refactors prover to compute rolling hashes for message validation
crates/l2/networking/rpc/rpc.rs Adds RPC endpoint for batch lookup by block number
crates/l2/networking/rpc/l2/messages.rs Removes L2 message proof generation RPC method
crates/l2/networking/rpc/l2/batch.rs Adds handler for batch retrieval by block number
crates/l2/networking/rpc/clients.rs Updates client to support batch retrieval by block
crates/l2/monitor/widget/l1_to_l2_messages.rs Updates widget to use renamed pending messages function
crates/l2/monitor/widget/batches.rs Updates batch display to use renamed message hash field
crates/l2/docker-compose.yaml Adds log level environment variable configuration
crates/l2/contracts/src/l1/interfaces/IRouter.sol Updates router interface to send multiple message hashes
crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol Updates proposer interface for rolling hash commitment
crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol Updates bridge interface for message hash tracking
crates/l2/contracts/src/l1/based/interfaces/IOnChainProposer.sol Adds non-privileged transaction count to based proposer interface
crates/l2/contracts/src/l1/based/OnChainProposer.sol Implements forced inclusion check in based proposer
crates/l2/contracts/src/l1/Router.sol Implements multi-hash message sending and removes merkle verification
crates/l2/contracts/src/l1/OnChainProposer.sol Implements rolling hash verification and forced inclusion enforcement
crates/l2/contracts/src/l1/CommonBridge.sol Implements message hash tracking and expiration checking
crates/l2/common/src/privileged_transactions.rs Adds function to extract L2 inbound messages from transactions
crates/l2/common/src/messages.rs Updates L2Message structure and encoding to include source chain ID
crates/l2/based/block_fetcher.rs Adds chain_id parameter to batch reconstruction
crates/common/types/transaction.rs Includes chain_id in privileged transaction hash computation
crates/common/types/l2/batch.rs Updates Batch structure with rolling hashes
crates/common/types/l2/balance_diff.rs Adds message_hashes field to BalanceDiff
cmd/ethrex/l2/deployer.rs Updates bridge initialization with chain_id parameter
cmd/ethrex/l2/command.rs Passes chain_id to batch reconstruction
cmd/ethrex/cli.rs Adds environment variable support for log level
.github/workflows/pr-main_l2.yaml Adds forced inclusion test matrix and debug logging
.github/workflows/pr-main_l1_l2_dev.yaml Fixes environment file location for tests
Comments suppressed due to low confidence (4)

crates/l2/tests/shared_bridge.rs:1

  • Use line.starts_with('#') with a character literal instead of a string literal for better performance and idiomatic code.
    crates/l2/tests/shared_bridge.rs:1
  • Corrected spelling of 'porpuse' to 'purpose'.
    crates/l2/sequencer/l1_committer.rs:1
  • The function signature string spans multiple lines. Consider keeping it on a single line or using a more readable format to improve maintainability.
    crates/l2/storage/src/store_db/sql.rs:1
  • Corrected spelling of 'pendinL2MessagesLength' to 'pendingL2MessagesLength' in function call.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

long = "log.level",
default_value_t = Level::INFO,
value_name = "LOG_LEVEL",
env = "ETHREX_LOG_LEVEL",
Copy link
Contributor

Choose a reason for hiding this comment

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

RUST_LOG does the job too

Copy link
Contributor

Choose a reason for hiding this comment

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

Here when encoding an L2Message we are not encoding the dest_chain_id. Can this be a problem given that when getting the L2 Message hash we do keccak(msg.encode())? I mean, 2 equal messages to different L2s could possibly have the same hash. Is that a problem or is it intentional?

@ilitteri ilitteri enabled auto-merge December 15, 2025 21:33
@ilitteri ilitteri added this pull request to the merge queue Dec 16, 2025
Merged via the queue into main with commit 6f4a54c Dec 16, 2025
52 checks passed
@ilitteri ilitteri deleted the feat/l2/shared_bridge_forced_inclusion branch December 16, 2025 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L2 Rollup client

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

6 participants