tests: fix flaky test_simple_close_delay_broadcast mempool race
What changed, and why it matters
This commit fixes a flaky automated test in Core Lightning. The test was sometimes failing because it mined a Bitcoin block immediately after seeing a log message that said a transaction was being broadcast. That log appears when Core Lightning submits the transaction, not when Bitcoin actually accepts it into the memory pool. Under timing variations, the block could be mined before the transaction arrived, producing an empty block and causing the test to time out. The fix waits for the transaction to enter the memory pool before mining. This is a test-only change and does not affect production code or user funds.
No security action required. This is a test reliability fix. Reviewers may optionally verify that generate_block's wait_for_mempool polling behaves correctly under the test framework's rpcproxy setup.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change is confined to tests/test_closing.py in test_simple_close_delay_broadcast. It replaces a direct bitcoind.generate_block(1) call with bitcoind.generate_block(1, wait_for_mempool=1) after the ‘Broadcasting txid’ log is observed. The new parameter polls getrawmempool until the expected transaction count is present, eliminating an rpcproxy-induced race where the block is generated before bitcoind accepts the mutual-close transaction. No protocol, wallet, or consensus code is modified.
Changed components
tests/test_closing.pytest_simple_close_delay_broadcastInspect captured patch +7 / −4
diff --git a/tests/test_closing.py b/tests/test_closing.py
index b846d9f1..88a9fb19 100644
--- a/tests/test_closing.py
+++ b/tests/test_closing.py
@@ -4358,11 +4358,14 @@ def test_simple_close_delay_broadcast(node_factory, bitcoind, executor):
== 'CLOSINGD_COMPLETE')
assert not l2.daemon.is_in_log('Simple close: delaying broadcast')
- # l2 broadcasts immediately; wait until its tx is confirmed.
- # We wait for the broadcast log rather than polling getrawmempool(),
- # which can miss a just-submitted tx under the rpcproxy timing.
+ # l2 broadcasts immediately; wait until its tx is actually in the mempool
+ # before mining. The 'Broadcasting txid' log only means CLN *called*
+ # sendrawtransaction, not that bitcoind accepted the tx: mining on the log
+ # alone can produce an empty block under rpcproxy timing, leaving the
+ # funding output unspent so MUTUAL_CLOSE never resolves. generate_block's
+ # wait_for_mempool polls until the tx appears, so it can't miss it.
l2.daemon.wait_for_log('Broadcasting txid')
- bitcoind.generate_block(1)
+ bitcoind.generate_block(1, wait_for_mempool=1)
l1.daemon.wait_for_log('Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by MUTUAL_CLOSE')
l2.daemon.wait_for_log('Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by MUTUAL_CLOSE')
fut.result(timeout=10)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.