
0. Revisão
- Protegendo o Ecossistema Solana (1) — Olá Solana
- Protegendo o Ecossistema Solana (2) — Chamadas Entre Programas
- Protegendo o Ecossistema Solana (3) — Atualização de Programa
- Protegendo o Ecossistema Solana (4) — Validação de Conta
- Protegendo o Ecossistema Solana (5) — Multi-Sig
1. Visão Geral
No post anterior, discutimos a implementação do Multi-Sig. No entanto, a implementação pressupõe que as assinaturas de múltiplos usuários podem ser coletadas ao mesmo tempo fora da cadeia. Neste post, apresentamos um programa Multi-Sig mais geral que permite aos usuários assinar totalmente na cadeia.
2. Design do Programa de Teste
O programa multi-sig permite que assinantes válidos assinem a proposta separadamente, e qualquer pessoa pode executar a proposta assim que ela for aprovada (assinaturas suficientes forem coletadas). Todo o código de teste pode ser encontrado aqui.
3. Revisão de Código
Este programa apresenta mais duas structs: TransactionAccount e Transaction. A struct TransactionAccount foi projetada para registrar as informações de conta utilizadas na transação proposta. A struct Transaction é usada para registrar as informações de uma proposta. Observe que o atributo signers é usado para registrar o número de assinaturas válidas. did_execute e is_initialized garantem que a execução e a inicialização só possam ser realizadas uma única vez.

O programa fornece cinco instruções diferentes. A instrução AllocatePDA tem como objetivo criar uma conta PDA única e utilizá-la como a conta multisig. Ela registrará todas as informações dos assinantes válidos. Na instrução InitializeMultisig, definimos o número de assinaturas necessárias para executar a instrução, bem como o array de chaves públicas dos assinantes válidos. A instrução CreateTransaction é usada para criar uma proposta, enquanto o assinante pode aprovar a proposta por meio da instrução approve. Assim que o número de aprovações atingir o limiar definido em multisig, a instrução ExecuteTransaction pode ser invocada para executar a transação.

Para submeter uma proposta, os usuários podem invocar a instrução createTransaction(). Ela recebe três contas: a conta transaction criada e as duas contas seguintes são usadas pela transação alvo. Para evitar que a conta seja reinicializada por usuários mal-intencionados, verificamos o atributo is_initialized (linhas 161-163). Em seguida, inicializamos a struct TransactionAccount com os dados especificados e a serializamos na conta de dados (linha 188).

Na função Approve(), verificamos primeiro se a conta Transaction e a conta multisig são de propriedade do programa. Observe que contas criadas por outros programas podem ser usadas por usuários mal-intencionados aqui, caso não haja verificação. Em seguida, comparamos a chave pública do assinante com as chaves armazenadas na conta multisig. Se houver correspondência, a assinatura será validada e o valor será alterado para true correspondentemente.

Na instrução ExecuteTransaction(), contamos o número de assinaturas válidas. Se o número não atingir o limiar, o programa será revertido.

Em seguida, inicializamos a Instruction alvo com os atributos especificados e invocamos a instrução do programa alvo por meio da função invoke_signed(). Por fim, definimos o atributo did_execute como verdadeiro para evitar que a proposta seja executada repetidamente.

Implantamos o programa na testnet e ele pode ser encontrado no seguinte link.
https://explorer.solana.com/address/CPzn7ptnJntjUB4NGKqQGRai8NFLNwFaspmJ7nEGbMHe?cluster=testnet
4. Enviar Transação
Após a implantação, criamos primeiro a conta multisig e a definimos como administradora da conta config ao inicializá-la. As transações relacionadas são mostradas abaixo, e a ordem é: createMultisig() (em General-Multisig) -> Implantar programa PriviligeOwner -> Allocate() (em PrivligeOwner) -> InitializeConfig() (em 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
Em seguida, invocamos a instrução InitializeMultisig(). Passamos quatro contas: a conta multisig e as contas de três assinantes válidos. Definimos o valor de m como 2, o que significa que as assinaturas de dois dos três assinantes são necessárias para executar funções privilegiadas.

Na função CreateTransaction(), passamos a conta Transaction criada, a chave pública do programa alvo (PrivilegeOwner) e a chave pública da conta config (linha 306 - linha 307). Além disso, também devemos definir _data como 3, o que corresponde à instrução unlock() no programa PrivilegeOwner.

No primeiro teste, apenas um assinante aprova a proposta criada. Nesse caso, ExecuteTransaction() falha, pois assinaturas insuficientes foram coletadas. O console exibe a seguinte saída.

Outro assinante aprova a proposta criada e invoca ExecuteTransaction(). O número total de assinaturas atingiu o limiar, de modo que a proposta pode ser executada com sucesso.
https://explorer.solana.com/tx/55Qy93RxybsT7c5v9AFgN8Dt1h3AVJfbsosLbstYVB6paY1wmau5sdtLfGpfryXnZTsBNRauvwLSmAu2nABFxVCe?cluster=testnet
https://explorer.solana.com/tx/4XF4MUhL4oftkDt4sn7NoREmGqcDMVP6HGypvJQMtiAbBKiCuy4B98vhQKtvm4mPv7SprrDDVsiwgb6pNwgJcTwz?cluster=testnet
4. Resumo
Neste artigo, apresentamos a implementação geral do multisig no Solana. A implementação faz uso do recurso de PDA, que permite ao programa assinar a transação por meio do PDA automaticamente quando o número de assinaturas válidas atende ao requisito. Continue acompanhando, e compartilharemos mais nos próximos posts.
Leia outros artigos desta série:
- Protegendo o Ecossistema Solana (1) — Olá Solana
- Protegendo o Ecossistema Solana (2) — Chamadas Entre Programas
- Protegendo o Ecossistema Solana (3) — Atualização de Programa
- Protegendo o Ecossistema Solana (4) — Validação de Conta
- Protegendo o Ecossistema Solana (5) — Multi-Sig
- Protegendo o Ecossistema Solana (7) — Confusão de Tipos
Sobre a BlockSec
A BlockSec é uma empresa pioneira em segurança de blockchain, fundada em 2021 por um grupo de especialistas em segurança de renome mundial. A empresa está comprometida em aprimorar a segurança e a usabilidade para o emergente mundo Web3, a fim de facilitar sua adoção em massa. Para isso, a BlockSec oferece serviços de auditoria de segurança de contratos inteligentes e cadeias EVM, a plataforma Phalcon para desenvolvimento de segurança e bloqueio proativo de ameaças, a plataforma MetaSleuth para rastreamento e investigação de fundos, e a extensão MetaSuites para construtores web3 que navegam com eficiência no mundo cripto.
Até o momento, a empresa atendeu mais de 300 clientes renomados, como MetaMask, Uniswap Foundation, Compound, Forta e PancakeSwap, e recebeu dezenas de milhões de dólares em duas rodadas de financiamento de investidores proeminentes, incluindo Matrix Partners, Vitalbridge Capital e Fenbushi Capital.
Site oficial: https://blocksec.com/
Conta oficial no Twitter: https://twitter.com/BlockSecTeam



