Back to Blog

Solana 생태계 보안 강화 (6) — 멀티시그2

April 24, 2022
5 min read

0. 복습

1. 개요

이전 게시물에서 우리는 다중 서명(Multi-Sig) 구현에 대해 논의했습니다. 그러나 해당 구현은 여러 사용자의 서명을 오프체인에서 동시에 수집할 수 있다는 것을 전제로 합니다. 이번 게시물에서는 사용자가 완전히 온체인에서 서명할 수 있는 보다 일반적인 다중 서명 프로그램을 소개합니다.

2. 테스트 프로그램 설계

다중 서명 프로그램은 유효한 서명자들이 제안자에게 개별적으로 서명할 수 있도록 하며, 충분한 서명이 수집되어 승인되면 누구든지 제안자를 실행할 수 있습니다. 모든 테스트 코드는 여기에서 확인할 수 있습니다.

3. 코드 검토

이 프로그램은 TransactionAccountTransaction 두 개의 구조체를 추가로 도입합니다. TransactionAccount 구조체는 제안된 트랜잭션에 사용되는 계정 정보를 기록하기 위해 설계되었습니다. 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() 명령어에서는 유효한 서명의 수를 계산합니다. 수가 임계값에 도달하지 못하면 프로그램이 되돌려집니다(revert).

이후 지정된 속성으로 대상 Instruction을 초기화하고 invoke_signed() 함수를 통해 대상 프로그램의 명령어를 호출합니다. 제안이 반복 실행되지 않도록 마지막으로 did_execute 속성을 true로 설정합니다.

프로그램을 테스트넷에 배포하였으며 다음 링크에서 확인할 수 있습니다.

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

4. 트랜잭션 전송

배포 후, 먼저 multisig 계정을 생성하고 config 계정을 초기화할 때 multisig 계정을 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/

공식 트위터 계정: https://twitter.com/BlockSecTeam