Back to Blog

保護 Solana 生態系統 (6) — 多重簽名 2

April 24, 2022
6 min read

0. 回顧

1. 概述

在上一篇 文章 中,我們討論了多重簽章(Multi-Sig)的實作。然而,該實作的前提是多個使用者的簽章可以在鏈下同時收集完成。在本文中,我們將介紹一個更通用的多重簽章程式,允許使用者完全在鏈上進行簽章。

2. 測試程式設計

該多重簽章程式允許有效的簽章者分別對提案進行簽章,且一旦獲得足夠的簽章數,任何人都可以執行該提案。所有測試程式碼皆可在此 找到。

3. 程式碼審查

本程式引入了兩個額外的結構:TransactionAccountTransactionTransactionAccount 結構旨在記錄建議交易(proposed transaction)所使用的帳戶資訊。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,以防提案被重複執行。

我們已將該程式部署至測試網(testnet),可在以下連結中找到:

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 的特性,使得當有效簽章數量符合要求時,程式能夠自動透過 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/

官方 Twitter 帳號:https://twitter.com/BlockSecTeam