pytest: test for splicing while channel is not announced yet.
What changed, and why it matters
This commit adds a test that reproduces a crash in Core Lightning when a user performs a channel splice before the channel has been publicly announced. The crash is an assertion failure in the code that handles funding transaction confirmations. The test is marked as expected to fail for now, meaning the bug exists but is not yet fixed.
Treat this as a known crash bug in the splicing implementation. A developer should investigate the assertion in funding_depth_cb when a splice completes on an unannounced channel, then fix the underlying logic and remove the xfail marker from the new test. Node operators should avoid splicing unannounced channels until a fix is released.
Security signals we found
Daemon abort due to assertion failure in funding_depth_cb
Crash triggered by splicing an unannounced channel
Test marked xfail, documenting a reproducible failure path
Backtrace points to peer_control.c funding confirmation logic
Evidence from the diff
The commit introduces test_splice_unannounced in tests/test_splicing.py. It creates a two-node line graph with an unannounced channel, initiates a splice via splice_init/splice_update/splice_signed, mines a block, and then mines another block. The included log excerpt shows that during the second block’s depth change, lightningd hits an assertion failure in funding_depth_cb (lightningd/peer_control.c:2202) and aborts with SIGABRT. The @pytest.mark.xfail(strict=True) decorator indicates the test documents a known crash that is not yet resolved.
Changed components
lightningd/peer_control.c (funding_depth_cb)lightningd/watch.clightningd/chaintopology.cchannel splicing protocol implementationtests/test_splicing.pyInspect captured patch +28 / −0
diff --git a/tests/test_splicing.py b/tests/test_splicing.py
index 996afcec..ec758006 100644
--- a/tests/test_splicing.py
+++ b/tests/test_splicing.py
@@ -556,3 +556,31 @@ def test_route_by_old_scid(node_factory, bitcoind):
wait_for(lambda: only_one(l1.rpc.listpeers()['peers'])['connected'] is True)
l1.rpc.sendpay(route, inv2['payment_hash'], payment_secret=inv2['payment_secret'])
l1.rpc.waitsendpay(inv2['payment_hash'])
+
+
+@pytest.mark.xfail(strict=True)
+@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
+def test_splice_unannounced(node_factory, bitcoind):
+ l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=False, opts={'experimental-splicing': None})
+
+ chan_id = l1.get_channel_id(l2)
+
+ # add extra sats to pay fee
+ funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True)
+ result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
+ result = l1.rpc.splice_update(chan_id, result['psbt'])
+ assert(result['commitments_secured'] is False)
+ result = l1.rpc.splice_update(chan_id, result['psbt'])
+ assert(result['commitments_secured'] is True)
+ result = l1.rpc.signpsbt(result['psbt'])
+ result = l1.rpc.splice_signed(chan_id, result['signed_psbt'])
+
+ l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
+ l1.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE')
+
+ bitcoind.generate_block(1, wait_for_mempool=1)
+
+ l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
+ l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
+ bitcoind.generate_block(1)
+ sync_blockheight(bitcoind, [l1, l2])
Why this scored 54/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.