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.

Hanzo MPC - Multi-Party Computation for Distributed Wallet Management

Category: Hanzo Ecosystem Related Skills: hanzo/hanzo-kms.md, hanzo/hanzo-vault.md, hanzo/hanzo-web3.md

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?

Tech Stack

OSS Base

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

When to use

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

| Item | Value | |------|-------| | API | https://mpc.hanzo.ai (port 8080, IAM auth) | | Repo | github.com/hanzoai/mpc | | Module | github.com/hanzoai/mpc | | Branch | main | | Image | ghcr.io/hanzoai/mpc:v0.4.3 | | K8s | StatefulSet hanzo-mpc (3 replicas) in hanzo namespace | | Threshold | 2-of-3 (default) | | Binaries | hanzo-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:

KV Backend Architecture

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

| Backend | Config | Transport | Use Case | |---------|--------|-----------|----------| | consensus | kv_backend: consensus | NATS + Lux Quasar | Production (dual-cert PQ finality) | | nats | kv_backend: nats | NATS JetStream KV | Dev/staging | | consul | kv_backend: consul | Consul HTTP | Legacy |

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

Policy Engine

Fireblocks/Utila-style transaction governance:

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

| Topic | Purpose | |-------|---------| | mpc.keygen_request.<walletID> | Keygen request | | mpc.mpc_keygen_result.<walletID> | Keygen result | | mpc.mpc_signing_result.<walletID> | Signing result | | mpc.consensus.<chainID>.blocks | Consensus blocks | | mpc.consensus.<chainID>.proposals | Consensus proposals |

Blockchain Support

| Chain | Curve | Protocol | Status | |-------|-------|----------|--------| | Bitcoin (Legacy/SegWit) | secp256k1 | CGGMP21/LSS | Full | | Bitcoin (Taproot) | secp256k1 | FROST | Full | | Ethereum/EVM | secp256k1 | CGGMP21/LSS | Full | | XRPL | secp256k1 | CGGMP21/LSS | Full | | Lux Network | secp256k1 | CGGMP21/LSS | Full | | Solana | Ed25519 | FROST (Taproot) | Partial | | TON | Ed25519 | FROST (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)

| Service | Port | Purpose | |---------|------|---------| | hanzo-mpc-{0,1,2} | 6000-6002 | MPC nodes | | hanzo-kms | 8080 | Key management | | nats | 4222 | Message broker | | minio | 9000 | S3 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

Troubleshooting

| Issue | Cause | Solution | |-------|-------|----------| | "Handler cannot accept message" | Normal broadcast self-receipt | Ignore (expected behavior) | | Keygen stuck | Nodes not discovering peers | Check NATS connectivity and peer registration | | BadgerDB error | Wrong password | Verify BADGER_PASSWORD is exactly 32 bytes | | E2E test failures | Stale binary | Run go install ./cmd/hanzo-mpc && go install ./cmd/hanzo-mpc-cli | | Signing fails | Insufficient threshold | Ensure at least t nodes are healthy |

Related Skills


Last Updated: 2026-05-12 Category: Hanzo Ecosystem Related: mpc, threshold-signing, wallet, cryptography, custody Prerequisites: Go 1.23+, NATS, BadgerDB