#324 Phase 3 — concurrent candidate solve + cache-key robustness #809

Merged
PlasticDigits merged 1 commit from cursor/gitlab-issue-workflow-08a1 into main 2026-06-05 13:52:00 +00:00
PlasticDigits commented 2026-06-05 13:47:05 +00:00 (Migrated from gitlab.com)

Summary

Implements GitLab #324 (Phase 3 of #279):

  1. Concurrent candidate evaluation — solve_global_best_execution fans out per-path optimize + maybe_simulate under SOLVE_CONCURRENCY (= MAX_PATH_CANDIDATES = 5) using tokio::task::JoinSet (no new futures crate). Fail-fast on first candidate error; deterministic first-seen tie-break merge matches the prior serial loop.
  2. Cache-key robustness — hybrid_cache_key buckets max_maker_fills via cache_key_maker_fills (retail 1–8 → 8), drops raw trader address (relies on discount_bps per #283). Bumps solver_version to global_v3 (LCD) / global_v4 (DB) to invalidate stale cache entries.
  3. Truncation honesty — search_truncated on BestExecutionMeta / response + hybrid_notes warning when concurrency cap < enumerated candidates.

Acceptance checklist

Criterion Verification Result
Concurrent eval under bounded cap; latency ~max(candidate) cd indexer && cargo test concurrent_fanout_latency --lib PASS
Same winner/splits/output as serial (incl. tie-break) cd indexer && cargo test merge_ --lib PASS
Meta aggregation (paths, queries, degraded, book leg) cd indexer && cargo test merge_ --lib PASS
max_maker_fills 7/8 share cache key cd indexer && cargo test hybrid_cache_key_maker_fills --lib PASS
Same-tier traders share key; cross-tier isolation cd indexer && cargo test hybrid_cache_key_distinguishes_discount_bps --lib PASS
Truncation flag + hybrid_notes cd indexer && cargo test hybrid_notes_warn_when_search_truncated --lib PASS
Fail-fast on candidate sim error cd indexer && cargo test concurrent_eval_fail_fast --lib PASS
No futures crate added `grep -q '^futures' indexer/Cargo.toml && echo FAIL
cargo test lib + cache-key green cd indexer && cargo test --lib (127 passed) PASS
Integration api_route_solve Requires Postgres (indexer/.env); not run in Cloud Agent VM SKIP
make lint / docs drift python3 scripts/check_route_solver_docs.py PASS

Verification for third parties

cd indexer && cargo test --lib concurrent_solve
cd indexer && cargo test --lib hybrid_cache_key
cd indexer && cargo test --test api_route_solve -- --test-threads=1   # needs Postgres
python3 scripts/check_route_solver_docs.py

Issue left open until merge.


Note

Medium Risk
Changes hybrid route quote caching and solver versioning—wrong cache sharing could serve mismatched fee-tier quotes, though discount_bps isolation and version bump mitigate that; concurrent LCD load increases burst pressure on heavy routes.

Overview
Implements GitLab #324 for global best-execution GET /api/v1/route/solve: path candidates are evaluated concurrently under SOLVE_CONCURRENCY (5, same as top-K cap) via tokio::task::JoinSet, with fail-fast errors and merge logic that preserves serial semantics (max estimated_amount_out, first-seen tie-break, cumulative LCD/DB query counts through the winner).

Cache and versioning: Hybrid GET cache keys now bucket max_maker_fills (cache_key_maker_fills, retail 1–8 → 8), key on discount_bps instead of wallet address (same discount tier shares cache per #283), and bump solver_version to global_v3 (LCD) / global_v4 (DB) to drop stale entries. Responses add optional search_truncated plus a hybrid_notes warning when evaluation hits the concurrency cap.

Docs (route-solver.md, indexer-invariants.md), drift check script, integration expectations, QA #245 script, and agent skill test notes are aligned with the new constants and cache behavior.

Reviewed by Cursor Bugbot for commit 864e072ec1. Bugbot is set up for automated code reviews on this repo. Configure here.

## Summary Implements GitLab [#324](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/324) (Phase 3 of #279): 1. **Concurrent candidate evaluation** — `solve_global_best_execution` fans out per-path `optimize + maybe_simulate` under `SOLVE_CONCURRENCY` (= `MAX_PATH_CANDIDATES` = 5) using `tokio::task::JoinSet` (no new `futures` crate). Fail-fast on first candidate error; deterministic first-seen tie-break merge matches the prior serial loop. 2. **Cache-key robustness** — `hybrid_cache_key` buckets `max_maker_fills` via `cache_key_maker_fills` (retail 1–8 → 8), drops raw trader address (relies on `discount_bps` per #283). Bumps `solver_version` to `global_v3` (LCD) / `global_v4` (DB) to invalidate stale cache entries. 3. **Truncation honesty** — `search_truncated` on `BestExecutionMeta` / response + `hybrid_notes` warning when concurrency cap < enumerated candidates. ## Acceptance checklist | Criterion | Verification | Result | |-----------|--------------|--------| | Concurrent eval under bounded cap; latency ~max(candidate) | `cd indexer && cargo test concurrent_fanout_latency --lib` | PASS | | Same winner/splits/output as serial (incl. tie-break) | `cd indexer && cargo test merge_ --lib` | PASS | | Meta aggregation (paths, queries, degraded, book leg) | `cd indexer && cargo test merge_ --lib` | PASS | | `max_maker_fills` 7/8 share cache key | `cd indexer && cargo test hybrid_cache_key_maker_fills --lib` | PASS | | Same-tier traders share key; cross-tier isolation | `cd indexer && cargo test hybrid_cache_key_distinguishes_discount_bps --lib` | PASS | | Truncation flag + hybrid_notes | `cd indexer && cargo test hybrid_notes_warn_when_search_truncated --lib` | PASS | | Fail-fast on candidate sim error | `cd indexer && cargo test concurrent_eval_fail_fast --lib` | PASS | | No `futures` crate added | `grep -q '^futures' indexer/Cargo.toml && echo FAIL || echo PASS` | PASS | | `cargo test` lib + cache-key green | `cd indexer && cargo test --lib` (127 passed) | PASS | | Integration `api_route_solve` | Requires Postgres (`indexer/.env`); not run in Cloud Agent VM | SKIP | | `make lint` / docs drift | `python3 scripts/check_route_solver_docs.py` | PASS | ## Verification for third parties ```bash cd indexer && cargo test --lib concurrent_solve cd indexer && cargo test --lib hybrid_cache_key cd indexer && cargo test --test api_route_solve -- --test-threads=1 # needs Postgres python3 scripts/check_route_solver_docs.py ``` Issue left open until merge. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes hybrid route quote caching and solver versioning—wrong cache sharing could serve mismatched fee-tier quotes, though discount_bps isolation and version bump mitigate that; concurrent LCD load increases burst pressure on heavy routes. > > **Overview** > Implements GitLab **#324** for global best-execution **`GET /api/v1/route/solve`**: path candidates are evaluated **concurrently** under **`SOLVE_CONCURRENCY`** (5, same as top-K cap) via **`tokio::task::JoinSet`**, with fail-fast errors and merge logic that preserves serial semantics (max **`estimated_amount_out`**, first-seen tie-break, cumulative LCD/DB query counts through the winner). > > **Cache and versioning:** Hybrid GET cache keys now bucket **`max_maker_fills`** (`cache_key_maker_fills`, retail 1–8 → 8), key on **`discount_bps`** instead of wallet address (same discount tier shares cache per **#283**), and bump **`solver_version`** to **`global_v3`** (LCD) / **`global_v4`** (DB) to drop stale entries. Responses add optional **`search_truncated`** plus a **`hybrid_notes`** warning when evaluation hits the concurrency cap. > > Docs (`route-solver.md`, `indexer-invariants.md`), drift check script, integration expectations, QA **#245** script, and agent skill test notes are aligned with the new constants and cache behavior. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 864e072ec1f931020b7b089006a17978946f16b5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
ghost1 commented 2026-06-05 13:47:12 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 13:47:17 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 13:47:18 +00:00 (Migrated from gitlab.com)

mentioned in issue #324

mentioned in issue #324
ghost1 commented 2026-06-05 13:47:25 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 13:47:42 +00:00 (Migrated from gitlab.com)

added 3 commits

  • 806456a4...e41f61bb - 2 commits from branch main
  • 864e072e - feat(indexer): concurrent candidate solve + cache-key robustness (#324)

Compare with previous version

added 3 commits <ul><li>806456a4...e41f61bb - 2 commits from branch <code>main</code></li><li>864e072e - feat(indexer): concurrent candidate solve + cache-key robustness (#324)</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/91/diffs?diff_id=1836836280&start_sha=806456a49713b69bd3b20378bdbbc8477c18ed1a)
PlasticDigits commented 2026-06-05 13:47:44 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 13:47:55 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 13:49:36 +00:00 (Migrated from gitlab.com)

Security review

Commit reviewed: 864e072ec1f931020b7b089006a17978946f16b5
Scope: indexer/src/api/best_execution.rs (concurrent JoinSet candidate eval, merge parity), indexer/src/api/route_solver.rs (hybrid_cache_key / cache_key_maker_fills, resolve_discount_bps, solver version bump), response search_truncated field, docs/tests.

Outcome: FINDINGS: 0 medium+

Summary

Reviewed attacker-controlled inputs (token_in, token_out, amount_in, trader/sender, max_maker_fills) through the hybrid GET cache path and concurrent solve pipeline.

  • Concurrent evaluation: Fan-out is hard-capped at SOLVE_CONCURRENCY (= MAX_PATH_CANDIDATES = 5) per request; JoinSet uses read-only shared state (Arc<AppState>, Arc<HashMap> mirrors). Fail-fast aborts remaining tasks on first candidate error. No unbounded task spawn or cross-request shared mutable state observed.
  • Cache-key change: Trader address removed from key; isolation is via resolved discount_bps (on-chain GetDiscount when configured, else tier_discount_bps from synced tier). Cross-tier collision is covered by unit tests and existing integration tests (route_solve_get_cache_tier_isolation, route_solve_get_cache_same_tier_reuses_lcd). max_maker_fills bucketing (1–8 → 8) can only serve a quote computed with equal or higher fill budget — suboptimal for some callers, not an exploitable over-quote path. Solver version bump (global_v3/global_v4) invalidates stale entries.
  • Auth / injection / leakage: Route solve remains unauthenticated read-only quoting; trader/sender validated as terra1 addresses; LCD 502 bodies stay sanitized; existing LCD-heavy rate limits (10 RPS/IP) still apply. No new SSRF, deserialization, or secret-logging surfaces in this diff.

Inline threads: none (no medium+ findings).


Automated security review (Cursor Cloud Agent)

## Security review **Commit reviewed:** `864e072ec1f931020b7b089006a17978946f16b5` **Scope:** `indexer/src/api/best_execution.rs` (concurrent `JoinSet` candidate eval, merge parity), `indexer/src/api/route_solver.rs` (`hybrid_cache_key` / `cache_key_maker_fills`, `resolve_discount_bps`, solver version bump), response `search_truncated` field, docs/tests. **Outcome:** `FINDINGS: 0` medium+ ### Summary Reviewed attacker-controlled inputs (`token_in`, `token_out`, `amount_in`, `trader`/`sender`, `max_maker_fills`) through the hybrid GET cache path and concurrent solve pipeline. - **Concurrent evaluation:** Fan-out is hard-capped at `SOLVE_CONCURRENCY` (= `MAX_PATH_CANDIDATES` = 5) per request; `JoinSet` uses read-only shared state (`Arc<AppState>`, `Arc<HashMap>` mirrors). Fail-fast aborts remaining tasks on first candidate error. No unbounded task spawn or cross-request shared mutable state observed. - **Cache-key change:** Trader address removed from key; isolation is via resolved `discount_bps` (on-chain `GetDiscount` when configured, else `tier_discount_bps` from synced tier). Cross-tier collision is covered by unit tests and existing integration tests (`route_solve_get_cache_tier_isolation`, `route_solve_get_cache_same_tier_reuses_lcd`). `max_maker_fills` bucketing (1–8 → 8) can only serve a quote computed with equal or higher fill budget — suboptimal for some callers, not an exploitable over-quote path. Solver version bump (`global_v3`/`global_v4`) invalidates stale entries. - **Auth / injection / leakage:** Route solve remains unauthenticated read-only quoting; `trader`/`sender` validated as `terra1` addresses; LCD 502 bodies stay sanitized; existing LCD-heavy rate limits (10 RPS/IP) still apply. No new SSRF, deserialization, or secret-logging surfaces in this diff. **Inline threads:** none (no medium+ findings). --- *Automated security review (Cursor Cloud Agent)*
PlasticDigits commented 2026-06-05 13:50:35 +00:00 (Migrated from gitlab.com)

Security review

Commit reviewed: 864e072ec1f931020b7b089006a17978946f16b5
Scope: MR !809 — concurrent path-candidate evaluation (JoinSet / SOLVE_CONCURRENCY), hybrid GET cache-key changes (cache_key_maker_fills, trader dropped from key, solver_version bump to global_v3/global_v4), search_truncated response metadata, docs/tests.

Outcome: FINDINGS: 0 medium+

Security review: no medium+ findings on this diff.

Areas examined

Area Result
Cache-key / fee-tier isolation hybrid_cache_key now keys on discount_bps + bucketed max_maker_fills; trader address removed. Traced resolve_discount_bps → on-chain GetDiscount (trusted-router trader/sender rules) and DB tier_discount_bps fallback. Cross-tier collision is prevented by distinct discount_bps in the key; same-tier sharing is intentional (#283). Existing integration coverage: route_solve_get_cache_tier_isolation, route_solve_get_cache_same_tier_reuses_lcd. No plausible path for one caller to obtain another wallet's discounted quote via cache poisoning.
Concurrent candidate eval Bounded fan-out (SOLVE_CONCURRENCY = MAX_PATH_CANDIDATES = 5); fail-fast on first candidate error with abort_all. Shared Arc<AppState> / read-only mirror map — no authz bypass or data races identified. Per-request LCD query budget unchanged vs the prior serial loop; burst parallelism is bounded and mitigated by existing per-IP LCD-heavy rate limiting (rate_limit_lcd_heavy_rps, default 10 RPS).
Injection / auth / secrets No new attacker-controlled sinks; terra1 address validation unchanged; no secret leakage or unsafe logging in the diff.

Inline threads: none (no medium+ findings).

## Security review **Commit reviewed:** `864e072ec1f931020b7b089006a17978946f16b5` **Scope:** MR !809 — concurrent path-candidate evaluation (`JoinSet` / `SOLVE_CONCURRENCY`), hybrid GET cache-key changes (`cache_key_maker_fills`, trader dropped from key, `solver_version` bump to `global_v3`/`global_v4`), `search_truncated` response metadata, docs/tests. **Outcome:** `FINDINGS: 0` medium+ Security review: **no medium+ findings** on this diff. ### Areas examined | Area | Result | |------|--------| | **Cache-key / fee-tier isolation** | `hybrid_cache_key` now keys on `discount_bps` + bucketed `max_maker_fills`; trader address removed. Traced `resolve_discount_bps` → on-chain `GetDiscount` (trusted-router `trader`/`sender` rules) and DB `tier_discount_bps` fallback. Cross-tier collision is prevented by distinct `discount_bps` in the key; same-tier sharing is intentional (#283). Existing integration coverage: `route_solve_get_cache_tier_isolation`, `route_solve_get_cache_same_tier_reuses_lcd`. No plausible path for one caller to obtain another wallet's discounted quote via cache poisoning. | | **Concurrent candidate eval** | Bounded fan-out (`SOLVE_CONCURRENCY` = `MAX_PATH_CANDIDATES` = 5); fail-fast on first candidate error with `abort_all`. Shared `Arc<AppState>` / read-only mirror map — no authz bypass or data races identified. Per-request LCD query budget unchanged vs the prior serial loop; burst parallelism is bounded and mitigated by existing per-IP LCD-heavy rate limiting (`rate_limit_lcd_heavy_rps`, default 10 RPS). | | **Injection / auth / secrets** | No new attacker-controlled sinks; `terra1` address validation unchanged; no secret leakage or unsafe logging in the diff. | **Inline threads:** none (no medium+ findings).
PlasticDigits (Migrated from gitlab.com) merged commit 04d38a98d8 into main 2026-06-05 13:52:00 +00:00
PlasticDigits commented 2026-06-05 13:52:01 +00:00 (Migrated from gitlab.com)

mentioned in commit 04d38a98d8

mentioned in commit 04d38a98d8ba8e7c3c5d39c8575520d3cea25fde
PlasticDigits commented 2026-06-05 13:56:16 +00:00 (Migrated from gitlab.com)

mentioned in issue #335

mentioned in issue #335
PlasticDigits commented 2026-06-05 14:08:12 +00:00 (Migrated from gitlab.com)

mentioned in merge request !818

mentioned in merge request !818
PlasticDigits commented 2026-06-08 08:43:13 +00:00 (Migrated from gitlab.com)

mentioned in commit bbe9ae1f3e

mentioned in commit bbe9ae1f3e5ae268a96825523a1387039a14a99a
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!809
No description provided.