Implemented the remaining STM verification layers: - internal/stm/lottery.go: EvaluateSigma (Blake2b-512 lottery draw) + IsLotteryWon with Taylor-series threshold comparison (ported from mithril-stm::eligibility), big.Rat-based to match Rust's num_bigint/ num_rational path - internal/stm/merkle.go: Blake2b-256 Merkle batch-proof verification, faithful port of mithril-stm's verify_leaves_membership_from_batch_path including the 'current is left/right child' branch logic and the 1-byte zero pad for missing siblings - internal/stm/verify.go: top-level stm.Verify(msg, ms, avk, params) glues all four checks: k-threshold, lottery, Merkle, BLS aggregate - cmd: 'verify head' now runs full STM verification; JSON output shows signers, wins, params, verified flag - MCP: new 'mithril_verify_certificate' tool dispatches genesis Ed25519 vs STM by cert kind Verified against live networks: mainnet head cert bc00b551… epoch=626 59 signers 1972/16948 wins ✓ mainnet genesis 25acfcfe… epoch=539 Ed25519 ✓ preprod head dd9c4fcb… epoch=284 2 signers 11/100 wins ✓ preprod genesis 69bc3bdf… epoch=196 Ed25519 ✓ This is a consensus-correct pure-Go Mithril client. Single binary, CGo-free, no upstream Rust dependency. Next: full chain verification (walk head → genesis, check continuity). |
||
|---|---|---|
| cmd/mithril-go | ||
| internal | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
| STM-SPRINT.md | ||
mithril-go
Pure-Go client for the Cardano Mithril protocol.
Mithril is Cardano's stake-based certified-snapshot system — it lets a new node bootstrap the chain from a cryptographically-verified snapshot instead of replaying every block from genesis.
The official mithril-client
is Rust. This project is a pure-Go reimplementation that produces a single
static binary with no runtime dependencies — useful for:
- Embedding a Mithril bootstrap into Go-based Cardano tooling
(alongside
gouroboros,dingo, and friends) - Running on constrained ARM/embedded targets where shipping the Rust binary + its deps is overkill
- Operators who prefer a single
go install-able helper
Status
Full Mithril verification working — genesis Ed25519 AND STM BLS12-381 — against live mainnet and preprod.
| Piece | Status |
|---|---|
| Aggregator REST client | ✅ list, get, cert, chain |
list / show / info / cert commands |
✅ mainnet + preprod |
| Resumable HTTP download (single stream, SHA hook) | ✅ |
| Streamed zstd+tar extract (tar-slip defended) | ✅ |
download — digests + ancillary |
✅ (full immutables loop pending) |
| Genesis Ed25519 verification | ✅ live mainnet + preprod |
| STM BLS12-381 aggregate verification | ✅ live mainnet + preprod |
| MCP stdio server | ✅ 7 tools, Claude/Cursor/Zed compatible |
| Full cert-chain verify (genesis → head) | ⏳ next |
Usage
mithril-go info -network mainnet
mithril-go list -network mainnet
mithril-go show -network mainnet latest
mithril-go cert -network mainnet head
mithril-go cert -network mainnet -chain head # walk to genesis
mithril-go download -network preprod -out ./db latest # digests + ancillary
Verification sprint plan
The verification story splits into two layers:
1. Genesis Ed25519 verification
The genesis certificate (terminates the chain; its previous_hash is
empty and genesis_signature is non-empty) is signed by a static
Ed25519 key baked into this client per network (internal/networks).
- Key encoding: the Mithril genesis key is serialized as an ASCII-
representation of a 32-byte array literal (e.g.
"[191,66,...]") then hex-encoded. Decoder needs to unwrap both levels before handing 32 raw bytes toed25519.Verify. - Signed payload:
signed_messagefield (32 bytes hex) is the output of hashing the serializedprotocol_message— the exact hash function and canonicalization must match the Rust reference (mithril-common/src/protocol/in the upstream repo). Likely Blake2b-256 over a deterministic CBOR or JSON encoding; needs confirming against upstream. - Wire location:
internal/verify/verify.go→Genesis(...).
2. STM BLS12-381 aggregate verification
Every non-genesis certificate carries a multi_signature that is an
STM (Stake-based Threshold Multi-signature) aggregate proof over BLS12-381.
- Scheme: Chotard/Kiayias/Peters "Stake-based Threshold Multisignatures" (Mithril paper §5-6).
- Library:
github.com/supranational/blstGo bindings (IETF-draft BLS12-381 operations; production-grade, consensus layers use it). - Inputs:
next_aggregate_verification_keyfrom the previous-epoch cert'sprotocol_message(the "trust handoff" between certs)multi_signaturebytes (CBOR-encoded STM aggregate signature)signed_message(what was signed)
- Output: pass/fail, plus the epoch-boundary decision to promote
that cert's
next_aggregate_verification_keyfor use by the NEXT verification. - Wire location:
internal/verify/verify.go→STM(...).
Downstream once verification lands
verifysubcommand: takes a snapshot directory, walks the cert chain, verifies genesis Ed25519 + each STM signature in order, validates themerkle_rootagainst the digests manifest's computed root, reports per-stage pass/fail.- Per-immutable SHA check against the
digests.jsonmanifest (already downloaded — 16836 entries for preprod as of epoch 284). - Full immutables loop for the
download -immutablespath.
Machine / LLM usage
Every query command accepts -json for structured output:
mithril-go list -network mainnet -json # snapshot array
mithril-go show -network mainnet latest -json
mithril-go cert -network mainnet head -json
mithril-go cert -network mainnet head -chain -json
mithril-go info -network mainnet -json
Exit codes are stable:
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | generic error |
| 2 | usage error |
| 3 | network / aggregator error |
| 4 | integrity failure (SHA, tar-slip, truncated archive) |
| 5 | signature verification failure (genesis or STM) |
| 130 | canceled (SIGINT) |
These are the contract — existing codes won't renumber.
Planned: mithril-go mcp stdio server (Model Context Protocol) so MCP-native
agents (Claude Code, Cursor, etc.) can discover + call commands without
shelling out. Not yet implemented.
Dependencies
github.com/klauspost/compress/zstd— pure Go zstd decoder- (pending) BLS12-381:
github.com/supranational/blstvia its Go bindings
Building
go build -o mithril-go ./cmd/mithril-go
Produces a single static binary (~9.5 MB). CGo is not used; cross-
compilation is GOOS=linux GOARCH=arm64 go build ./cmd/mithril-go.
License
TBD