pytest: test to reproduce failed to retransmit funding transaction
What changed, and why it matters
This commit only adds a new pytest test case that reproduces a minor startup logging bug. Core Lightning was unnecessarily trying to re-broadcast already-confirmed channel funding transactions every time it restarted. Bitcoin rejected the rebroadcast, causing harmless but noisy 'UNUSUAL' log messages. There is no loss of funds, remote attacker capability, or code change to the daemon itself in this commit.
Verify that the corresponding daemon-side fix (likely a separate commit) has already landed before relying on this test. The test itself is safe to merge as a regression check. No urgent security response is needed.
Security signals we found
Spurious rebroadcast of funding transactions on restart
Incorrect channel depth check at startup due to DB load ordering
Regression test added; no daemon code patched in this commit
Evidence from the diff
The diff adds test_no_retransmit_confirmed_funding in tests/test_opening.py. It starts a two-node line graph, confirms the channel reaches CHANNELD_NORMAL, restarts l1, and asserts that the log contains ‘Failed to re-transmit funding tx’ but not ‘Successfully rexmitted funding tx’. The commit message explains the root cause: resend_opening_transactions gated on channel->depth != 0, but depth is reset to 0 when channels are loaded from the DB and only repopulated after begin_topology() runs, so every channel matched at startup and bitcoind returned -27. The actual fix is referenced in the changelog but not present in this diff; this commit is the regression test only.
Changed components
tests/test_opening.pylightningd resend_opening_transactions startup path (referenced, not patched here)Inspect captured patch +16 / −0
diff --git a/tests/test_opening.py b/tests/test_opening.py
index dcfbdfdc..2c21a78e 100644
--- a/tests/test_opening.py
+++ b/tests/test_opening.py
@@ -3073,3 +3073,19 @@ def test_zeroconf_withhold_htlc_failback(node_factory, bitcoind):
# l1's channel to l2 is still normal — no force-close
assert only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['state'] == 'CHANNELD_NORMAL'
+
+
+@pytest.mark.openchannel('v1')
+@pytest.mark.openchannel('v2')
+def test_no_retransmit_confirmed_funding(node_factory):
+ """An channel must not trigger funding tx re-transmission on restart."""
+ l1, _ = node_factory.line_graph(2, wait_for_announce=True)
+
+ # Channel is in CHANNELD_NORMAL and funding tx is confirmed.
+ assert only_one(l1.rpc.listpeerchannels()['channels'])['state'] == 'CHANNELD_NORMAL'
+
+ l1.restart()
+
+ # Should not have attempted (and failed) to re-broadcast the funding tx.
+ assert l1.daemon.is_in_log('Failed to re-transmit funding tx')
+ assert not l1.daemon.is_in_log('Successfully rexmitted funding tx')
Why this scored 17/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.