Volver al blog

Asegura el ecosistema Solana (6) — Multi-Sig2

24 de abril de 2022
6 min de lectura

0. Revisión

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:

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

Apúntate para recibir las novedades
Cómo la solución de seguridad de pagos de BlockSec ayuda a las instituciones a mantenerse seguras en la era de la IA
Security Services

Cómo la solución de seguridad de pagos de BlockSec ayuda a las instituciones a mantenerse seguras en la era de la IA

Descubra cómo BlockSec ayuda a las instituciones de pago a proteger los fondos y los datos, y a reforzar su resiliencia mediante evaluaciones de seguridad, pruebas y monitoreo continuo.

Pérdidas de ~5,57 millones USD: exploits de X100 Freezer y NEM | Resumen semanal de BlockSec
Security Insights

Pérdidas de ~5,57 millones USD: exploits de X100 Freezer y NEM | Resumen semanal de BlockSec

Este informe semanal cubre dos incidentes de seguridad ocurridos en Ethereum y BNB Chain durante el período 19/10/2026–25/10/2026. Examina una toma de control de la gobernanza de X100 Freezer financiada mediante un préstamo flash y un fallo en la liquidación de impuestos que afectó a un pool de liquidez de un token NEM en BNB Chain. Las pérdidas estimadas dentro del alcance del informe suman aproximadamente 5,57 millones USD: ~4,75 millones USD de la transacción representativa de X100 y ~820 mil USD del incidente del pool de NEM. El total excluye las extracciones posteriores de X100 reportadas por separado.

Pérdidas de aproximadamente 3,87 millones USD: hackeos de Autheo Network y UNCX | Resumen semanal de BlockSec
Security Insights

Pérdidas de aproximadamente 3,87 millones USD: hackeos de Autheo Network y UNCX | Resumen semanal de BlockSec

Este informe semanal cubre 3 incidentes de seguridad correspondientes al período 12/10/2026–18/10/2026, con pérdidas totales estimadas en aproximadamente 3,87 millones USD. Autheo Network sufrió una vulneración de clave privada con pérdidas de aproximadamente 1,76 millones USD; Qubic Wallet perdió aproximadamente 1,30 millones USD debido a la generación de una semilla débil; y los contratos Smart Token Vesting V2 de UNCX Network sufrieron un error contable con pérdidas de aproximadamente 807 mil USD en Ethereum, BNB Chain, Base y Robinhood Chain. El análisis destacado de UNCX explica cómo un cálculo agregado de participaciones defectuoso mezcló tramos de adquisición de derechos creados con distintas proporciones entre tokens y participaciones, lo que permitió retiros excesivos de pools compartidos.