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)))