示例#1
0
    def __init__(self, master_key: BIP32, utxos: List[scanner.Utxo],
                 address: str, amount_in_sat: int):
        """
        Craft and sign a transaction that spends all the UTXOs and sends the requested funds to a specific address.
        """
        output_script = scripts.build_output_script_from_address(address)
        if output_script is None:
            raise ValueError(
                'The address is invalid or the format isn\'t recognized.')

        if amount_in_sat < NON_SEGWIT_DUST:
            raise ValueError('Not enough funds to create a sweep transaction.')

        self.outputs = [(amount_in_sat, output_script)]
        self.inputs = []

        for index in range(len(utxos)):
            utxo = utxos[index]

            # Build the inputs for signing: they should all have empty scripts, save for the input that we are signing,
            # which should have the output script of a P2PKH output.
            pubkey = master_key.get_pubkey_from_path(utxo.path.to_list())
            script = scripts.ScriptType.LEGACY.build_output_script(pubkey)
            inputs = [(u, script if u == utxo else b'', []) for u in utxos]

            if utxo.script_type == scripts.ScriptType.LEGACY:
                # If this is a legacy input, then the transaction digest is just the wire format serialization.
                tx = _serialize_tx(inputs, self.outputs, include_witness=False)
            else:
                # If this is a segwit input (native or not), then the transaction digest is the one defined in BIP143.
                tx = _serialize_tx_for_segwit_signing(index, inputs,
                                                      self.outputs)

            # To produce the final message digest we need to append the sig-hash type, and double sha256 the message.
            tx.extend(SIGHASH_ALL.to_bytes(4, 'little'))
            hash = scripts.sha256(scripts.sha256(bytes(tx)))

            privkey = master_key.get_privkey_from_path(utxo.path.to_list())
            signature = coincurve.PrivateKey(privkey).sign(hash, hasher=None)

            extended_signature = bytearray(signature)
            extended_signature.append(SIGHASH_ALL)
            extended_signature = bytes(extended_signature)

            self.inputs.append(
                (utxo,
                 utxo.script_type.build_input_script(pubkey,
                                                     extended_signature),
                 utxo.script_type.build_witness(pubkey, extended_signature)))