
0. Revisión
- Asegurando el Ecosistema Solana (1) — Hola Solana
- Asegurando el Ecosistema Solana (2) — Llamadas entre Programas
- Asegurando el Ecosistema Solana (3) — Actualización de Programas
- Asegurando el Ecosistema Solana (4) — Validación de Cuentas
- Asegurando el Ecosistema Solana (5) — Multi-Sig
1. Descripción General
En la publicación anterior, analizamos la implementación del Multi-Sig. Sin embargo, dicha implementación asume que las firmas de múltiples usuarios pueden recopilarse al mismo tiempo fuera de la cadena. En esta publicación, presentamos un programa Multi-sig más general que permite a los usuarios firmar completamente en cadena.
2. Diseño del Programa de Prueba
El programa multi-sig permite a los firmantes válidos firmar la propuesta de forma separada, y cualquiera puede ejecutar la propuesta una vez que sea aprobada (cuando se hayan recopilado suficientes firmas). Todo el código de prueba se puede encontrar aquí.
3. Revisión del Código
Este programa introduce dos estructuras adicionales: TransactionAccount y Transaction. La estructura TransactionAccount está diseñada para registrar la información de la cuenta utilizada en la transacción propuesta. La estructura Transaction se utiliza para registrar la información de una propuesta. Cabe destacar que el atributo signers se usa para registrar el número de firmas válidas. did_execute e is_initialized aseguran que la ejecución y la inicialización solo puedan realizarse una vez.

El programa ofrece cinco instrucciones diferentes. La instrucción AllocatePDA tiene como objetivo crear una cuenta PDA única y utilizarla como cuenta multisig. Esta registrará la información de todos los firmantes válidos. En la instrucción InitializeMultisig, establecemos el número de firmas requeridas para ejecutar la instrucción, así como el arreglo de claves públicas de los firmantes válidos. La instrucción CreateTransaction se utiliza para crear una propuesta, mientras que los firmantes pueden aprobar la propuesta mediante la instrucción approve. Una vez que el número de aprobaciones alcanza el umbral establecido en multisig, se puede invocar la instrucción ExecuteTransaction para ejecutar la transacción.

Para enviar una propuesta, los usuarios pueden invocar la instrucción createTransaction(). Esta toma tres cuentas: la cuenta transaction creada y las dos cuentas siguientes son utilizadas por la transacción objetivo. Para evitar que la cuenta sea re-inicializada por usuarios maliciosos, verificamos el atributo is_initialized (líneas 161-163). Después de eso, inicializamos la estructura TransactionAccount con los datos especificados y la serializamos en la cuenta de datos (línea 188).

En la función Approve(), primero verificamos si la cuenta Transaction y la cuenta multisig son propiedad del programa. Cabe señalar que cuentas creadas desde otros programas podrían ser utilizadas por usuarios maliciosos si no se realiza esta verificación. A continuación, comparamos la clave pública del firmante con las claves almacenadas en la cuenta multisig. Si coinciden, se validará su firma y se cambiará el valor a true de forma correspondiente.

En la instrucción ExecuteTransaction(), contamos el número de firmas válidas. Si el número no alcanza el umbral, el programa revertirá.

Después de eso, inicializamos la Instrucción objetivo con los atributos especificados e invocamos la instrucción del programa objetivo mediante la función invoke_signed(). Finalmente, establecemos el atributo did_execute en verdadero para evitar que la propuesta sea ejecutada repetidamente.

Desplegamos el programa en la red de prueba y se puede encontrar en el siguiente enlace.
https://explorer.solana.com/address/CPzn7ptnJntjUB4NGKqQGRai8NFLNwFaspmJ7nEGbMHe?cluster=testnet
4. Enviar Transacción
Tras el despliegue, primero creamos la cuenta multisig y la establecemos como administrador de la cuenta config al inicializarla. Las transacciones relacionadas se muestran a continuación, y el orden es: createMultisig() (en General-Multisig) -> Desplegar el programa PriviligeOwner -> Allocate() (en PrivligeOwner) -> InitializeConfig() (en 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
A continuación, invocamos la instrucción InitializeMultisig(). Pasamos cuatro cuentas: la cuenta multisig y las cuentas de tres firmantes válidos. Establecemos el valor de m en 2, lo que significa que se requieren las firmas de dos de los tres firmantes para ejecutar las funciones privilegiadas.

En la función CreateTransaction(), pasamos la cuenta Transaction creada, la clave pública del programa objetivo (PrivilegeOwner) y la clave pública de la cuenta config (línea 306 - línea 307). Además, también debemos establecer _data en 3, lo que corresponde a la instrucción unlock() en el programa PrivilegeOwner.

Para la primera prueba, solo un firmante aprueba la propuesta creada. En este caso, ExecuteTransaction() falla ya que no se han recopilado suficientes firmas. La consola muestra la siguiente salida.

Otro firmante aprueba la propuesta creada e invoca ExecuteTransaction(). El número total de firmas ha alcanzado el umbral, por lo que la propuesta puede ejecutarse con éxito.
https://explorer.solana.com/tx/55Qy93RxybsT7c5v9AFgN8Dt1h3AVJfbsosLbstYVB6paY1wmau5sdtLfGpfryXnZTsBNRauvwLSmAu2nABFxVCe?cluster=testnet
https://explorer.solana.com/tx/4XF4MUhL4oftkDt4sn7NoREmGqcDMVP6HGypvJQMtiAbBKiCuy4B98vhQKtvm4mPv7SprrDDVsiwgb6pNwgJcTwz?cluster=testnet
4. Resumen
En este artículo, presentamos la implementación general del multisig en Solana. La implementación hace uso de la característica de PDA, que permite al programa firmar la transacción mediante PDA automáticamente cuando el número de firmas válidas cumple con el requisito. Sigue pendiente de nuestras publicaciones, ya que compartiremos más contenido en las próximas entradas.
Lee otros artículos de esta serie:
- Asegurando el Ecosistema Solana (1) — Hola Solana
- Asegurando el Ecosistema Solana (2) — Llamadas entre Programas
- Asegurando el Ecosistema Solana (3) — Actualización de Programas
- Asegurando el Ecosistema Solana (4) — Validación de Cuentas
- Asegurando el Ecosistema Solana (5) — Multi-Sig
- Asegurando el Ecosistema Solana (7) — Confusión de Tipos
Acerca de BlockSec
BlockSec es una empresa pionera en seguridad blockchain fundada en 2021 por un grupo de expertos en seguridad de reconocimiento mundial. La empresa está comprometida con mejorar la seguridad y la usabilidad del emergente mundo Web3 con el fin de facilitar su adopción masiva. Con este fin, BlockSec ofrece servicios de auditoría de seguridad de contratos inteligentes y cadenas EVM, la plataforma Phalcon para el desarrollo seguro y el bloqueo proactivo de amenazas, la plataforma MetaSleuth para el rastreo e investigación de fondos, y la extensión MetaSuites para que los desarrolladores de web3 naveguen eficientemente en el mundo cripto.
Hasta la fecha, la empresa ha prestado servicios a más de 300 distinguidos clientes como MetaMask, Uniswap Foundation, Compound, Forta y PancakeSwap, y ha recibido decenas de millones de dólares en dos rondas de financiamiento de destacados inversores, entre ellos Matrix Partners, Vitalbridge Capital y Fenbushi Capital.
Sitio web oficial: https://blocksec.com/
Cuenta oficial de Twitter: https://twitter.com/BlockSecTeam



