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).
This commit is contained in:
parent
9d6c7cffbe
commit
7b9b09133b
7 changed files with 63 additions and 82 deletions
100
README.md
100
README.md
|
|
@ -2,46 +2,38 @@
|
||||||
|
|
||||||
Pure-Go client for the Cardano [Mithril](https://mithril.network) protocol.
|
Pure-Go client for the Cardano [Mithril](https://mithril.network) protocol.
|
||||||
|
|
||||||
Mithril is Cardano's stake-based certified-snapshot system — it lets a new
|
Mithril is Cardano's stake-based certified-snapshot system. A new node
|
||||||
node bootstrap the chain from a cryptographically-verified snapshot
|
bootstraps the chain from a cryptographically-verified snapshot instead
|
||||||
instead of replaying every block from genesis.
|
of replaying every block from genesis.
|
||||||
|
|
||||||
The official [`mithril-client`](https://github.com/input-output-hk/mithril)
|
The reference [`mithril-client`](https://github.com/input-output-hk/mithril)
|
||||||
is Rust. `mithril-go` is a pure-Go reimplementation that produces a single
|
is Rust. `mithril-go` is a pure-Go reimplementation: single static binary,
|
||||||
static binary with no CGo, no upstream Rust runtime, and an MCP-native
|
no CGo, no `blst`, no upstream Rust runtime. Also ships an MCP stdio
|
||||||
tool surface for AI agents — useful for:
|
server for agent use.
|
||||||
|
|
||||||
- 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
|
## Status
|
||||||
|
|
||||||
**Working consensus-correct verification against live mainnet and preprod.**
|
Consensus-correct verification against live mainnet and preprod.
|
||||||
|
|
||||||
| Capability | Status |
|
| Capability | Status |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Aggregator REST client | ✅ list, show, cert, walk-chain |
|
| Aggregator REST client (list, show, cert, walk-chain) | done |
|
||||||
| Resumable HTTP download (SHA hook + progress) | ✅ |
|
| Resumable HTTP download (SHA hook + progress) | done |
|
||||||
| Streamed zstd+tar extract (tar-slip defended) | ✅ |
|
| Streamed zstd+tar extract (tar-slip defended) | done |
|
||||||
| Genesis Ed25519 verification | ✅ live mainnet + preprod |
|
| Genesis Ed25519 verification | done |
|
||||||
| STM BLS12-381 aggregate verification | ✅ live mainnet + preprod |
|
| STM BLS12-381 aggregate verification | done |
|
||||||
| Lottery-win threshold (Taylor series, big.Rat) | ✅ |
|
| Lottery-win threshold (Taylor series, big.Rat) | done |
|
||||||
| Merkle batch-proof verification (Blake2b-256) | ✅ |
|
| Merkle batch-proof verification (Blake2b-256) | done |
|
||||||
| AVK chaining + epoch + hash continuity | ✅ |
|
| AVK chaining + epoch + hash continuity | done |
|
||||||
| **Full chain verification (genesis → head)** | ✅ live mainnet + preprod |
|
| Full chain verification (genesis → head) | done |
|
||||||
| Per-immutable SHA manifest verification | ✅ |
|
| Per-immutable SHA manifest verification | done |
|
||||||
| MCP stdio server (8 tools) | ✅ |
|
| MCP stdio server (8 tools) | done |
|
||||||
| Full immutables-download loop (8000+ files) | ⏳ |
|
| Full immutables-download loop (8000+ files) | pending |
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
```bash
|
```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 info -network mainnet
|
||||||
mithril-go list -network mainnet
|
mithril-go list -network mainnet
|
||||||
|
|
@ -79,27 +71,24 @@ internal/
|
||||||
verify/ Genesis Ed25519 verification
|
verify/ Genesis Ed25519 verification
|
||||||
```
|
```
|
||||||
|
|
||||||
## What was non-obvious (so future-you doesn't have to dig)
|
## Upstream details that aren't documented
|
||||||
|
|
||||||
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
|
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_`.
|
separation tag, not the IETF standard
|
||||||
The Rust calls `blst.verify(sig, msg, &[], &[], pk, ...)` — the
|
`BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_`. The Rust calls
|
||||||
`&[]` is the empty DST.
|
`blst.verify(sig, msg, &[], &[], pk, ...)` — the `&[]` is the empty DST.
|
||||||
2. **The signed message is `signed_message_bytes || mt_root_bytes`**,
|
2. **Signed message is `signed_message_bytes || mt_root_bytes`**,
|
||||||
not `signed_message` alone. The Merkle commitment root is appended
|
not `signed_message` alone. The Merkle commitment root is appended
|
||||||
before BLS verify.
|
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))`,
|
`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`.
|
then `aggr_sig = Σ t_i·sig_i` and `aggr_vk = Σ t_i·vk_i`.
|
||||||
Plain summation does not interop with blst.
|
Plain summation does not interop with blst.
|
||||||
|
|
||||||
Plus the `protocol_message` hash is SHA-256 over key-then-value, with
|
The `protocol_message` hash is SHA-256 over key-then-value, with keys
|
||||||
keys ordered by **Rust enum declaration order**, not alphabetical.
|
ordered by **Rust enum declaration order**, not alphabetical.
|
||||||
|
|
||||||
## Machine / LLM usage
|
## JSON + exit codes
|
||||||
|
|
||||||
Every query command accepts `-json`:
|
Every query command accepts `-json`:
|
||||||
|
|
||||||
|
|
@ -119,12 +108,11 @@ Stable exit codes:
|
||||||
| 5 | signature verification failure (genesis or STM) |
|
| 5 | signature verification failure (genesis or STM) |
|
||||||
| 130 | canceled (SIGINT) |
|
| 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.
|
`mithril-go mcp` brings up a Model Context Protocol stdio server.
|
||||||
Compatible with any MCP client (Claude Code, Cursor, Zed, custom agents).
|
|
||||||
|
|
||||||
Tools exposed:
|
Tools exposed:
|
||||||
|
|
||||||
|
|
@ -135,15 +123,9 @@ Tools exposed:
|
||||||
| `mithril_show_snapshot` | Detail for a snapshot (or `latest`) |
|
| `mithril_show_snapshot` | Detail for a snapshot (or `latest`) |
|
||||||
| `mithril_get_certificate` | Cert by hash (or `head`) |
|
| `mithril_get_certificate` | Cert by hash (or `head`) |
|
||||||
| `mithril_walk_cert_chain` | Walk previous_hash from head to genesis |
|
| `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_chain` | Full chain verify with per-step report |
|
||||||
| `mithril_verify_genesis` | Walk to genesis + Ed25519 verify (legacy single-purpose tool) |
|
| `mithril_verify_genesis` | Walk to genesis + Ed25519 verify |
|
||||||
|
|
||||||
Example agent flow:
|
|
||||||
```
|
|
||||||
agent: tools/call mithril_verify_chain {network: mainnet}
|
|
||||||
→ {verified: true, length: 89, genesis_hash: "...", steps: [...]}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
|
@ -165,14 +147,14 @@ go test -tags live ./... # hits live preprod aggregator
|
||||||
## Verified against live networks (latest run)
|
## Verified against live networks (latest run)
|
||||||
|
|
||||||
```
|
```
|
||||||
mainnet chain 89 STM + 1 genesis ✓
|
mainnet chain 89 STM + 1 genesis ok
|
||||||
mainnet head 59 signers, 1972 wins ✓
|
mainnet head 59 signers, 1972 wins ok
|
||||||
mainnet genesis Ed25519 ✓
|
mainnet genesis Ed25519 ok
|
||||||
preprod chain 89 STM + 1 genesis ✓
|
preprod chain 89 STM + 1 genesis ok
|
||||||
preprod head 2 signers, 11 wins ✓
|
preprod head 2 signers, 11 wins ok
|
||||||
preprod genesis Ed25519 ✓
|
preprod genesis Ed25519 ok
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Apache-2.0. See `LICENSE`. Matches the upstream Mithril project.
|
Apache-2.0. See `LICENSE`. Matches upstream Mithril.
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,14 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/aggregator"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/artifact"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/artifact"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/chain"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/chain"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/manifest"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/manifest"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/mcp"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/mcp"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/networks"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/stm"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/stm"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/verify"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/verify"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "1.0.1"
|
const version = "1.0.1"
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/aggregator"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/chain"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/chain"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/mcp"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/mcp"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/networks"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/stm"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/stm"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/verify"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/verify"
|
||||||
)
|
)
|
||||||
|
|
||||||
func errString(e error) string {
|
func errString(e error) string {
|
||||||
|
|
|
||||||
2
go.mod
2
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
|
go 1.26
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/aggregator"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/networks"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/stm"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/stm"
|
||||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/verify"
|
"git.sulkta.com/Sulkta-Coop/mithril-go/internal/verify"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Step is the per-cert record in a chain-verification report.
|
// Step is the per-cert record in a chain-verification report.
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@
|
||||||
// 4. Lottery check: for each (index, sigma), evaluate_dense_mapping < threshold(stake)
|
// 4. Lottery check: for each (index, sigma), evaluate_dense_mapping < threshold(stake)
|
||||||
// 5. Threshold: total distinct lottery wins >= k
|
// 5. Threshold: total distinct lottery wins >= k
|
||||||
//
|
//
|
||||||
// Phases 2-5 are stubbed in verify.go pending the BLS crypto sprint.
|
// Phases 2-5 are implemented in verify.go (BLS, lottery, Merkle, threshold).
|
||||||
// This package's current role is rock-solid decoding.
|
|
||||||
package stm
|
package stm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
// 2. Subsequent certificates carry an STM (Stake-based Threshold Multi-
|
// 2. Subsequent certificates carry an STM (Stake-based Threshold Multi-
|
||||||
// signature) aggregate signature over BLS12-381.
|
// signature) aggregate signature over BLS12-381.
|
||||||
//
|
//
|
||||||
// Ed25519 (genesis) verification is fully implemented here. STM verification
|
// Ed25519 (genesis) verification lives here. STM BLS verification is in
|
||||||
// is stubbed pending the BLS crypto sprint.
|
// the sibling internal/stm package.
|
||||||
package verify
|
package verify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue