server: HTTP verify sidecar for a trustless indexer#2
Merged
Conversation
Add `mina-verify-server` — a long-lived HTTP service wrapping
`Verifier::verify_precomputed_and_extract`: POST a precomputed block, get its
proof-backed facts ({valid, height, state_hash, previous_state_hash,
staged_ledger_hash}). An indexer gates ingestion on `valid` with no trusted
daemon; a valid proof attests the whole chain to genesis by recursion.
- Links only the mina-verify lib (no networking) — small, stateless, CPU-bound.
Verifier built once at startup; each request is just the proof check.
- tiny_http (sync) with a worker pool — verification is blocking CPU work, so no
async/tokio.
- Reads the body as bytes + lossy UTF-8: real precomputed blocks are NOT strictly
UTF-8 (the daemon emits sok_digest in staged_ledger_diff as mixed raw/escaped
bytes); that field is ignored by verification, so lossy decode is safe and
necessary. Verified against fresh devnet blocks that carry these bytes.
- Config via env (BIND, MINA_VK_JSON for mesa, MINA_NETWORK, VERIFY_THREADS).
- Dockerfile builds the bin; run as the sidecar via --entrypoint mina-verify-server.
Native release verifies in ~1-2s/block, so an indexer can verify every block, not
just the tip. README documents the docker-compose indexer topology + the
--verify-block-exe curl-shim wiring.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add crates/mina-verify-server/deploy/:
- verify-block.sh — the indexer --verify-block-exe shim: curls the sidecar /verify
and exits 0 iff {"valid":true}, non-zero => reject. Mirrors the existing
--fetch-new-blocks-exe (mesa-pull) curl-wrapper convention.
- docker-compose.yml — runs the mina-verifier sidecar with a /health healthcheck,
plus a commented mina-indexer stub showing the wiring + mesa MINA_VK_JSON mount.
- README.md — the trustless-indexer topology + how to demo gating on devnet.
Dockerfile: add curl to the runtime image for the sidecar healthcheck.
Verified the gating contract end-to-end against the native sidecar on live devnet:
real block -> shim exit 0 (ingest); tampered block -> exit 22 (reject).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dd816ba to
4c16b05
Compare
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.
What
Adds
mina-verify-server— a long-lived HTTP service that answers one question: "is this precomputed block's proof honest?" Built for a trustless indexer: verify each block's SNARK proof before ingesting it, with no trusted daemon.The caller ingests iff
valid, keyed by the proof-backed hashes. A valid proof attests the entire chain to genesis by recursion, so trust in whoever produced the block isn't required.Design
mina-verifylib (the precomputed path needs no networking) → small, stateless, CPU-bound. The expensiveVerifiersetup is paid once at startup; each request is just the proof check.tiny_http+ a worker pool — verification is blocking CPU work, so no async/tokio.sok_digestinstaged_ledger_diff) as mixed raw/escaped bytes. Verification ignores those fields (onlyprotocol_state+ the proof, both ASCII, are read), so the body is decoded lossily — matching how JS clients read these blocks. Verified against fresh devnet blocks that carry these bytes.BIND,MINA_VK_JSON(for mesa/mesa-mut),MINA_NETWORK,VERIFY_THREADS.--entrypoint mina-verify-server.Verified (live devnet)
/health→ oksok_digest) →valid:true, correct height/hashes, ~1–2 svalid:falseNative release verifies in ~1–2 s/block (no wasm overhead / no
num-bigintopt penalty), so an indexer can afford to verify every block, not just the tip. The README documents the docker-compose indexer topology and the--verify-block-execurl-shim wiring (reusing the indexer's existing exe-hook pattern, so the Rust-1.94 toolchain stays bottled up in its own container).Notes
main(independent of themina-verify-wasm/ BlockSource PR monitor: unified BlockSource (precomputed | live node) → VerifiedBlock #1).cargo fmt --allcommit to satisfy the existing (currently-red-on-main) Format CI gate; isolated so reviewers can skip it.🤖 Generated with Claude Code