# mithril-go Pure-Go client for the Cardano [Mithril](https://mithril.network) 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`](https://github.com/input-output-hk/mithril) 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 to `ed25519.Verify`. - Signed payload: `signed_message` field (32 bytes hex) is the output of hashing the serialized `protocol_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/blst` Go bindings (IETF-draft BLS12-381 operations; production-grade, consensus layers use it). - Inputs: - `next_aggregate_verification_key` from the previous-epoch cert's `protocol_message` (the "trust handoff" between certs) - `multi_signature` bytes (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_key` for use by the NEXT verification. - Wire location: `internal/verify/verify.go` → `STM(...)`. ### Downstream once verification lands - `verify` subcommand: takes a snapshot directory, walks the cert chain, verifies genesis Ed25519 + each STM signature in order, validates the `merkle_root` against the digests manifest's computed root, reports per-stage pass/fail. - Per-immutable SHA check against the `digests.json` manifest (already downloaded — 16836 entries for preprod as of epoch 284). - Full immutables loop for the `download -immutables` path. ## 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/blst` via 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