mithril-go/README.md
Cobb Hayes 7b9b09133b Public-flip audit: module URL + README humanization
git.sulkta.coop → git.sulkta.com (matches the live public Forgejo endpoint).
README dropped AI-agent positioning + emoji status table; kept all
technical content (DST, MuSig aggregation, exit codes, MCP tool table).
2026-05-27 11:29:05 -07:00

160 lines
5.6 KiB
Markdown
Raw Permalink 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. A new node
bootstraps the chain from a cryptographically-verified snapshot instead
of replaying every block from genesis.
The reference [`mithril-client`](https://github.com/input-output-hk/mithril)
is Rust. `mithril-go` is a pure-Go reimplementation: single static binary,
no CGo, no `blst`, no upstream Rust runtime. Also ships an MCP stdio
server for agent use.
## Status
Consensus-correct verification against live mainnet and preprod.
| Capability | Status |
|---|---|
| Aggregator REST client (list, show, cert, walk-chain) | done |
| Resumable HTTP download (SHA hook + progress) | done |
| Streamed zstd+tar extract (tar-slip defended) | done |
| Genesis Ed25519 verification | done |
| STM BLS12-381 aggregate verification | done |
| Lottery-win threshold (Taylor series, big.Rat) | done |
| Merkle batch-proof verification (Blake2b-256) | done |
| AVK chaining + epoch + hash continuity | done |
| Full chain verification (genesis → head) | done |
| Per-immutable SHA manifest verification | done |
| MCP stdio server (8 tools) | done |
| Full immutables-download loop (8000+ files) | pending |
## Quick start
```bash
go build ./cmd/mithril-go # ~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
```
## Upstream details that aren't documented
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. **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.
The `protocol_message` hash is SHA-256 over key-then-value, with keys
ordered by **Rust enum declaration order**, not alphabetical.
## JSON + exit codes
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) |
Existing codes won't renumber.
## MCP server
`mithril-go mcp` brings up a Model Context Protocol stdio server.
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 |
## 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 ok
mainnet head 59 signers, 1972 wins ok
mainnet genesis Ed25519 ok
preprod chain 89 STM + 1 genesis ok
preprod head 2 signers, 11 wins ok
preprod genesis Ed25519 ok
```
## License
Apache-2.0. See `LICENSE`. Matches upstream Mithril.