Skip to main content

Zelana Architecture Overview

What is Zelana?

Zelana is a privacy-focused Layer 2 rollup prototype built on Solana. It combines:

  • Shielded transaction primitives for privacy (nullifiers, commitments, ZK proofs)
  • Threshold encryption building blocks for MEV resistance (transactions encrypted until ordering is finalized)
  • Low-latency UDP transport (Zephyr) for fast transaction submission
  • ZK rollup settlement on Solana using Groth16 proofs (BN254), with hooks for other proof systems

High-Level Architecture

 _______________________________
| ZELANA L2 ROLLUP |
|_______________________________|

_______________________________
| CLIENT LAYER |
| TypeScript SDK | React UI |
| Rust CLI | Zephyr UDP |
|_______________________________|

HTTP/REST + UDP/Zephyr
|
v

_______________________________
| SEQUENCER (core/) |
| API -> Pipeline -> Settlement |
| Threshold Mempool -> Batch |
| TxRouter <-> Storage Layer |
| Bridge (deposits/withdrawals) |
|_______________________________|

WebSocket (deposits) / Transactions (settlement)
|
v

_______________________________
| SOLANA L1 (onchain-programs/) |
| Bridge Program | Verifier |
|_______________________________|

Core Components

1. Sequencer (core/)

The sequencer is the heart of Zelana. It:

  • Receives transactions (HTTP or UDP)
  • Executes them against L2 state
  • Batches transactions into blocks
  • Generates ZK proofs
  • Settles batches on Solana L1

Key Modules:

ModulePathPurpose
APIcore/src/api/HTTP endpoints (Axum-based)
Pipelinecore/src/sequencer/pipeline.rsOrchestrates batch→prove→settle flow
BatchManagercore/src/sequencer/execution/batch.rsManages batch lifecycle
TxRoutercore/src/sequencer/execution/tx_router.rsRoutes and executes transactions
Storagecore/src/sequencer/storage/RocksDB persistence layer
Bridgecore/src/sequencer/bridge/L1↔L2 deposit/withdrawal handling
Provercore/src/sequencer/settlement/prover.rsZK proof generation
Settlercore/src/sequencer/settlement/settler.rsL1 batch submission

2. On-Chain Programs (onchain-programs/)

Two Solana programs secure the L1 side:

ProgramPurpose
BridgeHandles deposits, withdrawals, batch submissions
VerifierVerifies Groth16 proofs on-chain

3. SDK Crates (sdk/)

CratePurpose
zelana-transactionTransaction types and signing
zelana-privacyShielded transactions, notes, nullifiers
zelana-thresholdThreshold encryption for MEV resistance
zelana-blockBlock header structure
zelana-accountAccount ID and state types
txblobEncrypted transaction blob format + crypto
zephyrLow-latency UDP transport protocol

4. Prover (prover/)

The ZK prover generates Groth16 proofs (BN254 curve) that:

  • Prove correct state transitions
  • Verify all transactions were valid
  • Enable trustless L1 verification

Batches vs Blocks

Key Insight: A Block is the finalized form of a Batch

 ________________________________
| Batch (during processing) |
| batch_id: u64 |
| transactions: Vec<Tx> |
| state: BatchState |
| pre_state_root |
| post_state_root |
| diff: BatchDiff |
| proof: Option<BatchProof> |
|_______________________________|

________________________________
| Block (after finalization) |
| batch_id: u64 (same!) |
| prev_root: [u8; 32] |
| new_root: [u8; 32] |
| tx_count: u32 |
| open_at: u64 (timestamp) |
| flags: u32 |
| magic: "ZLNA" |
| hdr_version: u16 |
|_______________________________|

Batch Lifecycle

Accumulating → Sealed → Proving → Proved → Settling → Finalized

BlockHeader created

Stored in CF_BLOCKS

Why Two Concepts?

ConceptWhen UsedPurpose
BatchDuring processingInternal unit with full transaction data, proofs, diffs
BlockAfter settlementCompact 96-byte header for chain state

BlockHeader Structure

pub struct BlockHeader {
pub magic: [u8; 4], // "ZLNA" - identifies Zelana blocks
pub hdr_version: u16, // Currently 1
pub batch_id: u64, // Same ID as the batch (1:1 mapping)
pub prev_root: [u8; 32], // State root before batch execution
pub new_root: [u8; 32], // State root after batch execution
pub tx_count: u32, // Number of transactions in this block
pub open_at: u64, // Timestamp when batch was opened
pub flags: u32, // Reserved for future use
}

Pipeline Parallelism

The sequencer runs three operations in parallel:

Time ________________________________________________▶

________________________
| Batch N | -> Accumulating transactions
| ACCUMULATING |
|_______________________|

________________________
| Batch N-1 | -> Generating ZK proof
| PROVING |
|_______________________|

________________________
| Batch N-2 | -> Submitting to L1
| SETTLING |
|_______________________|

This maximizes throughput by overlapping:

  1. Accumulation - Collecting new transactions
  2. Proving - CPU-intensive ZK proof generation
  3. Settlement - Network-bound L1 submission

Transaction Types

Zelana supports four transaction types:

TypePrivacyDescription
TransferTransparentStandard L2 balance transfer
DepositTransparentL1 → L2 deposit (indexed from Solana)
WithdrawTransparentL2 → L1 withdrawal
ShieldedPrivateZK-shielded transfer with nullifier/commitment

State Machine Summary

ComponentStatesPrimary Trigger
Transactionpending → included → executed → settledSubmission, execution, settlement
BatchAccumulating → Sealed → Proving → Proved → Settling → FinalizedTX count, time, proof, L1 confirm
WithdrawalPending → InBatch → Submitted → FinalizedBatch progression
Shielded NoteCreated → Inserted → SpentCommitment, nullifier reveal
DepositIndexed → InBatch → CreditedL1 event, batch execution

Storage Architecture

RocksDB Column Families

CF NameKey FormatValue FormatPurpose
accounts[u8; 32] (AccountId)wincode(AccountState)L2 balances/nonces
blocksu64 (batch_id, BE)wincode(BlockHeader)Finalized block headers
batchesu64 (batch_id, BE)JSON(BatchSummary)Batch metadata
tx_index[u8; 32] (tx_hash)JSON(TxSummary)Transaction lookups
tx_blobs[u8; 32] (tx_hash)Vec<u8> (encrypted)Encrypted tx blobs
nullifiers[u8; 32][] (empty)Double-spend prevention
commitmentsu32 (position, BE)[u8; 32]Merkle tree notes
encrypted_notes[u8; 32] (commitment)JSON(EncryptedNote)For viewing key scanning
tree_metastring (key)variesMerkle tree frontier
withdrawals[u8; 32] (tx_hash)Vec<u8>Pending withdrawals
processed_depositsu64 (L1 seq, BE)u64 (slot, BE)Deposit deduplication
indexer_metastring (key)u64 (slot)Indexer checkpoint

Security Model

Trust Assumptions

  1. Sequencer: Currently centralized (single sequencer authority)
  2. ZK Proofs: State transitions are verified on L1 via Groth16
  3. Bridge: Deposits/withdrawals are secured by L1 program logic
  4. Privacy: Shielded transactions use Zcash-style nullifiers

MEV Resistance

When enabled, threshold encryption protects against MEV:

  1. Transactions are encrypted with threshold key
  2. Sequencer orders encrypted transactions
  3. After ordering is finalized, threshold is reached
  4. Transactions are decrypted and executed in the fixed order

Configuration

Configuration loads in this order:

  1. ZL_CONFIG (explicit config path)
  2. ./config.toml (repository root)
  3. ~/.zelana/config.toml

Environment variables override file values. Common overrides:

VariablePurpose
ZL_DB_PATHRocksDB storage path
ZL_API_HOSTSequencer host (HTTP)
ZL_UDP_PORTUDP ingest port
SOLANA_RPC_URLSolana RPC endpoint
SOLANA_WS_URLSolana WebSocket endpoint
ZL_BRIDGE_PROGRAMBridge program ID
ZL_VERIFIER_PROGRAMVerifier program ID
ZL_PROVER_MODEmock, groth16, or noir
ZL_SETTLEMENT_ENABLEDToggle settlement pipeline

Use these links to jump directly to key architecture files: