
钱包地址看起来是个简单的东西:一串你复制、粘贴并向它转账的字符。在比特币上,它几乎确实就这么简单。在 Solana 上,把一个共享钱包——一个 multisig——放在某个地址背后,却出乎意料地难。本文解释原因,并提出本系列其余部分要回答的问题。
一个 multisig 地址必须承诺什么
multisig 钱包由多把密钥控制,其中固定数量的密钥必须达成一致,资金才能转移。例如一个"2-of-3" multisig 有三把密钥,需要其中任意两把批准一笔付款。其目的是消除单点故障:你丢失一把密钥,或一把密钥被盗,你的资金依然安全。
要让这有用,地址必须兑现两个承诺。第一,它必须事先可知——你想在尚未完成任何设置之前就把一个存款地址交给别人。第二,它必须诚实:向该地址转账的人应当能够相信,只有约定的那组密钥、按照约定的规则,才能从中花费。请记住这两个承诺。它们是下文一切内容的主线。
在比特币上,地址就是规则
比特币让这件事看起来很容易。一个比特币 multisig 由一段小脚本描述:公钥列表加上"M-of-N"规则。要得到地址,你取这段脚本并对它做哈希。地址(一个 P2WSH 地址)从字面意义上就是花费规则的哈希。
这有一个悄然有力的结果。任何人都能离线计算地址,在一台没有网络的笔记本电脑上,在广播任何一笔交易之前就完成。没有"创建钱包"这一步——钱包无需在网络上存在就能接收资金。脚本只在之后、花费资金时才被揭示,网络会检查揭示的脚本是否与地址匹配、是否有足够的有效签名。地址事先可知:是。诚实:是——因为地址源自规则本身,一组不同的密钥会产生一个不同的地址。
在 Solana 上,地址是必须被创建的账户
Solana 的运作方式不同。在 Solana 上,万物皆为账户——一个带有所有者的链上存储槽。你的资金住在账户里,程序住在账户里,一个 multisig 的配置也住在一个账户里。关键在于,账户不会凭空免费出现。一个账户必须被显式创建并付费:有人用一小笔称为"租金"的 SOL 为它注资,网络才会存储它的数据。
因此,Solana 上的 multisig 不只是一个地址——它是一个由程序控制、保存成员列表和阈值的账户。而在 multisig 能做任何事之前,这个账户必须由一笔交易创建出来。这就是困难的根源:Solana 上的共享钱包有一个设置步骤,而比特币根本没有。
PDA:没有私钥的地址
Solana 确实有一个为此而生的优雅工具,叫作程序派生地址(Program Derived Address),即 PDA。一个普通的 Solana 地址有一把与之对应的私钥——谁持有密钥,谁就控制地址。PDA 被刻意构造为位于曲线之外:它是一个看起来有效的地址,但没有私钥存在,也不可能存在。没有人能以个人身份为它签名。
取而代之,PDA 是被确定性地派生出来的。你取一些输入值——称为"种子"(seeds)——加上一个程序的 ID,让它们经过一个单向函数,输出就是地址。相同的种子和相同的程序总会产生相同的 PDA,因此任何人都能复现它。而且由于没有私钥,只有作为所有者的程序才能为该地址授权动作,它通过一种称为跨程序调用、使用 invoke_signed 的机制来做到这一点:程序把种子出示给 Solana 运行时,运行时便授予它对该 PDA 的签名权限。从不产生任何密码学签名——行动的权利来自知道种子,而非持有密钥。
PDA 正是 multisig 的合适归宿:一个由程序逻辑而非任何单一个人控制的地址。到目前为止一切顺利。难点在于,什么被选作种子。
先注资再创建的难题
正是在这里,Solana 上占主导地位的 multisig 遇到了麻烦。与比特币的确定性模型不同,Solana 上使用最广的 multisig——Squads V4 是其中的领头例子,成熟且经过大量审计——是从一个在创建时新生成并选定的随机值派生出 multisig 地址的,而不是从成员集合派生。在 Squads V4 中,这个值叫作 create_key,是当某个创建者运行创建交易时产生的一把临时密钥。
从随机的 create_key 派生地址是一个深思熟虑、合理的设计选择——它绕开了一个尴尬的边界情形,即两个不同的群组想要完全相同的成员组合。但它有两个值得清楚理解的后果:
- 你无法事先知道地址。 在有人运行创建交易之前,种子并不存在,因此地址也不存在。没有办法打印一个存款地址并在设置之前为它注资——这就是先注资再创建的难题。第一个承诺破裂了。
- 创建者是设置阶段的单点信任。 必须由某个特定账户运行那笔创建交易并选定那个随机值。在设置的那段短暂窗口里,你信任那一方会正确地完成它。
这些都不会使 Squads V4 不安全——它是 Solana 上身经百战的 multisig,守护着极为庞大的资金。这只是与比特币不同的一种信任形态。地址不再是"规则的哈希";它成了"创建交易碰巧产生的东西"。
以太坊找到了一条折中之路
以太坊面对过类似的问题,并用一个名为 CREATE2 的特性作答。它让你能够在合约部署之前、根据固定的输入计算出一个智能合约的地址。Safe 之类的钱包用它来给你一个所谓的反事实地址:一个真实、可注资的地址,你可以分享它并在其上接收资金,而真正的合约则被惰性地部署——只在资金首次需要转移时才部署。较新的账户抽象标准 ERC-4337 把同样的理念正式化。如此一来,以太坊重新取回了"事先可知"这个承诺,尽管它和 Solana 一样,最终仍需要一个链上对象存在。
本系列要回答的问题
把这三种模型并排放在一起。比特币:地址是规则的哈希——可离线获知、由构造而诚实、没有创建步骤。以太坊:一个反事实地址——可事先获知、部署被推迟。Solana 的通用 multisig:地址来自创建时刻的随机性——无法事先获知、设置时有一个需要信任的创建者。
那么问题来了。Solana 需要账户,账户需要被创建——这一点不会消失。但一个 Solana multisig 非得放弃比特币的那个性质吗?地址能否改为纯粹从成员集合与阈值——也就是规则本身——派生,从而做到可离线获知、可在设置前注资,并且因为一组不同的密钥产生一个不同的地址而诚实?
这正是 SSP 团队在自己的 Solana multisig 程序中构建出的性质。下一篇文章展示其做法:一个就是成员集合的地址,一个你可以在任何东西被记入链上之前注资的金库,以及一个完全不需要创建者的注册步骤。该设计随 SSP Wallet 的 Solana 支持一同发布——见版本公告——并且,与 SSP 对待安全的一贯方式一致,该程序目前仅在 devnet 上,正在主网之前等待一次外部审计。如果你对 multisig 本身仍然陌生,请先从什么是 multisig 以及它为何重要开始;否则,请继续阅读。


