a note on citrea's state transition function

july 9, 2025
Citrea state transition diagram

Citrea is a bitcoin rollup. This means that it uses bitcoin for data availability. It is live on testnet and is approaching mainnet.

To advance Citrea's state, like any blockchain, a state transition function is applied over the network's previous state to generate a new state. This is how it works in Citrea:

Citrea's users submit transactions to a sequencer - an offchain node that is responsible for ordering transactions and submitting them to bitcoin on behalf of users.

As the sequencer constructs these L2 "blocks" offchain, Citrea's full nodes need to agree on the state that the sequencer is proposing. To do this, they connect to the sequencer directly, offchain, receive blocks, and execute/apply the state transition function over the transactions. This means they execute all of the proposed transactions that have been sent to the sequencer. After all of the nodes do this, a new state root is generated. From the view of full nodes, the rollup state is finalized.

Periodically, the sequencer posts a commitment transaction with the latest generated state root. This commitment transaction attesting to the most recent state in Citrea, highlighting the differences in the previous state and new state. Full nodes additionally watch bitcoin to ensure that the commitment transaction, in fact, matches the most recent state they generated locally.

The Citrea prover watches these commitments, computes the state differences between each commitment. If valid, it posts proofs of execution to bitcoin. After these proofs are posted, the rollup is considered final from the view of light clients (i.e. bridges). Citrea full nodes are also able to detect any errors in proof submission.

If the sequencer commitment, or proof submission, were invalid, the network would halt. Additionally, the prover cannot generate an "invalid proof" per se, so any light clients would not finalize as a result. So if the sequencer posted "malicious" data, the network would freeze (as would corresponding bridges).

Citrea full nodes do not need to keep a full history of this state as the data required to construct the state of Citrea is made available by bitcoin. After the commitments match the locally state generated, Citrea nodes discard the data. If a node went offline, they could sync their node directly from the data made available by bitcoin.

And by anchoring its state to bitcoin through SNARKs, Citrea is also able to provide a mechanism to convince bridge programs of the state of the rollup. Thus, finalizing them and giving them the ability to execute withdrawals based on the most recent state of Citrea.

I was given some feedback from the Citrea team after this was posted to Twitter. When a node pulls, and applies the STF over, a block from the sequencer, they don't list it as "finalized". They list it as "trusted" until the corresponding sequencer commitment is posted onto bitcoin. After the sequencer commitment it is "final". They then mark it as "proven" after the batch proof is submitted to bitcoin.

← back to blog