audit: harden the verify sidecar + add tests, benchmark, coverage docs#3
Merged
Conversation
Move all logic into the library (`mina_verify_server`) behind a thin `main`, so the router and verify path are unit-testable without spawning a process or running a proof. `dispatch(method, path, body) -> (status, json)` is now pure. Two hardening fixes for untrusted input (the POST body): - cap the buffered body at 32 MiB (MAX_BODY_BYTES); an oversized body is truncated into a clean 400 rather than an unbounded allocation. - run verification inside catch_unwind: a malformed-but-decodable block that trips an assertion deep in the verifier now fails that one request (500) instead of killing a worker thread (which would silently shrink the pool over time). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Before this the workspace had a single test. Add:
- mina-verify: fast decode tests for `header_from_precomputed` (bad JSON, missing
protocol_state / proof, non-base64 proof, bare vs {version,data} envelope), and a
heavy `#[ignore]`d integration test that verifies a real devnet block end-to-end
and rejects a height-tampered one (ProofInvalid).
- mina-verify-server: pure-router unit tests (dispatch: health/404/400 mapping) and
acceptance tests that spawn the real binary and drive it over a dependency-free
HTTP/1.1 client (fast: health/bad-request/not-found; heavy `#[ignore]`d:
valid:true with correct facts, and a tampered block -> valid:false).
- a `cargo bench -p mina-verify` harness (harness=false, no new deps) timing
decode+verify: ~0.4 s/block warm (~2.25 blocks/sec/core), first verify ~2.7 s.
Fixture: tests/fixtures/devnet-528700.json — a real precomputed devnet block from
the public mina_network_block_data bucket. It is not strictly UTF-8, so it also
exercises the lossy-decode path. Heavy tests/bench run in release:
cargo test --workspace --release -- --ignored
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- root README: list mina-verify-server and mina-verify-wasm in the crates table; add a Testing & benchmarks section (fast vs heavy `--ignored`, the shared fixture, the tarpaulin coverage command). - server README: document the body cap + per-request panic isolation, the `network:"custom"` health label under MINA_VK_JSON, a Tests section, and the measured warm throughput (~0.4 s/block) in place of the old ~1-2 s estimate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e for the server) The plain tarpaulin command measured the vendored `openmina/` tree (7485 lines) and the ptrace engine can't follow the server acceptance test's spawned child. Document `--exclude-files 'openmina/*'` and `--engine llvm` for the server, and note that the verify paths are covered by the heavy `#[ignore]`d tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2 (the HTTP verify sidecar). Review/merge #2 first; this branch's base
will retarget to
mainautomatically once #2 merges.An audit pass over the sidecar plus the test/benchmark coverage the workspace was
missing (it had a single test before this).
Audit → robustness fixes
The sidecar accepts an untrusted POST body, so two hardening fixes:
MAX_BODY_BYTES= 32 MiB). The body was read with an unboundedread_to_endinto aVec; a single oversized POST could exhaust memory. Oversizedbodies now truncate into a clean
400instead.catch_unwind, so amalformed-but-decodable block that trips an assertion deep in the verifier fails
that one request (
500) instead of killing a worker thread (which would silentlyshrink the pool over time).
main.rs→ lib + thin bin so the router is a pure, unit-testabledispatch(method, path, body) -> (status, json).Non-blocking observation (not changed):
header_from_precomputedlabels block-decodefailures as
VerifierError::InvalidIndexJson(a clearerBlockDecodevariant exists);it maps to
400correctly, so it's cosmetic.Tests
header_from_precomputed(badJSON, missing
protocol_state/proof, non-base64 proof, bare vs{version,data}envelope).
#[ignore]) — verifies a real devnetblock end-to-end and rejects a height-tampered one (
ProofInvalid).dispatch: health / 404 /400mapping) andacceptance tests that spawn the real binary and drive it over a dependency-free
HTTP/1.1 client (fast: health / bad-request / not-found; heavy
#[ignore]: a realblock →
valid:truewith correct hashes, and a tampered one →valid:false).Fast suite runs in CI; heavy proof tests via
cargo test --workspace --release -- --ignored.Benchmark
cargo bench -p mina-verify(aharness=falsebinary, no new deps) times decode +verify: warm ~0.4 s/block (~2.25 blocks/sec/core), first verify ~2.7 s (SRS
priming), VK build ~5 s.
Fixture
tests/fixtures/devnet-528700.json— a real precomputed devnet block (height 528700)from the public
mina_network_block_databucket, shared by the heavy tests and thebench. It is intentionally not strictly UTF-8, so it also exercises the lossy-decode
path.
Docs
Root README gains the missing
mina-verify-server/mina-verify-wasmcrate rows and aTesting / Benchmarks / Coverage section; server README documents the hardening, the
network:"custom"health label underMINA_VK_JSON, a Tests section, and the measuredthroughput.
🤖 Generated with Claude Code