diff --git a/bitcoinutils/transactions.py b/bitcoinutils/transactions.py index 2c4b5e40..139c6ba8 100644 --- a/bitcoinutils/transactions.py +++ b/bitcoinutils/transactions.py @@ -310,7 +310,7 @@ def from_raw(txoutputrawhex: Union[str, bytes], cursor: int = 0, has_segwit: boo txoutputraw = txoutputrawhex else: raise TypeError("Input must be a hexadecimal string or bytes") - + # Unpack the amount of the TxOutput directly in bytes amount_format = " "Transaction": wits = [TxWitnessInput.copy(witness) for witness in tx.witnesses] return cls(ins, outs, tx.locktime, tx.version, tx.has_segwit, wits) + # this sets empty witness slots (if necessary) + # makes length of witness equal to the number of inputs, to prevent expliclty defining empty witness inputs + # for non segwit inputs + def set_witness(self, txin_index: int, witness: TxWitnessInput): + """Safely set a witness at the specified index""" + if not self.has_segwit: + raise RuntimeError( + "Transaction should be segwit in order to set segwit slots" + ) + witness_len = len(self.witnesses) + input_len = len(self.inputs) + if witness_len < input_len: + # append empty witness inputs if input_len>witness_len + for _ in range(input_len - witness_len): + self.witnesses.append(TxWitnessInput([])) + + if txin_index < 0 or txin_index >= len(self.inputs): + raise IndexError("txin_index out of range") + self.witnesses[txin_index] = witness + def get_transaction_digest( self, txin_index: int, script: Script, sighash: int = SIGHASH_ALL ): diff --git a/examples/spend_multi_input_p2tr_and_p2pkh.py b/examples/spend_multi_input_p2tr_and_p2pkh.py index 23b4fadb..c0343909 100644 --- a/examples/spend_multi_input_p2tr_and_p2pkh.py +++ b/examples/spend_multi_input_p2tr_and_p2pkh.py @@ -84,12 +84,10 @@ def main(): sig2 = priv2.sign_input(tx, 1, utxos_script_pubkeys[1]) sig3 = priv3.sign_taproot_input(tx, 2, utxos_script_pubkeys, amounts) - tx.witnesses.append(TxWitnessInput([sig1])) + #set witness sets the witness at a particular input index + tx.set_witness(0, TxWitnessInput([sig1])) txin2.script_sig = Script([sig2, pub2.to_hex()]) - # the second input is not segwit but we still need to add an empty - # witness input script - tx.witnesses.append(TxWitnessInput([])) - tx.witnesses.append(TxWitnessInput([sig3])) + tx.set_witness(2, TxWitnessInput([sig3])) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + tx.serialize()) diff --git a/run_all_examples.sh b/run_all_examples.sh index fee1aaf3..d8dcde9a 100755 --- a/run_all_examples.sh +++ b/run_all_examples.sh @@ -1,6 +1,6 @@ #!/bin/bash -for fil in ./examples/*.py; do +for fil in ./examples/*.py; do python $fil; sleep 2; done