¿Cómo funcionarán las direcciones multisig?

¿Cómo funcionarán las direcciones multisig? ¿Consistirán en varias direcciones tradicionales o tendrán alguna estructura diferente? ¿Se podrá especificar si requerirán 2 de 2, 2 de 3 o M de N firmas? ¿Dónde puedo obtener más información sobre sus especificaciones?

Las direcciones multisig funcionan desde 2013.
@gladoscc Esta pregunta se hizo el 2013-01-12

Respuestas (2)

Sé que esta pregunta es vieja, pero me topé con ella buscando cómo aprender cómo funcionan las direcciones multisig, e imagino que otros lo harán. Así que voy a tratar de explicar el flujo típico para crear, agregar bitcoins y eventualmente gastar una dirección multisig. Esta explicación está dirigida a principiantes, así que disculpe mi falta de brevedad. En primer lugar, alguna terminología que deberíamos eliminar.

Dirección de Bitcoin: una dirección de Bitcoin es una cadena de (generalmente) 33 o 34 dígitos que le damos a las personas cuando queremos que nos envíen Bitcoins. Aquí hay un ejemplo de megafonía

19evXeJDDLNeRS4st4bGUJNGk8eBgVCCg4

Clave pública: una clave pública se utiliza para derivar una dirección de bitcoin, aunque conocer una dirección de bitcoin NO le permitirá encontrar la clave pública correspondiente a esa dirección. Para obtener más información sobre la relación clave pública/dirección de bitcoin, vaya a https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses . Así es como se ve la clave pública para la dirección de bitcoin pegada arriba

035739f07de25c205525d81b126ed87bc30377e688705072d186e4f5c88908ce3a

Tenga en cuenta que solo conozco esa clave pública porque está almacenada junto con mi clave privada en mi billetera, publico esta información generalmente confidencial aquí porque es más fácil entender bitcoin cuando tiene ejemplos.

Transacción/dirección multisig: una transacción multisig es solo una transacción que tiene como una de sus entradas una dirección multisig. Las direcciones multisig se utilizan para hacerlo, por lo que se necesitan múltiples claves propiedad de entidades separadas para mover los bitcoins en una dirección.

¡Vale genial! Ahora, estos son los pasos y los antecedentes para crear una dirección multisig. Primero explicaré las cosas en un lenguaje sencillo y luego seguiré con los comandos bash/Terminal que usará para crear/agregar dinero/gastar la dirección multisig. Estoy usando el delimitador bash estándar "$>" para indicar que lo que viene después de "$>" es lo que debe ingresar en su terminal. Las líneas que vienen después de la línea que contiene "$>" son la salida de ese comando. Si alguna vez tiene alguna pregunta sobre un comando que está ingresando, puede escribir lo siguiente en la Terminal para mostrar qué argumentos se deben pasar al comando

$> bitcoind help <nameofcommandhere>

Esta explicación asume que tiene una actualización actualizada y un servidor bitcoind en funcionamiento que puede aceptar comandos RPC.

i. Cree las claves públicas que conformarán la dirección multisig. Vas a utilizar estas claves públicas y otra información para crear tu dirección multisig. La distribución más común de las direcciones en una dirección multisig de 3 direcciones (es posible tener una dirección multisig compuesta por más de tres direcciones, pero no todos los mineros las admiten, por lo que para esta explicación nos ocuparemos de las más comunes Dirección multisig de 3 direcciones) son las siguientes. Por lo general, PubKey#1 es de su propiedad y se almacena en un dispositivo al que tiene fácil acceso (como su teléfono móvil). Por lo general, PubKey # 2 también es de su propiedad, pero se almacena en un lugar seguro (como almacenamiento en frío o en una billetera de papel). PubKey#3 suele ser la clave pública de un tercero, como su hermano o una empresa que ofrece servicios relacionados con bitcoin como Coinbase. Llamemos entidad a cada uno de estos propietarios de una clave pública. Recuerde que Bitcoin usa criptografía de clave privada/pública, por lo que quien crea una clave pública también se queda con la clave privada correspondiente. Esta clave privada será importante más adelante en la explicación. ¡Así que vamos a crear 3 nuevas direcciones públicas que terminaremos usando para crear una dirección multisig! Tenga en cuenta que, como expliqué anteriormente, si estuviera usando una dirección multisig en una situación del mundo real, probablemente obtendría una de las tres claves públicas de un tercero, pero para esta explicación aquí solo vamos a crear las tres nosotros mismos. . Estos son los comandos RPC relevantes para crear claves públicas: Esta clave privada será importante más adelante en la explicación. ¡Así que vamos a crear 3 nuevas direcciones públicas que terminaremos usando para crear una dirección multisig! Tenga en cuenta que, como expliqué anteriormente, si estuviera usando una dirección multisig en una situación del mundo real, probablemente obtendría una de las tres claves públicas de un tercero, pero para esta explicación aquí solo vamos a crear las tres nosotros mismos. . Estos son los comandos RPC relevantes para crear claves públicas: Esta clave privada será importante más adelante en la explicación. ¡Así que vamos a crear 3 nuevas direcciones públicas que terminaremos usando para crear una dirección multisig! Tenga en cuenta que, como expliqué anteriormente, si estuviera usando una dirección multisig en una situación del mundo real, probablemente obtendría una de las tres claves públicas de un tercero, pero para esta explicación aquí solo vamos a crear las tres nosotros mismos. . Estos son los comandos RPC relevantes para crear claves públicas:

Ingrese este comando para ver todas sus cuentas. Suponiendo que está comenzando de nuevo, solo tendrá la cuenta con el nombre cadena vacía y sin bitcoins en ella

$> bitcoind listaccounts
{
    "" : 0.00000000
}

Ingrese el siguiente comando tres veces para crear tres nuevas direcciones en esta cuenta

$> bitcoind getnewaddress “"

Ingrese este comando para ver sus direcciones recién creadas

$> bitcoind getaddressesbyaccount “”
[
    "1CtfcziAhqx83CtSPdufgZDGmL8ohTFTdd",
    "1JeK7TZR85BL8WvtHgCiTSYtPJupdYYXgR",
    "1MP3BzdhzoBmGoBiVfLmhv7B4Czxm3MbrU"
]

Sin embargo, no has terminado. Hasta ahora solo has visto las direcciones públicas. Necesita obtener las claves públicas de estas direcciones. Afortunadamente, puede hacerlo simplemente escribiendo el siguiente comando tres veces, sustituyendo cada vez por una de las direcciones que creó.

$> bitcoind validateaddress <btcaddress>
{
    "isvalid" : true,
    "address" : "19evXeJDDLNeRS4st4bGUJNGk8eBgVCCg4",
    "ismine" : true,
    "isscript" : false,
    "pubkey" : "035739f07de25c205525d81b126ed87bc30377e688705072d186e4f5c88908ce3a",
    "iscompressed" : true,
    "account" : ""
}

El valor a la derecha de "pubkey" es la clave pública de esa dirección.

ii. Luego usa estas tres claves para crear la dirección multisig. En el párrafo anterior mencioné cómo necesitabas las claves públicas más otra información para crear la billetera multisig. Ese dato es la cantidad de firmas necesarias para gastar los bitcoins en una dirección multisig. Una de las cosas útiles de una dirección multisig es que, para enviar el dinero en la dirección, se necesitan varias claves privadas (¡le dije que volveríamos a estas!) firmando la transacción para que sea válida. Así que para este ejemplo vamos a usar el número 2; dos de las tres entidades deberán firmar la transacción para que los bitcoins se muevan a cualquier lugar. Cuando creamos la dirección multisig, bitcoind devolverá la dirección multisig de 34 dígitos, así como un montón de datos hexadecimales llamados "redeemScript". Tenga en cuenta que el primer dígito de la dirección es un "3". La mayoría de las direcciones que solías comenzar probablemente con un "1", pero todas las multisig comienzan con "3". Copie, pegue y guarde la dirección y los valores de script de redimir en algún lugar, ya que los necesitaremos en un momento. Entonces, creamos la dirección multisig ingresando el siguiente comando. Asegúrese de escribir los apóstrofes y las comillas exactamente como yo lo hice, y sustituya las claves públicas que obtuvo de la dirección de validación.

$> bitcoind createmultisig 2 ‘[“<pubkey>", "<pubkey>", "<pubkey>”]'


{
    "address" : "3DS7Y6bdePdnFCoXqddkevovh4s5M8NhgM",
    "redeemScript" :     "5221027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a321022cc9874ba092095dd    a47a4e4edb1781c43c35b3ec0429ac005df37b9d6eec94b21035739f07de25c205525d81b126ed87bc30377e6887    05072d186e4f5c88908ce3a53ae"
}

Copie el resultado que obtenga en alguna parte, lo necesitaremos pronto.

iii. Envía algunos bitcoins desde una de tus billeteras a la dirección multisig. Me sorprendió saber que Coinbase no cree que las direcciones multisig sean válidas, por lo que si está utilizando Coinbase, no puede enviar directamente desde su billetera Coinbase a la dirección multisig. Como solución alternativa, puede usar Coinbase para enviar una pequeña cantidad de bitcoins (envié el valor de 1 dólar) a una de las tres direcciones que creó originalmente, espere a que se confirme la transacción y luego use el siguiente comando para enviar bitcoins desde esa dirección regular a la dirección multisig. Reemplace con la dirección multisig y con una cantidad de bitcoins que valga menos que la cantidad que envió a la dirección normal. ¡Recuerde que tendrá que pagar tarifas de transacción! Si el comando funciona, devolverá el hash de transacción de la transacción.

$> bitcoind sendtoaddress <bitcoindaddress> <amount>
0ac29fc675909eb565a0984fe13a47dae16ca53fb477b9e03446c898b925ab6b

IV. Finalmente, vamos a gastar los bitcoins que acabamos de recibir en la dirección multisig. Usaremos las claves privadas de las dos primeras direcciones que creamos en el paso 1. Para obtener las claves privadas, ingresamos el siguiente comando dos veces en la Terminal, reemplazando cada vez con una de las direcciones de bitcoin que creaste:

$> bitcoind dumpprivkey <btcaddress>
KyiRjmZYPH7cfyKf1WNb3BZFz1ySurWEYKxLngkH6VmTcSCirBPG

(Como nota al margen, lo peor que puede hacer en la comunidad bitcoin es pegar la clave privada de una de sus direcciones en un foro público. ¡NUNCA HAGA ESTO! Solo estoy haciendo esto porque quiero asegurarme de que los lectores puedan sigue mi explicación, y solo hay un par de dólares en estas direcciones)

v. Ahora que tiene dos pares de claves pública/privada, finalmente podemos gastar los bitcoins que enviamos a la dirección multisig. Para hacerlo, primero debemos recopilar información sobre esa transacción en la que enviamos bitcoins a la dirección multisig, porque debemos elegir la salida correcta de esa transacción para usarla como entrada en la transacción sin procesar que estamos a punto de crear. Escriba lo siguiente en la terminal, reemplazándolo con el hash de transacción que se devolvió anteriormente.

$> bitcoind getrawtransaction <txid> 1
{
    "hex" : "010000000175783b2ca3381efb15ee7f5f44632a2c699171a924185386460b91d0f211d3bb000000006a47304402207707875d5c29ed0d97cd72087c67c17c57e2ef34d0b6208a054fffece8704477022045aec0ea57830f53fa0e52094400dd4fb654d7712f2ac3341a762d0f46c02d370121027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a3ffffffff0210270000000000001976a91431e71089318d7b1ea51a1add0dd6525423f713c488ac702402000000000017a91480cff499983050ec4268d749a1f898bec53e9fc28700000000",
    "txid" : "0ac29fc675909eb565a0984fe13a47dae16ca53fb477b9e03446c898b925ab6b",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
        {
            "txid" : "bbd311f2d0910b4686531824a97191692c2a63445f7fee15fb1e38a32c3b7875",
            "vout" : 0,
            "scriptSig" : {
                "asm" : "304402207707875d5c29ed0d97cd72087c67c17c57e2ef34d0b6208a054fffece8704477022045aec0ea57830f53fa0e52094400dd4fb654d7712f2ac3341a762d0f46c02d3701 027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a3",
                "hex" : "47304402207707875d5c29ed0d97cd72087c67c17c57e2ef34d0b6208a054fffece8704477022045aec0ea57830f53fa0e52094400dd4fb654d7712f2ac3341a762d0f46c02d370121027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a3"
            },
            "sequence" : 4294967295
        }
    ],
    "vout" : [
        {
            "value" : 0.00010000,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 31e71089318d7b1ea51a1add0dd6525423f713c4 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a91431e71089318d7b1ea51a1add0dd6525423f713c488ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "15Yrv3rAVxYTTGePM3ZZwumSnMfS9St9uD"
                ]
            }
        },
        {
            "value" : 0.00140400,
            "n" : 1,
            "scriptPubKey" : {
                "asm" : "OP_HASH160 80cff499983050ec4268d749a1f898bec53e9fc2 OP_EQUAL",
                "hex" : "a91480cff499983050ec4268d749a1f898bec53e9fc287",
                "reqSigs" : 1,
                "type" : "scripthash",
                "addresses" : [
                    "3DS7Y6bdePdnFCoXqddkevovh4s5M8NhgM"
                ]
            }
        }
    ],
    "blockhash" : "00000000000000002ab5cb0ee400200b8575fe393fef57d41b41a5d533a414a3",
    "confirmations" : 5,
    "time" : 1404775273,
    "blocktime" : 1404775273
}

Busque la clave "vout", que debe tener una matriz JSON como valor. Necesitamos dos valores aquí; el índice de la salida en vout que tiene el mayor valor, y el valor de la tecla “hex” dentro de esa misma salida. Cuando envié originalmente esta transacción, había enviado 0.00160400 bitcoins. 0.0001 de eso se destinó al pago de tarifas de minero, y los 0.0010000 restantes se destinaron a una dirección de cambio que mi software de cliente creó para mí. Querremos usar la salida con el valor más grande (aquí 0.00140400) como entrada en nuestra transacción cuando creamos nuestra transacción sin procesar. Así que aquí el índice es igual a 1. En esta misma transacción necesitaremos el valor de la clave "hexadecimal" dentro de "scriptPubKey. Es demasiado entrar en detalles aquí en cuanto a lo que representa este valor,https://bitcointalk.org/index.php?topic=377604.0 . En un nivel alto, el valor “hexadecimal” de scriptPubKey es una codificación hexadecimal del script que se ejecuta como parte de una entrada de transacción para verificar que la transacción es válida. De todos modos, el valor de "hexadecimal" que queremos es a91480cff499983050ec4268d749a1f898bec53e9fc287

¿Recuerdas cuando creamos la dirección multisig, uno de los valores que se devolvió fue algo llamado "redeemScript"? Con suerte, lo copió y lo pegó en alguna parte porque también lo necesitaremos para crear nuestra transacción sin procesar. Esto también se usa para verificar que la transacción es válida y, por lo tanto, los nodos pueden transmitirla cuando se transmite a la red.

Bien, aquí viene la parte más confusa en cuanto a la codificación; vamos a hacer algunas operaciones de bitcoin de nivel relativamente bajo que es lo que realmente sucede cuando envía monedas de una dirección a otra, aunque con la complicación adicional de usar una dirección multisig. Vamos a usar el hash de la transacción, el índice en la matriz vout que acabamos de encontrar, el scriptPubKey, el script redimido, así como una dirección de bitcoin que recibirá una cierta cantidad de monedas que especifiquemos. Ingrese lo siguiente en la Terminal exactamente como lo he escrito, reemplazando con el hash de la transacción, con 1, con el scriptPubKey, con el script redimido, con la dirección a la que desea enviar estos bitcoins (utilicé uno de los tres que creé en el inicio), y (adivinaste) con la cantidad que quieres enviar. No olvide tener en cuenta una tarifa de transacción de aproximadamente 0.0001.

$> bitcoind createrawtransaction '[{"txid”:”<txid>","vout”:<vindex>,"scriptPubKey”:”<scriptPubKey","redeemScript”:”<redeemScript>"}]' ‘{“<sentToAddress”:<amount>}'’


01000000016bab25b998c84634e0b977b43fa56ce1da473ae14f98a065b59e9075c69fc20a0100000000ffffffff0160fd0100000000001976a9145eed147e77af70c64c31c056c3b3474c79c65da088ac00000000

Ese comando acaba de devolver una transacción codificada en hexadecimal sin procesar, esta es la colección de bytes que los clientes de bitcoin transmiten a la red y que contienen la información necesaria para verificar que las salidas que se utilizan como entrada en la transacción son válidas. Pero ahora mismo esta transacción NO es válida, porque no ha sido firmada por al menos dos de las claves privadas que están asociadas a esta dirección multisig. Hagamos eso ahora. Vamos a tomar esta transacción hexadecimal sin procesar, la mayor parte de la información que acabamos de ingresar en el comando anterior y la clave privada de la primera dirección que creamos y firmaremos la transacción. El comando se ve así, donde reemplazará con la salida del comando anterior y con la clave privada de la primera dirección que creamos (¿recuerda, la que obtuvimos al ejecutar "bitcoind dumprivkey"?)

$> bitcoind signrawtransaction ‘<rawhextransaction>' '[{"txid”:”<txid>","vout”:<vindex>,"scriptPubKey”:”<scriptPubKey","redeemScript”:”<redeemScript>"}]' ‘[“<privkeyone>”]'


{
    "hex" :     "01000000016bab25b998c84634e0b977b43fa56ce1da473ae14f98a065b59e9075c69fc20a01000000b500483045022100f98068a026e2fc75cfeffe84bbac4223ed172df42bca01fd748a14bd960b1695022062c61a7f4f2a63a65d96b0feaf2a048bc2ca93e5de13013978a187395f880b6d014c695221027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a321022cc9874ba092095dda47a4e4edb1781c43c35b3ec0429ac005df37b9d6eec94b21035739f07de25c205525d81b126ed87bc30377e688705072d186e4f5c88908ce3a53aeffffffff0160fd0100000000001976a9145eed147e77af70c64c31c056c3b3474c79c65da088ac00000000",
    "complete" : false
}

Notará que la clave "completa" es falsa. Esto se debe a que solo proporcionamos una de las dos firmas que necesitamos para que esta sea una transacción válida. El valor de "hexadecimal" es la representación hexadecimal de la transacción sin procesar que creamos, pero con una firma incluida. A continuación, tomaremos la transacción con una firma y la firmaremos con la clave privada de la segunda dirección que creamos. El comando Terminal es muy similar:

$> bitcoind signrawtransaction ‘<onesigrawtransaction>' '[{"txid”:”<txid>","vout”:<vindex>,"scriptPubKey”:”<scriptPubKey","redeemScript”:”<redeemScript>"}]' ‘[“<privkeytwo>”]'

{
    "hex" : "01000000016bab25b998c84634e0b977b43fa56ce1da473ae14f98a065b59e9075c69fc20a01000000fdfd0000483045022100f98068a026e2fc75cfeffe84bbac4223ed172df42bca01fd748a14bd960b1695022062c61a7f4f2a63a65d96b0feaf2a048bc2ca93e5de13013978a187395f880b6d0147304402201ce986e3fd780f4fe81f40ceb271a8ff34c3845e385b8424f8b20d1b91f1282102205dc71831baf5606f59d06b1d115bda3ec28817cdb4bf9df06643d550c30ef193014c695221027ca87e1aa2595ec7771afee8fdc6efdbc301b8370c4386731b4bd82247dc74a321022cc9874ba092095dda47a4e4edb1781c43c35b3ec0429ac005df37b9d6eec94b21035739f07de25c205525d81b126ed87bc30377e688705072d186e4f5c88908ce3a53aeffffffff0160fd0100000000001976a9145eed147e77af70c64c31c056c3b3474c79c65da088ac00000000",
    "complete" : true
}

Probablemente esté feliz de notar que "completo" ahora es verdadero. ¡Ahora solo nos queda un paso más! Vamos a tomar el resultado de este último comando, que es una transacción válida y totalmente firmada que envía bitcoins desde una dirección multisig a una dirección que especifiques, y lo enviaremos usando el comando "sendrawtransaction", así

$> bitcoind sendrawtransaction <fullysignedtransaction>

bc26380619a36e0ecbb5bae4eebf78d8fdef24ba5ed5fd040e7bff37311e180d

Y finalmente, esto devolverá el hash de la transacción que acaba de enviar.

¡Eso es todo! Puede usar blockchain.info para ver esa transacción en la red. Ahora sabe cómo se crean las direcciones multisig, cómo enviar dinero a direcciones multisig y, lo que es más importante, cómo gastar esos bitcoins. Ahora, por favor, salga y ayude a crear un software de billetera que implemente transacciones multisig de una manera fácil de usar.

esto es genial Muchas gracias por esta respuesta tan detallada. te daría +1000 ;)
¿Qué sucede si el valuevalor voutde la transacción de entrada que está utilizando createrawtransactiones menor que el total de bitcoins que desea enviar? ¿Necesita seleccionar varias transacciones hasta llegar a la cantidad que necesita?
@FelipeLima siento que esta respuesta llega tan tarde! Eche un vistazo al comando createrawtransaction y verá que el primer argumento es en realidad una matriz (se puede ver por los corchetes) que contiene un único elemento "txid + vout + scriptPubKey + redimirScript". Eso significa que puede pasar varios de esos elementos, cada uno contenido entre llaves, para especificar suficientes transacciones con votos que sean iguales o mayores que la cantidad de BTC que desea enviar (¡más un poco más para las tarifas de los mineros!)
@almel: En realidad, ¿cómo dos personas (A y B, por ejemplo) pueden firmar colectivamente una transacción multigrado?
@anhldbk Digamos que A firma primero, llama signrawtransactiony genera un objeto con un hexcampo. Envían estos datos hexadecimales a B, quien luego los firma y transmite la transacción a la red. Es seguro que A entregue el tx medio firmado a B, porque lo único que B puede hacer es firmar la transacción. Si intentan cambiarlo, invalidará la firma de A y B no podrá transmitir el tx modificado, incluso si B lo firma.
Equivocado. No existe tal cosa como una dirección de Bitcoin, toda su respuesta es engañosa.
@almel, ¿es posible usar multisig sin pubkeys? Me refiero a usar solo direcciones.
@ user2284570 No, no lo es. Sin las claves públicas, no hay forma de que pueda realizar firmas y verificaciones de claves públicas. Si solo tiene las direcciones, todo lo que tiene es un hash SHA256 de las claves públicas, que es inútil para cualquier algoritmo de firma digital. ¿Qué está tratando de hacer exactamente que requiere que use direcciones pero no claves públicas?

Las transacciones en bitcoin son en realidad scripts, donde normalmente establece una dirección de entrada y una de salida. Pero hay otro código de operación como el script CHECKMULTISIGVERIFY. Cada parte firmante tendrá su propia clave pública, por lo tanto, su propia dirección. La forma en que funciona es como se muestra:

N K1 K2 K3 M COMPROBAR MULTISIG VERIFICAR

Dónde :

-N es el número de firma para continuar
-K1, K2, K3 Las 3 claves públicas reales
-M El número de clave pública que proporcionó

Lo que hace la transacción real puede establecerse en el script de entrada.

Vea aquí un ejemplo de una transacción con un tercero.