electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit cb3977798ce021c5c6e821c1cc5c81f9eddfc243
parent d34b8d69f63e957e775cc8f2f24a431cf2926c7c
Author: rage-proof <47944736+rage-proof@users.noreply.github.com>
Date:   Thu,  4 Feb 2021 03:52:40 +0100

add function to determine script-type for all inputs in a psbt (#6984)

* Add functions to determine the script type from a psbt.

* add a function inside PartialTransaction

* P2wsh uses the witness-script field to save the script.

* Limit the detection of script-types that are not multisig.
Diffstat:
Melectrum/transaction.py | 42++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+), 0 deletions(-)

diff --git a/electrum/transaction.py b/electrum/transaction.py @@ -424,6 +424,8 @@ SCRIPTPUBKEY_TEMPLATE_P2PKH = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG] SCRIPTPUBKEY_TEMPLATE_P2SH = [opcodes.OP_HASH160, OPPushDataGeneric(lambda x: x == 20), opcodes.OP_EQUAL] SCRIPTPUBKEY_TEMPLATE_WITNESS_V0 = [opcodes.OP_0, OPPushDataGeneric(lambda x: x in (20, 32))] +SCRIPTPUBKEY_TEMPLATE_P2WPKH = [opcodes.OP_0, OPPushDataGeneric(lambda x: x == 20)] +SCRIPTPUBKEY_TEMPLATE_P2WSH = [opcodes.OP_0, OPPushDataGeneric(lambda x: x == 32)] def match_script_against_template(script, template) -> bool: @@ -447,6 +449,22 @@ def match_script_against_template(script, template) -> bool: return False return True +def get_script_type_from_output_script(_bytes: bytes) -> Optional[str]: + if _bytes is None: + return None + try: + decoded = [x for x in script_GetOp(_bytes)] + except MalformedBitcoinScript: + return None + if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_P2PKH): + return 'p2pkh' + if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_P2SH): + return 'p2sh' + if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_P2WPKH): + return 'p2wpkh' + if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_P2WSH): + return 'p2wsh' + return None def get_address_from_output_script(_bytes: bytes, *, net=None) -> Optional[str]: try: @@ -1331,6 +1349,22 @@ class PartialTxInput(TxInput, PSBTSection): return self.witness_utxo.scriptpubkey return None + def set_script_type(self) -> None: + if self.scriptpubkey is None: + return + type = get_script_type_from_output_script(self.scriptpubkey) + inner_type = None + if type is not None: + if type == 'p2sh': + inner_type = get_script_type_from_output_script(self.redeem_script) + elif type == 'p2wsh': + inner_type = get_script_type_from_output_script(self.witness_script) + if inner_type is not None: + type = inner_type + '-' + type + if type in ('p2pkh', 'p2wpkh-p2sh', 'p2wpkh'): + self.script_type = type + return + def is_complete(self) -> bool: if self.script_sig is not None and self.witness is not None: return True @@ -2000,6 +2034,14 @@ class PartialTransaction(Transaction): assert not self.is_complete() self.invalidate_ser_cache() + def update_txin_script_type(self): + """Determine the script_type of each input by analyzing the scripts. + It updates all tx-Inputs, NOT only the wallet owned, if the + scriptpubkey is present. + """ + for txin in self.inputs(): + if txin.script_type in ('unknown', 'address'): + txin.set_script_type() def pack_bip32_root_fingerprint_and_int_path(xfp: bytes, path: Sequence[int]) -> bytes: if len(xfp) != 4: