Skip to content

Commit 734f292

Browse files
committed
pytest: Reproduce issue #3847
Reported-by: Rusty Russell <@rustyrussell>
1 parent 9582443 commit 734f292

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

tests/plugins/hold_htlcs.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
settled/forwarded/
66
77
"""
8-
9-
108
from pyln.client import Plugin
119
import json
1210
import os
@@ -23,20 +21,35 @@ def on_htlc_accepted(htlc, onion, plugin, **kwargs):
2321
with open(fname, 'w') as f:
2422
f.write(json.dumps(onion))
2523

26-
plugin.log("Holding onto an incoming htlc for 10 seconds")
24+
plugin.log("Holding onto an incoming htlc for {hold_time} seconds".format(
25+
hold_time=plugin.hold_time
26+
))
2727

28-
time.sleep(10)
28+
time.sleep(plugin.hold_time)
2929

3030
print("Onion written to {}".format(fname))
3131

3232
# Give the tester something to look for
3333
plugin.log("htlc_accepted hook called")
34-
return {'result': 'continue'}
34+
return {'result': plugin.hold_result}
35+
36+
37+
plugin.add_option(
38+
'hold-time', 10,
39+
'How long should we hold on to HTLCs?',
40+
opt_type='int'
41+
)
42+
plugin.add_option(
43+
'hold-result',
44+
'continue', 'How should we continue after holding?',
45+
)
3546

3647

3748
@plugin.init()
3849
def init(options, configuration, plugin):
3950
plugin.log("hold_htlcs.py initializing")
51+
plugin.hold_time = options['hold-time']
52+
plugin.hold_result = options['hold-result']
4053

4154

4255
plugin.run()

tests/test_plugin.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,3 +1497,41 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
14971497
check_coin_moves(l2, chanid_3, l2_l3_mvts, chainparams)
14981498
check_coin_moves(l2, 'wallet', l2_wallet_mvts, chainparams)
14991499
check_coin_moves_idx(l2)
1500+
1501+
1502+
@pytest.mark.xfail(strict=True)
1503+
def test_3847_repro(node_factory, bitcoind):
1504+
"""Reproduces the issue in #3847: duplicate response from plugin
1505+
1506+
l2 holds on to HTLCs until the deadline expires. Then we allow them
1507+
through and either should terminate the payment attempt, and the second
1508+
would return a redundant result.
1509+
1510+
"""
1511+
l1, l2, l3 = node_factory.line_graph(3, opts=[
1512+
{},
1513+
{},
1514+
{
1515+
'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_htlcs.py'),
1516+
'hold-time': 11,
1517+
'hold-result': 'fail',
1518+
},
1519+
], wait_for_announce=True)
1520+
wait_for(lambda: len(l1.rpc.listchannels()['channels']) == 4)
1521+
1522+
# Amount sufficient to trigger the presplit modifier
1523+
amt = 20 * 1000 * 1000
1524+
1525+
i1 = l3.rpc.invoice(
1526+
msatoshi=amt, label="direct", description="desc"
1527+
)['bolt11']
1528+
with pytest.raises(RpcError):
1529+
l1.rpc.pay(i1, retry_for=10)
1530+
1531+
# We wait for at least two parts, and the bug would cause the `pay` plugin
1532+
# to crash
1533+
l1.daemon.wait_for_logs([r'Payment deadline expired, not retrying'] * 2)
1534+
1535+
# This call to paystatus would fail if the pay plugin crashed (it's
1536+
# provided by the plugin)
1537+
l1.rpc.paystatus(i1)

0 commit comments

Comments
 (0)