Skip to content

Commit

Permalink
Merge #1625: cache deserialized form of txs in history method
Browse files Browse the repository at this point in the history
8491431 cache deserialized form of txs in history method (Adam Gibson)

Pull request description:

  Prior to this commit, while the result of the gettransaction rpc call was being cached so as to not have to repeat these rpc calls, the deserialized form of the transaction created by a call to CMutableTransaction.deserialize, was not, and since this call is rather expensive, the history method was running more slowly than needed. After this commit, we cache the deserialized form also, resulting in a speedup to the wallet_utils.wallet_fetch_history method.

ACKs for top commit:
  kristapsk:
    ACK 8491431

Tree-SHA512: 868a92dbd02c4c52f5b609b1d085bc1c56d959fb4399bc1f3166bc8bbe71727a39aa266a7ebd4f77cb96430bfbba1af51dbe6bc995ed54955bea3b54d10624b5
  • Loading branch information
kristapsk committed Dec 31, 2023
2 parents 8072b8d + 8491431 commit e87dccc
Showing 1 changed file with 16 additions and 14 deletions.
30 changes: 16 additions & 14 deletions src/jmclient/wallet_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from numbers import Integral
from collections import Counter, defaultdict
from itertools import islice, chain
from typing import Optional, Tuple
from jmclient import (get_network, WALLET_IMPLEMENTATIONS, Storage, podle,
jm_single, WalletError, BaseWallet, VolatileStorage,
StoragePasswordError, is_segwit_mode, SegwitLegacyWallet, LegacyWallet,
Expand Down Expand Up @@ -364,7 +365,8 @@ def serialize_json(self, summarize=False):
json_serialized.update(self.get_fmt_balance_json())
return json_serialized

def get_tx_info(txid, tx_cache=None):
def get_tx_info(txid: str, tx_cache: Optional[dict] = None) -> Tuple[
bool, int, int, dict, int, btc.CTransaction]:
"""
Retrieve some basic information about the given transaction.
Expand All @@ -379,14 +381,14 @@ def get_tx_info(txid, tx_cache=None):
txd: deserialized transaction object (hex-encoded data)
"""
if tx_cache is not None and txid in tx_cache:
rpctx = tx_cache[txid]
rpctx, rpctx_deser = tx_cache[txid]
else:
rpctx = jm_single().bc_interface.get_transaction(txid)
txhex = str(rpctx['hex'])
rpctx_deser = btc.CMutableTransaction.deserialize(hextobin(txhex))
if tx_cache is not None:
tx_cache[txid] = rpctx
txhex = str(rpctx['hex'])
tx = btc.CMutableTransaction.deserialize(hextobin(txhex))
output_script_values = {x.scriptPubKey: x.nValue for x in tx.vout}
tx_cache[txid] = (rpctx, rpctx_deser)
output_script_values = {x.scriptPubKey: x.nValue for x in rpctx_deser.vout}
value_freq_list = sorted(
Counter(output_script_values.values()).most_common(),
key=lambda x: -x[1])
Expand All @@ -398,7 +400,7 @@ def get_tx_info(txid, tx_cache=None):
cj_amount = value_freq_list[0][0]
cj_n = value_freq_list[0][1]
return is_coinjoin, cj_amount, cj_n, output_script_values,\
rpctx.get('blocktime', 0), tx
rpctx.get('blocktime', 0), rpctx_deser


def get_imported_privkey_branch(wallet_service, m, showprivkey):
Expand Down Expand Up @@ -846,7 +848,6 @@ def wallet_fetch_history(wallet, options):
'blocktme' not in tx)
tx_db.executemany('INSERT INTO transactions VALUES(?, ?, ?, ?);',
uc_tx_data)

txes = tx_db.execute(
'SELECT DISTINCT txid, blockhash, blocktime '
'FROM transactions '
Expand Down Expand Up @@ -903,22 +904,23 @@ def print_row(index, time, tx_type, amount, delta, balance, cj_n,

our_output_scripts = wallet_script_set.intersection(
output_script_values.keys())

rpc_inputs = []
for ins in txd.vin:
if ins.prevout.hash[::-1] in tx_cache:
wallet_tx = tx_cache[ins.prevout.hash[::-1]]
wallet_tx, wallet_tx_deser = tx_cache[ins.prevout.hash[::-1]]
else:
wallet_tx = jm_single().bc_interface.get_transaction(
ins.prevout.hash[::-1])
tx_cache[ins.prevout.hash[::-1]] = wallet_tx
if wallet_tx:
wallet_tx_deser = btc.CMutableTransaction.deserialize(
hextobin(wallet_tx['hex']))
tx_cache[ins.prevout.hash[::-1]] = (wallet_tx,
wallet_tx_deser)
if wallet_tx is None:
continue
inp = btc.CMutableTransaction.deserialize(hextobin(
wallet_tx['hex'])).vout[ins.prevout.n]
inp = wallet_tx_deser.vout[ins.prevout.n]
input_dict = {"script": inp.scriptPubKey, "value": inp.nValue}
rpc_inputs.append(input_dict)

rpc_input_scripts = set(ind['script'] for ind in rpc_inputs)
our_input_scripts = wallet_script_set.intersection(rpc_input_scripts)
our_input_values = [
Expand Down

0 comments on commit e87dccc

Please sign in to comment.