From 7b9b09133b43c36067ac0877a700d17e9d520d78 Mon Sep 17 00:00:00 2001 From: Cobb Hayes Date: Wed, 27 May 2026 11:29:05 -0700 Subject: [PATCH] Public-flip audit: module URL + README humanization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- README.md | 100 ++++++++++++++++---------------------- cmd/mithril-go/main.go | 16 +++--- cmd/mithril-go/mcp.go | 12 ++--- go.mod | 2 +- internal/chain/chain.go | 8 +-- internal/stm/types.go | 3 +- internal/verify/verify.go | 4 +- 7 files changed, 63 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 4688b85..952e820 100644 --- a/README.md +++ b/README.md @@ -2,46 +2,38 @@ 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. +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 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 +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 -**Working consensus-correct verification against live mainnet and preprod.** +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) | ⏳ | +| 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 # produces a 9.5 MB single static binary +go build ./cmd/mithril-go # ~9.5 MB single static binary mithril-go info -network mainnet mithril-go list -network mainnet @@ -79,27 +71,24 @@ internal/ 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: +## 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. **The signed message is `signed_message_bytes || mt_root_bytes`**, + 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.** +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. +The `protocol_message` hash is SHA-256 over key-then-value, with keys +ordered by **Rust enum declaration order**, not alphabetical. -## Machine / LLM usage +## JSON + exit codes Every query command accepts `-json`: @@ -119,12 +108,11 @@ Stable exit codes: | 5 | signature verification failure (genesis or STM) | | 130 | canceled (SIGINT) | -These are the contract — existing codes won't renumber. +Existing codes won't renumber. -### MCP server +## 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: @@ -135,15 +123,9 @@ Tools exposed: | `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_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: [...]} -``` +| `mithril_verify_genesis` | Walk to genesis + Ed25519 verify | ## Dependencies @@ -165,14 +147,14 @@ 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 ✓ +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 the upstream Mithril project. +Apache-2.0. See `LICENSE`. Matches upstream Mithril. diff --git a/cmd/mithril-go/main.go b/cmd/mithril-go/main.go index 635c755..e4318af 100644 --- a/cmd/mithril-go/main.go +++ b/cmd/mithril-go/main.go @@ -25,14 +25,14 @@ import ( "text/tabwriter" "time" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/artifact" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/chain" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/manifest" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/mcp" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/stm" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/verify" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/aggregator" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/artifact" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/chain" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/manifest" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/mcp" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/networks" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/stm" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/verify" ) const version = "1.0.1" diff --git a/cmd/mithril-go/mcp.go b/cmd/mithril-go/mcp.go index 3e8f9a7..684a36b 100644 --- a/cmd/mithril-go/mcp.go +++ b/cmd/mithril-go/mcp.go @@ -4,12 +4,12 @@ import ( "context" "fmt" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/chain" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/mcp" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/stm" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/verify" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/aggregator" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/chain" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/mcp" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/networks" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/stm" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/verify" ) func errString(e error) string { diff --git a/go.mod b/go.mod index 9344073..f2de901 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module git.sulkta.coop/Sulkta-Coop/mithril-go +module git.sulkta.com/Sulkta-Coop/mithril-go go 1.26 diff --git a/internal/chain/chain.go b/internal/chain/chain.go index 0bdb061..7e17b9f 100644 --- a/internal/chain/chain.go +++ b/internal/chain/chain.go @@ -24,10 +24,10 @@ import ( "io" "net/http" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/stm" - "git.sulkta.coop/Sulkta-Coop/mithril-go/internal/verify" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/aggregator" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/networks" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/stm" + "git.sulkta.com/Sulkta-Coop/mithril-go/internal/verify" ) // Step is the per-cert record in a chain-verification report. diff --git a/internal/stm/types.go b/internal/stm/types.go index 6873067..c040edb 100644 --- a/internal/stm/types.go +++ b/internal/stm/types.go @@ -16,8 +16,7 @@ // 4. Lottery check: for each (index, sigma), evaluate_dense_mapping < threshold(stake) // 5. Threshold: total distinct lottery wins >= k // -// Phases 2-5 are stubbed in verify.go pending the BLS crypto sprint. -// This package's current role is rock-solid decoding. +// Phases 2-5 are implemented in verify.go (BLS, lottery, Merkle, threshold). package stm import ( diff --git a/internal/verify/verify.go b/internal/verify/verify.go index 3fce58e..a49cf5d 100644 --- a/internal/verify/verify.go +++ b/internal/verify/verify.go @@ -7,8 +7,8 @@ // 2. Subsequent certificates carry an STM (Stake-based Threshold Multi- // signature) aggregate signature over BLS12-381. // -// Ed25519 (genesis) verification is fully implemented here. STM verification -// is stubbed pending the BLS crypto sprint. +// Ed25519 (genesis) verification lives here. STM BLS verification is in +// the sibling internal/stm package. package verify import (