Prevent unnecessary farming delays of height-asserted spends at exact match height (#20786)

* Prevent unnecessary farming delays at exact height

* Update tests

* Integrate new conditions into existing tests
This commit is contained in:
trgarrett
2026-04-16 09:13:23 -05:00
committed by GitHub
parent 38bb6d358d
commit b0bc56dffc
3 changed files with 28 additions and 14 deletions
+11 -3
View File
@@ -290,23 +290,31 @@ class TestPendingTxCache:
for i in items:
c.add(i)
# drain(101) uses <=, so it releases items with assert_height <= 101:
# items[0] (assert_height=100) and items[1] (assert_height=101)
tx = c.drain(uint32(101))
assert tx == {items[0].spend_bundle_name: items[0]}
assert tx == {
items[0].spend_bundle_name: items[0],
items[1].spend_bundle_name: items[1],
}
# drain(105) releases items with assert_height <= 105:
# items[2] (102), items[3] (103), items[4] (104), items[5] (105)
tx = c.drain(uint32(105))
assert tx == {
items[1].spend_bundle_name: items[1],
items[2].spend_bundle_name: items[2],
items[3].spend_bundle_name: items[3],
items[4].spend_bundle_name: items[4],
items[5].spend_bundle_name: items[5],
}
tx = c.drain(uint32(105))
assert tx == {}
# drain(110) releases items with assert_height <= 110:
# items[6] (106), items[7] (107), items[8] (108), items[9] (109)
tx = c.drain(uint32(110))
assert tx == {
items[5].spend_bundle_name: items[5],
items[6].spend_bundle_name: items[6],
items[7].spend_bundle_name: items[7],
items[8].spend_bundle_name: items[8],
@@ -3449,6 +3449,11 @@ async def test_new_peak_txs_added(condition_and_error: tuple[ConditionOpcode, Er
"""
Tests that deferred transactions because of time-lock are retried once the
time-lock allows them to be reconsidered.
drain() uses <=, so when new_peak.height == condition_height the item is
promoted immediately (check_time_locks accepts ASSERT_HEIGHT_ABSOLUTE(H)
when peak.height >= H, and ASSERT_HEIGHT_RELATIVE(R) when
peak.height >= coin_confirmed + R).
"""
coins = TestCoins([TEST_COIN], {})
async with setup_mempool(coins) as mempool_manager:
@@ -3460,23 +3465,24 @@ async def test_new_peak_txs_added(condition_and_error: tuple[ConditionOpcode, Er
_, status, error = result
assert status == MempoolInclusionStatus.PENDING
assert error == expected_error
# Advance the mempool beyond the asserted height to retry the test item
# Advance the mempool to exactly the asserted height.
# drain() uses <=, so the item is promoted at condition_height (not condition_height + 1).
if optimized_path:
spent_coins: list[bytes32] | None = []
new_peak_info = await mempool_manager.new_peak(
create_test_block_record(height=uint32(condition_height)), spent_coins
)
# We're not there yet (needs to be higher, not equal)
assert new_peak_info.spend_bundle_ids == []
assert mempool_manager.get_mempool_item(sb_name, include_pending=False) is None
# The item is retried and promoted at exactly condition_height
assert new_peak_info.spend_bundle_ids == [sb_name]
assert mempool_manager.get_mempool_item(sb_name, include_pending=False) is not None
else:
spent_coins = None
new_peak_info = await mempool_manager.new_peak(
create_test_block_record(height=uint32(condition_height + 1)), spent_coins
)
# The item gets retried successfully now
assert new_peak_info.spend_bundle_ids == [sb_name]
assert mempool_manager.get_mempool_item(sb_name, include_pending=False) is not None
new_peak_info = await mempool_manager.new_peak(
create_test_block_record(height=uint32(condition_height)), spent_coins
)
# The item is retried and promoted at exactly condition_height
assert new_peak_info.spend_bundle_ids == [sb_name]
assert mempool_manager.get_mempool_item(sb_name, include_pending=False) is not None
@pytest.mark.anyio
+1 -1
View File
@@ -95,7 +95,7 @@ class PendingTxCache:
return ret
height_line = self._by_height.items()[0]
while height_line[0] < up_to_height:
while height_line[0] <= up_to_height:
ret.update(height_line[1])
for name, item in height_line[1].items():
self._cache_cost -= item.cost