Skip to content

Commit db8eafd

Browse files
committed
pytest: test withhold parameter to fundchannel_complete.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 3862681 commit db8eafd

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

contrib/pyln-client/pyln/client/lightning.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,13 +847,14 @@ def fundchannel_cancel(self, node_id):
847847
}
848848
return self.call("fundchannel_cancel", payload)
849849

850-
def fundchannel_complete(self, node_id, psbt):
850+
def fundchannel_complete(self, node_id, psbt, withhold=True):
851851
"""
852852
Complete channel establishment with {id}, using {psbt}.
853853
"""
854854
payload = {
855855
"id": node_id,
856856
"psbt": psbt,
857+
"withhold": withhold,
857858
}
858859
return self.call("fundchannel_complete", payload)
859860

tests/test_opening.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,3 +2868,70 @@ def test_sendpsbt_crash(bitcoind, node_factory):
28682868
bitcoind.generate_block(1, wait_for_mempool=1)
28692869

28702870
assert l1.daemon.is_in_log('Signed and sent psbt for waiting channel')
2871+
2872+
2873+
@pytest.mark.parametrize("stay_withheld", [True, False])
2874+
@pytest.mark.parametrize("mutual_close", [True, False])
2875+
def test_zeroconf_withhold(node_factory, bitcoind, stay_withheld, mutual_close):
2876+
plugin_path = Path(__file__).parent / "plugins" / "zeroconf-selective.py"
2877+
2878+
l1, l2 = node_factory.get_nodes(2, opts=[{'may_reconnect': True},
2879+
{
2880+
'plugin': str(plugin_path),
2881+
'zeroconf_allow': '0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518',
2882+
'may_reconnect': True
2883+
}])
2884+
# Try to open a mindepth=0 channel
2885+
l1.fundwallet(10**7)
2886+
2887+
l1.connect(l2)
2888+
amount = 1000000
2889+
funding_addr = l1.rpc.fundchannel_start(l2.info['id'], f"{amount}sat", mindepth=0)['funding_address']
2890+
2891+
# Create the funding transaction
2892+
psbt = l1.rpc.fundpsbt(amount, "1000perkw", 1000, excess_as_change=True)['psbt']
2893+
psbt = l1.rpc.addpsbtoutput(1000000, psbt, destination=funding_addr)['psbt']
2894+
2895+
# Be sure fundchannel_complete is successful
2896+
assert l1.rpc.fundchannel_complete(l2.info['id'], psbt, withhold=True)['commitments_secured']
2897+
2898+
# It's withheld.
2899+
assert only_one(l1.rpc.listpeerchannels()['channels'])['funding']['withheld'] is True
2900+
2901+
# We can use the channel.
2902+
l1.rpc.xpay(l2.rpc.invoice(100, "test_zeroconf_withhold", "test_zeroconf_withhold")['bolt11'])
2903+
2904+
# But mempool is empty! No funding tx!
2905+
assert bitcoind.rpc.getrawmempool() == []
2906+
2907+
# Restarting doesn't make it transmit!
2908+
l1.restart()
2909+
assert bitcoind.rpc.getrawmempool() == []
2910+
2911+
if mutual_close:
2912+
l1.connect(l2)
2913+
2914+
if not stay_withheld:
2915+
# sendpsbt marks it as no longer withheld.
2916+
l1.rpc.sendpsbt(l1.rpc.signpsbt(psbt)['signed_psbt'])
2917+
assert only_one(l1.rpc.listpeerchannels()['channels'])['funding']['withheld'] is False
2918+
assert l1.daemon.is_in_log(r'Funding PSBT sent, and stored for rexmit \(was withheld\)')
2919+
wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 1)
2920+
2921+
ret = l1.rpc.close(l2.info['id'], unilateraltimeout=10)
2922+
if stay_withheld:
2923+
assert ret['txs'] == []
2924+
assert ret['txids'] == []
2925+
assert bitcoind.rpc.getrawmempool() == []
2926+
else:
2927+
assert len(ret['txs']) == 1
2928+
assert len(ret['txids']) == 1
2929+
wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 2)
2930+
2931+
# If withheld, it's moved to closed immediately.
2932+
if stay_withheld:
2933+
assert l1.rpc.listpeerchannels()['channels'] == []
2934+
assert only_one(l1.rpc.listclosedchannels()['closedchannels'])['funding_withheld'] is True
2935+
else:
2936+
wait_for(lambda: only_one(l1.rpc.listpeerchannels()['channels'])['state'] == 'CLOSINGD_COMPLETE')
2937+

0 commit comments

Comments
 (0)