自启动的 Solana 多签钱包

·阅读 7 分钟·作者:SSP Editorial Team
SSP 自启动 Solana 多签钱包示意图,置于 SSP 品牌深蓝色封面之上

地址即成员集合的 Solana 多签钱包

多签钱包需要两把或更多密钥才能批准任何一笔支出。在比特币上,钱包地址只是其自身规则的一个哈希——公钥列表和"需要多少个签名"这个数字。你可以在便签纸上算出这个地址,把它分发出去,并在任何人接触区块链之前很久就收到资金。

Solana 传统上做不到这一点。正如本系列的第一篇文章所解释的,主流的 Solana 多签要求你在钱包地址尚不存在之时,先运行一笔由创建者选取随机数的创建交易。SSP 自己的 Solana 多签程序则采用了比特币式的方法。它是自启动的:钱包地址就是成员集合。

先说明一点:SSP 的 Solana 多签程序是开源的(RunOnFlux/Solana-Multisig),目前仅运行于 devnet,即 Solana 的测试网。主网部署取决于一次外部安全审计。

两个地址:多签地址与 vault 地址

SSP 的设计为每个多签钱包使用两个独立的地址。

多签地址保存规则——排序后的成员密钥列表、阈值("M-of-N"中的 M)以及一个已提议交易的计数器。它归 SSP 的程序所有。

vault 地址保存资金——SOL 和 SPL 代币。它归 Solana 内置的 System Program 所有,自身不存储任何数据。vault 就是充值地址:你把它给任何想付款给你的人。

两者都是一种程序派生地址(Program Derived Address,简称 PDA)——一个没有私钥的地址,被刻意放置在密码学曲线之外,因此任何密钥都无法控制它。只有派生出它的程序才能授权从中转出。这个细节在文末很重要。

地址如何由成员计算得出

正是这一部分让钱包能够自启动。用通俗的话说,要派生多签地址:取字面标签 multisig、一个对排序后成员列表的 SHA-256 哈希,以及阈值;然后把这些连同 SSP 的程序 ID 一起送入 Solana 的地址派生函数。有三个细节值得注意。

**成员会先被排序和去重。**一个由成员 A、B、C 组成的 2-of-3 钱包,无论你把他们列为 C, A, B 还是 B, C, A,都会产生相同的地址。顺序无关紧要;重要的只是这个集合

**使用完整的 32 字节哈希,绝不使用截短的版本。**截短哈希会打开一个真实的攻击面:攻击者可以去寻找一个不同的成员集合,使其哈希出相同的截短值,随后在你的地址上注册他们自己的成员,并抽干你预先存入的任何资金。完整的 32 字节哈希让这种搜索的代价高到天文数字,因此永远不会发生。

**阈值是地址的一部分。**一个 2-of-3 钱包和一个成员完全相同的 3-of-3 钱包是位于不同地址的不同钱包。规则被铭刻进了身份之中。

vault 地址随后由多签地址加上一个小的索引号派生而来(SSP 始终使用索引 0),因此 vault 同样完全由成员集合和阈值决定。

实际效果是:**任何人都可以离线计算出这两个地址,在发送任何一笔交易之前。**你可以分发 vault 地址,并把资金收进一个在链上还不存在的钱包——这就是比特币的特性,被带到了 Solana。

无需许可的注册:任何人都能将其启用

只要你知道成员,钱包地址就已经存在了。但要从中支出,规则终究需要写到链上——程序把这一步称为 initialize

在大多数 Solana 多签中,只有一个有特权的创建者才能完成对应的步骤。而在 SSP 的程序中,初始化是无需许可的:任何人都可以做。没有创建者账户,没有成员签名,没有特殊权限。通常由 SSP 的 relay 服务支付那一小笔租金费用并启用钱包,但究竟由谁来做其实无关紧要。

这听起来令人警觉,直到你看到那项安全检查。当有人初始化钱包时,程序会重新计算其所提供成员列表的 SHA-256 哈希,并**除非该哈希与铭刻在地址中的哈希相符,否则拒绝该交易。**Solana 的账户框架会独立地把地址绑定到同一个哈希上。这两项检查合在一起意味着:**规范地址只能容纳规范的成员集合。**没有人能用自己选定的成员列表注册你的地址——哈希不会相符,交易就会失败。

为什么陌生人初始化你的钱包伤害不了你

来梳理一下攻击者实际上能尝试什么。

**他用一个不同的成员集合初始化。**不同的集合哈希出不同的值,从而派生出一个不同的地址。攻击者只是在 Solana 上别处创建了自己一个毫无关联的钱包——与你的 vault 没有联系,对你的资金没有主张权。

**他用你的成员集合初始化。**哈希相符,所以交易成功,但他所做的一切只是替你付了租金费用。钱包如今以你所预期的规则被注册,而攻击者并非成员,因此他无法提议、批准或执行任何东西。资金从不停留在多签地址本身——它停留在 vault 中,而 vault 归系统所有,无法被劫持。无论由谁初始化钱包、何时初始化,结果都是同一个规则正确的规范钱包。

阈值在你支出时校验,而非在注册时

这与比特币 P2WSH 多签所用的模型相同,值得明确说一句:M-of-N 阈值只在资金转移时执行,绝不在注册时执行。

注册只是记录"这些是成员,这是阈值"。它不要求签名,因为它造不成任何伤害。真正的关卡是支出流程,程序在那里清点批准数,并在足够多的成员表示同意之前拒绝行动。地址是规则的哈希;任何人都可以为它注资;只有有效的签名才能支出。要复习"M-of-N"的含义,请参阅2-of-2 与 2-of-3 与 M-of-N 多签对比

完整的生命周期,从头到尾

把各个部分拼起来,一个 SSP Solana 多签钱包的一生:

  1. **派生。**任何人根据成员和阈值离线计算出多签地址和 vault 地址。不涉及区块链,没有成本。
  2. **预先注资。**任何人向 vault 地址发送 SOL 或代币;即便钱包尚未注册,这也行得通。
  3. **初始化。**任何人,通常是 SSP 的 relay,提交那笔无需许可的注册交易。程序验证成员哈希,并把规范规则写到链上。
  4. **提议。**一位成员创建一项交易提议,紧凑地存储在一个专用的提议账户上。
  5. **批准。**每位成员各批准提议一次。批准在链上累积。
  6. **执行。**当批准数达到阈值时,任何人都可以触发执行。程序先把提议标记为已执行——一项刻意的保护,使其永远不会被执行两次——然后逐条执行每个指令,由 vault 本身充当签名者

最后这一步正是无私钥 vault 地址发挥作用之处。由于 vault 是一个没有私钥的 PDA,没有任何人或程序能以常规方式通过签名来转移它的资金。唯一的出口是 SSP 的程序去执行一项已批准、已达阈值的提议——它通过把 vault 的派生配方呈交给 Solana 运行时来为 vault"签名",而它能获得这一许可,纯粹是因为它是该地址的所有者。

没有创建者、没有管理员、不在原地轮换密钥

最后两项特性把整个设计串了起来。

**成员集合和阈值是不可变的。**钱包一旦初始化,程序中的任何指令都无法更改其成员或阈值——根本不存在这样的代码路径。要更改谁控制一个钱包——其他系统含糊地称之为"轮换密钥"——你要用新的成员集合创建一个新的多签,并把资金转移过去。旧地址永远保留它的旧规则。

**永远没有创建者角色,也没有管理员密钥。**许多多签设计保留一个有特权的账户,可以推翻成员或更改配置。SSP 的程序一个都没有:没有可被攻陷的东西,没有可被仿冒的管理员密钥,没有可被胁迫的创建者。成员和阈值就是故事的全部。

这种极简是一种刻意的取舍:SSP 构建的是一个小巧、确定性的基本单元,而非一个功能丰富的治理平台。下一篇文章SSP 的 Solana 多签对比 Squads,会诚实地把这一设计与 Squads V4——成熟、经过审计、占主导地位的 Solana 多签——进行对比。要了解产品背景,Solana 支持的发布公告介绍了 SSP Wallet v1.39.0 带来了什么。

核心思想小到足以装进脑海:在 SSP 的 Solana 多签上,钱包地址是其自身规则的一枚指纹。知道了成员和阈值,你就知道了地址。不需要别的,也不信任别的。

分享本文

相关文章