ZUL://DOCSPRIVACY LAYER 2 — SETTLED ON SOLANA
INDEX
CHAIN — /docs/chain/blocks

Blocks & slots

ZUL produces one block per slot, and a slot is a fixed 500 ms of wall-clock time (configurable at genesis). There is no fork choice and no missed-leader case: a single sequencer runs a production loop, so slot numbers and block heights are the same thing.

Block anatomy

BLOCK
Block {
  slot:          u64        // monotonic, one per 500 ms
  parent_hash:   Hash       // blockhash of slot - 1
  blockhash:     Hash       // hash over this block's contents
  timestamp:     i64        // sequencer wall clock, ms
  state_root:    Hash       // blake3 SMT root after executing txs[]
  txs:           [Transaction]
  sequencer_sig: Signature  // sequencer key signs the block
}
  • parent_hash chains blocks; genesis has a sentinel parent.
  • state_root commits to the entire account state after this block — every block, not just settlement batches. See State commitment.
  • sequencer_sig makes a block self-authenticating: anyone replaying DA data can check it was produced by the sequencer key.

The production loop

  1. Drain the mempool (bounded FIFO with signature dedup).
  2. Execute the batch through the SVM against the current account store. Failed transactions are included with their error — like Solana, inclusion ≠ success.
  3. Update the state SMT for touched accounts, advance sysvars (Clock each slot), push the new blockhash into the 150-deep blockhash queue.
  4. Sign, persist, and announce the block over WebSocket.

Empty slots

Blocks are produced every slot locally even when there are no transactions — but only non-empty data is batched to L1, so an idle chain costs almost nothing in settlement fees. The explorer shows empty slots as blocks with zero transactions.

EXPLORER

Watch blocks land twice a second on /explorer/blocks.