pytest: test failure if we crash after fundchannel_complete but before sendpsbt.
What changed, and why it matters
This commit only adds a new automated test and a small test helper plugin. The test deliberately crashes a node between two internal steps of opening a payment channel, then checks whether the channel eventually opens after the node restarts. It is marked as expected to fail (xfail), meaning the test documents a known bug rather than fixing it. There is no production code change here.
Treat this as a test addition only. If investigating the underlying issue, focus on recovery logic after fundchannel_complete but before sendpsbt in the dual-funding / v2 opening path. No deployment or patching action is required from this commit alone.
Security signals we found
Crash during channel-funding workflow
Test-only plugin uses SIGKILL to simulate node failure
Test marked xfail, indicating a known unresolved issue
Evidence from the diff
The diff adds tests/plugins/stop_sendpsbt.py, a test-only plugin that hooks rpc_command and sends SIGKILL to its parent process when it sees a sendpsbt RPC call. It also adds test_sendpsbt_crash in tests/test_opening.py, which loads that plugin, funds a wallet, connects two nodes, calls fundchannel, expects the node to die with ‘Connection to RPC server lost.’, restarts the node without the plugin, and waits for a mempool transaction. The test is decorated with @pytest.mark.xfail(strict=True), so it is documenting a reproducible failure/bug, not resolving it. No Core Lightning source code is modified.
Changed components
tests/test_opening.pytests/plugins/stop_sendpsbt.pyInspect captured patch +40 / −0
diff --git a/tests/plugins/stop_sendpsbt.py b/tests/plugins/stop_sendpsbt.py
new file mode 100755
index 0000000..0692e81
--- /dev/null
+++ b/tests/plugins/stop_sendpsbt.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+"""
+This plugin is used to shutdown a node before processing the sendpsbt command
+"""
+from pyln.client import Plugin
+import os
+import signal
+
+plugin = Plugin()
+
+
+@plugin.hook("rpc_command")
+def on_rpc_command(plugin, rpc_command, **kwargs):
+ request = rpc_command
+ if request["method"] == "sendpsbt":
+ os.kill(os.getppid(), signal.SIGKILL)
+
+ return {"result": "continue"}
+
+
+plugin.run()
diff --git a/tests/test_opening.py b/tests/test_opening.py
index 3e9e587..2258a14 100644
--- a/tests/test_opening.py
+++ b/tests/test_opening.py
@@ -2847,3 +2847,22 @@ def test_opening_crash(bitcoind, node_factory):
l1.start()
bitcoind.generate_block(1, wait_for_mempool=txid)
+
+
+@pytest.mark.xfail(strict=True)
+@pytest.mark.openchannel('v1')
+def test_sendpsbt_crash(bitcoind, node_factory):
+ """Stop sendpsbt, check it eventually opens"""
+ plugin_path = Path(__file__).parent / "plugins" / "stop_sendpsbt.py"
+ l1, l2 = node_factory.get_nodes(2, opts=[{"plugin": plugin_path, 'may_fail': True}, {}])
+
+ l1.fundwallet(3_000_000)
+ l1.connect(l2)
+
+ # signpsbt kills l1.
+ with pytest.raises(RpcError, match=r'Connection to RPC server lost.'):
+ l1.rpc.fundchannel(l2.info['id'], "2000000sat")
+
+ del l1.daemon.opts['plugin']
+ l1.start()
+ bitcoind.generate_block(1, wait_for_mempool=1)
Why this scored 12/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.