feat(indexer): #279 Phase 1a — pair_reserves + resting_limit_orders schema #761

Merged
Brouie merged 1 commit from qa/279-phase1a-state-mirror-schema into main 2026-06-05 04:35:30 +00:00
Brouie commented 2026-06-05 03:46:19 +00:00 (Migrated from gitlab.com)

Starting #279 (the 0-LCD solver) — this is Phase 1a, the schema foundation, scoped deliberately small and self-contained. It lands the two Postgres tables + their query layer with full CRUD tests and touches nothing in the live solver/API — so no fidelity risk and nothing to coordinate yet.

Adds:

  • migration pair_reserves — current v2 pool state (reserve_0/1, fee_bps, height), one row per pair, upserted per snapshot. Reserves aren't event-sourced today (they only live on-chain behind {pool:{}}), so this is the table the snapshot loop will fill.
  • migration resting_limit_orders — a materialized current-state book (live remaining per order), distinct from the append-only placement/cancel/fill logs; indexed for the walk order (price + FIFO).
  • db::queries::pair_reserves (upsert/get; missing -> None = degrade-not-error) and db::queries::resting_orders (atomic replace-pair-book; get-book ordered best-price-then-FIFO).
  • revert/*.down.sql for both; test-DB cleanup truncates the new tables.

Tests 3/3: reserves upsert-replace + missing-is-None; resting-book replace + walk ordering (bids DESC, asks ASC, FIFO at equal price).

Subsequent increments (need live fidelity validation, hence not bundled): 1b the book_snapshot loop that populates these from chain state (modeled on the oracle/tier-sync loops); 1c db_orderbook_sim (port the pool+book math, reuse the CG/CMC #220 sim) + rewire hybrid_route_opt/best_execution to read DB instead of LCD, keeping the final maybe_simulate LCD validation on the winning route as the fidelity-drift guard; then Phase 2 (4-hop bump) and Phase 3 (cache-key — #283 already shipped standalone as !751). The breaking quote_kind rename lands with 1c → coordinate with frontend then. No closing keyword.

Starting #279 (the 0-LCD solver) — this is **Phase 1a, the schema foundation**, scoped deliberately small and self-contained. It lands the two Postgres tables + their query layer with full CRUD tests and **touches nothing in the live solver/API** — so no fidelity risk and nothing to coordinate yet. Adds: - migration `pair_reserves` — current v2 pool state (reserve_0/1, fee_bps, height), one row per pair, upserted per snapshot. Reserves aren't event-sourced today (they only live on-chain behind `{pool:{}}`), so this is the table the snapshot loop will fill. - migration `resting_limit_orders` — a materialized current-state book (live `remaining` per order), distinct from the append-only placement/cancel/fill logs; indexed for the walk order (price + FIFO). - `db::queries::pair_reserves` (upsert/get; missing -> `None` = degrade-not-error) and `db::queries::resting_orders` (atomic replace-pair-book; get-book ordered best-price-then-FIFO). - `revert/*.down.sql` for both; test-DB cleanup truncates the new tables. Tests 3/3: reserves upsert-replace + missing-is-None; resting-book replace + walk ordering (bids DESC, asks ASC, FIFO at equal price). Subsequent increments (need live fidelity validation, hence not bundled): **1b** the `book_snapshot` loop that populates these from chain state (modeled on the oracle/tier-sync loops); **1c** `db_orderbook_sim` (port the pool+book math, reuse the CG/CMC #220 sim) + rewire `hybrid_route_opt`/`best_execution` to read DB instead of LCD, keeping the final `maybe_simulate` LCD validation on the winning route as the fidelity-drift guard; then Phase 2 (4-hop bump) and Phase 3 (cache-key — #283 already shipped standalone as !751). The breaking `quote_kind` rename lands with 1c → coordinate with frontend then. No closing keyword.
PlasticDigits commented 2026-06-05 03:47:46 +00:00 (Migrated from gitlab.com)

Security review (automated)

Commit reviewed: 5392f968f9d2e57b5b576efd14b104aa1e77b22b
Scope: Phase 1a schema foundation — pair_reserves + resting_limit_orders migrations, db::queries::{pair_reserves,resting_orders}, integration tests, test DB cleanup. No HTTP/API/solver wiring in this diff.

Outcome: FINDINGS: 0 medium+

Inline threads: none (no medium+ findings to anchor)

Summary

Reviewed attacker-controlled input paths and sinks across the added query layer:

  • SQL injection: All user/caller-facing values use sqlx parameter binding ($1…$8). In get_pair_resting_book, the only format! interpolation is price_dir, constrained to "DESC" or "ASC" via side == "bid" — not derived from raw caller strings. side itself is bound as $2.
  • Authn/authz: No new HTTP routes or externally callable handlers; functions are only referenced from integration tests in this MR.
  • Secret leakage / logging: None introduced.
  • SSRF / XSS / deserialization: Not applicable to this DB-only change set.

Phase 1c solver fidelity / poisoned-mirror concerns are out of scope for this diff (tables are not read by the live solver yet; MR description defers wiring to later phases with LCD validation guard).

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `5392f968f9d2e57b5b576efd14b104aa1e77b22b` **Scope:** Phase 1a schema foundation — `pair_reserves` + `resting_limit_orders` migrations, `db::queries::{pair_reserves,resting_orders}`, integration tests, test DB cleanup. No HTTP/API/solver wiring in this diff. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none (no medium+ findings to anchor) ### Summary Reviewed attacker-controlled input paths and sinks across the added query layer: - **SQL injection:** All user/caller-facing values use sqlx parameter binding (`$1`…`$8`). In `get_pair_resting_book`, the only `format!` interpolation is `price_dir`, constrained to `"DESC"` or `"ASC"` via `side == "bid"` — not derived from raw caller strings. `side` itself is bound as `$2`. - **Authn/authz:** No new HTTP routes or externally callable handlers; functions are only referenced from integration tests in this MR. - **Secret leakage / logging:** None introduced. - **SSRF / XSS / deserialization:** Not applicable to this DB-only change set. Phase 1c solver fidelity / poisoned-mirror concerns are out of scope for this diff (tables are not read by the live solver yet; MR description defers wiring to later phases with LCD validation guard). **Security review: no medium+ findings on this diff.**
PlasticDigits commented 2026-06-05 04:19:53 +00:00 (Migrated from gitlab.com)

mentioned in issue #319

mentioned in issue #319
PlasticDigits (Migrated from gitlab.com) merged commit 8ea4bc1420 into main 2026-06-05 04:35:30 +00:00
PlasticDigits commented 2026-06-05 04:35:31 +00:00 (Migrated from gitlab.com)

mentioned in commit 8ea4bc1420

mentioned in commit 8ea4bc1420869273b102acca681c6836f9e13fb1
Brouie commented 2026-06-05 08:23:01 +00:00 (Migrated from gitlab.com)

mentioned in issue #322

mentioned in issue #322
Brouie commented 2026-06-05 08:23:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #279

mentioned in issue #279
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic!761
No description provided.