¿Cómo firmar una transacción con múltiples entradas?

He podido programar una aplicación en python que envía transacciones válidas que gastan 1 entrada, pero realmente no puedo hacer que funcione con 2 o más entradas.

Entonces mi pregunta es, ¿cómo se calcula exactamente el hash que debe firmarse para cada entrada?

Lo que he estado haciendo hasta ahora es, por ejemplo, si tenemos 2 entradas, generamos una transacción que gasta solo esa primera entrada, y ese es el hash que debe firmarse para la primera entrada. Y lo mismo con la segunda entrada, generamos una transacción que solo gasta esa segunda entrada. Ambas transacciones deben tener los mismos resultados.

¿Es eso correcto? Por ejemplo, queremos gastar input aaaa:0 e input bbbb:1 y queremos enviarlos a alguna dirección:

Para calcular el hash que tiene que firmar la primera entrada, necesitamos generar esta transacción:

'version': 1,
'inputs': (1)
    'output_tx_hash': 'aaaa',
    'output_position': 0,
    'script': the original script, like: '76a914' + hash + '88ac',
    'sequence': ffffffff,
'outputs': (1)
    'value' : 100000
    'script' : '76a914' + hash of btc pub key + '88ac'
'locktime': 0

Y para calcular el hash que tiene que firmar la segunda entrada:

'version': 1,
'inputs': (1)
    'output_tx_hash': 'bbbb', # this changes
    'output_position': 1,     # this changes
    'script': the original script, like: '76a914' + hash + '88ac',
    'sequence': ffffffff,
'outputs': (1)
    'value' : 100000
    'script' : '76a914' + hash of btc pub key + '88ac'
'locktime': 0

Los serializamos, les agregamos 01000000 (SIGHASH_ALL), duplicamos sha256 eso, lo firmamos y agregamos 01. De esa manera obtenemos las dos firmas que usaremos en cada entrada respectivamente. Mi aplicación hace exactamente eso y no funciona. ¿Qué me estoy perdiendo?

Quizás eche un vistazo a python-bitcoinlib .
El procedimiento exacto está documentado en esta pregunta: bitcoin.stackexchange.com/questions/3374/…
Ese procedimiento muestra cómo firmar una transacción con una sola entrada. Esa es la respuesta que usé para aprender a firmar 1 entrada, y lo logré, pero con 2 o más entradas simplemente no puedo hacer que funcione, y esa respuesta no dice cómo se debe hacer.

Respuestas (3)

Encontré la manera de hacerlo, así que, si alguien está interesado, aquí está cómo hacerlo:

Cuando tiene más de 1 entrada, no tiene que eliminar las entradas que no va a firmar, solo tiene que eliminar sus scripts . Entonces, si desea firmar la transacción publicada en la pregunta, el primer hash se calcularía así:

'version': 1,
'inputs': (2)
    {
    'output_tx_hash': 'aaaa',
    'output_position': 0,
    'script': the original script, like: '76a914' + hash + '88ac',
    'sequence': ffffffff,
    }, {
    'output_tx_hash': 'bbbb',
    'output_position': 1,
    'script': '', # Nothing
    'sequence': ffffffff,
    }
'outputs': (1)
    'value' : 100000
    'script' : '76a914' + hash of btc pub key + '88ac'
'locktime': 0

Y el segundo hash:

'version': 1,
'inputs': (2)
    {
    'output_tx_hash': 'aaaa',
    'output_position': 0,
    'script': '', # Nothing
    'sequence': ffffffff,
    }, {
    'output_tx_hash': 'bbbb',
    'output_position': 1,
    'script': the original script, like: '76a914' + hash + '88ac',
    'sequence': ffffffff,
    }
'outputs': (1)
    'value' : 100000
    'script' : '76a914' + hash of btc pub key + '88ac'
'locktime': 0

Espero que ayude a alguien.

Amigo, he estado investigando esto todo el maldito día. Ojalá hubiera visto esto hace cinco horas. Muchas gracias.
¡Mismo! No podría estar más feliz de encontrar esto.
Entonces, ¿qué haces con los dos hashes?

A mí también me funcionó.

Sólo tienes que

1) Redactar firmable para la primera entrada, con cadena de longitud cero como secuencia de comandos para todas las entradas además de la que está firmada

2) Firme la primera entrada con la codificación der de firmado firmable desde 1.

3) Tener la misma operación en cada entrada

Sí, esto funciona, solo tenga en cuenta que cuando dice

'script': '' # Nothing

en realidad deberías colocar un 0x00 allí. Una vez que hice eso, logré transmitir con éxito mi transacción de entradas múltiples. Inicialmente, literalmente no tenía nada allí (ni un solo byte), lo que no funcionará.