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
ddf1ec3491
8 changed files with 450 additions and 0 deletions
61
internal/verify/verify.go
Normal file
61
internal/verify/verify.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Package verify implements signature verification for Mithril certificates.
|
||||
//
|
||||
// Two layers of verification exist in Mithril:
|
||||
//
|
||||
// 1. The genesis certificate is signed by a static Ed25519 key baked into
|
||||
// the client (per-network). This bootstraps trust into the STM protocol.
|
||||
// 2. Subsequent certificates carry an STM (Stake-based Threshold Multi-
|
||||
// signature) aggregate signature over BLS12-381. Verification requires
|
||||
// the stake distribution snapshot plus the signers' verification keys
|
||||
// and their individual signature shares.
|
||||
//
|
||||
// v1 scope: genesis Ed25519 verification only. STM/BLS verification is a
|
||||
// separate follow-on milestone — it is the bulk of the cryptographic work
|
||||
// in this project.
|
||||
package verify
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotGenesis = errors.New("certificate is not a genesis certificate")
|
||||
ErrBadSignature = errors.New("genesis signature verification failed")
|
||||
ErrSTMNotImplemented = errors.New("STM signature verification not implemented yet")
|
||||
)
|
||||
|
||||
// Genesis verifies that the certificate was signed by the network's genesis
|
||||
// verification key. signedPayload is the exact bytes the aggregator stated
|
||||
// were signed (derived from the certificate's protocol_message, not this
|
||||
// function's job to construct).
|
||||
func Genesis(verifyKeyHex, genesisSignatureHex string, signedPayload []byte) error {
|
||||
pkHex, err := hex.DecodeString(verifyKeyHex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode verify key: %w", err)
|
||||
}
|
||||
// Mithril genesis keys are serialized as hex(ascii-of-byte-array-literal),
|
||||
// e.g. "[191,66,140,...]" → outer hex → inner ASCII → parse. The real decoder
|
||||
// will unpack this; for now accept a raw 32-byte hex as well.
|
||||
pk := ed25519.PublicKey(pkHex)
|
||||
if len(pk) != ed25519.PublicKeySize {
|
||||
return fmt.Errorf("verify key wrong size: got %d, want %d", len(pk), ed25519.PublicKeySize)
|
||||
}
|
||||
sig, err := hex.DecodeString(genesisSignatureHex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode signature: %w", err)
|
||||
}
|
||||
if !ed25519.Verify(pk, signedPayload, sig) {
|
||||
return ErrBadSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// STM verifies a non-genesis certificate's aggregate BLS signature against
|
||||
// the stake distribution. Stub — implementation target: Mithril STM paper
|
||||
// §5 (signing protocol) + §6 (aggregation) using a BLS12-381 library.
|
||||
func STM(protocolMessage, multiSignature []byte, stakeDistribution any) error {
|
||||
return ErrSTMNotImplemented
|
||||
}
|
||||
Reference in a new issue