Mpcium is a high-performance, open-source Multi-Party Computation (MPC) engine for securely generating and managing cryptographic wallets across distributed nodes—without ever exposing the full private key.
At its cryptographic core, Mpcium integrates tss-lib, a production-grade threshold signature scheme library developed by Binance. It supports:
-
ECDSA (secp256k1): Bitcoin, Ethereum, BNB, Polygon, and EVM-compatible L2 chains
-
EdDSA (Ed25519): for Solana, Polkadot, Cardano, and other modern blockchains
Resources
- MPC nodes architecture: MPC Fundamental and MPCIUM architecture
- MPC clients:
📦 Dependencies Overview
| Dependency | Purpose |
|---|---|
| NATS | Lightweight and resilient messaging layer for coordinating MPC nodes in real time. Enables pub/sub communication even under partial failure. |
| Badger KV | High-performance embedded key-value store used for local encrypted storage of MPC key shares and session data. |
| Consul | Service discovery and health checking to allow nodes to dynamically find each other and maintain cluster integrity. |
| tss-lib | Cryptographic engine for threshold key generation and signing, supporting ECDSA and EdDSA (used in Bitcoin, Ethereum, Solana, etc). |
| age | Modern encryption tool used for secure key material storage and protection with password-based encryption. |
Threshold & Nodes
Mpcium uses a t-of-n threshold scheme to securely generate and sign with private keys.
n= total number of MPC nodes (key shares)t= minimum number of nodes required to sign
Only t out of n nodes need to participate — the full private key is never reconstructed.
To maintain security against compromised nodes, Mpcium enforces:
Example: 2-of-3 Threshold
- ✅
node0 + node1→ signs successfully - ✅
node1 + node2→ signs successfully - ❌
node0alone → not enough shares
This ensures:
- No single point of compromise
- Fault tolerance if some nodes go offline
- Configurable security by adjusting
tandn
Architecture
Overview
Each Mpcium node:
- Holds a key share in local AES-256 encrypted storage (via Badger KV)
- Participates in threshold signing using
tss-lib - Communicates over a resilient messaging layer using NATS
- Registers itself with Consul for service discovery and health checks
- Verifies incoming messages using Ed25519-based mutual authentication
Message Flow & Signature Verification
- A signing request is broadcast to the MPC cluster through NATS as an authenticated event. Each node verifies the sender's Ed25519 signature before processing the request.
- NATS broadcasts the request to the MPC nodes.
- Each participating node verifies:
- The signature of the sender (Ed25519)
- The authenticity of the message (non-replayable, unique session)
- If the node is healthy and within the quorum (
t), it:- Computes a partial signature using its share
- Publishes the result back via NATS
- Once
tpartial signatures are received, they are aggregated into a full signature.
Properties
- No single point of compromise: Keys are never fully assembled
- Byzantine-resilient: Only
tofnnodes are required to proceed - Scalable and pluggable: Easily expand the cluster or integrate additional tools
- Secure peer authentication: All inter-node messages are signed and verified using Ed25519
Installation and Run
For full installation and run instructions, see INSTALLATION.md.
Preview usage
Start nodes
$ mpcium start -n node0 $ mpcium start -n node1 $ mpcium start -n node2
Client Implementations
- Go: Available in the
pkg/clientdirectory. Check theexamplesfolder for usage samples. - TypeScript: Available at github.com/fystack/mpcium-client-ts
Client
import ( "github.com/fystack/mpcium/client" "github.com/nats-io/nats.go" ) func main () { natsConn, err := nats.Connect(natsURL) if err != nil { logger.Fatal("Failed to connect to NATS", err) } defer natsConn.Close() mpcClient := client.NewMPCClient(client.Options{ NatsConn: natsConn, KeyPath: "./event_initiator.key", }) err = mpcClient.OnWalletCreationResult(func(event event.KeygenSuccessEvent) { logger.Info("Received wallet creation result", "event", event) }) if err != nil { logger.Fatal("Failed to subscribe to wallet-creation results", err) } walletID := uuid.New().String() if err := mpcClient.CreateWallet(walletID); err != nil { logger.Fatal("CreateWallet failed", err) } logger.Info("CreateWallet sent, awaiting result...", "walletID", walletID) }

