Search
K

System Overview

Rollups interact with the Espresso Sequencer, and both interact with the layer 1 blockchain to facilitate trustless state checkpoints. This diagram shows the flow of information through the entire system, starting with transaction submission through clients to various integrated rollups and finally to being certified and checkpointed on the layer 1.
The next sections dive into these components and their interactions in more detail.

Rollup Components

The internal architecture of each rollup will vary greatly depending on the type of rollup (e.g., ZK/optimistic; EVM/app-specific) but all rollups will have a few similar basic components. The internal structure of Rollup 1 is shown in detail in the diagram (for simplicity, the other rollups are abstracted).
A rollup must provide an interface for clients to interact with it. This can be any kind of API, although Ethereum-compatible JSON-RPC will be common. The API responds to queries about the rollup state by reading from a state database, which is populated by the executor, a component which executes every block provided by the sequencer. Finally, a prover (which may be part of a decentralized prover network) is triggered by updates to the state and is responsible for justifying those state updates. For ZK-rollups, the prover will be triggered by every block and produce a validity proof for the state update. For optimistic rollups, the prover will only be triggered if another node publishes an invalid state update, in which case the prover will generate a fraud proof.
In addition to answering state queries, the rollup API may also serve as an endpoint for clients to submit transactions. While clients can submit transactions directly to a sequencer node, doing so is inconvenient for a few reasons:
  • The sequencer’s transaction submission interface is not specific to any one rollup. Clients will have to wrap their rollup-specific transactions into a more generic kind of transaction before submitting.
  • It requires clients to interact with two different services: the rollup API for state queries and the sequencer for transaction submissions. Depending on the client software, this may not even be possible. MetaMask, for example, requires a single URL for each chain that it can use for queries and transaction submission.
It is therefore recommended that rollup servers provide a transaction submission interface as part of their API, for those clients who are already using the rest of the API. Such an interface is actually required for conforming JSON-RPC implementations, since the eth_sendRawTransaction RPC method allows clients of the RPC to submit a transaction. Whatever its interface, the implementation of the rollup’s submission API can be as simple as wrapping rollup transactions into generic transactions and forwarding them to the sequencer.

Transaction Flow

Once a transaction is forwarded or submitted to the sequencer, it will be sequenced into a block, which then propagates back through the rollups’ executors and provers before it is finalized on the layer 1. The sequencer also sends a block commitment (i.e., commitment to the block) to the layer 1 sequencer contract, along with a quorum certificate that the contract uses to authenticate the block. This allows the layer 1 rollup contracts to compare the rollup state update proof against a block commitment which is certified as having been finalized by consensus.
The diagram below shows in more detail the flow of a single transaction from a client through the system.

Transaction Lifecycle

  1. 1.
    User sends a transaction to a rollup server (e.g. an RPC service).
  2. 2.
    The rollup forwards the transaction, along with an identifier for that rollup, to a sequencer node.
  3. 3.
    The sequencer includes the transaction in a block, which is broadcasted to subscribers. One of these subscribers, the rollup node, executes the transaction (along with any other transactions in the block belonging to that rollup). In the case of a ZK rollup, the node may produce a proof of correct execution, which can be broadcast to clients to quickly convince them of the new state.
  4. 4.
    A commitment to the block containing the transaction is persisted in the L1 sequencer contract (along with a proof that the block has been finalized by consensus).
  5. 5.
    A rollup node which has executed the block sends the new rollup state to the L1. It may include a validity proof (for ZK rollups) or open a window for fraud proofs (optimistic rollups).
  6. 6.
    The L1 rollup contract verifies any proofs related to the state update, using the certified block commitment from the sequencer contract to check that the state update corresponds to the correct block.

Finality

The client can very quickly get a strong finality guarantee for their transaction: the instant it is included in a sequencer block (step 3), its finality is guaranteed by the HotShot consensus protocol. That is, as long as no adversary controls more than one third of the HotShot stake, this transaction can never be rolled back. Clients that are especially paranoid about their transaction (maybe it's an especially high-value transaction) can wait a while for the transaction to be certified by the L1, but the strong pre-confirmation provided by HotShot will be good enough for most clients, and provides them with a low-latency experience.
Once a transaction is finalized, clients may want to read the updated rollup state, either to check the results of their transaction's execution or to prepare another transaction. They have several options (listed below) for doing this, depending on who they trust and how much work they are willing to do themselves. Depending on which option they choose, each client can get their preferred tradeoff between latency, trust, and the amount of work they are required to perform.
  • They can leverage HotShot's low latency to get the pre-confirmed block and immediately execute it themselves to compute the new state.
  • They can get an equally fast state update, at the cost of additional trust assumptions, by trusting a rollup server who has executed the transaction to give them the new state, even before a state update proof is generated.
  • In the case of a ZK rollup, they can wait for a state update proof to be generated (step 3) and check that proof. This requires less computation than executing the block, and it is still trustless.
  • Finally, if a client does not want to do any computation on their own (or in the case of an optimistic rollup, where there is no validity proof for the client to check) and does not want to trust a rollup server, they can wait until a state update is certified by the L1 (step 6) to fetch the updated state with no trust or computation.

Multi-rollup Blocks

In general, a block produced by the sequencer (step 3) may include transactions from many different rollups. If we weren't careful, this could create confusion when rollups need to decide which transactions in the block to execute, or it could lead to inefficiencies if rollups need to search through a large block with only one or two transactions for that rollup. To ease this process, each transaction submitted to the sequencer must be associated with a rollup-specific identifier (step 2). When the sequencer produces a block, it organizes all of the transactions in that block into a namespace Merkle tree, using the rollup-specific identifiers as the namespaces.
The namespace Merkle tree is a very specialized kind of key-value map, associating ordered sequences of transactions with each VM identifier. The tree has a unique, short commitment which can be used to verify proofs about the contents of the tree. This allows rollups to prove that a certain commitment corresponds to a tree which contains a certain sequence of transactions for that rollup, and that those are the only transactions in the tree belonging to that rollup. These proofs are small and computationally cheap to check, which makes them suitable for verification by an L1 smart contract. This functionality is essential for ZK rollups that need to prove they have executed all the relevant transactions in a certain block in order to compute a new state, and for optimistic rollups that need to arbitrate a fraud challenge about the execution of relevant transactions in a block.
This namespace Merkle tree commitment is the commitment that is certified and stored in the L1 sequencer contract (step 4). When rollup contracts need to verify an inclusion proof for a sequence of rollup-specific transactions in a particular block, they can read the corresponding block commitment directly from the sequencer contract and use it to verify the proof.
Note that the sequencer does not authenticate the mapping from rollup IDs to transaction sequences. Nothing stops a bad actor from submitting a transaction for one rollup with the ID of another, or from submitting a transaction which is invalid in a particular rollup with the ID of that rollup. As such, rollups will still need the ability to detect and exclude invalid transactions in their execution layers. This is fundamental to rollups with permissionless sequencing.
A well-behaved rollup should choose an ID for itself which is distinct from any IDs which are in use by other well-behaved rollups. This is similar to how, in the Ethereum ecosystem, different EVM blockchains choose different chain IDs, and the responsiblity ultimately falls on users to avoid using a malicious chain which copies the chain ID of some other system. In fact, EVM rollups could in theory use their EVM chain IDs as their Espresso rollup identifiers.