docs / components / sequencer

Block signing (podseq-core)

Block headers are signed so full nodes can attribute each block to the authorized sequencer. Reth owns transaction selection and ordering (PayloadAttributes has no transactions field, so Reth fills each block from its own mempool, gas-price greedy and gas-limit capped). Podseq's role is block production: timing, signing, DA publication, settlement, and P2P broadcast.

Ed25519BlockSigner#

The canonical BlockSigner implementation lives in podseq-core, next to the trait. It signs block headers with an ed25519 key loaded from a suiprivkey file. Full nodes verify signatures against the configured signer.sequencer_pubkey.

let signer = Ed25519BlockSigner::from_suiprivkey_file(path)?;
let signature = signer.sign_header(&header)?;

Forced inclusion#

The single sequencer can censor any ordinary tx by refusing to include it. Forced inclusion removes that power: users post a tx to a Sui-side inbox, and the sequencer must include it within N blocks or halt. After each engine.build(), the sequencer pulls unread inbox entries, submits each to Reth's mempool via eth_sendRawTransaction, and advances the inbox cursor once the tx is mined. Full nodes verify the liveness invariant on settlement.

Forced txs enter the same mempool as user txs and ride the same gas-limit cap, so block validity is unchanged. The sequencer's only choice is to include the forced tx or stop producing blocks.

Trust model#

The single sequencer is trusted for liveness (block production halts if it goes offline). State validity is verifiable by anyone: every block is executed by Reth, and every block's data is anchored on Walrus + Sui so full nodes independently reconstruct the chain. Forced inclusion bounds the sequencer's censorship power; exit queues bound its liveness power.