Skip to content

Hub tx_cache doing negative caching, with negative effect on jsonrpc_transaction_show test. #104

@moodyjon

Description

@moodyjon

Context: lbryio/lbry-sdk#3665

Test can call jsonrpc_transaction_show() too early, and the transaction is not known to Hub. Not even in Hubs model of the mempool.

I changed the test to remove sleep(0.2) and do some retries with sleep(0.1) in between instead. The problem is no matter how many times I retry, hub sends the response ""No such mempool or blockchain transaction." If I restore the initial sleep(0.2), it works again (95+% of the time).

It's like sending the "blockchain.transaction.info" very early will cause the nonexistence of the transaction to be locked in.

If I make the following change, the problem seems to be fixed:

hub/hub/db/db.py

Line 1230 in 9b3618f

async def get_transactions_and_merkles(self, txids: List[str]):

swdev1@Jonathans-Mac-mini hub % git diff -U10 
diff --git a/hub/db/db.py b/hub/db/db.py
index 36b8da5..1a377ad 100644
--- a/hub/db/db.py
+++ b/hub/db/db.py
@@ -1299,21 +1299,22 @@ class SecondaryDB:
                     'block_height': tx_height,
                     'merkle': get_merkle_branch(tx_pos),
                     'pos': tx_pos
                 }
         for tx_hash_bytes, tx in cached_mempool:
             tx_infos[tx_hash_bytes[::-1].hex()] = None if not tx else tx.hex(), {'block_height': -1}
         if needed_mempool:
             for tx_hash_bytes, tx in zip(needed_mempool, await run_in_executor(
                     self._executor, self.prefix_db.mempool_tx.multi_get, [(tx_hash,) for tx_hash in needed_mempool],
                     True, False)):
-                self.tx_cache[tx_hash_bytes] = tx, None, None, -1
+                if tx:
+                    self.tx_cache[tx_hash_bytes] = tx, None, None, -1
                 tx_infos[tx_hash_bytes[::-1].hex()] = None if not tx else tx.hex(), {'block_height': -1}
                 await asyncio.sleep(0)
         return {txid: tx_infos.get(txid) for txid in txids}  # match ordering of the txs in the request
 
     async def fs_block_hashes(self, height, count):
         if height + count > self.db_height + 1:
             raise DBError(f'only got {len(self.block_hashes) - height:,d} headers starting at {height:,d}, not {count:,d}')
         return self.block_hashes[height:height + count]
 
     def _read_history(self, hashX: bytes, limit: Optional[int] = 1000) -> List[int]:

There is one other place in get_transactions_and_merkles() that updates self.tx_cache that does something similar. Wondering whether that one in the needed_confirmed clause is a problem too.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions