Pure Go client for the Cardano Mithril certified-snapshot protocol
Find a file
Kayos e9557ca05b json schema polish: count on list, hash alias on verify_certificate (v1)
Acceptance test report flagged three cosmetic JSON-schema gaps:

1. 'list -json' had no top-level 'count' — caller had to use .snapshots|length.
   Added 'count' alongside 'snapshots'.
2. 'verify -json chain' top-level 'kind' was reported null — actually a
   missing field rather than null. Chain results have per-step kind in
   .steps[]; chain-level kind would be misleading. Documented intent
   in README rather than adding the field.
3. MCP 'mithril_verify_certificate' returned 'cert_hash' but agents
   often look for 'hash'. Added 'hash' alias alongside 'cert_hash' in
   both genesis and STM result paths so either lookup works.

End-to-end loop test on mainnet+preprod: full PASS (89-cert mainnet
chain + 90-cert preprod chain both verified, MCP all 8 tools work,
exit codes correct, manifest detection clean). v1-tag-able now.
2026-04-23 16:31:27 -07:00
cmd/mithril-go json schema polish: count on list, hash alias on verify_certificate (v1) 2026-04-23 16:31:27 -07:00
internal wrap: chain verify + manifest verify + LICENSE + final docs 2026-04-23 16:15:47 -07:00
.gitignore initial scaffold 2026-04-23 15:12:39 -07:00
go.mod wrap: chain verify + manifest verify + LICENSE + final docs 2026-04-23 16:15:47 -07:00
go.sum wrap: chain verify + manifest verify + LICENSE + final docs 2026-04-23 16:15:47 -07:00
LICENSE wrap: chain verify + manifest verify + LICENSE + final docs 2026-04-23 16:15:47 -07:00
README.md wrap: chain verify + manifest verify + LICENSE + final docs 2026-04-23 16:15:47 -07:00
STM-SPRINT.md STM-SPRINT.md: detailed plan for the BLS verification sprint 2026-04-23 15:36:05 -07:00

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. mithril-go is a pure-Go reimplementation that produces a single static binary with no CGo, no upstream Rust runtime, and an MCP-native tool surface for AI agents — useful for:

  • Embedding Mithril bootstrap into Go-based Cardano tooling (alongside gouroboros, dingo, etc.)
  • Constrained ARM/embedded targets where shipping the Rust binary + its deps is overkill
  • Operators who prefer a single go install-able helper
  • AI agents (Claude Code, Cursor, Zed, ...) that want to verify Mithril certs as a callable tool

Status

Working consensus-correct verification against live mainnet and preprod.

Capability Status
Aggregator REST client list, show, cert, walk-chain
Resumable HTTP download (SHA hook + progress)
Streamed zstd+tar extract (tar-slip defended)
Genesis Ed25519 verification live mainnet + preprod
STM BLS12-381 aggregate verification live mainnet + preprod
Lottery-win threshold (Taylor series, big.Rat)
Merkle batch-proof verification (Blake2b-256)
AVK chaining + epoch + hash continuity
Full chain verification (genesis → head) live mainnet + preprod
Per-immutable SHA manifest verification
MCP stdio server (8 tools)
Full immutables-download loop (8000+ files)

Quick start

go build ./cmd/mithril-go        # produces a 9.5 MB single static binary

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 ./snap latest
mithril-go verify   -network preprod manifest ./snap   # SHA-check downloaded files

mithril-go verify   -network mainnet genesis           # Ed25519
mithril-go verify   -network mainnet head              # STM BLS aggregate
mithril-go verify   -network mainnet chain             # full walk + every cert

Every query command supports -json for structured output.

Architecture

cmd/mithril-go/
  main.go               CLI entrypoint, subcommand dispatch
  mcp.go                MCP tool registration
  json.go               Structured-output helpers

internal/
  aggregator/           REST client (list, get, cert, walk-chain)
  artifact/             Resumable HTTP download + streamed zstd-tar extract
  chain/                End-to-end chain verify (genesis → head, AVK chaining)
  manifest/             Per-immutable SHA-256 verification against digests.json
  mcp/                  Minimal JSON-RPC 2.0 stdio MCP server (no deps)
  networks/             Per-network aggregator URLs + genesis verify keys
  stm/                  STM BLS12-381 verification: types, BLS, aggregation,
                        lottery, Merkle, top-level Verify
  verify/               Genesis Ed25519 verification

What was non-obvious (so future-you doesn't have to dig)

Three things in the upstream Rust that aren't documented anywhere prominent:

  1. DST is empty. Mithril's BLS hash-to-G1 uses an empty domain separation tag, not the IETF standard BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_. The Rust calls blst.verify(sig, msg, &[], &[], pk, ...) — the &[] is the empty DST.
  2. The signed message is signed_message_bytes || mt_root_bytes, not signed_message alone. The Merkle commitment root is appended before BLS verify.
  3. Aggregation is MuSig-style scalar-weighted, not plain. t_i = Blake2b-128(Blake2b-128(σ_0‖…‖σ_{n-1}) ‖ be_u64(i)), then aggr_sig = Σ t_i·sig_i and aggr_vk = Σ t_i·vk_i. Plain summation does not interop with blst.

Plus the protocol_message hash is SHA-256 over key-then-value, with keys ordered by Rust enum declaration order, not alphabetical.

Machine / LLM usage

Every query command accepts -json:

mithril-go verify -network mainnet -json chain | jq '.steps[] | select(.kind=="genesis")'

Stable exit codes:

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.

MCP server

mithril-go mcp brings up a Model Context Protocol stdio server. Compatible with any MCP client (Claude Code, Cursor, Zed, custom agents).

Tools exposed:

Tool Purpose
mithril_info Network + aggregator + genesis verify key
mithril_list_snapshots Newest-first list of cardano-database snapshots
mithril_show_snapshot Detail for a snapshot (or latest)
mithril_get_certificate Cert by hash (or head)
mithril_walk_cert_chain Walk previous_hash from head to genesis
mithril_verify_certificate Ed25519 OR STM BLS verify, dispatched by cert kind
mithril_verify_chain Full chain verify with per-step report
mithril_verify_genesis Walk to genesis + Ed25519 verify (legacy single-purpose tool)

Example agent flow:

agent: tools/call mithril_verify_chain {network: mainnet}
  → {verified: true, length: 89, genesis_hash: "...", steps: [...]}

Dependencies

  • github.com/consensys/gnark-crypto — pure Go BLS12-381 (audited)
  • golang.org/x/crypto/blake2b — stdlib-adjacent Blake2b
  • github.com/klauspost/compress/zstd — pure Go zstd

No CGo. No blst. go build ./cmd/mithril-go produces a single static binary. Cross-compile with GOOS=linux GOARCH=arm64 go build.

Building

go build -o mithril-go ./cmd/mithril-go
go test ./...
go test -tags live ./...        # hits live preprod aggregator

Verified against live networks (latest run)

mainnet  chain    89 STM + 1 genesis    ✓
mainnet  head     59 signers, 1972 wins ✓
mainnet  genesis  Ed25519               ✓
preprod  chain    89 STM + 1 genesis    ✓
preprod  head      2 signers,   11 wins ✓
preprod  genesis  Ed25519               ✓

License

Apache-2.0. See LICENSE. Matches the upstream Mithril project.