Consensus and the Engine API
Frost separates consensus from execution, as Ethereum does after the Merge, but changes who decides what goes into a block. On Ethereum the consensus client says “build a block” and the execution client picks transactions from its own mempool. On Frost the consensus layer decides the exact contents, and the execution layer’s job is to reproduce them.
Why a DAG
Section titled “Why a DAG”Consensus on Frost is Mysticeti V2, a DAG-based BFT protocol extracted from the Sui codebase.
Leader-based protocols elect one proposer per round. That proposer’s bandwidth bounds throughput, and a slow or unavailable leader stalls the round until a timeout fires. Both properties get worse when the payload is large — and post-quantum transactions are large.
DAG protocols let every validator propose continuously, with blocks referencing what their author has seen from others. The resulting graph already encodes who saw what and when, so the total order can be computed locally from its structure rather than agreed in a separate voting round. Throughput scales with the whole committee rather than one member, and no single participant can stall a round.
For a chain whose transactions are kilobytes rather than hundreds of bytes, that is the difference between a comfortable one-second block interval and a bottleneck.
Why the execution layer does not choose
Section titled “Why the execution layer does not choose”Once consensus has fixed an order, the execution layer must produce exactly the block that order implies. If it could add transactions from its own mempool, reorder, or drop, then two nodes could build different blocks from the same committed input — which is a fork.
So the driver uses a forced-transaction profile of the Engine API: it passes the committed list as an explicit payload attribute together with a flag telling the execution layer to add nothing of its own, retrieves the built payload, and delivers it back as the head. The execution client additionally runs with a guard that refuses to build from its own mempool at all, so the property is enforced rather than merely requested.
The upside beyond correctness: there is no local discretion to censor or reorder with. An operator who wants to exclude a transaction has to convince consensus, not just their own node.
Deterministic skipping
Section titled “Deterministic skipping”This is the load-bearing property of the whole design, and it deserves stating precisely.
Consensus orders opaque bytes. It does not run the EVM, cannot decode a transaction, and does not know whether one is valid. So the committed list will sometimes contain transactions that cannot execute — a stale nonce, an insufficient balance, a corrupt post-quantum witness.
Every execution layer must therefore skip exactly the same transactions, for exactly the same reasons. Skipping is specified as a pure function of the ordered list and the parent state. Two nodes given identical input produce byte-identical blocks, including identical state roots.
Note what this means for the submission gate. The ingress validates transactions before forwarding them, but that validation is a courtesy — it saves block space and gives users an immediate reason for rejection. It is not the safety property. The safety property is underneath, and it is tested directly by smuggling known-invalid transactions past the gate and asserting every node still agrees.
Why the interface is narrow
Section titled “Why the interface is narrow”The execution and consensus layers are separate codebases in different languages. The interface between them is a small, versioned profile of an existing standard rather than a bespoke integration.
That has practical consequences: the execution layer stays close to upstream go-ethereum and can absorb upstream changes; the consensus layer stays close to its own upstream; and the surface where a mistake becomes a consensus bug is small enough to reason about exhaustively.
Crash safety
Section titled “Crash safety”A driver that has told consensus “committed” and then crashes before the execution layer has the block must not lose it. So the driver keeps a write-ahead journal, appended before each committing call, and reconciles it against the execution layer’s head on startup.
A clean restart resumes. An execution layer that lost blocks — say it was killed and recovered at an earlier state — has them re-driven from replayed commits, with every rebuild asserted against the journaled block hash.
That assertion is the important part. If a rebuild produces a different hash than the journal recorded, the node has encountered nondeterminism, and it halts rather than continuing. Halting is a bad outcome; forking is a worse one, and a node that quietly proceeds past a determinism failure is exactly how a chain splits.
Finality
Section titled “Finality”Because ordering is decided by consensus rather than by accumulated work, a transaction’s position is fixed when it is committed. There is no reorg window and no probabilistic settlement.
The distinction users meet is between ordered and executed: submission acknowledgement means the transaction is in a proposed block, not that it has run. Wait for the receipt to learn what happened.
See also
Section titled “See also”- Architecture — the components and how they connect.
- Consensus and blocks — what the DAG does.
- Fee-blind ordering — a direct consequence of ordering opaque bytes.