URI:
       tRewrite unconf tx handler to use getmempoolentry - electrum-personal-server - Maximally lightweight electrum server for a single user
  HTML git clone https://git.parazyd.org/electrum-personal-server
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
   DIR commit dcdb893dff33d36bda7dbd2778100a3df8dcf06f
   DIR parent 169fac9130b38230f141123ca51ebb2cef69fcad
  HTML Author: chris-belcher <chris-belcher@users.noreply.github.com>
       Date:   Tue, 23 Feb 2021 23:09:47 +0000
       
       Rewrite unconf tx handler to use getmempoolentry
       
       Previously when handling an unconfirmed transaction the code
       would use an ugly cascade of calls to `getrawtransaction`
       and `gettxout` in an effort to learn whether an unconfirmed
       had unconfirmed parents, and what its miner fee was.
       
       This is replaced by using the `getmempoolentry` RPC call which
       is much cleaner and shorter.
       
       Update tests
       
       Diffstat:
         M electrumpersonalserver/server/tran… |      51 +++++++++++--------------------
         M test/test_transactionmonitor.py     |      10 +++++++++-
       
       2 files changed, 27 insertions(+), 34 deletions(-)
       ---
   DIR diff --git a/electrumpersonalserver/server/transactionmonitor.py b/electrumpersonalserver/server/transactionmonitor.py
       t@@ -147,6 +147,9 @@ class TransactionMonitor(object):
                            input_scripthashes))
                        if len(sh_to_add) == 0:
                            continue
       +                new_history_element = self.generate_new_history_element(tx, txd)
       +                if new_history_element == None:
       +                    continue
        
                        for wal in self.deterministic_wallets:
                            overrun_depths = wal.have_scriptpubkeys_overrun_gaplimit(
       t@@ -160,7 +163,6 @@ class TransactionMonitor(object):
                                # check whether all initial_import_count addresses are
                                # imported rather than just the first one
                                return False
       -                new_history_element = self.generate_new_history_element(tx, txd)
                        for scripthash in sh_to_add:
                            address_history[scripthash][
                                "history"].append(new_history_element)
       t@@ -217,37 +219,16 @@ class TransactionMonitor(object):
            def generate_new_history_element(self, tx, txd):
                logger = self.logger
                if tx["confirmations"] == 0:
       -            unconfirmed_input = False
       -            total_input_value = 0
       -            for inn in txd["vin"]:
       -                try:
       -                    utxo = self.rpc.call("gettxout", [inn["txid"],
       -                        inn["vout"], True])
       -                    if utxo is None:
       -                        utxo = self.rpc.call("gettxout", [inn["txid"],
       -                            inn["vout"], False])
       -                        if utxo is None:
       -                            rawtx = self.rpc.call("getrawtransaction",
       -                                [inn["txid"], True])
       -                            if rawtx is not None:
       -                                utxo = {"confirmations": 0,
       -                                    "value": rawtx["vout"][
       -                                    inn["vout"]]["value"]}
       -                except JsonRpcError:
       -                    #error somewhere, unable to get input value, just carry on
       -                    pass
       -                if utxo is not None:
       -                    total_input_value += int(Decimal(utxo["value"]) *
       -                        Decimal(1e8))
       -                    unconfirmed_input = (unconfirmed_input or
       -                        utxo["confirmations"] == 0)
       -                else:
       -                    # Electrum will now display a weird negative fee
       -                    logger.warning("input utxo not found(!)")
       -
       -            logger.debug("total_input_value = " + str(total_input_value))
       -            fee = total_input_value - sum([int(Decimal(out["value"])
       -                * Decimal(1e8)) for out in txd["vout"]])
       +            try:
       +                mempool_tx = self.rpc.call("getmempoolentry", [tx["txid"]])
       +                fee = int(Decimal(str(mempool_tx["fees"]["base"]))
       +                    * Decimal(1e8))
       +                unconfirmed_input = mempool_tx["ancestorcount"] > 1
       +            except JsonRpcError as e:
       +                #not in mempool, return None
       +                logger.debug("txid in wallet but not in mempool = "
       +                    + tx["txid"])
       +                return None
                    height = -1 if unconfirmed_input else 0
                    new_history_element = ({"tx_hash": tx["txid"], "height": height,
                        "fee": fee})
       t@@ -318,6 +299,8 @@ class TransactionMonitor(object):
                                txd = self.rpc.call("decoderawtransaction", [tx["hex"]])
                                new_history_element = self.generate_new_history_element(
                                    tx, txd)
       +                        if new_history_element == None:
       +                            continue
                                for scrhash in scrhashes:
                                    self.address_history[scrhash]["history"].append(
                                        new_history_element)
       t@@ -455,6 +438,9 @@ class TransactionMonitor(object):
                            matching_scripthashes.append(scripthash)
                    if len(matching_scripthashes) == 0:
                        continue
       +            new_history_element = self.generate_new_history_element(tx, txd)
       +            if new_history_element == None:
       +                continue
        
                    for wal in self.deterministic_wallets:
                        overrun_depths = wal.have_scriptpubkeys_overrun_gaplimit(
       t@@ -471,7 +457,6 @@ class TransactionMonitor(object):
                                import_addresses(self.rpc, new_addrs, [], -1, 0, logger)
        
                    updated_scripthashes.extend(matching_scripthashes)
       -            new_history_element = self.generate_new_history_element(tx, txd)
                    logger.info("Found new tx: " + str(new_history_element))
                    for scrhash in matching_scripthashes:
                        self.address_history[scrhash]["history"].append(
   DIR diff --git a/test/test_transactionmonitor.py b/test/test_transactionmonitor.py
       t@@ -55,8 +55,16 @@ class DummyJsonRpc(object):
                    return {"addresses": [dummy_spk_to_address(params[0])]}
                elif method == "importaddress":
                    self.imported_addresses.append(params[0])
       +        elif method == "getmempoolentry":
       +            for t in self.txlist:
       +                if t["txid"] == params[0]:
       +                    return {"fees": {"base": 0},
       +                        "ancestorcount":
       +                            1 if t["vin"][0]["confirmations"] > 0 else 2}
       +            logger.debug(params[0])
       +            assert 0
                else:
       -            raise ValueError("unknown method in dummy jsonrpc")
       +            raise ValueError("unknown method in dummy jsonrpc " + method)
        
            def add_transaction(self, tx):
                self.txlist = [tx] + self.txlist