Pure Go client for the Cardano Mithril certified-snapshot protocol
Find a file
Kayos 920d7cf177 STM full verification landing — milestones C/D/E complete
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).
2026-04-23 15:58:44 -07:00
cmd/mithril-go STM full verification landing — milestones C/D/E complete 2026-04-23 15:58:44 -07:00
internal STM full verification landing — milestones C/D/E complete 2026-04-23 15:58:44 -07:00
.gitignore initial scaffold 2026-04-23 15:12:39 -07:00
go.mod STM BLS verification WORKING against live preprod (milestones A, B, partial C) 2026-04-23 15:53:00 -07:00
go.sum STM BLS verification WORKING against live preprod (milestones A, B, partial C) 2026-04-23 15:53:00 -07:00
README.md STM full verification landing — milestones C/D/E complete 2026-04-23 15:58:44 -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. 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.goGenesis(...).

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.goSTM(...).

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