mithril-go/README.md
Kayos 599085eaa9 wrap: chain verify + manifest verify + LICENSE + final docs
- internal/chain: end-to-end chain verification. Walks head → genesis,
  verifies every cert (Ed25519 or STM as appropriate), and checks
  continuity at every boundary:
    epoch:    same or +1 from previous
    hash:     current.previous_hash == previous.hash
    AVK:      same epoch  → equal aggregate_verification_key
              new epoch   → matches previous.protocol_message.next_aggregate_verification_key
- cmd: 'verify chain' subcommand + 'verify manifest <dir>' for SHA-checking
  downloaded immutable files
- internal/manifest: per-file SHA-256 verification against the digests.json
  shipped in the snapshot's digests archive
- MCP: 8th tool 'mithril_verify_chain' for agent-driven full-chain verify
- README: complete rewrite — status table, architecture, gotchas, MCP
  tool surface, exit code contract, build instructions
- LICENSE: Apache-2.0 (matches upstream Mithril)

Verified end to end against live networks:
  preprod  chain  90 certs (89 STM + 1 genesis)  1124 wins   ✓
  mainnet  chain  89 certs (88 STM + 1 genesis)  210921 wins ✓

That's the wrap. Pure-Go consensus-correct Mithril client, single 10 MB
static binary, MCP-native, no CGo, no upstream Rust runtime.
2026-04-23 16:15:47 -07:00

178 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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. `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
```bash
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
```bash
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.