Overview
After processing one or more blocks the outputs will need to be synchronized with the settlement layer (L1) for trustless execution of L2-to-L1 messaging, such as withdrawals. These output proposals act as the bridge’s view into the L2 state. Actors called “Proposers” submit the output roots to the settlement layer (L1) and can be contested with a proof, with a bond at stake if the proof is wrong. The op-proposer in one such implementation of a proposer.Proposing L2 Output Commitments
The proposer’s role is to construct and submit output roots, which are commitments to the L2’s state, to theL2OutputOracle contract on L1 (the settlement layer). To do this, the proposer periodically
queries the rollup node for the latest output root derived from the latest
finalized L1 block. It then takes the output root and
submits it to the L2OutputOracle contract on the settlement layer (L1).
L2OutputOracle v1.0.0
The submission of output proposals is permissioned to a single account. It is expected that this account will continue to submit output proposals over time to ensure that user withdrawals do not halt. The L2 output proposer is expected to submit output roots on a deterministic interval based on the configuredSUBMISSION_INTERVAL in the L2OutputOracle. The larger
the SUBMISSION_INTERVAL, the less often L1 transactions need to be sent to the L2OutputOracle
contract, but L2 users will need to wait a bit longer for an output root to be included in L1 (the settlement layer)
that includes their intention to withdraw from the system.
The honest op-proposer algorithm assumes a connection to the L2OutputOracle contract to know
the L2 block number that corresponds to the next output proposal that must be submitted. It also
assumes a connection to an op-node to be able to query the optimism_syncStatus RPC endpoint.
CHALLENGER account can delete multiple output roots by calling the deleteL2Outputs() function
and specifying the index of the first output to delete, this will also delete all subsequent outputs.
L2 Output Commitment Construction
Theoutput_root is a 32 byte string, which is derived based on the a versioned scheme:
-
version_byte(bytes32) a simple version string which increments anytime the construction of the output root is changed. -
payload(bytes) is a byte string of arbitrary length.
bytes32(0), and the payload is defined
as:
-
The
latest_block_hash(bytes32) is the block hash for the latest L2 block. -
The
state_root(bytes32) is the Merkle-Patricia-Trie (MPT) root of all execution-layer accounts. This value is frequently used and thus elevated closer to the L2 output root, which removes the need to prove its inclusion in the pre-image of thelatest_block_hash. This reduces the merkle proof depth and cost of accessing the L2 state root on L1. -
The
withdrawal_storage_root(bytes32) elevates the Merkle-Patricia-Trie (MPT) root of the Message Passer contract storage. Instead of making an MPT proof for a withdrawal against the state root (proving first the storage root of the L2toL1MessagePasser against the state root, then the withdrawal against that storage root), we can prove against the L2toL1MessagePasser’s storage root directly, thus reducing the verification cost of withdrawals on L1. After Isthmus hard fork, thewithdrawal_storage_rootis present in the block header aswithdrawalsRootand can be used directly, instead of computing the storage root of the L2toL1MessagePasser contract. Similarly, if Isthmus hard fork is active at the genesis block, thewithdrawal_storage_rootis present in the block header aswithdrawalsRoot.
L2 Output Oracle Smart Contract
L2 blocks are produced at a constant rate ofL2_BLOCK_TIME (2 seconds).
A new L2 output MUST be appended to the chain once per SUBMISSION_INTERVAL which is based on a number of blocks.
The exact number is yet to be determined, and will depend on the design of the fault proving game.
The L2 Output Oracle contract implements the following interface:
Configuration
ThestartingBlockNumber must be at least the number of the first Bedrock block.
The startingTimestamp MUST be the same as the timestamp of the start block.
The first outputRoot proposed will thus be at height startingBlockNumber + SUBMISSION_INTERVAL