Phase 1b: book_snapshot loop — mirror reserves + resting book (#322) #793
No reviewers
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic!793
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "cursor/gitlab-issue-workflow-dfd6"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements GitLab #322 (Phase 1b): a background
book_snapshotloop that periodically mirrors on-chain pool reserves, fee config, and resting limit books into the Phase 1a Postgres tables (pair_reserves,resting_limit_orders).Why: Phase 1c (#319) needs a populated mirror and a documented freshness contract before the 0-LCD solver can read from Postgres instead of per-request LCD.
Changes
indexer/src/indexer/book_snapshot.rswithrun_book_snapshot_loop,snapshot_all_pairs, freshness constants (BOOK_SNAPSHOT_MAX_STALENESS_MS, etc.), and documented LCD budget (book_snapshot_lcd_budget).book_snapshot_interval_ms/BOOK_SNAPSHOT_INTERVAL_MS(default 10s).tokio::spawninpoller.rs::run_indexer.docs/runbooks/book-snapshot-mirror.md, row indocs/indexer-invariants.md.indexer/tests/book_snapshot_loop.rs, atomicity test indb_orderbook_mirror.rs, wiremock helperstart_book_snapshot_mock.Acceptance checklist
book_snapshotloop exists and is spawned inpoller.rsbook_snapshot.rs,poller.rscargo test --test book_snapshot_loop snapshot_populates_reserves_and_resting_book -j 1 -- --test-threads=1reserve_0/reserve_1;fee_bpsfromget_fee_configasi16get_pair_resting_bookcargo test --lib book_snapshot::tests+lcd_budget_constant_matches_formulasnapshot_at+block_heightwhen availabledocs/runbooks/book-snapshot-mirror.mdsnapshot_skips_failed_pair_and_keeps_prior_snapshotbook_snapshot_interval_mswiredconfig.rs,.env.exampleVerification for third parties
Unblocks Phase 1c (#319).
Issue: https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/322
changed the description
changed the description
mentioned in issue #322
changed the description
Stale Security Review comment
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues.
Reviewed by Cursor Bugbot for commit
6c5a09acee. Configure here.Staleness ignores configured cadence
Medium Severity
BOOK_SNAPSHOT_MAX_STALENESS_MSis fixed at default cadence × tolerance, whileBOOK_SNAPSHOT_INTERVAL_MScan change the loop interval. Phase 1c is documented to import the constant as the TTL, so custom intervals make staleness checks too strict or too loose relative to the actual mirror cadence.Additional Locations (1)
indexer/src/config.rs#L195-L199Reviewed by Cursor Bugbot for commit
6c5a09acee. Configure here.Reserves commit before book
High Severity
snapshot_single_pairupsertspair_reservesbefore the resting-book LCD walk andreplace_pair_resting_orders. If anything fails afterward, the pair is skipped but reserves already reflect the new pool state whileresting_limit_ordersstays on the prior snapshot, breaking the intended per-pair consistent mirror for Phase 1c hybrid quotes.Reviewed by Cursor Bugbot for commit
6c5a09acee. Configure here.Security review (automated)
Commit reviewed:
6c5a09acee8cc131c6d1025bb49c66449bfa3a59MR: !793 — Phase 1b:
book_snapshotloop (mirror reserves + resting book, #322)Scope: 11 files — new
book_snapshot.rs, poller spawn, config/env, docs/runbook, integration tests (no new HTTP routes).Method
limit_book_lcd.rs(HTTP path already has per-request LCD budgets).Outcome
FINDINGS: 0 (no medium, high, or critical issues on this diff)
Inline threads: none
Notes (below medium / not reported as findings)
upsert_pair_reserves/replace_pair_resting_ordersuse parameterizedsqlxbinds;sidein reads is limited to"bid"/"ask"forORDER BYonly.pair.contract_addressfrom factory-syncedpairsrows (same trust boundary as existing indexer LCD usage); not a new external input surface.BOOK_SNAPSHOT_MAX_STALENESS_MS). Operational concern, not an authn/authz or injection flaw introduced here.Security review: no medium+ findings on this diff.
changed this line in version 2 of the diff
changed this line in version 2 of the diff
added 1 commit
66b3ce95- Fix book snapshot atomicity and staleness TTL cadence linkageCompare with previous version
changed the description
resolved all threads
resolved all threads
Security review (automated)
Commit reviewed:
66b3ce95acebdf069356b6f90d6b4c05f9f37cb5MR: !793 — Phase 1b:
book_snapshotloop (mirror reserves + resting book, #322)Scope: 13 files —
book_snapshot.rs, poller spawn, config/env, DB query transaction wiring, docs/runbook, integration tests (no new HTTP routes).Method
main, with sink tracing for injection, authz, SSRF, secret leakage, and LCD/DB amplification.6c5a09aand Bugbot threads; the atomicity fix (single transaction for reserves + resting book) and cadence-linked staleness TTL are present in this commit.limit_book_lcd.rs(HTTP path already has per-request LCD budgets).Outcome
FINDINGS: 0 (no medium, high, or critical issues on this diff)
Inline threads: none
Notes (below medium / not reported as findings)
upsert_pair_reserves/replace_pair_resting_orders_in_txuse parameterizedsqlxbinds;sidein reads is limited to"bid"/"ask"forORDER BYonly.pair.contract_addressfrom factory-syncedpairsrows (same trust boundary as existing indexer LCD usage); not a new external input surface.pool.begin()→ upsert → replace →commit); rollback path tested indb_orderbook_mirror.rs.book_snapshot_max_staleness_ms). Operational concern, not an authn/authz or injection flaw introduced here.Security review: no medium+ findings on this diff.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
66b3ce95ac. Configure here.Book walk lacks cycle guard
Medium Severity
walk_resting_book_sidefollowsnextpointers untilNonewith no visited-order check or iteration cap. A cyclic or corrupted on-chain book can keep the snapshot task in an endless LCD walk instead of failing the pair and keeping the last good mirror.Reviewed by Cursor Bugbot for commit
66b3ce95ac. Configure here.added 1 commit
af03fbda- fix(indexer): detect cycles when walking resting book for snapshotCompare with previous version
changed the description
resolved all threads
Security review (automated)
Commit reviewed:
af03fbda73270bb119bf9cd0b09a75e9871e3c00MR: !793 — Phase 1b:
book_snapshotloop (mirror reserves + resting book, #322)Scope: 13 files —
book_snapshot.rs, poller spawn, config/env, DB query + migrations, docs/runbook, integration tests (no new HTTP routes).Method
mainon the book_snapshot scope, with sink tracing for injection, authz, SSRF, secret leakage, and LCD/DB amplification.6c5a09a/66b3ce9, Bugbot threads, and the cycle-guard fix in this commit (walk_resting_book_sideHashSet+ earlyErron revisitedorder_id).limit_book_lcd.rs(HTTP path has per-request LCD budgets; background mirror intentionally walks full books).Outcome
FINDINGS: 0 (no medium, high, or critical issues on this diff)
Inline threads: none
Notes (below medium / not reported as findings)
upsert_pair_reserves/replace_pair_resting_orders_in_txuse parameterizedsqlxbinds;get_pair_resting_bookinterpolates onlyASC/DESCfrom a"bid"/"ask"branch —sidevalue itself is bound as$2.pair.contract_addressfrom factory-syncedpairsrows (same trust boundary as existing indexer LCD usage); not a new external input surface.pool.begin()→ upsert → replace →commit); rollback path tested indb_orderbook_mirror.rs.resting_limit_orders.sideCHECK constraint blocks invalid sides.book_snapshot_max_staleness_ms). Operational concern, not an authn/authz or injection flaw introduced here.Security review: no medium+ findings on this diff.
mentioned in commit
74c0449118