Ejemplo paso a paso para canjear una salida P2SH requerida

He estado siguiendo BIP16 en la creación de una transacción P2SH. Quiero crear un P2SH simple (una firma). Recibo un error al intentar transmitir el tx. El error es16: mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)

Para ser claros, no estoy intentando multisig. Lo que estoy haciendo se puede describir mejor como P2SH-P2PK, aunque no he visto este término. Este es el único ejemplo dado en BIP16, por lo que debería funcionar.

Esto es lo que he probado (testnet):

private key: BB2AC60BC518C0E239D5AF9D8D051A6BDFD0D931268DCA70C59E5992 
public key: 039f53e45f8f18b8ed294378bda342eff69b2053debf27fbede7d2d6bd84be6235 
(compressed)

redeemScript: [{pubKeySize,pubKey}] [OP_CHECKSIG]
21039F53E45F8F18B8ED294378BDA342EFF69B2053DEBF27FBEDE7D2D6BD84BE6235AC 

redeemScriptHash: RIPEMD160(SHA256(redeemScript))  
323D0E8A083E98010299109337850D05DD6157F7

p2shAddress: Base58Check(0xC4 + redeemScriptHash) (C4 for testnet)
2MwprvB9tUMtX4vK8zJK8K329fNu79CJgR7

La dirección anterior tiene dos UTOX en testnet:

UTXO1: e434a13cac79dc3d26e7279bff05c0f071a2df03e2ba6ca13c88f0e82dca9998:0
UTXO2: 9b4943e7ab5f4512e42c94254eb6aab4c6823ce06d4ff816b7ce4fda155a2571:0

Ahora quiero gastar ambos UTXO y seguir con los siguientes resultados:

Out1: 2MwprvB9tUMtX4vK8zJK8K329fNu79CJgR7 34000000 Satoshis
Out2: 2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF 100000000 Satoshis   

Creé el tx de la siguiente manera:

  1. Cree transacciones sin firmar con todos los scriptSigs vacíos

  2. Para que cada entrada se firme, configure su scriptSig para redimirScript: 21039F53E45F8F18B8ED294378BDA342EFF69B2053DEBF27FBEDE7D2D6BD84BE6235AC, manteniendo otros scriptSigs vacíos.

  3. Serialice el nuevo tx y agregue los bytes SIGHASHALL (0x01) en little endian 4 bytes

  4. Doble Sha256 arriba y firme el valor resultante. Agregue un byte 0x01 a la firma para indicar SIGHASH_ALL. Sea sigel valor resultante.

  5. Establezca scriptSig como:

    [0x00] [{sigSize, sig}] [{pubKeySize, pubKey}] [OP_CHECKSIG]

Supongo que se usará el siguiente scriptPubKey:

[OP_HASH160] [{scriptHashSize, scriptHash}] [OP_EQUAL]

Los siguientes son los valores y kpara la firma de cada entrada:rs

Entrada 1:

k = 98790447509501799195296257240616657470656053786701275200434341714298778299820  
r = 96398386359095408146340664941016369169423137684113382189227162443480418477689
s = 62903510511574365450545635776206168644738316078298063260649088246548574249129

Entrada 2:

k = 109372172176680138721552873719725202562296645126925021083510279924852033069204  
r = 105162394984132461723584277789901247831150698039237112243693144757926439529504
s = 62903510511574365450545635776206168644738316078298063260649088246548574249129

Después de esto, recibo el siguiente error en bitcoind para enviar el tx:

error code: -26
error message:
16: mandatory-script-verify-flag-failed 
(Signature must be zero for failed CHECK(MULTI)SIG operation)

¿Qué estoy haciendo mal?

EDITAR: Gracias a la respuesta de arubi, descubrí que había dos problemas con los pasos anteriores. Lo primero que estaba haciendo mal era no codificar los redeemScriptdatos de la pila. [0x00]En segundo lugar , lo que estaba haciendo mal era poner scriptSig. Después de arreglar eso, el Paso 5 debería ser:

  1. Establecer redeemScriptcomo[{pubKeySize, pubKey}] [OP_CHECKSIG]

  2. Establecer scriptSigcomo[{sigSize, sig}] [{redeemScriptSize, redeemScript}]

Respuestas (1)

El problema es que scriptsig contiene el script redimido real en lugar del script serializado como una inserción. El segundo error, el script de redención contiene un 0x00valor extraño que no debería estar allí, ya que se trata de un simple CHECKSIG.

Vale la pena señalar que el 0x00valor que queda en la pila no invalida la transacción, sino que no se detectará antes de la retransmisión por la política local, ya que no se adhiere a la cleanstackregla.
Si algún nodo extrae el tx con el encabezado 0x00, ¿se considerará válido?
Sí, creo que será válido ya que el OP_CHECKSIGúltimo que se ejecuta empujará un valor que se evalúa como Verdadero ( 0x01en este caso) a la parte superior de la pila. La pila será: 0x01 0x00 Hacer que todo el script se evalúe como Verdadero.