
多重签名钱包在理论上看似简单。两个朋友想要共同签署交易、一个 DAO 金库需要理事会批准、一个拥有多个利益相关者的企业——概念很直观。困难的部分不在于密码学或链上机制,而在于协调。
参与者如何发现待处理的签名会话?谁负责广播最终交易?如果 Alice 在签名过程中断线、Bob 的协调器崩溃、Charlie 不记得自己是否已经发送了部分签名,该怎么办?传统的解决方案对这些问题含糊其辞:"使用受信任的服务器"或"带外协调"或"自己搭建基础设施"。
这些不是解决方案——而是向中心化或运维负担的妥协。但通过精心的分布式系统工程,点对点协调是可以实现的。
本文描述了我们如何为 Lotus 构建了真正去中心化的多重签名协调,以及为什么这对更广泛的加密货币生态系统很重要。
什么是 MuSig2?为什么它很重要?
MuSig2 是一种用于 Schnorr 签名的多重签名协议。多个参与方协作生成单个聚合签名,该签名在密码学上与单签名交易无法区分。
隐私和效率方面的提升是显著的。传统的 P2SH 三方多重签名需要99字节的公钥和210字节的签名——总计309字节。MuSig2 配合 Taproot 仅使用33字节的公钥和64字节的签名——97字节,减少了69%。更重要的是,该交易不会泄露有多少参与方或签名阈值是多少。
安全性属性是严格的。MuSig2 通过从所有参与者密钥派生的密钥聚合系数来防止恶意密钥攻击。它通过严格的会话管理和确定性 nonce 生成来防止 nonce 重用攻击(这种攻击会泄露私钥)。该方案在离散对数假设下具有可证明的安全性,与单签名 Schnorr 和 ECDSA 使用的安全假设相同。
当与 Taproot 结合时,MuSig2 能够实现看起来像基本支付的复杂链上行为:
- 支付通道,具有复杂的争议解决机制——Alice 和 Bob 的 Lightning 式通道看起来就像一个标准地址
- DAO 金库,需要理事会一致批准——3-of-3 或 5-of-5 多重签名看起来就像一个单密钥
- 带时间锁的金库——资金锁定六个月,除非所有各方同意提前释放
- 条件花费——"如果满足这些条件则支付给 Bob,否则退还给 Alice"
除非使用脚本路径,否则所有这些在链上都表现为简单的单签名交易。这不仅仅是隐私的表面文章。当复杂交易与日常活动无缝融合时,区块链分析从根本上变得更加困难。每个人都会受益。
该协议已标准化为 BIP-327,在 Bitcoin Core 中已实现,并经过密码学家的审计。但关键在于:MuSig2 需要两轮交互式通信。
中心化协调的问题
MuSig2 不是一个部署后就不用管的智能合约。它是一个需要精心编排的交互式协议:
第一轮:Nonce 交换 每个参与者使用 RFC 6979 确定性生成(默认情况下在生产安全中使用额外的随机熵)生成 nonce,并共享公开 nonce。每个人都必须在继续之前收到其他所有人的公开 nonce。
第二轮:部分签名交换 每个参与者使用自己的私钥、聚合 nonce 和交易数据创建部分签名。这些部分签名被合并为最终签名。
广播 必须有人将交易提交到网络。谁来做?如果他们拒绝呢?如果他们崩溃了呢?
这产生了一个协调问题,包含几个具有挑战性的子问题:
发现和会话管理
当 Alice 想要从她与 Bob 和 Charlie 共享的 3-of-3 地址花费时,她的钱包如何告知 Bob 和 Charlie 签名会话已经开始?区块链帮不上忙——关键在于签名完成之前链上什么都不会发生。传统方法:
- 中心化协调服务器:每个人都连接到一个中央服务,该服务转发消息。这种方法在服务器宕机、审查交易、被入侵或运营者决定收费之前都能工作。
- 手动协调:"Alice 把交易十六进制数据通过邮件发给 Bob 和 Charlie。Bob 回复他的部分签名。Charlie 在度假,三天没有回复。"这无法扩展。
- 自托管基础设施:每个人运行一个有公网 IP 的服务器,通过直接连接进行协调。这排除了移动钱包、NAT 后的用户以及任何不愿管理服务器基础设施的人。
身份验证和安全性
参与者如何验证消息确实来自预期的共同签名人?在没有中央权威的去中心化系统中,每个节点都必须独立验证消息的真实性。解决方案需要密码学证明:消息使用发送者的私钥签名,接收者在处理之前根据声称的公钥验证签名。
重放攻击和 Nonce 重用
什么能阻止 Eve 录制 Alice 之前会话的 nonce 并重放它?使用不同消息重用 nonce 会泄露私钥。协议必须强制执行严格的阶段转换:在 nonce 收集完成之前不能提交部分签名,不能跨会话重用 nonce,不能在同一会话中签署不同的交易。
协调器故障和故障转移
需要有人来聚合部分签名并广播交易。最明显的选择是指定一个参与者作为协调器。但当他们断线时会发生什么?是无限期等待?还是参与者手动通过带外方式商定新的协调器?
速率限制和 DoS 防护
在点对点系统中,什么能防止恶意行为者用垃圾数据淹没签名会话?你需要速率限制、声誉追踪和封禁不当行为节点的能力——但没有中央权威。
Lotusia 的解决方案
我们的方法将三种经过验证的分布式系统模式结合成一个连贯的点对点协调层:
1. 多层发现
我们使用 libp2p 的成熟基础设施,配合三种互补的发现机制:
DHT(分布式哈希表):会话公告存储在 Kademlia DHT 中(k=20 复制因子),使用从参与签名者和消息派生的会话标识符。当 Alice 创建签名会话时,她将公告发布到 DHT。Bob 和 Charlie 可以通过使用会话 ID 查询 DHT 来发现它。这提供了持久的、去中心化的存储,无需中央服务器——即使创建者离线,会话仍然可被发现。
GossipSub:为了实时签名者发现,参与者将广告发布到按交易类型组织的 PubSub 主题(例如 musig2:signers:SWAP)。当 Bob 广告他可以进行原子交换时,如果 Alice 订阅了该主题,她会在10-100毫秒内收到通知。这提供了即时的节点发现,无需 DHT 轮询延迟。
直接消息协议:一旦参与者发现彼此,协调消息(nonce、部分签名)通过 libp2p 的消息协议以点对点路由的方式发送。消息使用 libp2p 的 Noise 协议加密,并通过网络路由到特定节点,而非全局广播。
分层方法处理各种场景:DHT 用于持久会话存储和离线参与者发现,GossipSub 用于实时签名者广告,直接点对点消息用于实际的签名轮次。
2. 全程密码学安全
每条协议消息都使用 Schnorr 签名进行密码学签名。会话公告、签名者广告、签名请求和参与者加入都携带签名,证明发送者控制其声称的私钥。这一认证层防止了 DHT 投毒、冒充攻击和消息篡改。
安全架构通过多个独立层实现纵深防御:
速率限制:节点每60秒最多发送一条广告。违规触发自动升级——10次违规将导致永久封禁。
Sybil 抵抗:每个节点默认最多可广告10个公钥(经过验证的身份为50个,机构用户为100个)。这防止了单个行为者用虚假参与者淹没网络。
节点声誉追踪:系统基于行为维护黑名单(永久封禁)和灰名单(临时暂停)。无效签名、速率限制违规和垃圾信息尝试都会影响声誉评分,从而决定节点的待遇。
协议阶段强制:状态机确保正确的消息顺序。在会话建立之前不能提交 nonce。在 nonce 聚合完成之前不能发送部分签名。在签名最终完成之前不能广播交易。
消息重放保护:每条消息包含一个按签名者按会话严格递增的序列号。重复或乱序的序列号会触发拒绝和声誉惩罚。
基于燃烧的身份(可选):参与者可以通过在特定 LOKAD 标记格式中可证明地燃烧 XPI,将其身份锚定到区块链交易。这些身份使密钥轮换不会导致声誉丢失——身份绑定到 (txId, outputIndex) 而非临时密钥,并需要成熟期(注册需144个区块,轮换需6个区块)以防止时间攻击。在未来的实现中,这可能成为建立节点声誉的必要组件。
3. 确定性协调器选举
这是使故障转移优雅运作的关键部分。所有参与者运行相同的确定性算法,而不是手动指定协调器。
默认的选举方法是字典序排序:
function electCoordinator(signers: PublicKey[]): ElectionResult {
// Sort public keys by binary buffer comparison
const sorted = signers
.map((pk, idx) => ({
originalIndex: idx,
publicKey: pk,
buffer: pk.toBuffer(),
}))
.sort((a, b) => a.buffer.compare(b.buffer))
// First in sorted order becomes coordinator
return {
coordinatorIndex: 0,
coordinatorPublicKey: sorted[0].publicKey,
sortedSigners: sorted.map(item => item.publicKey),
// ... index mappings and election proof
}
}
每个人提供相同的公钥,每个人以相同方式排序,每个人选择第一个——无需投票,无需通信,无歧义。排序与 MuSig2 密钥聚合对参与者的排序方式完全一致,确保了整个协议的一致性。
当协调器崩溃或拒绝广播时?系统自动故障转移到排序中的下一个参与者。这可以承受 N-1 次故障,意味着 3-of-3 多重签名只有在三个参与者同时离线时才会无法响应。
确定性是至关重要的。在分布式系统中,共识是昂贵的。但当你可以在不协调的情况下做出决策时——因为每个人都独立计算出相同的答案——你就消除了整类故障模式。实现还支持基于哈希、首签名者和末签名者的选举方法,以适应特定用例。
这些功能启用了什么
这些模式结合起来,支持了之前需要中心化基础设施的用例:
多重签名金库:从 2-of-2 共享账户到 10-of-10 理事会金库(均为 n-of-n),具有自动协调器故障转移,确保即使在部分故障期间也能进行花费。
支付通道:双方通道(Alice ↔ Bob),任一方都可以发起通道更新,即使一方的协调器软件崩溃,通道仍保持运行。
原子交换:真正的点对点跨链交换,参与者在没有第三方的情况下协调同时签署交换的两端。
时间锁金库:在超时前需要所有参与者签名,超时后只需单个签名——多重签名协调在后台无缝进行。
SwapSig 隐私协议:我们的 CoinJoin 等效方案,多方协调创建一个合并了输入和输出的单笔交易,打断链上可追溯性的同时保持对各个签名的验证。未来的博客文章将对 SwapSig 进行深入分析。
基础设施是通用的。任何需要交互式多方签名的场景都可以使用它。
对更广泛加密货币生态系统的意义
这个实现是与特定加密货币无关的。协调层独立于区块链共识运行——纯粹的点对点网络和密码学消息传递。Bitcoin 可以将其用于 Taproot 多重签名。Ethereum 可以将其用于账户抽象中的门限签名。任何支持 Schnorr 签名的加密货币都可以集成这一基础设施。Lightning 通道、原子交换、隐私协议、DAO 治理和 DeFi 操作都需要交互式多方协调。同一套基础设施解决了所有这些问题。
更重要的是,这证明了去中心化协调对于生产系统是可行的。行业默认使用中心化协调器,不是因为点对点协调不可能,而是因为没有人交付一个可用的实现。当可复用的基础设施存在时——就像 TCP/IP 之于网络或 TLS 之于加密——开发者就不再将这个问题视为可选的。这改变了基线预期:去中心化协调成为默认而非例外。
实现状态和下一步
实现已完成并可运行。超过91个测试验证了协议实现、协调器选举、故障转移场景、消息认证和重放保护。代码已经过数周的活跃开发,处理了我们通过广泛测试发现的边界情况。
连接管理被适当隔离。你的钱包与 Lotus 网络保持的通用点对点连接与特定于会话的签名连接是分开的。钱包连接限制不会阻碍多重签名会话,多重签名活动也不会耗尽你的通用节点槽位。
MuSig2 聚合公钥成为 Taproot 内部密钥。复杂的脚本树(用于回退条件或时间锁)除非通过脚本路径花费,否则保持隐藏,并且只揭示被使用的分支。
实现存放于 lotus-sdk,我们为 Lotus 打造的现代 TypeScript SDK。工作示例演示了:
- 基本的 2-of-2 签名与自动发现
- 多方协调器选举和故障转移
- Taproot 集成,支持密钥路径和脚本路径花费
- 会话管理和重放保护
技术文档涵盖了架构决策、安全考量、API 使用和测试流程。
前进之路
MuSig2 优雅而可证明地解决了多方 Schnorr 签名的数学问题,但协调基础设施仍然是中心化的。这个实现证明了点对点协调是切实可行的。基础设施是通用且可复用的——构建一次,随处使用。技术应该增强人际关系,而非阻碍或取代它们。
现在到了关键阶段:实验与迭代。软件通过真实使用而成熟,而非猜测。在 Lotusia 社交档案上查看社区声誉在实践中的运作方式,或阅读我们如何进行内容排名。安装 lotus-sdk,尝试示例,打破协议,报告问题。真实世界的使用将揭示边界情况并为下一次迭代提供信息。Lotus 一直致力于把事情做对。Lotusia 乌龟走得慢,但每一步都深思熟虑,稳步迈向胜利。
资源:
- MuSig2 P2P 文档 - 完整的 API 参考和示例
- lotus-sdk 代码库 - 源代码和测试套件
- BIP-327 规范 - MuSig2 协议规范
- Lotus 文档 - 区块链和开发者指南
社区:
- Discord - 实时技术讨论
- Telegram - 社区交流
- GitHub Issues - Bug 报告和功能请求