Back to Blog

安全 Solana 生态(6)——多签2

April 24, 2022
5 min read

0. 回顾

1. 概述

在上一篇 博客 中,我们讨论了多重签名的实现。然而,该实现假设可以链下同时收集多个用户的签名。在本文中,我们介绍了一个更通用的多重签名程序,该程序允许用户在链上完全签名。

2. 测试程序设计

多重签名程序允许有效的签名者分开签署提案,并且一旦提案获得批准(收集到足够的签名),任何人都可以执行该提案。所有测试代码都可以在 这里 找到。

3. 代码审查

本程序引入了两个额外的结构体,它们是 TransactionAccountTransactionTransactionAccount 结构体用于记录提议交易所使用的账户信息。Transaction 结构体用于记录提案的信息。请注意,signers 属性用于记录有效签名的数量。did_executeis_initialized 确保执行和初始化只能进行一次。

该程序提供了五种不同的指令。AllocatePDA 指令旨在创建一个唯一的 PDA 账户,并将其用作 multisig 账户。它将记录所有有效签名者的信息。在 InitializeMultisig 指令中,我们设置了执行指令所需的签名数量,以及有效签名公钥的数组。CreateTransaction 指令用于创建提案,而签名者可以通过 approve 指令批准提案。一旦批准数量达到 multisig 中设定的阈值,就可以调用 ExecuteTransaction 指令来执行交易。

要提交提案,用户可以调用 createTransaction() 指令。它需要三个账户,分别是创建的 transaction 账户,以及为目标交易使用的后两个账户。为了防止账户被恶意用户重新初始化,我们检查 is_initialized 属性(第 161-163 行)。之后,我们使用指定的数据初始化 TransactionAccount 结构体,并将其序列化到数据账户中(第 188 行)。

Approve() 函数中,我们首先检查 Transaction 账户和 multisig 账户是否由程序拥有。请注意,如果没有检查,来自其他程序的账户可能会被恶意用户在此处使用。接下来,我们将签名者的公钥与存储在 multisig 账户中的密钥进行匹配。如果匹配,将验证您的签名,并相应地将值更改为 true

ExecuteTransaction() 指令中,我们计算有效签名的数量。如果数量未达到阈值,程序将回滚。

之后,我们使用指定的属性初始化目标 Instruction,并通过 invoke_signed() 函数调用目标程序的指令。最后,我们将 did_execute 属性设置为 true,以防提案被重复执行。

我们将程序部署在测试网上,您可以在以下链接中找到它。

https://explorer.solana.com/address/CPzn7ptnJntjUB4NGKqQGRai8NFLNwFaspmJ7nEGbMHe?cluster=testnet

4. 发送交易

部署完成后,我们首先创建 multisig 账户,并在初始化 config 账户时将其设置为 config 账户的管理员。相关交易如下所示,顺序为:createMultisig() (在 General-Multisig 中) -> 部署 PriviligeOwner 程序 -> Allocate() (在 PrivligeOwner 中) -> InitializeConfig() (在 PrivligeOwner 中)。

https://explorer.solana.com/tx/2vXHmwbCsARstx8wi4eLACbrb6PuZZMktsqU8VnJLp64fvrpaE62QSTn5QLczzxnTvxRLWMSR3dKLGYXZasGMn69?cluster=testnet https://explorer.solana.com/tx/2EMq9y6HNnXq1n2XsqrBkJd8RGL27PCj5T4JyJ71ZoA3ipUggT6dF6S6uDv4TtxGGKk8BmiAJHS7BFRgZqWjkWVb?cluster=testnet https://explorer.solana.com/tx/3UhXKsTubUiPqRtLyNYskxvbyrTKHsbeptxuAfJQ348AU4b8gQET2HAMaqxwud6Wo3MKTYHWBneqa9z2WhCpwV6t?cluster=testnet https://explorer.solana.com/tx/5NA7Yw23uRf48Q3BYM21dtS7gD9YMECij43ZaRLMPe7svt3bsv2TPWwbCRP5akDmttjLEHWZtpqrZrVLNr9QLyJY?cluster=testnet

接下来,我们调用 InitializeMultisig() 指令。我们传入四个账户,它们是 multisig 账户和三个有效签名者的账户。我们将 m 的值设置为 2,这意味着需要三个签名者中的两个签名才能执行特权函数。

CreateTransaction() 函数中,我们传入创建的 Transaction 账户、目标程序 (PrivilegeOwner) 的公钥以及 config 账户的公钥(第 306 - 307 行)。此外,我们还应将 _data 设置为 3,这对应于 PrivilegeOwner 程序中的 unlock() 指令。

对于第一次测试,只有一个签名者批准了创建的提案。在这种情况下,由于收集到的签名有限,ExecuteTransaction() 失败。控制台打印以下输出。

另一个签名者批准了创建的提案并调用 ExecuteTransaction()。签名的总数已达到阈值,因此该提案可以成功执行。

https://explorer.solana.com/tx/55Qy93RxybsT7c5v9AFgN8Dt1h3AVJfbsosLbstYVB6paY1wmau5sdtLfGpfryXnZTsBNRauvwLSmAu2nABFxVCe?cluster=testnet https://explorer.solana.com/tx/4XF4MUhL4oftkDt4sn7NoREmGqcDMVP6HGypvJQMtiAbBKiCuy4B98vhQKtvm4mPv7SprrDDVsiwgb6pNwgJcTwz?cluster=testnet

4. 总结

在本文中,我们介绍了 Solana 中多重签名的通用实现。该实现利用了 PDA 的特性,该特性使得程序能够在有效签名数量满足要求时自动签署交易。请继续关注,我们将在后续文章中分享更多内容。

阅读本系列其他文章:

关于 BlockSec

BlockSec 是一家开创性的区块链安全公司,成立于 2021 年,由一群全球顶尖的安全专家创立。公司致力于提升新兴 Web3 世界的安全性和可用性,以促进其大规模采用。为此,BlockSec 提供智能合约和 EVM 链 安全审计 服务,用于主动开发和阻止威胁的 Phalcon 平台,用于资金追踪和调查的 MetaSleuth 平台,以及供 Web3 构建者在加密世界中高效冲浪的 MetaSuites 扩展。

迄今为止,公司已为 MetaMask、Uniswap Foundation、Compound、Forta 和 PancakeSwap 等 300 多家尊贵客户提供服务,并通过两轮融资从 Matrix Partners、Vitalbridge Capital 和 Fenbushi Capital 等知名投资机构获得了数千万美元的投资。

官方网站:https://blocksec.com/

官方推特账号:https://twitter.com/BlockSecTeam

Sign up for the latest updates
The Decentralization Dilemma: Cascading Risk and Emergency Power in the KelpDAO Crisis
Security Insights

The Decentralization Dilemma: Cascading Risk and Emergency Power in the KelpDAO Crisis

This BlockSec deep-dive analyzes the KelpDAO $290M rsETH cross-chain bridge exploit (April 18, 2026), attributed to the Lazarus Group, tracing a causal chain across three layers: how a single-point DVN dependency enabled the attack, how DeFi composability cascaded the damage through Aave V3 lending markets to freeze WETH liquidity exceeding $6.7B across Ethereum, Arbitrum, Base, Mantle, and Linea, and how the crisis forced decentralized governance to exercise centralized emergency powers. The article examines three parameters that shaped the cascade's severity (LTV, pool depth, and cross-chain deployment count) and provides an exclusive technical breakdown of Arbitrum Security Council's forced state transition, an atomic contract upgrade that moved 30,766 ETH without the holder's signature.

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026

This BlockSec weekly security report covers four attack incidents detected between April 13 and April 19, 2026, across multiple chains such as Ethereum, Unichain, Arbitrum, and NEAR, with total estimated losses of approximately $310M. The highlighted incident is the $290M KelpDAO rsETH bridge exploit, where an attacker poisoned the RPC infrastructure of the sole LayerZero DVN to fabricate a cross-chain message, triggering a cascading WETH freeze across five chains and an Arbitrum Security Council forced state transition that raises questions about the actual trust boundaries of decentralized systems. Other incidents include a $242K MMR proof forgery on Hyperbridge, a $1.5M signed integer abuse on Dango, and an $18.4M circular swap path exploit on Rhea Finance's Burrowland protocol.

Weekly Web3 Security Incident Roundup | Apr 6 – Apr 12, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 6 – Apr 12, 2026

This BlockSec weekly security report covers four DeFi attack incidents detected between April 6 and April 12, 2026, across Linea, BNB Chain, Arbitrum, Optimism, Avalanche, and Base, with total estimated losses of approximately $928.6K. Notable incidents include a $517K approval-related exploit where a user mistakenly approved a permissionless SquidMulticall contract enabling arbitrary external calls, a $193K business logic flaw in the HB token's reward-settlement logic that allowed direct AMM reserve manipulation, a $165.6K exploit in Denaria's perpetual DEX caused by a rounding asymmetry compounded with an unsafe cast, and a $53K access control issue in XBITVault caused by an initialization-dependent check that failed open. The report provides detailed vulnerability analysis and attack transaction breakdowns for each incident.