initial scaffold
- module layout: cmd/mithril-go, internal/{aggregator,artifact,verify,networks}
- aggregator REST client, list command working against mainnet
- download/extract/verify stubbed
- no deps yet, pure stdlib
This commit is contained in:
commit
f87b7fc3c4
8 changed files with 450 additions and 0 deletions
147
cmd/mithril-go/main.go
Normal file
147
cmd/mithril-go/main.go
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
// Command mithril-go is a pure-Go client for the Cardano Mithril protocol.
|
||||
//
|
||||
// It downloads, verifies, and extracts Mithril-certified snapshots of the
|
||||
// Cardano database without requiring the upstream Rust mithril-client.
|
||||
//
|
||||
// Subcommands:
|
||||
// list — list available cardano-database snapshots on an aggregator
|
||||
// download — fetch a snapshot (verify + extract optional)
|
||||
// verify — verify an already-downloaded snapshot
|
||||
// info — show aggregator + network details
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/aggregator"
|
||||
"git.sulkta.coop/Sulkta-Coop/mithril-go/internal/networks"
|
||||
)
|
||||
|
||||
const version = "0.0.1-dev"
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
cmd := os.Args[1]
|
||||
args := os.Args[2:]
|
||||
switch cmd {
|
||||
case "list":
|
||||
os.Exit(cmdList(args))
|
||||
case "download":
|
||||
os.Exit(cmdDownload(args))
|
||||
case "verify":
|
||||
os.Exit(cmdVerify(args))
|
||||
case "info":
|
||||
os.Exit(cmdInfo(args))
|
||||
case "version", "--version", "-v":
|
||||
fmt.Println("mithril-go", version)
|
||||
case "help", "--help", "-h":
|
||||
usage()
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unknown command: %s\n\n", cmd)
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintln(os.Stderr, `mithril-go — pure Go Mithril snapshot client
|
||||
|
||||
Usage:
|
||||
mithril-go <command> [flags]
|
||||
|
||||
Commands:
|
||||
list List available cardano-database snapshots
|
||||
download Download + verify + extract a snapshot
|
||||
verify Verify an already-downloaded snapshot
|
||||
info Show network + aggregator info
|
||||
version Print version
|
||||
help Show this help
|
||||
|
||||
Common flags:
|
||||
-network mainnet | preprod | preview (default: preprod)`)
|
||||
}
|
||||
|
||||
func resolveNetwork(fs *flag.FlagSet, args []string) (networks.Network, []string, error) {
|
||||
networkName := fs.String("network", "preprod", "Cardano network: mainnet | preprod | preview")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return networks.Network{}, nil, err
|
||||
}
|
||||
n, ok := networks.ByName(*networkName)
|
||||
if !ok {
|
||||
return networks.Network{}, nil, fmt.Errorf("unknown network: %s", *networkName)
|
||||
}
|
||||
return n, fs.Args(), nil
|
||||
}
|
||||
|
||||
func cmdList(args []string) int {
|
||||
fs := flag.NewFlagSet("list", flag.ExitOnError)
|
||||
n, _, err := resolveNetwork(fs, args)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 2
|
||||
}
|
||||
client := aggregator.New(n.AggregatorURL)
|
||||
snaps, err := client.ListCardanoDBSnapshots(context.Background())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "list:", err)
|
||||
return 1
|
||||
}
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(tw, "HASH\tEPOCH\tIMMUTABLE\tSIZE\tCREATED")
|
||||
for _, s := range snaps {
|
||||
fmt.Fprintf(tw, "%.16s\t%d\t%d\t%s\t%s\n",
|
||||
s.Hash, s.Beacon.Epoch, s.Beacon.ImmutableFileNumber,
|
||||
humanSize(s.TotalDBSizeUncompressed),
|
||||
s.CreatedAt.UTC().Format("2006-01-02 15:04 MST"))
|
||||
}
|
||||
if err := tw.Flush(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "flush:", err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func cmdDownload(args []string) int {
|
||||
fmt.Fprintln(os.Stderr, "download: not yet implemented")
|
||||
return 1
|
||||
}
|
||||
|
||||
func cmdVerify(args []string) int {
|
||||
fmt.Fprintln(os.Stderr, "verify: not yet implemented")
|
||||
return 1
|
||||
}
|
||||
|
||||
func cmdInfo(args []string) int {
|
||||
fs := flag.NewFlagSet("info", flag.ExitOnError)
|
||||
n, _, err := resolveNetwork(fs, args)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 2
|
||||
}
|
||||
fmt.Printf("network: %s\n", n.Name)
|
||||
fmt.Printf("aggregator: %s\n", n.AggregatorURL)
|
||||
fmt.Printf("genesis verify key: %s…\n", n.GenesisVerifyKey[:16])
|
||||
return 0
|
||||
}
|
||||
|
||||
func humanSize(b uint64) string {
|
||||
const k = 1024
|
||||
if b < k {
|
||||
return fmt.Sprintf("%dB", b)
|
||||
}
|
||||
units := []string{"K", "M", "G", "T"}
|
||||
v := float64(b)
|
||||
u := 0
|
||||
for v >= k && u < len(units)-1 {
|
||||
v /= k
|
||||
u++
|
||||
}
|
||||
return fmt.Sprintf("%.1f%s", v, units[u])
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue