From 2cac527c08a922b71f8d59d5132a5d1dd5c727e4 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Wed, 5 Nov 2025 14:47:39 +0000 Subject: [PATCH] interface: get_history: enforce order of mempool txs Intentionally surface servers that don't correctly implement this. --- electrum/interface.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/electrum/interface.py b/electrum/interface.py index 1e19b8dd7..b9827cf78 100644 --- a/electrum/interface.py +++ b/electrum/interface.py @@ -1455,6 +1455,8 @@ class Interface(Logger): height = assert_dict_contains_field(tx_item, field_name='height') assert_dict_contains_field(tx_item, field_name='tx_hash') assert_integer(height) + if height < -1: + raise RequestCorrupted(f'{height!r} is not a valid block height') assert_hash256_str(tx_item['tx_hash']) if height in (-1, 0): assert_dict_contains_field(tx_item, field_name='fee') @@ -1465,6 +1467,11 @@ class Interface(Logger): if height < prev_height: raise RequestCorrupted(f'heights of confirmed txs must be in increasing order') prev_height = height + if self.active_protocol_tuple >= (1, 6): + # enforce order of mempool txs + mempool_txs = [tx_item for tx_item in res if tx_item['height'] <= 0] + if mempool_txs != sorted(mempool_txs, key=lambda x: (-x['height'], bytes.fromhex(x['tx_hash']))): + raise RequestCorrupted(f'mempool txs not in canonical order') hashes = set(map(lambda item: item['tx_hash'], res)) if len(hashes) != len(res): # Either server is sending garbage... or maybe if server is race-prone