Ejemplo n.º 1
0
def recover_tx_from_psbt(first: BasicPSBT, wallet: Abstract_Wallet) -> Transaction:
    # Take a PSBT object and re-construct the Electrum transaction object.
    # - does not include signatures, see merge_sigs_from_psbt
    # - any PSBT in the group could be used for this purpose; all must share tx details
    
    tx = Transaction(first.txn.hex())
    tx.deserialize(force_full_parse=True)

    # .. add back some data that's been preserved in the PSBT, but isn't part of
    # of the unsigned bitcoin txn
    tx.is_partial_originally = True

    for idx, inp in enumerate(tx.inputs()):
        scr = first.inputs[idx].redeem_script or first.inputs[idx].witness_script

        # XXX should use transaction.py parse_scriptSig() here!
        if scr:
            try:
                M, N, __, pubkeys, __ = parse_redeemScript_multisig(scr)
            except NotRecognizedRedeemScript:
                # limitation: we can only handle M-of-N multisig here
                raise ValueError("Cannot handle non M-of-N multisig input")

            inp['pubkeys'] = pubkeys
            inp['x_pubkeys'] = pubkeys
            inp['num_sig'] = M
            inp['type'] = 'p2wsh' if first.inputs[idx].witness_script else 'p2sh'

            # bugfix: transaction.py:parse_input() puts empty dict here, but need a list
            inp['signatures'] = [None] * N

        if 'prev_tx' not in inp:
            # fetch info about inputs' previous txn
            wallet.add_hw_info(tx)

        if 'value' not in inp:
            # we'll need to know the value of the outpts used as part
            # of the witness data, much later...
            inp['value'] = inp['prev_tx'].outputs()[inp['prevout_n']].value

    return tx