
0. 回顾
- 保护 Solana 生态系统 (1) — Hello Solana
- 保护 Solana 生态系统 (2) — 程序间调用
- 保护 Solana 生态系统 (3) — 程序升级
- 保护 Solana 生态系统 (4) — 账户验证
1. 概述
在上一篇 博客 中,我们讨论了 Solana 程序中对访问控制至关重要的账户验证。然而,对于去中心化 DApp 和保护潜在的私钥泄露,多重签名(multi-sig)非常重要。在本篇文章中,我们将介绍多重签名的实现。
2. 多重签名的概念
多重签名是一种数字签名方案,它允许多个用户对单个交易进行签名。该交易可以是对特权函数(例如 mint)的调用、资金转账指令等。多重签名的机制是,给定 n 个拥有自己私钥的参与方,至少需要 m 个私钥签名才能执行交易。这可以使 DeFi 中的资金更加安全,并保护私钥泄露和“地毯式拉盘”(rug pull)等潜在风险。
3. 多重签名的使用
在 Solana 中,有一个来自 Serum 的 多重签名程序,其逻辑与 OpenZeppelin 开发的多重签名程序非常相似。这允许多个用户在链上完全签名一个交易。但是,如果您可以在链下收集所有必需的签名,过程会更容易。为了说明这一点,我们在上一篇文章的测试代码中添加了多重签名功能。所有测试代码都可以在 这里 找到。
3.1 代码审查
在 上一次介绍的项目 中,我们将 config 账户的管理员替换为 multisig 账户。在这种情况下,要执行 Lock 和 Unlock 指令,客户端必须在交易中包含足够的有效所有者签名。

我们添加了一个名为 Multisig 的结构体,包含四个属性:执行指令所需的签名数量、有效签名者的总数、账户状态(是否已初始化)以及有效签名者的公钥数组。

相应地,我们在 instruction.rs 中也添加了 InitializeMultisig 指令。请注意,它从客户端接收参数 m (u8)。这个值将被传入 InitializeMultisig() 函数。

InitializeMultisig() 函数接收创建的账户和值 m。为了防止账户被恶意用户重新初始化,我们验证账户是否已经初始化(第 385-388 行)。之后,我们通过分配 m、n 和签名者的公钥值来初始化多重签名账户。

在 Lock() 函数中,我们检查 config 账户的管理员是否是多重签名账户。如果是,它将验证并计算传入的签名(第 151 至 158 行)。一旦有效签名数量达到或超过所需数量,门将被锁定(第 163 至 168 行)。Unlock() 函数中的多重签名实现与 Lock() 函数类似。
我们将程序部署在测试网上,您可以在以下链接找到它:
https://explorer.solana.com/address/4g5ZA47pDQ1Bv93aNYdSKAXB6DvPAnnbi9cNEx7722SK?cluster=testnet
3.2 发送交易

在 InitializeMultisig() 函数中,keys 包含四个账户:多重签名账户和三个有效签名者的账户。请注意,其中一个签名者也是交易的费用支付者。我们将 m 的值设置为 2,这意味着执行特权函数需要三个签名者中的两个签名。

我们还通过在指令数据中传递多重签名账户的公钥,将 config 账户的管理员设置为 multisig 账户。

在 lock() 函数中,除了 config 账户(第 410 行)之外,我们还传入 multisig 账户(第 411 行)和两个(至少)有效签名者的账户(第 412-413 行)。我们将签名者的 isSigner 属性设置为 true。同样,unlock() 函数的逻辑与之类似。
所有测试交易如下所示。整个过程是 Allocate PDA()-> InitializeMultisig() -> InitializeDoor()-> InitializeConfig()-> Unlock() -> Open() -> Close()-> Lock()。
https://explorer.solana.com/tx/2inXLHv34NzkmwmvQ7iimdNbEX2Hj8qWS3MVteAPtwhCAPy1yxXXdvfzMmUL7tESsd4wat4LMcPNiEQav18kQTrZ?cluster=testnet
https://explorer.solana.com/tx/4GErNusHLXpUHBsAJ55c7v1Ur1jfv5hAR88CK8nabLnzc92b1UhDnNRryKVjKmcnJDXppmyk6m5RUdpR2w7MEbrU?cluster=testnet
https://explorer.solana.com/tx/2S8h66oWfh7cn4fwFCVPtgGw1o3NgzyWwU1GyRpDjH4PEBfe8LDMZGAEBYLRJpzL3anH9ENShntjg3q5K8gcZSrN?cluster=testnet
https://explorer.solana.com/tx/nVKxPYegbpH324y57uHDZiajpNA5u4bSSJ2gHFHHRx4GJBy1DcpxnccKh1Ltkv9dah1qJNi9jWuBnXbyHWXCJyw?cluster=testnet
https://explorer.solana.com/tx/3KK5CU88oV59VfdTrNpT4LsiUsetuGdc6qW3sNyyGEWVYtKJfD6XA2Nfknrriwuka9wknHpZs3WZ1WkeduDA1pZX?cluster=testnet
https://explorer.solana.com/tx/3rFo37CrLSsMehLk4kwmMSDnbRfLfoPCWZzRDXhwwLg1uq32gu4ddxkYYB3pJX1yiMN8MofnV1Y9CSaf8bQaNJ9Y?cluster=testnet
https://explorer.solana.com/tx/5yFq4dZAMpccn96jKNkYFVcmhmtrwZYSFEQ6pkNgSMd7e1Vy1ztAM3RdFUZjEtThjFssz1TFytowePPyY59we9rX?cluster=testnet
https://explorer.solana.com/tx/3Ut4DqjCQi1MoCsjRx24DxykyDMsmyRsjJSXS7D4FBeZQwrx4UzxWt2gDe6YRiwUHzFkH3eWkFHub6FNSp2Us4Q7?cluster=testnet
3.3 测试交易
为了测试多重签名是否真的有效,我们修改了客户端的脚本。

如上所示,我们只传入了一个签名者账户,并只提供了一个有效签名。

我们注意到,由于签名不足,门无法解锁。
4. 总结
本文介绍了 Solana 中多重签名的一个简单实现。它适用于您可以离线收集多个用户签名的场景。交易需要完全在链上签名的场景将在稍后介绍。敬请关注,我们将在接下来的文章中分享更多内容。
阅读本系列的其他文章:
- 保护 Solana 生态系统 (1) — Hello Solana
- 保护 Solana 生态系统 (2) — 程序间调用
- 保护 Solana 生态系统 (3) — 程序升级
- 保护 Solana 生态系统 (4) — 账户验证
- 保护 Solana 生态系统 (6) — 多重签名 2
- 保护 Solana 生态系统 (7) — 类型混淆
关于 BlockSec
BlockSec 是一家开创性的区块链安全公司,由一群全球知名的安全专家于 2021 年创立。公司致力于提高新兴 Web3 世界的安全性和可用性,以促进其大规模采用。为此,BlockSec 提供智能合约和 EVM 链 安全审计 服务,用于安全开发和主动威胁拦截的 Phalcon 平台,用于资金追踪和调查的 MetaSleuth 平台,以及供 Web3 构建者高效浏览加密世界的 MetaSuites 扩展。
至今,公司已服务超过 300 家知名客户,如 MetaMask、Uniswap Foundation、Compound、Forta 和 PancakeSwap,并在两轮融资中从 Matrix Partners、Vitalbridge Capital 和 Fenbushi Capital 等知名投资者那里获得了数千万美元的投资。
官方 Twitter 账号:https://twitter.com/BlockSecTeam



