MPCium:高弹性、安全的 MPC 引擎
Mpcium 是一个用 Go 编写的高性能框架,使用多方计算(MPC)实现安全的分布式门限签名方案。与将私钥存放在单一位置的传统密码系统不同,Mpcium 将私钥分片分布在多个独立节点上,只有达到门限数量的节点协同配合,才能执行交易签名等密码学操作。
这一架构带来:
- 更强的安全性: 不存在单点泄露风险
- 分布式信任: 无需信任任何单一实体
- 容错能力: 即使部分节点故障,系统仍能正常运行
- 隐私保护: 没有任何单个节点持有完整密钥
在密码学核心层面,Mpcium 集成了 tss-lib,这是由 Binance 开发的生产级门限签名方案库。它支持:
-
ECDSA (secp256k1):Bitcoin、Ethereum、BNB、Polygon 以及 EVM 兼容的 L2 链
-
EdDSA (Ed25519):用于 Solana、Polkadot、Cardano 及其他现代区块链
架构文档

👉 详细架构文档
门限与节点
Mpcium 使用 t-of-n 门限方案来安全地生成私钥并使用私钥签名。
n= MPC 节点(密钥分片)总数t= 签名所需的最少节点数
n 个节点中只需 t 个参与即可,完整私钥永远不会被重建。
为了在节点被攻破时仍能保持安全,Mpcium 强制要求:
t ≥ ⌊n / 2⌋ + 1
示例:2-of-3 门限
- ✅
node0 + node1→ 签名成功 - ✅
node1 + node2→ 签名成功 - ❌ 仅
node0→ 分片数量不足
这可以确保:
- 不存在单点泄露风险
- 部分节点离线时仍具备容错能力
- 可通过调整
t和n配置安全级别
架构
概述
每个 Mpcium 节点:
- 在本地 AES-256 加密存储(基于 Badger KV)中保存一个密钥分片
- 使用
tss-lib参与门限签名 - 通过基于 NATS 的弹性消息层进行通信
- 向 Consul 注册自身,用于服务发现和健康检查
- 使用基于 Ed25519 的双向认证校验收到的消息
消息流与签名校验
- 签名请求作为经过认证的事件,通过 NATS 广播到 MPC 集群。每个节点在处理请求前都会校验发送方的 Ed25519 签名。
- NATS 将请求广播给各 MPC 节点。
- 每个参与节点都会校验:
- 发送方的签名(Ed25519)
- 消息的真实性(不可重放、会话唯一)
- 如果节点健康且属于法定数量(
t)之内,它会:- 使用其分片计算部分签名
- 通过 NATS 发布计算结果
- 收到
t个部分签名后,将其聚合为完整签名。
特性
- 无单点泄露风险:密钥永远不会被完整组装
- 拜占庭容错:只需
n个节点中的t个即可继续执行 - 可扩展、可插拔:可轻松扩展集群或集成其他工具
- 安全的节点认证:所有节点间消息都使用 Ed25519 签名和校验
安装与运行
使用预览
启动节点
$ mpcium start -n node0
$ mpcium start -n node1
$ mpcium start -n node2
客户端实现
- Go:位于
pkg/client目录中。使用示例请查看examples文件夹。 - TypeScript:位于 github.com/fystack/mpcium-client-ts
客户端
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 mpc.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)
}