Hanzo
Hanzo Skills Reference

Hanzo MPC

Hanzo MPC is a threshold signing service for securely generating and managing cryptographic wallets across distributed nodes without ever exposing the full private key. Written in Go, it implements...

Overview

Hanzo MPC is a threshold signing service for securely generating and managing cryptographic wallets across distributed nodes without ever exposing the full private key. Written in Go, it implements ECDSA (secp256k1) via CGGMP21 and EdDSA (Ed25519) via FROST protocols. Supports Bitcoin, Ethereum, Lux, XRPL, Solana, TON, and all EVM-compatible chains. Pluggable signer backend for Hanzo KMS. Production-deployed as a 2-of-3 StatefulSet on hanzo-k8s at mpc.hanzo.ai.

Why Hanzo MPC?

  • No single point of compromise: Private keys are never fully assembled
  • Threshold signing: Only t-of-n nodes needed to sign (default: 2-of-3)
  • Multi-chain: ECDSA (Bitcoin, Ethereum, EVM, XRPL, Lux) + EdDSA (Solana, TON)
  • Policy engine: Fireblocks-style transaction governance (signers, limits, whitelists)
  • FHE integration: Threshold FHE via luxfi/fhe for encrypted policy evaluation
  • ConsensusKV: Private BFT blockchain with dual-certificate finality (Ed25519 + ML-DSA-65 post-quantum)
  • Bridge compatible: Drop-in replacement for Rust-based MPC via HTTP API on port 6000

Tech Stack

  • Language: Go 1.26
  • Crypto: luxfi/threshold (CGGMP21 + FROST), luxfi/crypto, luxfi/fhe
  • Messaging: NATS (JetStream + pub/sub + P2P)
  • Storage: BadgerDB (AES-256 encrypted key shares)
  • Discovery: Consul (legacy), NATS KV, or ConsensusKV
  • Identity: Ed25519 node identity keys (age-encrypted)
  • HSM: Pluggable (file, AWS KMS, GCP KMS, Azure HSM, Zymbit, Hanzo KMS)
  • Smart Contracts: ThresholdPolicy.sol (on-chain policy enforcement)
  • Build: Make + Go

OSS Base

Repo: hanzoai/mpc. Module: github.com/hanzoai/mpc.

When to use

  • Generating distributed crypto wallets without exposing private keys
  • Threshold signing for multi-chain transactions
  • Building custody solutions with policy-based governance
  • Integrating with Hanzo KMS as a signing backend
  • Bridge migration from Rust-based MPC to Go

Hard requirements

  1. Go 1.23+ for building
  2. NATS server for inter-node messaging
  3. At least 3 nodes for production (2-of-3 threshold minimum)
  4. BadgerDB password (32-byte AES-256 key) for encrypted storage

Quick reference

ItemValue
APIhttps://mpc.hanzo.ai (port 8080, IAM auth)
Repogithub.com/hanzoai/mpc
Modulegithub.com/hanzoai/mpc
Branchmain
Imageghcr.io/hanzoai/mpc:v0.4.3
K8sStatefulSet hanzo-mpc (3 replicas) in hanzo namespace
Threshold2-of-3 (default)
Binarieshanzo-mpc (node), hanzo-mpc-cli (CLI tools)

One-file quickstart

Build and run

# Build all binaries
make build

# Generate peer configuration (3 nodes)
hanzo-mpc-cli generate-peers -n 3
hanzo-mpc-cli register-peers
hanzo-mpc-cli generate-initiator
hanzo-mpc-cli generate-identity --node node0

# Start a node
hanzo-mpc start -n node0

Docker Compose (full stack)

cd deploy
docker-compose up -d
# Starts: 3 MPC nodes, NATS, MinIO (backup), KMS

Go client

import (
    "github.com/hanzoai/mpc/pkg/client"
    "github.com/nats-io/nats.go"
)

func main() {
    natsConn, _ := nats.Connect("nats://localhost:4222")
    defer natsConn.Close()

    mpcClient := client.NewMPCClient(client.Options{
        NatsConn: natsConn,
        KeyPath:  "./event_initiator.key",
    })

    // Create a wallet (distributed key generation)
    walletID := "my-wallet-001"
    mpcClient.CreateWallet(walletID)

    // Listen for results
    mpcClient.OnWalletCreationResult(func(event event.KeygenSuccessEvent) {
        fmt.Println("Wallet created:", event)
    })
}

Core Concepts

Architecture

hanzoai/mpc/
  cmd/
    hanzo-mpc/              Main node binary
    hanzo-mpc-cli/          CLI tools (generate-peers, register, identity)
  pkg/
    mpc/                    TSS implementation (CGGMP21, FROST, LSS)
    kvstore/                BadgerDB storage (AES-256 encrypted)
    messaging/              NATS JetStream (pub/sub + P2P)
    identity/               Ed25519 node identity (age encrypted)
    client/                 Go client library
    api/                    HTTP API handlers
    policy/                 Policy engine (signers, limits, whitelist, FHE)
    threshold/              ThresholdVM (policy enforcement in signing)
    storage/                BadgerDB store + S3 backup client
    eventconsumer/          Event processing
    hsm/                    HSM abstraction (file, AWS, GCP, Azure, Zymbit, KMS)
    kms/                    Hanzo KMS integration
    encryption/             Encryption utilities
    encoding/               Serialization (CBOR for FROST/LSS configs)
    config/                 Configuration management
    infra/                  KV backends (ConsensusKV, NATS KV, Consul)
    keyinfo/                Key metadata management
    protocol/               Protocol message types
    types/                  Shared type definitions
    common/                 Common utilities
    constant/               Constants
    logger/                 Structured logging (zerolog)
    utils/                  Helper functions
  contracts/
    ThresholdPolicy.sol     On-chain policy enforcement contract
  deploy/
    compose.yml             Full stack Docker deployment
    Makefile                Deployment automation
  e2e/                      End-to-end integration tests
  examples/                 Usage examples
  docs/                     Documentation
  identity/                 Identity key templates
  config.yaml               Default configuration

Threshold Signing

Uses a t-of-n threshold scheme where t >= floor(n/2) + 1:

  • ECDSA (secp256k1): CGGMP21 protocol for Bitcoin, Ethereum, EVM, XRPL, Lux
  • ECDSA Taproot: FROST protocol for Bitcoin Taproot (BIP-340)
  • EdDSA (Ed25519): FROST (Taproot mode) for Solana, TON (partial)
  • LSS: Dynamic resharing (change t-of-n without key reconstruction)

KV Backend Architecture

All cluster state goes through an abstract infra.KV interface:

BackendConfigTransportUse Case
consensuskv_backend: consensusNATS + Lux QuasarProduction (dual-cert PQ finality)
natskv_backend: natsNATS JetStream KVDev/staging
consulkv_backend: consulConsul HTTPLegacy

ConsensusKV runs a private BFT blockchain with dual-certificate finality:

  • Classical: Ed25519 (64-byte signatures)
  • Post-quantum: ML-DSA-65 (FIPS 204, NIST Level 3, 3,309-byte signatures)
  • Block finalized only when BOTH signature types reach t-of-n threshold

Policy Engine

Fireblocks/Utila-style transaction governance:

  • Signers and roles (ADMIN, SIGNER, VIEWER)
  • Spending limits (per-tx, daily, monthly by asset)
  • Whitelist/blacklist, time windows, rate limiting
  • ThresholdVM: evaluates policies before signature shares
  • FHE private policies via luxfi/fhe (encrypted amount checks, cumulative spending)

HSM Configuration

hsm:
  provider: file  # file, aws, gcp, azure, zymbit, kms
  file:
    base_path: "."
    hex_encoded: true
  # aws:
  #   region: us-east-1
  #   key_arn: arn:aws:kms:us-east-1:123456:key/abc-def
  # gcp:
  #   project: my-project
  #   location: us-east1
  #   key_ring: mpc-keys
  # kms:
  #   site_url: https://kms.hanzo.ai
  #   client_id: ""
  #   client_secret: ""
  #   project_id: ""

NATS Topics

TopicPurpose
mpc.keygen_request.<walletID>Keygen request
mpc.mpc_keygen_result.<walletID>Keygen result
mpc.mpc_signing_result.<walletID>Signing result
mpc.consensus.<chainID>.blocksConsensus blocks
mpc.consensus.<chainID>.proposalsConsensus proposals

Blockchain Support

ChainCurveProtocolStatus
Bitcoin (Legacy/SegWit)secp256k1CGGMP21/LSSFull
Bitcoin (Taproot)secp256k1FROSTFull
Ethereum/EVMsecp256k1CGGMP21/LSSFull
XRPLsecp256k1CGGMP21/LSSFull
Lux Networksecp256k1CGGMP21/LSSFull
SolanaEd25519FROST (Taproot)Partial
TONEd25519FROST (Taproot)Partial

Production Deployment

K8s Cluster: hanzo-k8s (do-sfo3)
  Namespace: hanzo
  StatefulSet: hanzo-mpc (3 replicas)
  Image: ghcr.io/hanzoai/mpc:v0.4.3
  NATS: nats://nats.hanzo.svc.cluster.local:4222
  KV Backend: consensus (M-Chain)
  Config: ConfigMap hanzo-mpc-config
  Identity: Secret hanzo-mpc-identity
  Key shards: BadgerDB on PVC at /data/mpc/db/hanzo-mpc-{N}/

Deploy Stack (compose.yml)

ServicePortPurpose
hanzo-mpc-26000-6002MPC nodes
hanzo-kms8080Key management
nats4222Message broker
minio9000S3 backup storage

Testing

make test            # Unit tests
make test-coverage   # With coverage report
make e2e-test        # End-to-end (builds binaries first)
make test-all        # Unit + E2E

Critical Serialization Notes

  • Protocol messages MUST use MarshalBinary/UnmarshalBinary, NOT JSON
  • FROST TaprootConfig has no JSON marshalers -- use CBOR via MarshalFROSTConfig()
  • LSS lssConfig.Config same -- use CBOR via MarshalLSSConfig()
  • Party IDs must be sorted consistently across all nodes

Troubleshooting

IssueCauseSolution
"Handler cannot accept message"Normal broadcast self-receiptIgnore (expected behavior)
Keygen stuckNodes not discovering peersCheck NATS connectivity and peer registration
BadgerDB errorWrong passwordVerify BADGER_PASSWORD is exactly 32 bytes
E2E test failuresStale binaryRun go install ./cmd/hanzo-mpc && go install ./cmd/hanzo-mpc-cli
Signing failsInsufficient thresholdEnsure at least t nodes are healthy
  • hanzo/hanzo-kms.md - Key management service (control plane for MPC)
  • hanzo/hanzo-vault.md - PCI-compliant card tokenization
  • hanzo/hanzo-web3.md - Web3 services and gateway
  • hanzo/hanzo-evm.md - EVM execution engine

How is this guide?

Last updated on

On this page