Phase 2 — raise GET_DEFAULT_MAX_HOPS 3→4 for hybrid GET (#323) #796

Merged
PlasticDigits merged 1 commit from cursor/gitlab-issue-workflow-7eef into main 2026-06-05 12:30:13 +00:00
PlasticDigits commented 2026-06-05 11:09:48 +00:00 (Migrated from gitlab.com)

Summary

Closes #323.

Raises GET_DEFAULT_MAX_HOPS from 3 to 4 so the default hybrid GET best-execution solver discovers and prices 4-hop routes, matching GET_POOL_ONLY_MAX_HOPS, the POST BFS cap, and the on-chain router MAX_HOPS = 4.

Changes

  • GET_DEFAULT_MAX_HOPS = 4 in route_solver.rs (module doc + OpenAPI comments updated)
  • LCD_HYBRID_SIM_BUDGET re-derived to 1700 (5 × 4 × 85); comment notes DB-backed pricing post-#319; unit test pins exact magnitude
  • route_paths.rs: 4-hop-only linear graph test + unreachable-goal instrumented test at max_hops = 4
  • api_route_solve.rs: default GET hybrid quote over seeded 4-hop chain (seed_route_solve_4hop)
  • Docs: route-solver.md, integrators.md, indexer-invariants.md; check_route_solver_docs.py expects 1700

No change to hybrid_cache_key shape or discount-tier keying (#283).

Acceptance checklist

Criterion Verification Result
GET_DEFAULT_MAX_HOPS = 4; module doc updated grep GET_DEFAULT_MAX_HOPS indexer/src/api/route_solver.rs PASS
4-hop-only pair discovered via default GET route_solve_get_default_hybrid_four_hops in api_route_solve.rs PASS (path unit tests); integration test added — needs Postgres
LCD_HYBRID_SIM_BUDGET = 1700; budget test pins value cargo test --lib lcd_budget_is_documented_constant PASS
find_paths_top_k reachability at max_hops=4 unchanged four_hop_only_route_within_budget_is_found, unreachable_goal_at_four_hops_does_zero_enumeration PASS
No hybrid_cache_key / tier keying change diff review PASS
Route tests pass cargo test --lib route_paths::tests; cargo test -p indexer route with Postgres PASS (lib); SKIP (integration — no Postgres on agent VM)

Verification for third parties

cd indexer
cargo test --lib route_paths::tests
cargo test --lib lcd_budget_is_documented_constant
python3 ../scripts/check_route_solver_docs.py
# With Postgres + TEST_DATABASE_URL:
cargo test -p indexer route

Blockers

  • #319 dependency: Issue gates this on Phase 1c (db_orderbook_sim) so the 4th hop is DB-priced, not LCD-backed. #319 is not yet on main; merge this MR only after #319 lands to avoid extra LCD load per hybrid GET.
  • Integration tests (api_route_solve.rs) require PostgreSQL; not run on this Cloud Agent VM (no dockerd/Postgres).

Note

Medium Risk
Changes default route discovery/optimization depth and worst-case sim budget on LCD-heavy route endpoints; behavior is covered by new integration tests but may surface longer paths and slightly higher load per quote.

Overview
Phase 2 (#323): Default hybrid GET /api/v1/route/solve (and /best, global global_v1 with amount_in) now allows 4 hops, up from 3, matching pool_only and POST caps.

GET_DEFAULT_MAX_HOPS in route_solver.rs is 4; discovery-only GET without amount_in uses the same default. OpenAPI 404 text and module comments reflect 4 hops.

LCD_HYBRID_SIM_BUDGET rises 1275 → 1700 (5×4×85); comments note post-#319 hop pricing uses the DB orderbook mirror. A unit test pins the budget formula.

Docs (indexer-invariants.md, integrators.md, route-solver.md) and check_route_solver_docs.py expect 1700 and 4 hops. route_paths adds 4-hop path and reachability tests. Integration coverage: seed_route_solve_4hop, route_solve_get_default_hybrid_four_hops.

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

## Summary Closes [#323](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/323). Raises `GET_DEFAULT_MAX_HOPS` from 3 to 4 so the default hybrid GET best-execution solver discovers and prices 4-hop routes, matching `GET_POOL_ONLY_MAX_HOPS`, the POST BFS cap, and the on-chain router `MAX_HOPS = 4`. ## Changes - `GET_DEFAULT_MAX_HOPS = 4` in `route_solver.rs` (module doc + OpenAPI comments updated) - `LCD_HYBRID_SIM_BUDGET` re-derived to **1700** (`5 × 4 × 85`); comment notes DB-backed pricing post-#319; unit test pins exact magnitude - `route_paths.rs`: 4-hop-only linear graph test + unreachable-goal instrumented test at `max_hops = 4` - `api_route_solve.rs`: default GET hybrid quote over seeded 4-hop chain (`seed_route_solve_4hop`) - Docs: `route-solver.md`, `integrators.md`, `indexer-invariants.md`; `check_route_solver_docs.py` expects 1700 **No change** to `hybrid_cache_key` shape or discount-tier keying (#283). ## Acceptance checklist | Criterion | Verification | Result | |-----------|--------------|--------| | `GET_DEFAULT_MAX_HOPS = 4`; module doc updated | `grep GET_DEFAULT_MAX_HOPS indexer/src/api/route_solver.rs` | PASS | | 4-hop-only pair discovered via default GET | `route_solve_get_default_hybrid_four_hops` in `api_route_solve.rs` | PASS (path unit tests); integration test added — needs Postgres | | `LCD_HYBRID_SIM_BUDGET = 1700`; budget test pins value | `cargo test --lib lcd_budget_is_documented_constant` | PASS | | `find_paths_top_k` reachability at max_hops=4 unchanged | `four_hop_only_route_within_budget_is_found`, `unreachable_goal_at_four_hops_does_zero_enumeration` | PASS | | No `hybrid_cache_key` / tier keying change | diff review | PASS | | Route tests pass | `cargo test --lib route_paths::tests`; `cargo test -p indexer route` with Postgres | PASS (lib); SKIP (integration — no Postgres on agent VM) | ## Verification for third parties ```bash cd indexer cargo test --lib route_paths::tests cargo test --lib lcd_budget_is_documented_constant python3 ../scripts/check_route_solver_docs.py # With Postgres + TEST_DATABASE_URL: cargo test -p indexer route ``` ## Blockers - **#319 dependency**: Issue gates this on Phase 1c (`db_orderbook_sim`) so the 4th hop is DB-priced, not LCD-backed. #319 is not yet on `main`; merge this MR only after #319 lands to avoid extra LCD load per hybrid GET. - Integration tests (`api_route_solve.rs`) require PostgreSQL; not run on this Cloud Agent VM (no dockerd/Postgres). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes default route discovery/optimization depth and worst-case sim budget on LCD-heavy route endpoints; behavior is covered by new integration tests but may surface longer paths and slightly higher load per quote. > > **Overview** > **Phase 2 (#323):** Default hybrid **`GET /api/v1/route/solve`** (and **`/best`**, global `global_v1` with `amount_in`) now allows **4 hops**, up from **3**, matching **`pool_only`** and **POST** caps. > > **`GET_DEFAULT_MAX_HOPS`** in `route_solver.rs` is **4**; discovery-only GET without `amount_in` uses the same default. OpenAPI 404 text and module comments reflect **4 hops**. > > **`LCD_HYBRID_SIM_BUDGET`** rises **1275 → 1700** (`5×4×85`); comments note post-#319 hop pricing uses the DB orderbook mirror. A unit test pins the budget formula. > > Docs (`indexer-invariants.md`, `integrators.md`, `route-solver.md`) and **`check_route_solver_docs.py`** expect **1700** and **4 hops**. **`route_paths`** adds 4-hop path and reachability tests. Integration coverage: **`seed_route_solve_4hop`**, **`route_solve_get_default_hybrid_four_hops`**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0bc6390cecc9b1f7f5f2522cf26b7b8d06886f9a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
PlasticDigits commented 2026-06-05 11:09:55 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 11:09:56 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 11:10:02 +00:00 (Migrated from gitlab.com)

mentioned in issue #323

mentioned in issue #323
ghost1 commented 2026-06-05 11:10:06 +00:00 (Migrated from gitlab.com)

changed the description

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

Security review

Commit reviewed: 0bc6390cecc9b1f7f5f2522cf26b7b8d06886f9a

Scope: GET_DEFAULT_MAX_HOPS 3→4, LCD_HYBRID_SIM_BUDGET 1275→1700, path-enumeration unit tests, 4-hop hybrid GET integration test, docs/drift-checker updates.

Outcome: FINDINGS: 0 medium+

Review summary

Reviewed attacker-controlled inputs on GET|POST /api/v1/route/solve and /best (token_in, token_out, amount_in, optional trader/sender) through path enumeration, hybrid optimization, LCD gateway, caching, and rate limiting.

Area Assessment
Injection No production SQL/query construction changes; test seeds use parameterized binds.
Authn/authz Unchanged — public read-only route API.
LCD amplification (H7) Worst-case sim budget rises ~33% (1275→1700) via 5×4×85; still documented, formula-pinned by unit test, and bounded by existing RATE_LIMIT_LCD_HEAVY_RPS (default 10) on lcd_heavy_router. No new bypass of prod floor (0 → forced 10).
Path enumeration DoS (#286) Reachability gate remains O(V+E); new unreachable_goal_at_four_hops_does_zero_enumeration test confirms 0 DFS expansions for unreachable goals at max_hops=4. CPU work still offloaded via spawn_blocking.
Cache poisoning / tier collision (#283) hybrid_cache_key shape unchanged (confirmed in MR scope).
Error leakage (H6) No changes to lcd_gateway_err or 502 sanitization.
SSRF / XSS / secrets Not in diff.

The hop-cap alignment (hybrid GET now matches POST/pool-only/router MAX_HOPS=4) is an intentional capability increase within existing guardrails, not a new unbounded attack surface.

Inline threads: none (no medium+ findings).

## Security review **Commit reviewed:** `0bc6390cecc9b1f7f5f2522cf26b7b8d06886f9a` **Scope:** `GET_DEFAULT_MAX_HOPS` 3→4, `LCD_HYBRID_SIM_BUDGET` 1275→1700, path-enumeration unit tests, 4-hop hybrid GET integration test, docs/drift-checker updates. **Outcome:** `FINDINGS: 0` medium+ ### Review summary Reviewed attacker-controlled inputs on `GET|POST /api/v1/route/solve` and `/best` (`token_in`, `token_out`, `amount_in`, optional `trader`/`sender`) through path enumeration, hybrid optimization, LCD gateway, caching, and rate limiting. | Area | Assessment | |------|------------| | **Injection** | No production SQL/query construction changes; test seeds use parameterized binds. | | **Authn/authz** | Unchanged — public read-only route API. | | **LCD amplification (H7)** | Worst-case sim budget rises ~33% (1275→1700) via `5×4×85`; still documented, formula-pinned by unit test, and bounded by existing `RATE_LIMIT_LCD_HEAVY_RPS` (default 10) on `lcd_heavy_router`. No new bypass of prod floor (`0` → forced 10). | | **Path enumeration DoS (#286)** | Reachability gate remains O(V+E); new `unreachable_goal_at_four_hops_does_zero_enumeration` test confirms 0 DFS expansions for unreachable goals at `max_hops=4`. CPU work still offloaded via `spawn_blocking`. | | **Cache poisoning / tier collision (#283)** | `hybrid_cache_key` shape unchanged (confirmed in MR scope). | | **Error leakage (H6)** | No changes to `lcd_gateway_err` or 502 sanitization. | | **SSRF / XSS / secrets** | Not in diff. | The hop-cap alignment (hybrid GET now matches POST/pool-only/router `MAX_HOPS=4`) is an intentional capability increase within existing guardrails, not a new unbounded attack surface. **Inline threads:** none (no medium+ findings).
PlasticDigits (Migrated from gitlab.com) merged commit 7f2f716ac3 into main 2026-06-05 12:30:13 +00:00
PlasticDigits commented 2026-06-05 12:30:15 +00:00 (Migrated from gitlab.com)

mentioned in commit 7f2f716ac3

mentioned in commit 7f2f716ac338a0f337ff5535a40f7c05f49a9f69
PlasticDigits commented 2026-06-05 13:38:50 +00:00 (Migrated from gitlab.com)

mentioned in merge request !808

mentioned in merge request !808
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!796
No description provided.