fix(ledger): validate complete Terra execution responses and BSC provider events #36

Closed
opened 2026-10-14 03:10:45 +00:00 by PlasticDigits · 2 comments
Owner

Scope and source

Priority: P0. Gap coverage: GAP-001, GAP-009, GAP-012, GAP-040. Derived from GAP_1791945837.md, reviewed code commit f8dbe93df953a78b17cb3304b717dcf84c4cd517. Current e476a68da09645c2308cbf47b90211fcaffcb7af adds only the report, so implementation findings remain applicable. Report evidence is local reproduction/source inspection unless explicitly proposed; no production exploit or current live-readiness claim.

Coverage and sequencing: gap backlog tracker. Workstream 01.

Current codebase

The Terra LCD adapter deserializes transaction bodies from txs instead of tx_responses, permits empty execution identities, fetches only one 100-row page and can advance without transfers. BSC providers are not checked with eth_chainId; event fields default on missing data, removed logs/block hashes are ignored, and malformed successful JSON stops failover. Existing parser/DB tests mostly bypass HTTP adapters.

Why this implementation is needed

Incomplete or wrong-chain ingest silently changes eligibility and voting weights. Fix response completeness before making indexing faster or automating opening.

Relevant files

Consume validated execution responses from the supported Terra SDK, checking status/hash/height and preserving source transaction/event order. Implement supported pagination, totals and completion checks; ignore failed executions without mistaking schema errors for empty blocks. Validate Terra/BSC network identity and pinned token emitters, complete event identities, topic/uint256 widths, block hashes and removed logs. Classify malformed/transient responses for bounded failover/backoff; split provider-capped BSC ranges adaptively. Build recorded supported-LCD and mock HTTP/RPC → adapter → ingest → Postgres fixtures.

Constraints and guardrails

Preserve standalone offchain advisory voting, no new smart contracts or archive-node dependency, BSC as a core electorate, raw 18-decimal integer balances and separate Terra/BSC address identities. Keep Legal fail-closed transactional UI and the proven DEX Terra/Bridge EVM connectors; no browser BSC balance RPC, seed/key prompt or embedded admin/model credential. API must retain a restricted role separate from the ledger writer. Freeze at actual opening, never at draft creation or a client-supplied height. Agents own design, implementation, review and evidence under repository guidance; do not shift approvals/tests to the human or invent PASS evidence.

Acceptance criteria

Valid empty blocks advance; missing/incomplete/schema-invalid blocks do not. Every page/event is processed once in verified source order, and a failed later page cannot publish a complete cursor. Wrong-network providers are rejected; BSC log identities and token attribution remain explicit. Permanent regression coverage includes the report's standard-response REAL_HASH fixture.

Test plan: supported paths, failure paths and concurrency

Terra: empty, one page, >100 rows, multiple events, failed execution, base64 attributes and later-page failure. BSC: no logs, multiple logs/ranges, reorder/duplicates, removed logs, missing/invalid hash/block/data, maximum uint256, capped ranges, 429, timeout, failover and malformed 200 JSON. Exercise the actual HTTP adapter and DB on both chains; assert cursor and checkpoint state after each injected failure.

Test plan: attack, hack and abuse vectors

Wrong-chain endpoint and wrong-token emitter; forged topics/oversized numeric values; hostile JSON, repeated pagination keys/infinite pages, duplicate identities and removed-log reinjection; provider outages/response-size exhaustion. Bound requests, retries and memory, and verify malformed data never earns vote power or advances completeness.

Verification and completion criteria

Attach sanitized network/version fixtures, deterministic adapter-to-DB output and complete failure-matrix results. Compare final registered balances and ordered event identities against fixture expectations. Run Rust unit and isolated Postgres integration suites; no production RPC credentials in fixtures.

Record commit and pinned toolchain, commands/results and sanitized artifacts. Relevant Rust changes require cargo test --workspace --lib plus isolated Postgres integration (explicit guarded LEDGER_TEST_DATABASE_URL); frontend changes require npm test and production build plus relevant browser cases. Run secret scanning for new fixtures/config. Exercise fresh/upgrade migrations when schema/grants change; report skipped/live-only checks explicitly.

<!-- voting-gap-1791945837:01 --> ## Scope and source **Priority:** P0. **Gap coverage:** GAP-001, GAP-009, GAP-012, GAP-040. Derived from [GAP_1791945837.md](https://git.cl8y.com/code/voting/src/branch/main/gaps/GAP_1791945837.md), reviewed code commit `f8dbe93df953a78b17cb3304b717dcf84c4cd517`. Current `e476a68da09645c2308cbf47b90211fcaffcb7af` adds only the report, so implementation findings remain applicable. Report evidence is local reproduction/source inspection unless explicitly proposed; no production exploit or current live-readiness claim. Coverage and sequencing: [gap backlog tracker](https://git.cl8y.com/code/voting/issues/35). Workstream **01**. ## Current codebase The Terra LCD adapter deserializes transaction bodies from `txs` instead of `tx_responses`, permits empty execution identities, fetches only one 100-row page and can advance without transfers. BSC providers are not checked with eth_chainId; event fields default on missing data, removed logs/block hashes are ignored, and malformed successful JSON stops failover. Existing parser/DB tests mostly bypass HTTP adapters. ## Why this implementation is needed Incomplete or wrong-chain ingest silently changes eligibility and voting weights. Fix response completeness before making indexing faster or automating opening. ## Relevant files - [`ledger/src/lcd.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/src/lcd.rs) - [`ledger/src/bsc.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/src/bsc.rs) - [`ledger/src/ingest.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/src/ingest.rs) - [`ledger/src/parser/cw20.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/src/parser/cw20.rs) - [`ledger/src/parser/bep20.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/src/parser/bep20.rs) - [`ledger/src/config.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/src/config.rs) - [`ledger/tests/ledger_integration.rs`](https://git.cl8y.com/code/voting/src/branch/main/ledger/tests/ledger_integration.rs) - [`docs/LEDGER_INVARIANTS.md`](https://git.cl8y.com/code/voting/src/branch/main/docs/LEDGER_INVARIANTS.md) ## Recommended solution Consume validated execution responses from the supported Terra SDK, checking status/hash/height and preserving source transaction/event order. Implement supported pagination, totals and completion checks; ignore failed executions without mistaking schema errors for empty blocks. Validate Terra/BSC network identity and pinned token emitters, complete event identities, topic/uint256 widths, block hashes and removed logs. Classify malformed/transient responses for bounded failover/backoff; split provider-capped BSC ranges adaptively. Build recorded supported-LCD and mock HTTP/RPC → adapter → ingest → Postgres fixtures. ## Constraints and guardrails Preserve standalone offchain advisory voting, no new smart contracts or archive-node dependency, BSC as a core electorate, raw 18-decimal integer balances and separate Terra/BSC address identities. Keep Legal fail-closed transactional UI and the proven DEX Terra/Bridge EVM connectors; no browser BSC balance RPC, seed/key prompt or embedded admin/model credential. API must retain a restricted role separate from the ledger writer. Freeze at actual opening, never at draft creation or a client-supplied height. Agents own design, implementation, review and evidence under repository guidance; do not shift approvals/tests to the human or invent PASS evidence. ## Acceptance criteria Valid empty blocks advance; missing/incomplete/schema-invalid blocks do not. Every page/event is processed once in verified source order, and a failed later page cannot publish a complete cursor. Wrong-network providers are rejected; BSC log identities and token attribution remain explicit. Permanent regression coverage includes the report's standard-response `REAL_HASH` fixture. ## Test plan: supported paths, failure paths and concurrency Terra: empty, one page, >100 rows, multiple events, failed execution, base64 attributes and later-page failure. BSC: no logs, multiple logs/ranges, reorder/duplicates, removed logs, missing/invalid hash/block/data, maximum uint256, capped ranges, 429, timeout, failover and malformed 200 JSON. Exercise the actual HTTP adapter and DB on both chains; assert cursor and checkpoint state after each injected failure. ## Test plan: attack, hack and abuse vectors Wrong-chain endpoint and wrong-token emitter; forged topics/oversized numeric values; hostile JSON, repeated pagination keys/infinite pages, duplicate identities and removed-log reinjection; provider outages/response-size exhaustion. Bound requests, retries and memory, and verify malformed data never earns vote power or advances completeness. ## Verification and completion criteria Attach sanitized network/version fixtures, deterministic adapter-to-DB output and complete failure-matrix results. Compare final registered balances and ordered event identities against fixture expectations. Run Rust unit and isolated Postgres integration suites; no production RPC credentials in fixtures. Record commit and pinned toolchain, commands/results and sanitized artifacts. Relevant Rust changes require `cargo test --workspace --lib` plus isolated Postgres integration (explicit guarded LEDGER_TEST_DATABASE_URL); frontend changes require `npm test` and production build plus relevant browser cases. Run secret scanning for new fixtures/config. Exercise fresh/upgrade migrations when schema/grants change; report skipped/live-only checks explicitly.
Author
Owner

Implementation status after main merge PR #53, commit cd07f00f32f04ad02f8b760ed34588fd9645919e:

  • Complete Terra/BSC observations and bounded provider failure handling implemented with regression tests and crosslinked invariants/agent guidance.
  • Combined Rust1.88.0, isolated PostgreSQL, frontend/build/browser, OpenAPI and secret checks passed; see evidence.
  • Live release verification is still in progress. The first Coolify attempts failed before healthy acceptance. PR #54 fixes native-RPC entrypoint wiring, frontend image mode, liveness probes and pooled schema selection, with additional process/fault/privilege tests.

Services are paused while existing storage is audited and the corrected pinned release is prepared. No production wallet transaction or hardware-wallet/Legal QA is claimed. This is an interim report; the issue remains open and the final comment will map the original criteria to actual live results and any unverified cases.

Implementation status after main merge [PR #53](https://git.cl8y.com/code/voting/pulls/53), commit `cd07f00f32f04ad02f8b760ed34588fd9645919e`: - [x] Complete Terra/BSC observations and bounded provider failure handling implemented with regression tests and crosslinked invariants/agent guidance. - [x] Combined Rust1.88.0, isolated PostgreSQL, frontend/build/browser, OpenAPI and secret checks passed; see [evidence](https://git.cl8y.com/code/voting/src/branch/main/docs/verification/2026-10-14-issues-36-43.md). - [ ] Live release verification is still in progress. The first Coolify attempts failed before healthy acceptance. [PR #54](https://git.cl8y.com/code/voting/pulls/54) fixes native-RPC entrypoint wiring, frontend image mode, liveness probes and pooled schema selection, with additional process/fault/privilege tests. Services are paused while existing storage is audited and the corrected pinned release is prepared. No production wallet transaction or hardware-wallet/Legal QA is claimed. This is an interim report; the issue remains open and the final comment will map the original criteria to actual live results and any unverified cases.
Author
Owner

Implemented through PR53, 54, 55, 56, 57, 58, and PR59. Final code release 5cd9363 (PR59; CI passed) is deployed across all three Coolify services, each finished and healthy. This draft records completed issue criteria for the parent to post after publishing the final evidence artifact.

Verification checklist:

  • Complete supported Terra tx_responses/page-limit and legacy-next-key responses are validated against physical block transaction count/order, including failed executions. The REAL_HASH regression and normalized WASM positions pass.

  • Empty complete blocks commit; missing pages, wrong totals/order, malformed schemas, oversized bodies, wrong networks, stale heads and later-page failures publish no complete cursor.

  • BSC token/topic/data/uint256, removal/duplicate identity and canonical hash validation pass. Adaptive log ranges and whole-observation failover retain source identity.

  • Fixture expectations match ordered identities and final raw balances through the actual HTTP adapters and guarded PostgreSQL; fresh source/version fixtures contain no production credentials.

  • Same-provider bounded header batches retain every requested height in order and reject invalid interior headers before publication. Header concurrency stays8; the independent end-hash and log reads bring the complete observation limit to 10. Complete-observation failover never combines forks.

  • Pinned Rust1.88.0 complete fresh disposable release13 passed: 74 unit/supervisor tests, 121 integration tests (66 ledger hardening), 245 schema-validated API responses and 146 frontend tests, with production build/browser, nginx and Gitleaks checks. PR59 CI passed. Commands and results are recorded in the release report.

  • All three Coolify deployments of 5cd9363 finished healthy. Private readiness was green in 240 + 240 + 600 samples (1080 total), with maximum Terra lag 2 and BSC lag 17; both checkpoints stayed complete/canonical and intents/baselines healthy. The final two public rounds passed 45/45 each through 14:07:21 UTC. Live smoke (13 checks), four canonical checks, both original expired-action exact receipt replays, both-chain offchain registration/receipt checks and runtime configuration passed. Grafana/Loki has no post-activation worker warnings; the direct Coolify RPC warning at 13:56:21 belongs to the old container before 13:58:22 activation. See final live evidence.

  • Invariants, recovery/finality/freshness/rollback policy and third-party agent guidance are crosslinked in LEDGER_INVARIANTS.md, OPS.md and AGENTS_LEDGER_HARDENING.md.

  • Cached lower Terra/BSC heads fail over against the post-rewind cursor minimum; all-behind providers publish nothing. Mutable LCD latest/transaction-search requests send cache revalidation headers; genuinely stale/incomplete origins still fail physical manifest, network, time and hash validation. No settlement delay or policy relaxation.

Regression evidence: standard_real_hash_response_paginates_execution_events, failed_later_page_cannot_commit_any_event_or_cursor, valid_empty_terra_block_advances_bound_cursor_without_invented_events, failed_terra_execution_and_base64_wasm_attributes_ingest_atomically_through_http, bsc_http_to_database_adaptive_ranges_and_fail_closed_matrix, bsc_http_429_timeout_malformed_json_and_empty_logs_preserve_atomic_progress, maximum_uint256_bsc_http_event_persists_exact_debit_credit_and_replay, cached_lower_head_fails_over_at_canonical_cursor_and_all_lower_publish_nothing_both_chains, and mutable_lcd_cache_bypass_avoids_false_refusals_and_incoherent_origin_still_rejects. See HTTP-to-Postgres tests and the linked release report for the complete matrix.

Observed exception: the first public round had one unexplained 503 at 14:00:58.805988 UTC (44/45), recovering by 14:01:01; it fell outside the first private capture window. That earlier round is not the final acceptance window. The subsequent two public rounds and 1080 private samples passed; this is bounded observation evidence, not a promise of permanent availability or a reason to relax fail-closed readiness.

Limits: no blockchain transaction, new contract, archive dependency, chain-identity merge or browser BSC balance RPC. Funded human/hardware/mobile wallet and Legal QA, prolonged external CPU stress and production database downgrade/destructive attacks are not claimed by the isolated fixtures or unfunded live probes. Grafana currently provides Loki only; no Prometheus datasource was available. Legacy hash-only receipts and uncertified polls retain their documented limits.

The body acceptance/completion criteria and current comment requirements are satisfied by the named deterministic regressions, final release checks and recorded live evidence. Closing is supported after the parent publishes the final artifact; no remaining mandatory implementation or verification gap is identified.

Final evidence is published through PR #60. All mandatory body/comment criteria are satisfied by the checklist above; closing this issue.

Implemented through [PR53](https://git.cl8y.com/code/voting/pulls/53), [54](https://git.cl8y.com/code/voting/pulls/54), [55](https://git.cl8y.com/code/voting/pulls/55), [56](https://git.cl8y.com/code/voting/pulls/56), [57](https://git.cl8y.com/code/voting/pulls/57), [58](https://git.cl8y.com/code/voting/pulls/58), and [PR59](https://git.cl8y.com/code/voting/pulls/59). Final code release `5cd9363` (PR59; CI passed) is deployed across all three Coolify services, each finished and healthy. This draft records completed issue criteria for the parent to post after publishing the final evidence artifact. Verification checklist: - [x] Complete supported Terra tx_responses/page-limit and legacy-next-key responses are validated against physical block transaction count/order, including failed executions. The REAL_HASH regression and normalized WASM positions pass. - [x] Empty complete blocks commit; missing pages, wrong totals/order, malformed schemas, oversized bodies, wrong networks, stale heads and later-page failures publish no complete cursor. - [x] BSC token/topic/data/uint256, removal/duplicate identity and canonical hash validation pass. Adaptive log ranges and whole-observation failover retain source identity. - [x] Fixture expectations match ordered identities and final raw balances through the actual HTTP adapters and guarded PostgreSQL; fresh source/version fixtures contain no production credentials. - [x] Same-provider bounded header batches retain every requested height in order and reject invalid interior headers before publication. Header concurrency stays8; the independent end-hash and log reads bring the complete observation limit to 10. Complete-observation failover never combines forks. - [x] Pinned Rust1.88.0 complete fresh disposable release13 passed: 74 unit/supervisor tests, 121 integration tests (66 ledger hardening), 245 schema-validated API responses and 146 frontend tests, with production build/browser, nginx and Gitleaks checks. PR59 CI passed. Commands and results are recorded in the [release report](https://git.cl8y.com/code/voting/src/branch/main/docs/verification/2026-10-14-issues-36-43.md). - [x] All three Coolify deployments of `5cd9363` finished healthy. Private readiness was green in 240 + 240 + 600 samples (1080 total), with maximum Terra lag 2 and BSC lag 17; both checkpoints stayed complete/canonical and intents/baselines healthy. The final two public rounds passed 45/45 each through 14:07:21 UTC. Live smoke (13 checks), four canonical checks, both original expired-action exact receipt replays, both-chain offchain registration/receipt checks and runtime configuration passed. Grafana/Loki has no post-activation worker warnings; the direct Coolify RPC warning at 13:56:21 belongs to the old container before 13:58:22 activation. See [final live evidence](https://git.cl8y.com/code/voting/src/branch/main/docs/verification/2026-10-14-final-live.json). - [x] Invariants, recovery/finality/freshness/rollback policy and third-party agent guidance are crosslinked in [LEDGER_INVARIANTS.md](https://git.cl8y.com/code/voting/src/branch/main/docs/LEDGER_INVARIANTS.md), [OPS.md](https://git.cl8y.com/code/voting/src/branch/main/docs/OPS.md) and [AGENTS_LEDGER_HARDENING.md](https://git.cl8y.com/code/voting/src/branch/main/skills/AGENTS_LEDGER_HARDENING.md). - [x] Cached lower Terra/BSC heads fail over against the post-rewind cursor minimum; all-behind providers publish nothing. Mutable LCD latest/transaction-search requests send cache revalidation headers; genuinely stale/incomplete origins still fail physical manifest, network, time and hash validation. No settlement delay or policy relaxation. Regression evidence: `standard_real_hash_response_paginates_execution_events`, `failed_later_page_cannot_commit_any_event_or_cursor`, `valid_empty_terra_block_advances_bound_cursor_without_invented_events`, `failed_terra_execution_and_base64_wasm_attributes_ingest_atomically_through_http`, `bsc_http_to_database_adaptive_ranges_and_fail_closed_matrix`, `bsc_http_429_timeout_malformed_json_and_empty_logs_preserve_atomic_progress`, `maximum_uint256_bsc_http_event_persists_exact_debit_credit_and_replay`, `cached_lower_head_fails_over_at_canonical_cursor_and_all_lower_publish_nothing_both_chains`, and `mutable_lcd_cache_bypass_avoids_false_refusals_and_incoherent_origin_still_rejects`. See [HTTP-to-Postgres tests](https://git.cl8y.com/code/voting/src/branch/main/ledger/tests/hardening.rs) and the linked release report for the complete matrix. Observed exception: the first public round had one unexplained 503 at 14:00:58.805988 UTC (44/45), recovering by 14:01:01; it fell outside the first private capture window. That earlier round is not the final acceptance window. The subsequent two public rounds and 1080 private samples passed; this is bounded observation evidence, not a promise of permanent availability or a reason to relax fail-closed readiness. Limits: no blockchain transaction, new contract, archive dependency, chain-identity merge or browser BSC balance RPC. Funded human/hardware/mobile wallet and Legal QA, prolonged external CPU stress and production database downgrade/destructive attacks are not claimed by the isolated fixtures or unfunded live probes. Grafana currently provides Loki only; no Prometheus datasource was available. Legacy hash-only receipts and uncertified polls retain their documented limits. The body acceptance/completion criteria and current comment requirements are satisfied by the named deterministic regressions, final release checks and recorded live evidence. Closing is supported after the parent publishes the final artifact; no remaining mandatory implementation or verification gap is identified. Final evidence is published through [PR #60](https://git.cl8y.com/code/voting/pulls/60). All mandatory body/comment criteria are satisfied by the checklist above; closing this issue.
Sign in to join this conversation.
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/voting#36
No description provided.