Cómo firmar una transacción multisig sin formato desde una clave privada externa

Estoy creando una billetera multisig de 2 de 3, donde las 2 teclas de acceso rápido son dispositivos HSM externos. Estoy usando Bcoin para crear mis transacciones. Después de crear las transacciones, enviaré la transacción sin procesar a una aplicación externa para realizar la firma.

Mi pregunta es, ¿qué parte exactamente necesita ser firmada por la clave privada?

Por ejemplo, esta es mi transacción:

{
    "hash": "e82c7bdfc864ab4d0592045dd86b81a438eeee77f8415c0a84e1aa0ea8e17786",
    "witnessHash": "e82c7bdfc864ab4d0592045dd86b81a438eeee77f8415c0a84e1aa0ea8e17786",
    "fee": 1000000,
    "rate": 4424778,
    "mtime": 1568880046,
    "version": 1,
    "inputs": [
        {
            "prevout": {
                "hash": "3b1dd17cc82e2ac43ba62bf8f1c6a0fe805df43911653d22c902571eb3a212ce",
                "index": 0
            },
            "script": "000000004c6952210209ad6cf408e41362fa175d5869e4561f1890c0d8d74353c86095fdecde34459721024a92aa3f883cc4438b75205555e517a4f7cc10ffd42517297a17821ae6f0bb8821037d2a259a52f62fee96fea072844139224fbd9027116ac7582025dd446fc73e3e53ae",
            "witness": "00",
            "sequence": 4294967295,
            "coin": {
                "version": 1,
                "height": -1,
                "value": 10000000000,
                "script": "a9144de6d3580732a7c7c2b1eb043cb1b89350c265fa87",
                "address": "38nvUMbXFdXDp4PTWvbohCbnPJuLUVwzXr",
                "coinbase": false
            }
        }
    ],
    "outputs": [
        {
            "value": 5000000000,
            "script": "a91481be67198d33319415d09b03f2dc2cfa4cdb42aa87",
            "address": "3DX3BhmdRGf5vYbtzHKzazGmZ7WgUkhFRk"
        },
        {
            "value": 4999000000,
            "script": "a9144de6d3580732a7c7c2b1eb043cb1b89350c265fa87",
            "address": "38nvUMbXFdXDp4PTWvbohCbnPJuLUVwzXr"
        }
    ],
    "locktime": 0,
    "hex": "0100000001ce12a2b31e5702c9223d651139f45d80fea0c6f1f82ba63bc42a2ec87cd11d3b000000006f000000004c6952210209ad6cf408e41362fa175d5869e4561f1890c0d8d74353c86095fdecde34459721024a92aa3f883cc4438b75205555e517a4f7cc10ffd42517297a17821ae6f0bb8821037d2a259a52f62fee96fea072844139224fbd9027116ac7582025dd446fc73e3e53aeffffffff0200f2052a0100000017a91481be67198d33319415d09b03f2dc2cfa4cdb42aa87c0aff6290100000017a9144de6d3580732a7c7c2b1eb043cb1b89350c265fa8700000000"
}

Si decodificas el scripten el inputses:

OP_0 OP_0 OP_0 OP_0 52210209ad6cf408e41362fa175d5869e4561f1890c0d8d74353c86095fdecde34459721024a92aa3f883cc4438b75205555e517a4f7cc10ffd42517297a17821ae6f0bb8821037d2a259a52f62fee96fea072844139224fbd9027116ac7582025dd446fc73e3e53ae

Como puede ver, hay 4 OP_0 marcadores de posición para ingresar las firmas. Ahora mi pregunta es qué parte de la transacción debe firmar la aplicación de firma externa. es solo la 000000004c6952210209ad6cf408e41362fa175d5869e4561f1890c0d8d74353c86095fdecde34459721024a92aa3f883cc4438b75205555e517a4f7cc10ffd42517297a17821ae6f0bb8821037d2a259a52f62fee96fea072844139224fbd9027116ac7582025dd446fc73e3e53aepieza?

Cualquier referencia es muy apreciada. He leído https://en.bitcoin.it/wiki/Transaction y https://en.bitcoin.it/wiki/OP_CHECKSIG pero no puedo estar seguro. Gracias.

Respuestas (1)

La entrada de Bitcoin Wiki para OP_CHECKSIG responde a su pregunta. OP_CHECKMULTISIG funciona de la misma manera, solo se aplica a cada firma en la secuencia.

En primer lugar, depende del tipo SIGHASH que usted, como firmante, elija. Lo más probable es que use el valor predeterminado SIGHASH_ALLpara cada una de las firmas requeridas, pero en realidad podría usar diferentes métodos SIGHASH para cada firma individual.

Como mencionó bcoin, puede revisar los métodos hash de firma aquí lib/primitives/tx.js y en los métodos inmediatamente siguientes.

Muy corto:

El método SIGHASH_ALL serializará todas las entradas* y todas las salidas de la transacción, incluido el nLocktime, y firmará ese blob.

*Todos los scripts de entrada se reemplazan con un solo 0x00byte. La secuencia de comandos de la entrada que se está firmando/verificando se reemplaza por la secuencia de comandos de salida correspondiente de la transacción de financiación. Entonces, en realidad, la cadena hexadecimal que publicó (el script de entrada con plantilla 000000004c695...) es la única parte de la transacción que NO será firmada por ninguno de los participantes multigrado para esta entrada.

Información adicional: la plantilla de firma 2 de 3 tiene CUATRO OP_0. ¿Por qué? Bien. el primero es sacado de la pila por OP_CHECKMULTISIG, ese es un error que Satoshi nos dejó. Los otros tres son marcadores de posición para las firmas reales. Hay TRES en lugar de solo DOS porque las firmas deben estar en el mismo orden que las pubKeys en el script de canje. El marcador de posición adicional se elimina antes de transmitir la transacción. En bcoin, esta plantilla de script se ensambla aquí .

muchas gracias. ¿Puede explicar qué se firmará en caso de que haya varias entradas con diferentes scripts multisig para cada una de ellas? Cada vez que se firma la transacción, ¿se reemplazan todas las entradas 0x00por todas las entradas? Gracias.
Sí, en SIGHASH_ALL, cada entrada firma el mismo esquema: 0x00para cada secuencia de comandos de entrada , excepto la entrada que se firma, donde la secuencia de comandos se reemplaza con la secuencia de comandos de salida de los txs anteriores.