From 9b961eccefce136ce2a2b360dd932981febf9676 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Fri, 10 Jul 2026 14:36:17 -0700 Subject: [PATCH] tests: fix flaky test_sql blockheight race The test mines ~106 blocks (channel close, replacement channel funding, then generate_block(99)) immediately before making three payments, without waiting for the nodes to process those blocks. Under valgrind the paying node can lag far behind bitcoind when the payments start, so it builds onions whose cltv expiries the caught-up peers reject. Two CI failures showed both shapes of the race: In one run l1 was ~40 blocks behind (l2/l3 at block 210, l1 still catching up), so l2 failed the forward: "Expiry cltv 181 too close to current 210" (expiry_too_soon). Since the error came from the invoice's route-hint channel, xpay disabled it and the payment failed hard: "All 1 channels to the destination are disabled." In the other run l1 was only a few blocks behind, so l3 failed the final hop: "Expiry cltv too soon 211 < 210 + 5". xpay's waitblockheight retry then succeeded, but the failed first attempt left status 'failed' in the forwards row the test later asserts is 'settled'. The test paid with pay until 7f6a33394 ("pytest: use xpay, not pay in misc tests."); pay took its start height from bitcoind's headercount and tracked the node's chainlag, so a lagging node still built onions valid at the true chain tip. xpay uses its own notification-fed blockheight plus one block of slack, which is why this only started flaking recently. Sync the nodes' blockheights before paying, as other tests do after mining bursts. Changelog-None --- tests/test_plugin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_plugin.py b/tests/test_plugin.py index f0dc56c474b2..70639ff9632f 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -4360,6 +4360,11 @@ def test_sql(node_factory, bitcoind): # Make sure we have a node_announcement for l1 wait_for(lambda: l2.rpc.listnodes(l1.info['id'])['nodes'] != []) + # Under valgrind, the senders can still be digesting the blocks + # above and pick a stale blockheight for the payments below, which + # the caught-up peers reject as expiry_too_soon. + sync_blockheight(bitcoind, [l1, l2, l3]) + # This should create a forward through l2 l1.rpc.xpay(l3.rpc.invoice(amount_msat=12300, label='inv1', description='description')['bolt11'])