@@ -219,11 +219,6 @@ class BlockRef:
219219 height : int
220220 hash_rev : bytes
221221
222- def to_protocol_json (self ) -> tuple [int , str ]:
223- hash_hum = hash_to_hex_str (self .hash_rev )
224- compressed_hash_hum = hash_hum .lstrip ("0" )
225- return self .height , compressed_hash_hum
226-
227222
228223@dataclass (slots = True )
229224class SessionGroup :
@@ -892,7 +887,7 @@ def extra_cost(self, session: 'SessionBase') -> float:
892887
893888 def get_block_ref_for_chaintip (self ) -> BlockRef :
894889 """Returns a BlockRef for the current chaintip of the DB.
895- Raises ChainSyncError if the DB height is not up-to-date with the daemon height .
890+ Raises ChainSyncError if the mempool is not up-to-date with the DB .
896891 """
897892 # daemon_height = self.daemon.cached_height()
898893 bp_height = self .bp .height
@@ -909,9 +904,9 @@ def get_block_ref_for_chaintip(self) -> BlockRef:
909904 # the few that also query bitcoind need to implement their own logic to make sure
910905 # the state they present is consistent with e-x's current db state.
911906 if not (bp_height == db_height == notif_height ):
912- raise ChainSyncError (message = "DB is lagging behind daemon " )
907+ raise ChainSyncError (message = "DB/mempool still catching up with each other " )
913908 if not (bp_tip == db_tip == notif_tip ):
914- raise ChainSyncError (message = "DB is lagging behind daemon " )
909+ raise ChainSyncError (message = "DB/mempool still catching up with each other " )
915910 assert db_height >= 0
916911 assert db_tip is not None
917912 return BlockRef (
@@ -1035,7 +1030,7 @@ async def limited_history(self, hashX: bytes) -> tuple[Sequence[tuple[bytes, int
10351030 History is a sorted list of (txid_rev, height) tuples, or an RPCError.'''
10361031 # History DoS limit. Each element of history is about 99 bytes when encoded
10371032 # as JSON.
1038- max_byte_size_of_history_list = self .env .max_send - 100 # deduct a bit for overhead ("chaintip" in proto 1.7, etc)
1033+ max_byte_size_of_history_list = self .env .max_send - 100 # deduct a bit for overhead
10391034 limit = max_byte_size_of_history_list // 99
10401035 assert limit > 0
10411036 cost = 0.1
@@ -1505,12 +1500,14 @@ async def _notify_inner(
15051500 method = 'blockchain.outpoint.subscribe'
15061501 txo_to_status = {} # type: dict[TxOutpoint, TXOSpendStatus]
15071502 for prevout in touched_outpoints :
1503+ # TODO taskgroup?
15081504 txo_to_status [prevout ] = await self .txoutpoint_status_for_notif (* prevout ) # can raise RPCError
15091505
15101506 # Check mempool TXOs - the status is a function of the confirmed state of
15111507 # other transactions. (this is to detect if height changed from -1 to 0)
15121508 mempool_txoutpoint_statuses = self .mempool_txoutpoint_statuses .copy ()
15131509 for prevout , old_status in mempool_txoutpoint_statuses .items ():
1510+ # TODO taskgroup?
15141511 status = await self .txoutpoint_status_for_notif (* prevout ) # can raise RPCError
15151512 if status != old_status :
15161513 txo_to_status [prevout ] = status
@@ -1781,10 +1778,14 @@ async def confirmed_and_unconfirmed_history(self, hashX: bytes) -> list[dict[str
17811778 for txid_rev , height in history ]
17821779 unconf = await self .unconfirmed_history (hashX )
17831780 # note: the same tx could appear both in conf and unconf, if it was *just* mined.
1784- # For protocol 1.7, this race is eliminated due to @retry_on_chain_sync_error(check_chaintip=True),
1785- # which ensures (self.notified_height == db.db_height).
1786- # Even for older protocol, _history_cache makes this race extremely unlikely: it could only happen
1781+ # - more complicated example: tx1 could have been just mined, while
1782+ # our not-caught-up-mempool still contains a conflicting tx2.
1783+ # we should avoid sending an inconsistent response...
1784+ # _history_cache makes this race unlikely: it could only happen
17871785 # if we *also* get a cache-miss (but the cache is only cleared when notified_height is updated).
1786+ # Conceptually the same issue affects other methods too, e.g. get_balance:
1787+ # in general the DB and the mempool might be out-of-sync with each other.
1788+ # This issue is eliminated if the caller is wrapped in @retry_on_chain_sync_error(check_chaintip=True).
17881789 return conf + unconf
17891790
17901791 @retry_on_chain_sync_error (check_chaintip = True )
@@ -1824,7 +1825,6 @@ async def phandle_scriptpubkey_get_balance(self, spk: str | Any) -> dict[str, An
18241825 scripthash = spk_to_scripthash (spk )
18251826 hashX = scripthash_to_hashX (scripthash )
18261827 d = await self .get_balance (hashX )
1827- d ["chaintip" ] = self .session_mgr .get_block_ref_for_chaintip ().to_protocol_json ()
18281828 return d
18291829
18301830 @retry_on_chain_sync_error (check_chaintip = True )
@@ -1833,7 +1833,6 @@ async def phandle_scriptpubkey_get_history(self, spk: str) -> dict[str, Any]:
18331833 hashX = scripthash_to_hashX (scripthash )
18341834 d = dict ()
18351835 d ["history" ] = await self .confirmed_and_unconfirmed_history (hashX )
1836- d ["chaintip" ] = self .session_mgr .get_block_ref_for_chaintip ().to_protocol_json ()
18371836 return d
18381837
18391838 @retry_on_chain_sync_error (check_chaintip = True )
@@ -1842,7 +1841,6 @@ async def phandle_scriptpubkey_get_mempool(self, spk: str) -> dict[str, Any]:
18421841 hashX = scripthash_to_hashX (scripthash )
18431842 d = dict ()
18441843 d ["history" ] = await self .unconfirmed_history (hashX )
1845- d ["chaintip" ] = self .session_mgr .get_block_ref_for_chaintip ().to_protocol_json ()
18461844 return d
18471845
18481846 @retry_on_chain_sync_error (check_chaintip = True )
@@ -1851,7 +1849,6 @@ async def phandle_scriptpubkey_listunspent(self, spk: str) -> dict[str, Any]:
18511849 hashX = scripthash_to_hashX (scripthash )
18521850 d = dict ()
18531851 d ["utxos" ] = await self .hashX_listunspent (hashX )
1854- d ["chaintip" ] = self .session_mgr .get_block_ref_for_chaintip ().to_protocol_json ()
18551852 return d
18561853
18571854 @retry_on_chain_sync_error (check_chaintip = True )
@@ -1879,7 +1876,6 @@ async def phandle_txoutpoint_get_status(self, tx_hash: str | Any, txout_idx: int
18791876 if max (spend_status .funder_height or 0 , spend_status .spender_height or 0 ) > db_chaintip .height :
18801877 raise ChainSyncError (message = "DB is lagging behind daemon" )
18811878 d = self ._convert_txospendstatus_to_protocol_dict (spend_status )
1882- d ["chaintip" ] = db_chaintip .to_protocol_json ()
18831879 return d
18841880
18851881 @retry_on_chain_sync_error (check_chaintip = True )
@@ -1901,7 +1897,6 @@ async def phandle_txoutpoint_subscribe(self, tx_hash: str | Any, txout_idx: int
19011897 # sub to outpoint
19021898 self .txoutpoint_subs .add ((txid_rev , txout_idx ))
19031899 d = self ._convert_txospendstatus_to_protocol_dict (spend_status )
1904- d ["chaintip" ] = db_chaintip .to_protocol_json ()
19051900 return d
19061901
19071902 async def phandle_txoutpoint_unsubscribe (self , tx_hash : str | Any , txout_idx : int | Any ) -> bool :
0 commit comments