From 910832c153d736d042c429a58ab54075e973000c Mon Sep 17 00:00:00 2001 From: SomberNight Date: Wed, 26 Apr 2023 16:54:13 +0000 Subject: [PATCH] transaction: calc and cache TxInput/TxOutput.address on-demand In one wallet, before this, make_unsigned_transaction() took 120 sec, now it takes ~8 sec. hot path: ``` make_unsigned_transaction (electrum/wallet.py:1696) add_input_info (electrum/wallet.py:2261) utxo (electrum/transaction.py:289) tx_from_any (electrum/transaction.py:1232) deserialize (electrum/transaction.py:805) (electrum/transaction.py:805) parse_output (electrum/transaction.py:706) __init__ (electrum/transaction.py:127) scriptpubkey (electrum/transaction.py:173) get_address_from_output_script (electrum/transaction.py:672) ``` --- electrum/transaction.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/electrum/transaction.py b/electrum/transaction.py index d30183ffc..82aecaada 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -63,6 +63,9 @@ _logger = get_logger(__name__) DEBUG_PSBT_PARSING = False +_NEEDS_RECALC = ... # sentinel value + + class SerializationError(Exception): """ Thrown when there's a problem deserializing or serializing """ @@ -170,10 +173,12 @@ class TxOutput: @scriptpubkey.setter def scriptpubkey(self, scriptpubkey: bytes): self._scriptpubkey = scriptpubkey - self._address = get_address_from_output_script(scriptpubkey) + self._address = _NEEDS_RECALC @property def address(self) -> Optional[str]: + if self._address is _NEEDS_RECALC: + self._address = get_address_from_output_script(self._scriptpubkey) return self._address def get_ui_address_str(self) -> str: @@ -295,7 +300,7 @@ class TxInput: # update derived fields out_idx = self.prevout.out_idx self.__scriptpubkey = self._utxo.outputs()[out_idx].scriptpubkey - self.__address = get_address_from_output_script(self.__scriptpubkey) + self.__address = _NEEDS_RECALC self.__value_sats = self._utxo.outputs()[out_idx].value def validate_data(self, *, utxo: Optional['Transaction'] = None, **kwargs) -> None: @@ -320,6 +325,8 @@ class TxInput: @property def address(self) -> Optional[str]: + if self.__address is _NEEDS_RECALC: + self.__address = get_address_from_output_script(self.__scriptpubkey) return self.__address @property