chainside / btcpy

A Python3 SegWit-compliant library which provides tools to handle Bitcoin data structures in a simple fashion.
https://www.chainside.net
GNU Lesser General Public License v3.0
270 stars 73 forks source link

How to spend multiple UTXOs, from different transactions? #44

Closed peerchemist closed 6 years ago

peerchemist commented 6 years ago

In examples:

from btcpy.structs.sig import *
to_spend = Transaction.unhexlify('...')
unsigned = MutableTransction(version=1,
                              ins=[TxIn(txid=to_spend.txid,
                                        txout=0,
                                        script_sig=ScriptSig.empty(),
                                        sequence=Sequence.max())],
                              outs=[TxOut(value=100000,
                                          n=0,
                                          script_pubkey=P2pkhScript(pubk))],
                              locktime=Locktime(0))
solver = P2pkhSolver(privk)
signed = unsigned.spend([to_spend.outs[0]], [solver])

How to approach if to_spend does not cover enough value to feed the outs[0], what if there is need to use two or three TxOut inputs?

SimoneBronzini commented 6 years ago

Imagine you have 3 transactions in the variables tx1, tx2 and tx3. You want to spend output 0 of tx1, output 1 of tx2, output 2 of tx3. You'll go like this:


# create the transaction
unsigned = MutableTransction(version=1,
                             ins=[TxIn(txid=tx1.txid,
                                       txout=0,
                                       script_sig=ScriptSig.empty(),
                                       sequence=Sequence.max()),
                                  TxIn(txid=tx2.txid,
                                       txout=1,
                                       script_sig=ScriptSig.empty(),
                                       sequence=Sequence.max()),
                                  TxIn(txid=tx3.txid,
                                       txout=2,
                                       script_sig=ScriptSig.empty(),
                                       sequence=Sequence.max())],
                              outs=[TxOut(value=100000,
                                          n=0,
                                          script_pubkey=P2pkhScript(pubk))],
                              locktime=Locktime(0))

# create a solver for each input
solver1, solver2, solver3 = ..., ..., ...

# sign the transaction providing the txouts you want to spend and the solver in the respective order
signed = unsigned.spend([tx1.outs[0], tx2.outs[1], tx3.outs[2]], [solver1, solver2, solver3])
peerchemist commented 6 years ago

OK I get it now. It's quite complicated workflow overall though.

SimoneBronzini commented 6 years ago

A way to slightly improve it would be having the spend method take as input a list of couples instead of two lists (this fix has already been in my personal TODO list for a long time). If you have any other suggestion on how to simplify this workflow it would be more than welcome!