Se requiere un ejemplo de canje de una transacción sin procesar paso a paso

Estoy buscando, específicamente, una transacción de ejemplo paso a paso de envío de Bitcoin que utiliza una transacción real ( How To Redeem A Basic Txn , de hace unos años, hace un gran trabajo al describir la mayoría de los pasos para enviar un txn sin procesar, pero no no use un TxID real ).

He jugado con la biblioteca Python pybitcointools, la biblioteca SX y la salida JSON del cliente Bitcoin Core (Bitcoin-QT, Bitcoin-cli, Bitcoin daemon) pero aún tengo que encontrar una guía real paso a paso usando la salida de transacciones sin procesar ( entrada única/salida única Bitcoin txn, es decir, no multisig).

Con suerte, la recompensa traerá una transacción de ejemplo paso a paso (con claves privadas para la dirección de envío) que traerá una respuesta que muestre cómo se hace y, específicamente:

  • cómo encaja el elemento ScriptPubKey en el txn sin formato
  • cómo encaja el elemento ScriptSig en el txn sin procesar
  • cómo se firma el txn (con codificación DER).

EDITAR: Creo que el mejor recurso son los Bitcoins de Ken Shirriff de la manera difícil: usando el protocolo de Bitcoin sin procesar , pero nuevamente, no hay una sola fuente en línea que responda a mi pregunta sin pasar por alto áreas como scriptPubKey, firma, etc.

Cuando active la recompensa, si puede responder a esto, consulte este Tx , ya que puede servir como ejemplo real (es decir, proporcionaré ~ $ 1 en BTC y claves privadas para 1From/1MBngSqZbMydscpzSoehjP8kznMaHAzh9y si está interesado)

EDIT 2: The RoyalFork Blog: Deconstructing Txns proporciona una referencia increíblemente buena para la creación interactiva de Txn

¿Está buscando paso a paso con llamadas RPC, o paso a paso con manipulación de bytes a mano?
@NickODell: sí, lo he visto, Nick, y tienes razón, ¡es un recurso fantástico ! El problema persiste incluso después de leer el código de Python... Simplemente no entiendo la parte completa de ScriptPubKey / scriptSig y cada recurso que leo es muy opaco en esa parte. Editaré la pregunta para proporcionar más claridad una vez que pueda ofrecer la recompensa.
@StephenM347 ¿Busca un ejemplo paso a paso que sea lo más parecido a cómo crearía una transacción de Bitcoin con lápiz y papel? (similar a: bitcoin.stackexchange.com/q/808/9382 ). Ciertamente estoy evitando las llamadas RPC que "hacen el trabajo", por así decirlo.
¿Te importa que use el txid exacto que mencionaste? Solo creo que sería más fácil hacerlo con un tx que poseo. No revelaría la clave privada, pero daría a conocer las firmas que calcula.
@ stephenm347 no tiene que ser ese tx. Si desea hacer referencia a su propio txn, también está bien, pero configuré esto porque las salidas son de 1From y la dirección de 1 MB es una billetera cerebral que hace referencia a letras iguales a 1 MB (por lo que la clave privada es fácil de vincular a la dirección)
@StephenM347 Para la recompensa, necesito las claves privadas para poder repetir el proceso yo mismo. Incluso la sugerencia de Nick de ver "Bitcoin de la manera difícil" hace referencia al intercambio de pila Cómo canjear un TX sin procesar, por lo que no hay una respuesta canónica a esto en línea; github.com/shirriff/bitcoin-code/blob/master/txnUtils.py
Tenga en cuenta que incluso si repite el proceso proporcionado, la firma producida puede no ser idéntica a la de las instrucciones. Esto se debe a que las firmas DSA/ECDSA deben generarse con un valor secreto (a menudo llamado k) y un método para generar un valor secreto es un número aleatorio único. Si desea pasos perfectamente reproducibles, debe especificar que kse proporcione el valor de en las instrucciones o que se utilice la generación determinista de RFC6979k .

Respuestas (2)

Descripción paso a paso:

Comenzamos a crear una nueva transacción que procesamos y firmamos.

  1. Agregar campo de versión de cuatro bytes:01000000
  2. Varinte de un byte que especifica el número de entradas:01
  3. Hash de 32 bytes de la transacción de la que queremos canjear una salida (orden inverso):be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
  4. Campo de cuatro bytes que indica el índice de salida que queremos canjear de la transacción con el hash anterior (contando desde cero):00000000
  5. Ahora viene el scriptSig. A los efectos de firmar la transacción, esta se rellena temporalmente con el scriptPubKey de la salida que queremos redimir. Primero escribimos una variante de un byte que denota la longitud del scriptSig (0x19 = 25 bytes):19
  6. Luego escribimos el scriptSig real (que es el scriptPubKey de la salida que queremos canjear): 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac(mire la línea inferior en https://blockchain.info/tx/96534da2f213367a6d589f18d7d6d1689748cd911f8c33a9aee754a80de166be?show_adv=true )
  7. Luego escribimos un campo de cuatro bytes que indica la secuencia. Actualmente, esto siempre está configurado en 0xffffffff:ffffffff
  8. Luego viene una variante de un byte que contiene el número de salidas en nuestra nueva transacción. Estableceremos esto en 1 en este ejemplo:01
  9. Luego escribimos un campo de 8 bytes (entero de 64 bits, little-endian) que contiene la cantidad que queremos canjear de la salida especificada. Estableceré esto en la cantidad total disponible en la salida menos una tarifa de 0.0001 BTC (128307 - 10000):23ce010000000000
  10. Luego comenzamos a escribir el resultado de nuestra transacción. Comenzamos con una variante de un byte que indica la longitud del script de salida (0x19 o 25 bytes):19
  11. Luego, el script de salida real: 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac(esto es transferir fondos a la dirección 1FromKBPAS8MWsk1Yv1Yiu8rJbjfVioBHc)
  12. Luego escribimos el campo "lock time" de cuatro bytes:00000000
  13. Y por último, escribimos un "tipo de código hash" de cuatro bytes (1 en nuestro caso):01000000

bien, el resultado es

01000000
01
be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
00000000
19 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac
ffffffff
01
23ce010000000000
19 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac
00000000
01000000
  1. Ahora duplicamos el hash SHA256 de toda esta estructura, lo que produce el hash1cde0239b55717cca8003104abc2ec2673d4f6fabea0b74351940e382e88486f

  2. Ahora debemos crear la firma ECDSA... 1MBngSqZbMydscpzSoehjP8kznMaHAzh9yes una billetera cerebral de "mrbubbymrbubbymrbubby!" , que simplemente codifica una dirección que comienza en 'MB' (haciendo que vincular los 2 sea bastante fácil; consulte el comentario de @WizardOfAussie a continuación para conocer los orígenes de la frase). Clave privada en WIF:5HvofFG7K1e2aeWESm5pbCzRHtCSiZNbfLYXBvxyA57DhKHV4U3

En hexadecimal, la clave privada es 0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d. Hay un método de signo (clave, resumen) en cada biblioteca criptográfica. Devolverá una matriz de bytes. Esta matriz no tendrá más de 72 bytes y comenzará con el código hexadecimal 30. Imaginemos que la firma es 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180eA esta firma le agregamos el tipo de código hash de un byte: 01. La clave pública para 1MBngSqZbMydscpzSoehjP8kznMaHAzh9y es:042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9

  1. Construimos el scriptSig final concatenando: <OPCODE de secuencia de comandos de un byte que contiene la longitud de la firma codificada en DER más el tipo de código hash de un byte>|< La firma codificada en DER real más el tipo de código hash de un byte>| < Script OPCODE de un byte que contiene la longitud de la clave pública>|<La clave pública real>

scriptSig será

49 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e 01
41 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9

la primera línea es 'push signature concatenada con 01', la segunda línea es 'push pubkey'. La longitud de scriptSig es de 140 bytes (0x8c en hexadecimal)

  1. Luego reemplazamos el campo de longitud variable de un byte del paso 5 con la longitud de los datos del paso 16. La longitud es de 140 bytes, o 0x8C bytes:8c

  2. Y reemplazamos el scriptSig real con la estructura de datos construida en el paso 16.

  3. Terminamos eliminando el tipo de código hash de cuatro bytes que agregamos en el paso 13 y terminamos con la siguiente secuencia de bytes, que es la transacción final:

    01000000 01 be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396 00000000 8c 49 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e 01 41 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9 ffffffff 01 23ce010000000000 19 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac 00000000

¿No son estos los pasos descritos en el enlace de la pregunta? No creo que esto califique para la recompensa. @wizardofozzie Una cosa que debe entender sobre bitcoin es que probar transacciones es diferente a cualquier otro programa informático en la historia: es imposible replicar la misma situación dos veces como suele ser el caso con las pruebas. es decir, nunca puede volver atrás y volver a ejecutar exactamente la misma situación.
No pretendo recompensas. Acabo de responder una pregunta. Y sí, la mayor parte de mi respuesta es puro copiar y pegar. Pueden ser adiciones muy pequeñas. El inglés no es mi idioma nativo y es difícil para mí escribir la respuesta completa :)
¡Entiendo ahora! @amaclin si desea que las claves privadas editen su respuesta, puedo proporcionarla (o puedo editar la respuesta y dar la clave privada). Para tu información, fue la codificación DER (la parte que comienza con un byte 0x30) que no pude por la vida de mi lugar. Sabía que había una clave pública de 130 caracteres que comenzaba con 0x04 dentro de la matriz de bytes, pero no pude ubicar la primera parte. Entiendo que se firmará de manera diferente cada vez (¡es de esperar!) Pero esta es exactamente la aclaración que necesitaba. Probablemente tendré que esperar hasta que no esté usando la aplicación de iOS para otorgar la recompensa, ¡pero amaclin, gracias!
No debe publicar sus claves privadas. Ni siquiera deberías enviarme tus claves (mi correo electrónico está en el perfil). Creo que mi respuesta es lo suficientemente completa, nadie necesita que el resultado sea una transacción correcta existente en blockchain.
Aprecio lo que estás diciendo (¡y la fabulosa respuesta!) pero las direcciones no contienen BTC. El objetivo de esto era tener una respuesta canónica que no sea testnet, regtest o abstract. Así que voy a editar su respuesta ya que firmé con éxito el txn y lo transmití. blockchain.info/tx/…
Agregaré una respuesta que describa el proceso usando herramientas sx, pero para aquellos interesados, el brainwallet por 1 MB ... es "mrbubbymrbubbymrbubby". (sin comillas) => 1MBngSqZbMydscpzSoehjP8kznMaHAzh9y ... en caso de que te estés preguntando, es lo que la vecina le grita cada noche para llamar a su gato. Da la casualidad de que hash a 1 MB :)
Esperando su próxima pregunta: cómo canjear dos salidas en un tx (cómo crear y firmar transacciones con más de una entrada)
@amaclin Encontré esta referencia IMPRESIONANTE; este blog es increíblemente bueno para personas visuales como yo... royalforkblog.com/2014/11/20/txn-demo/…
¡Esto es genial! Sin embargo, ¿cómo se construye la transacción en bruto cuando hay más de una entrada/salida?
¿Hay un bip que describa lo anterior?
Es una gran publicación. Gracias. Escribí un código basado en su excelente respuesta, pero mi código no se ejecuta. ¿Podría ayudar a echar un vistazo a bitcoin.stackexchange.com/questions/92005/… ? Muchas gracias.

Esta es una excelente respuesta de amaclin y Wizard of Ozzie. Me gustaría agregar más detalles sobre la transacción del Mago de Ozzie en blockchain.info .

  1. La entrada correcta al proceso de firma para esta transacción es

     01000000
     01
     be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
     00000000
     19 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac
     ffffffff
     01
     23ce010000000000
     19 76 a9 14 2bc89c2702e0e618db7d59eb5ce2f0f147b40754 88 ac
     00000000
     01000000
    
  2. El hash doble-SHA256 de esto se calcula bxcomo

     d304448dff517bcf677cd36f3491e9ef2ccfdf40fb63af5782d9b768640af130
    

pero esto está escrito en orden "inverso" por alguna razón histórica peculiar (he oído que era compatible con M*soft CRAPi). Entonces, cuando use esto con los sign(key, digest)kits de herramientas criptográficos más sensibles, es posible que deba revertir el valor hash al orden "adecuado" paraSHA256(SHA256(m))

30f10a6468b7d98257af63fb40dfcf2cefe991346fd37c67cf7b51ff8d4404d3
  1. Los datos de entrada anteriores se validarán con la firma dada en la transacción real de la cadena de bloques.

      3045022100da43201760bda697222002f56266bf65023fef2094519e13077f777baed553b102205ce35d05eabda58cd50a67977a65706347cc25ef43153e309ff210a134722e9e
    

usando la clave pública dada

042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9
  1. Para generar una firma reproducible sobre los mismos datos, se ha realizado la siguiente firma por el método determinista de RFC6979 .

     30450220587ce0cf0252e2db3a7c3c91b355aa8f3385e128227cd8727c5f7777877ad772022100edc508b7c14891ed15ab38c687019d7ebaf5c12908cf21a83e8ae57e8c47e95c
    

utilizando la clave privada coincidente proporcionada por Wizard of Ozzie

0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d

Esta firma también valida los datos proporcionados utilizando la clave pública y debe ser reproducible.