Prototype sequencer, currently backed by a dummy wallet app (Transfer, Deposit, Withdrawal).
Current focus is reliability of sequencing, persistence, and replay semantics.
- Language: Rust (edition 2024)
- API: Axum (
POST /tx,GET /ws/subscribe) - Hot path: single blocking inclusion lane
- Storage: SQLite (
rusqlite, WAL) - Signing: EIP-712 (
alloy) - Payload encoding: SSZ
- User ops arrive through the API, are validated, executed, and persisted by the inclusion lane.
- Direct inputs are stored in SQLite (
direct_inputs) and sequenced in append-only replay order (sequenced_l2_txs). - Ordering is deterministic and persisted. Replay/catch-up reads
sequenced_l2_txs(joined withuser_ops/direct_inputs). - Frame fee is fixed per frame (
frames.fee):- users sign
max_fee - inclusion validates
max_fee >= current_frame_fee - execution charges
current_frame_fee(not signed max) - next frame fee is sampled from
recommended_feeswhen rotating to a new frame
- users sign
From repo root:
cargo check
cargo test
cargo fmt --all
cargo clippy --all-targets --all-features -- -D warningsRun server with defaults:
SEQ_HTTP_ADDR=127.0.0.1:3000 \
SEQ_DB_PATH=sequencer.db \
cargo run -p sequencerRequest shape:
{
"message": {
"nonce": 0,
"max_fee": 1,
"data": "0x..."
},
"signature": "0x...",
"sender": "0x..."
}POST notes:
signaturemust be 65 bytes.senderis required and must match recovered signer.message.datais SSZ-encoded method payload bytes.- payload size is bounded at ingress; oversized requests are rejected before they enter hot path.
WebSocket stream of sequenced L2 transactions from persisted order.
Notes:
from_offsetis optional (defaults to0).- messages are JSON text frames.
- binary fields are hex-encoded (
0x-prefixed). - handshake is rejected with
429whenSEQ_WS_MAX_SUBSCRIBERSis exceeded (default64). - connections with
live_start_offset - from_offset > SEQ_WS_MAX_CATCHUP_EVENTSare closed immediately (default50000).
Message shapes:
{ "kind": "user_op", "offset": 10, "sender": "0x...", "fee": 1, "data": "0x..." }{ "kind": "direct_input", "offset": 11, "payload": "0x..." }Success response:
{
"ok": true,
"sender": "0x...",
"nonce": 0
}Main environment variables:
SEQ_HTTP_ADDRSEQ_DB_PATHSEQ_QUEUE_CAPSEQ_OVERLOAD_MAX_INFLIGHT_SUBMISSIONSSEQ_MAX_USER_OPS_PER_CHUNK(SEQ_MAX_BATCHis legacy alias)SEQ_SAFE_DIRECT_BUFFER_CAPACITYSEQ_MAX_BATCH_OPEN_MSSEQ_MAX_BATCH_USER_OP_BYTESSEQ_INCLUSION_LANE_IDLE_POLL_INTERVAL_MSSEQ_INCLUSION_LANE_TICK_INTERVAL_MS(legacy alias)SEQ_COMMIT_LANE_TICK_INTERVAL_MS(legacy alias)SEQ_BROADCASTER_IDLE_POLL_INTERVAL_MSSEQ_BROADCASTER_PAGE_SIZESEQ_BROADCASTER_SUBSCRIBER_BUFFER_CAPACITYSEQ_WS_MAX_SUBSCRIBERSSEQ_WS_MAX_CATCHUP_EVENTSSEQ_MAX_BODY_BYTESSEQ_SQLITE_SYNCHRONOUSSEQ_DOMAIN_NAMESEQ_DOMAIN_VERSIONSEQ_DOMAIN_CHAIN_IDSEQ_DOMAIN_VERIFYING_CONTRACT
batches: batch metadataframes: frame boundaries within each batchframes.fee: committed fee for each frameuser_ops: included user operationsdirect_inputs: direct-input payload streamsequenced_l2_txs: append-only ordered replay rows (UserOpxorDirectInput)recommended_fees: singleton mutable recommendation for next frame fee
No SQL views are required in the current prototype schema.
sequencer/src/main.rs: bootstrap, env config, HTTP server + lane lifecyclesequencer/src/api/: HTTP API and error mappingsequencer/src/inclusion_lane/: hot-path inclusion loop, chunk/frame/batch rotation, catch-upsequencer/src/l2_tx_broadcaster/: centralized ordered-L2Tx poller + subscriber fanoutsequencer/src/storage/: schema, migrations, SQLite persistence and replay readssequencer-core/src/: shared sequencer domain types and interfaces (Application,SignedUserOp,SequencedL2Tx, broadcaster message types)examples/app-core/src/: wallet prototype implementing the sharedApplicationtraitexamples/canonical-app/src/main.rs: placeholder canonical runtime entrypoint
- Wallet state is in-memory (not persisted).
- Direct-input ingestion from chain is not implemented yet (currently append via storage APIs).
- Schema/migrations are still in prototype mode and may change.
Apache-2.0. See LICENSE.
Authors are listed in AUTHORS.