Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
jobs:
rust:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout
Expand All @@ -30,4 +31,5 @@ jobs:
run: cargo fmt --all -- --check

- name: Test
timeout-minutes: 15
run: cargo test --workspace --all-targets --all-features --locked
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
/target
sequencer.db
sequencer.db-shm
sequencer.db-wal
benchmarks/results/
33 changes: 21 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,28 @@ Primary objective in this phase: make sequencer behavior, safety checks, and per
## Architecture Map

- `sequencer/src/main.rs`: process bootstrap, env config, queue wiring, HTTP server.
- `sequencer/src/api/mod.rs`: `POST /tx` endpoint, JSON decode, signature recovery, enqueue + wait for commit result.
- `sequencer/src/api/mod.rs`: `POST /tx` and `GET /ws/subscribe` endpoints (tx ingress + replay broadcaster).
- `sequencer/src/api/error.rs`: API error model + HTTP mapping.
- `sequencer/src/inclusion_lane/mod.rs`: inclusion-lane exports and public surface.
- `sequencer/src/inclusion_lane/lane.rs`: batched execution/commit loop (single lane).
- `sequencer/src/inclusion_lane/types.rs`: inclusion-lane queue item and pipeline error types.
- `sequencer/src/inclusion_lane/error.rs`: inclusion-lane runtime and catch-up error types.
- `sequencer/src/l2_tx_broadcaster/mod.rs`: centralized ordered-L2Tx poller + live fanout to WS subscribers.
- `sequencer/src/storage/mod.rs`: DB open, migrations, frame persistence, and direct-input broker APIs.
- `sequencer/src/storage/migrations/`: DB schema/bootstrapping (`0001`) and views (`0002`).
- `app-core/src/application/mod.rs`: app execution interface (`Application`) and wallet prototype.
- `app-core/src/user_op.rs`: signed user-op domain types and EIP-712 payload.
- `app-core/src/l2_tx.rs`: sequenced L2 transaction types used for replay/broadcast boundaries.
- `canonical-app/src/main.rs`: placeholder canonical scheduler binary entrypoint.
- `sequencer/src/storage/migrations/`: DB schema/bootstrapping (`0001`).
- `sequencer-core/src/`: shared domain types/interfaces (`Application`, `SignedUserOp`, `SequencedL2Tx`, broadcast message model).
- `examples/app-core/src/application/mod.rs`: wallet prototype implementing `Application`.
- `examples/canonical-app/src/main.rs`: placeholder canonical scheduler binary entrypoint.

## Domain Truths (Important)

- This is a **sequencer prototype**, not a full DeFi stack yet.
- API validates signature and enqueues signed `UserOp`; method decoding happens during application execution.
- Rejections (`InvalidNonce`, fee cap too low, insufficient gas balance) produce no state mutation and are not persisted.
- Included txs are persisted as frame/batch data in `batches`, `frames`, `user_ops`, `direct_inputs`, and `frame_drains`.
- Batch fee is persisted in `batches.fee` and is fixed for the lifetime of that batch.
- The next batch fee is sampled from `recommended_fees` when rotating to a new batch (default bootstrap value is `1`).
- Included txs are persisted as frame/batch data in `batches`, `frames`, `user_ops`, `direct_inputs`, and `sequenced_l2_txs`.
- Frame fee is persisted in `frames.fee` and is fixed for the lifetime of that frame.
- The next frame fee is sampled from `recommended_fees` when rotating to a new frame (default bootstrap value is `0`).
- `/ws/subscribe` has soft operational guardrails: subscriber cap (`SEQ_WS_MAX_SUBSCRIBERS`, default `64`) and catch-up cap (`SEQ_WS_MAX_CATCHUP_EVENTS`, default `50000`).
- Wallet state (balances/nonces) is in-memory right now (not persisted).

## Hot-Path Invariants
Expand All @@ -68,9 +69,10 @@ Primary objective in this phase: make sequencer behavior, safety checks, and per

- Storage model is append-oriented; avoid mutable status flags for open/closed entities.
- Open batch/frame are derived by “latest row” convention.
- `drain_n` is represented by `frame_drains` rows and is derivable from stored data.
- `drain_n` is derivable from `sequenced_l2_txs` by counting direct-input rows per frame.
- Safe cursor/head values should be derived from persisted facts when possible, not duplicated as mutable fields.
- Replay/catch-up must use persisted ordering plus persisted batch fee (`batches.fee`) to mirror inclusion semantics.
- Replay/catch-up must use persisted ordering plus persisted frame fee (`frames.fee`) to mirror inclusion semantics.
- Included user-op identity is constrained by `UNIQUE(sender, nonce)`.

## Type Boundaries

Expand Down Expand Up @@ -111,7 +113,7 @@ Key env vars:
- `SEQ_HTTP_ADDR`
- `SEQ_DB_PATH`
- `SEQ_QUEUE_CAP`
- `SEQ_QUEUE_TIMEOUT_MS`
- `SEQ_OVERLOAD_MAX_INFLIGHT_SUBMISSIONS`
- `SEQ_MAX_USER_OPS_PER_CHUNK` (preferred)
- `SEQ_MAX_BATCH` (legacy alias)
- `SEQ_SAFE_DIRECT_BUFFER_CAPACITY`
Expand All @@ -120,6 +122,13 @@ Key env vars:
- `SEQ_INCLUSION_LANE_IDLE_POLL_INTERVAL_MS` (preferred)
- `SEQ_INCLUSION_LANE_TICK_INTERVAL_MS` (legacy alias)
- `SEQ_COMMIT_LANE_TICK_INTERVAL_MS` (legacy alias)
- `SEQ_BROADCASTER_IDLE_POLL_INTERVAL_MS`
- `SEQ_BROADCASTER_PAGE_SIZE`
- `SEQ_BROADCASTER_SUBSCRIBER_BUFFER_CAPACITY`
- `SEQ_WS_MAX_SUBSCRIBERS`
- `SEQ_WS_MAX_CATCHUP_EVENTS`
- `SEQ_RUNTIME_METRICS_ENABLED`
- `SEQ_RUNTIME_METRICS_LOG_INTERVAL_MS`
- `SEQ_MAX_BODY_BYTES`
- `SEQ_SQLITE_SYNCHRONOUS`
- `SEQ_DOMAIN_NAME`
Expand Down
Loading