Execution Node

The execution node is one of the core components in the Scroll protocol: it is responsible for maintaining the L2 blockchain. The execution node also ensures that the user and developer experience on Scroll closely resembles that on Ethereum. It achieves this by maintaining EVM and RPC behavior that is directly inherited from Ethereum, with very few modifications.

The primary functions of Scroll’s execution node are:

  • Collect transactions from L2 and L1.
  • Validate transactions and pack them into L2 blocks.
  • Execute blocks and maintain the L2 blockchain state.

It is worth highlighting that bridging messages and tokens from L1 to L2 (deposits) is also the execution node’s responsibility. Messages from L2 to L1 (withdraws), on the other hand, can be executed by any user on L1.

The secondary functions of Scroll’s execution node are:

  • Offer standard Ethereum RPC APIs and some Scroll extension APIs.
  • Allow peers (follower nodes) to sync the blockchain using Ethereum’s peer-to-peer protocol.

The execution node, being a fork of go-ethereum, inherits most of its functionality from Ethereum. This includes transaction and block data structures, EVM execution, RPC and p2p protocols. As these were not reimplemented but were directly inherited from go-ethereum, we can have a very high certainty of Scroll’s compatibility with Ethereum.

The following sections will introduce the main components of the execution node, the additional validation rules, and a summary of modification details.

l2geth Components

l2geth is Scroll’s fork of go-ethereum. It is responsible for building and executing blocks and maintaining the blockchain state. l2geth inherits most of its functionality from Ethereum, with some notable differences listed below. l2geth has the following submodules (not exhaustive list):

  • Storage: Ledger and state storage implemented using LevelDB.
  • EVM: The state transition rules of Ethereum.
  • Worker: Responsible for creating new L2 blocks.
  • L1 SyncService: Sync and store L1 messages in l2geth local database.
  • API layer: Standard Ethereum RPC and p2p interfaces.
  • Transaction pool: Mempool for L2 transactions.
  • Circuit capacity checker: checks if a transaction or a block exceeds the circuit capacity limit.

Circuit Capacity Checker

With Scroll’s current zkEVM circuits, it is possible to construct transactions and blocks that cannot be proven because they do not fit into the zkEVM circuit. We call this proof overflow. To avoid this, we implemented a circuit capacity checker module as part of l2geth. The circuit capacity checker is used both during block creation and block validation.

During block creation, if the next transaction would lead to proof overflow, then we seal the block and leave the transaction for the next block. If a single transaction leads to proof overflow, l2geth discards it. We call this mechanism skipping.

Skipping L2 transactions means simply discarding them. In this case, the user needs to submit another transaction with the same nonce that does not lead to proof overflow in order to proceed.

Skipping L1 messages is a more explicit process. Both the ScrollChain contract on L1 and the zkEVM verify that each L1 transaction in L1MessageQueue was either included and executed, or skipped. While the batch encoding does not contain L1 transactions, it does include a skip bitmap that indicates to ScrollChain which L1 messages were skipped. If an L1 deposit message is skipped, the user can get their tokens refunded on L1.

As the unit of zkEVM proving is the chunk, proof overflow must be avoided for chunks as well. This is achieved by incorporating the circuit capacity checker into the rollup-relayer to make sure that it never proposes unprovable chunks.

Validation Rules

Scroll adds a few validation rules in addition to Ethereum’s block validation rules. These new rules constrain the L2 behavior of L1 message inclusion and zkEVM circuit capacity limit.

  • The circuit capacity checker module outlined above verifies the block can fit into the circuit space capacity of the zkEVM circuit.
  • Rules related to L1 messages:
    • L1 messages in a block must be contiguous and at the front of the block.
    • L1 messages in a block must be included following their order in L1MessageQueue, i.e., they must be included with increasing QueueIndex.
    • L1 messages in a block must match those in the L1MessageQueue contract.
  • Most of these rules are considered both during block creation and block validation. As a result, if the block proposer node violates any of these rules, follower nodes will reject its blocks.

Summary of Modifications

The Scroll execution node inherits most of Ethereum’s behaviors. However, we needed to make some breaking changes to l2geth to enable more efficient proving. This section provides a non-exhaustive list of the modifications, along with their rationale.

  • State and storage tree: Ethereum uses the MPT (Merkle-Patricia Trie) as its state and contract storage data structure. This trie’s structure and the fact that it uses Keccak hash would make it prohibitively expensive for ZK circuits. l2geth instead uses zkTrie: a binary Merkle trie with Poseidon hash for its state and contract storage.
  • StateAccount: The modification of state account is described in the Accounts and State.
  • EVM: The modifications are described in the EVM Differences from Ethereum
  • Transaction fees
    • All fees collected on L2 are sent to a Scroll-maintained L2 fee vault contract.
    • L1 fee: In addition to the L2 gas fee that covers L2 block space and execution costs, we also collect an L1 fee that covers the costs of committing the transaction to L1. This fee is proportional to the size of the RLP-encoded transaction. The actual cost depends on the current settings stored in the L1GasOracle contract on L2. This fee is deducted from the sender balance directly (and not from the gas allowance).
  • L1MessageTx: We introduced a new transaction type L1MessageTx. We also added DB interfaces for storing such transactions and related metadata.
  • SyncService: monitors finalized blocks on L1 and collects L1 messages from these.
  • New API: The l2geth offers a trace API scroll_traceBlockByNumberOrHash for provers to query the trace information to generate proofs.

What's Next

Stay up-to-date on the latest Scroll Developer news
Roadmap updates, virtual and live events, ecosystem opportunities and more
Thank you for subscribing!

Resources

Follow Us