feat(indexer): MR !43 Phase 1c — db_orderbook_sim, solver rewire, poisoned-mirror fidelity #319
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#319
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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
Implement Phase 1c of the 0-LCD hybrid route solver program (MR !761 follow-up): port pool + resting-book math into a
db_orderbook_simmodule, rewirehybrid_route_opt/best_executionto price hops from Postgres (pair_reserves,resting_limit_orders) instead of per-gridHybridSimulationLCD calls, and harden against poisoned-mirror failures where stale or corrupt DB snapshots would mislead traders while still appearing “validated.”Keep one LCD fidelity guard on the winning route only:
maybe_simulate(simulate_swap_operationson the router) must reject or downgrade quotes that diverge from chain truth. Land the breakingquote_kindrename (*_lcd→ DB-backed kinds) in the same increment and coordinate the dApp.Hard dependency: Phase 1b (
book_snapshotloop that populatespair_reserves+resting_limit_orders) must be merged and healthy before 1c goes live; 1c must not ship without a freshness contract for mirrored state.Current codebase
Phase 1a (MR !761 — schema only, not wired to solver)
pair_reserves(one row/pair:reserve_0/1,fee_bps,block_height,snapshot_at),resting_limit_orders(materialized book with liveremaining, walk indexprice+ FIFOorder_id).indexer/src/db/queries/pair_reserves.rs(upsert/get→ missing =None, degrade-not-error),indexer/src/db/queries/resting_orders.rs(replace_pair_resting_orders,get_pair_resting_bookordered bids DESC / asks ASC).indexer/tests/db_orderbook_mirror.rs— CRUD + walk order only; no HTTP/solver paths.MR !761 security review explicitly defers Phase 1c solver fidelity / poisoned-mirror to this work (tables are not read by the live solver yet).
Live solver (LCD-heavy)
indexer/src/api/hybrid_route_opt.rs—optimize_multihop_hybrid_jointruns a 17-pointbook_inputgrid per hop via LCDhybrid_simulation(query_hybrid_sim); pool-only fallback when all grid points fail (degraded).indexer/src/api/best_execution.rs—solve_global_best_executionevaluates up to 5 path candidates serially; each candidate: joint hybrid optimize +maybe_simulateon router.indexer/src/api/route_solver.rs— GET cache (hybrid_cache_key+discount_tierper #283),RouteQuoteKindvaluesindexer_pool_lcd/indexer_hybrid_lcd/indexer_hybrid_lcd_degraded,maybe_simulateas final amount.LCD_HYBRID_SIM_BUDGETinbest_execution.rs; responses exposelcd_hybrid_queries,optimality_scope,hybrid_notes.Existing pure-Rust sim (CG/CMC listing — reuse target)
indexer/src/api/orderbook_sim.rs— AMM curve walk (walk_amm_book,ceil_div, fee on gross).indexer/src/api/hybrid_orderbook_sim.rs— merge pool levels + resting limits for listing depth (#220); still fetches limits via LCD today insimulate_orderbook_cached.smartcontracts/contracts/pair/src/contract.rsquery_hybrid_simulation+orderbook::simulate_match_bids/simulate_match_asks— normative hybrid math.Frontend contract
frontend-dapp/src/types/index.ts—IndexerRouteQuoteKindmirrors indexer snake_case kinds.frontend-dapp/src/utils/swapDisclosure.ts— disclosure copy keyed onindexer_hybrid_lcd/indexer_hybrid_lcd_degraded.Why this is needed
/route/solveslow and cheap to amplify even under per-IP rate limits. DB-backed hybrid grid evaluation removes hundreds of pair-level LCD calls per request while preserving search bounds (top-5 paths, 17-point grid, joint coordinate passes).HybridSimulation. Without explicit poisoned-mirror handling, integrators and the dApp could show optimistic or staleestimated_amount_outthat passes a weak final sim or none at all.quote_kindnames implying*_lcdbecome misleading; clients need honest labels (indexer_hybrid_db, degraded/fidelity-reject variants) and response metadata (snapshot height, drift flags).Constraints and guardrails
pair_reservesandresting_limit_ordersfrom chain (modeled on oracle/tier-sync loops). Define max staleness (block lag /snapshot_atTTL); 1c must degrade (LCD fallback or explicit error) when mirror is missing or too stale — never silent best-effort with empty book.maybe_simulateon the winning route only after DB optimization. If router sim is unavailable, response must usequote_kind/hybrid_notesthat do not imply chain-validated output.estimated_amount_outexceeds LCD sim by more than a documented tolerance (or sim fails), do not return the DB amount as final — downgrade toindexer_*_degraded/indexer_route_onlyor reject with 400/502 per existing LCD gateway patterns; log structured drift metrics (pair, hop, block heights).orderbook_sim/hybrid_orderbook_simand align with pairquery_hybrid_simulation(pool leg + book walk caps:max_maker_fills, scan steps, fee tier viaQuoteTraderwhen mirrored tier data exists). Property tests against LCD mock on sampled grids before cutover.trader/sender/discount_tierinputs as LCD path; cache keys must include tier and solver generation bump (e.g.global_v2ordb_hybrid_v1)./cg/orderbook(#278 rate-limit class) — optional follow-up; 1c focuses on route solver.quote_kindrename is intentional; coordinate frontend +docs/indexer-invariants.md+skills/AGENTS_INDEXER_HYBRID_BEST_EXECUTION.mdin the same release train.Relevant files
indexer/migrations/20260605010000_pair_reserves.sql,20260605010100_resting_limit_orders.sql,indexer/src/db/queries/pair_reserves.rs,resting_orders.rsoracle/trader_trackerpatterns)indexer/src/api/db_orderbook_sim.rs(orhybrid_sim_db.rs), exports used byhybrid_route_optindexer/src/api/hybrid_route_opt.rs,best_execution.rs,route_solver.rsorderbook_sim.rs,hybrid_orderbook_sim.rs,limit_book_lcd.rs(reference only)smartcontracts/contracts/pair/src/contract.rs,orderbook.rsindexer/tests/db_orderbook_mirror.rs,api_route_solve.rs,common/lcd_mock.rs; newapi_route_solve_db_hybrid.rsor extend existingfrontend-dapp/src/types/index.ts,utils/swapDisclosure.ts,services/indexer/__tests__/client.test.tsdocs/indexer-invariants.md,docs/adr/0002-global-best-execution-route-solver.md,docs/integrators.md,skills/AGENTS_INDEXER_HYBRID_BEST_EXECUTION.mdRecommended direction
db_orderbook_sim: Givenpair_id,offer_token,pool_input/book_input,max_maker_fills,QuoteTrader, and rows frompair_reserves+resting_limit_orders, returnreturn_amountmatchingHybridSimulationResponsesemantics. Unit-test againstwalk_amm_book+ book walk with seeded mirror rows (no LCD).hybrid_route_opt: Replacequery_hybrid_simLCD calls in the grid / coordinate passes with DB sim when mirror is fresh; on missing/stale mirror per hop → pool-only DB leg if reserves exist, else markdegradedand optionally LCD fallback for that hop only (document which path is taken).maybe_simulateonce. Compare DB grid winner output to router sim; implement drift detection (absolute/relative threshold configurable). Set newquote_kindvariants and extendhybrid_noteswith snapshotblock_height/ age.hybrid_notes) formirror_max_block_lag,db_hybrid_queries(replacing or supplementinglcd_hybrid_queries),fidelity_check: passed | drift | skipped.solver_version: e.g.global_v2/db_hybrid_v1so caches and integrators can distinguish LCD-grid vs DB-grid eras.quote_kindvalues; update disclosure strings (“indexed mirror” vs “LCD snapshot”).ROUTE_SOLVER_DB_HYBRID=1for staged rollout on mainnet; default off until drift tests green in CI.Acceptance criteria
GET /api/v1/route/solve?amount_in=…returns the same winning path/splits as LCD mock baseline within tolerance without pair-levelhybrid_simulationLCD calls during optimization (assert via wiremock request counts).maybe_simulateis invoked once per request on the winning route whenROUTER_ADDRESSis set.pair_reservesor emptyresting_limit_ordersfor a hop → documented degrade (pool-only DB or explicit error),quote_kindreflects degraded state, notindexer_hybrid_lcd.return_amountvs LCD mock truth) → final response does not advertise the poisoned amount as validated; drift flagged or sim error returned.quote_kindrename shipped with frontend + OpenAPI + docs; old*_lcdhybrid kinds removed or aliased with deprecation period documented.solver_versionand cache key generation updated; #283 tier isolation preserved.cargo testroute-solve + new db hybrid tests pass;make lint/ indexer lib tests green.Test plan (functional paths)
fidelity_check=passed; zero hybrid_sim LCD during gridquote_kindpool DB variant; amount matches pool walkpair_reservesfor hop pairsnapshot_at/ block lagrouter_addressunsetestimated_amount_outabsent;indexer_route_only; no false “validated” copytrader/sendertiertraders.tier_idseeds (#283)max_maker_fillscaphybrid_by_hopoverridepool_only=truequote_kindin API fixtureswapDisclosureshows correct copyTest plan (attack, hack, and abuse vectors)
reserve_*maybe_simulatefails closed; metric + warn; no inflatedestimated_amount_outhybrid_noteswarn; optional rejectdiscount_tier+ newsolver_versionamount_inmicro-units/route/solveindexer_route_only; frontend does not claim execution parityindexer_hybrid_*_degraded+ explicit notesremainingin mirrormax_maker_fillsAdd property or differential tests: random small grids comparing
db_orderbook_simvs wiremock LCDhybrid_simulationon identical mirror + chain state fixtures.Verification criteria
cd indexer && cargo test --test api_route_solve --test db_orderbook_mirror(+ new db hybrid test binary) all green.cd indexer && cargo test --libgreen.make test-frontend/swapDisclosuretests updated for new kinds./route/solveoutput to pre-1c LCD baseline on same block; drift rate < agreed threshold on smoke pairs.docs/indexer-invariants.mdrow for route GET updated (DB mirror, fidelity guard, newquote_kindtable).fidelity_drift,mirror_stale,db_hybrid_queriespresent in structured logs.Related
marked as related to #209
marked as related to #220
marked as related to #279
marked as related to #283
mentioned in issue #322
mentioned in issue #323
mentioned in issue #324
mentioned in issue #279
Your hard dependency here — Phase 1b, the book_snapshot loop that populates pair_reserves + resting_limit_orders and defines the staleness contract — is now tracked as #322 (split out of #279 along with Phase 2 #323 and Phase 3 #324). 1c shouldn't go live until #322 is merged and healthy, per the freshness contract.
marked as related to #322
marked as related to #323
marked as related to #324
mentioned in merge request !793
mentioned in merge request !796
mentioned in merge request !798
mentioned in commit
233eb6be64Phase 1c implementation pushed in !798.
Highlights:
db_orderbook_sim,global_v2behindROUTE_SOLVER_DB_HYBRID=1, routerfidelity_checkdrift guard, newindexer_*_dbquote kinds + frontend disclosure.Verify:
Do not enable
ROUTE_SOLVER_DB_HYBRIDin prod until #322 snapshot loop is healthy.mentioned in commit
e0f9e00ca2mentioned in commit
0dd92913f8mentioned in commit
c0dd1104ebmentioned in merge request !808
mentioned in commit
666d7f4c4bmentioned in merge request !818
mentioned in issue #332
mentioned in commit
abe16fc6a7mentioned in commit
17b9bba754mentioned in issue #418
mentioned in issue #420
mentioned in issue #485
mentioned in issue #493