Skip to content

Commit b99fd02

Browse files
rustyrussellShahanaFarooqui
authored andcommitted
pytest: add spendable tests for askrene.
Make sure we're not exceeding the spendable amount of a local channel. Signed-off-by: Rusty Russell <[email protected]>
1 parent 7fb7234 commit b99fd02

File tree

1 file changed

+74
-1
lines changed

1 file changed

+74
-1
lines changed

tests/test_askrene.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pyln.client import RpcError
33
from utils import (
44
only_one, first_scid, GenChannel, generate_gossip_store,
5-
TEST_NETWORK
5+
TEST_NETWORK, sync_blockheight, wait_for
66
)
77
import os
88
import pytest
@@ -415,3 +415,76 @@ def test_getroutes_auto_localchans(node_factory):
415415
paths=[[{'short_channel_id': scid12, 'amount_msat': 102010, 'delay': 99 + 6 + 6},
416416
{'short_channel_id': '0x1x0', 'amount_msat': 102010, 'delay': 99 + 6 + 6},
417417
{'short_channel_id': '1x2x1', 'amount_msat': 101000, 'delay': 99 + 6}]])
418+
419+
420+
def test_fees_dont_exceed_constraints(node_factory):
421+
l1 = node_factory.get_node(start=False)
422+
423+
msat = 100000000
424+
max_msat = int(msat * 0.45)
425+
# 0 has to use two paths (1 and 2) to reach 3. But we tell it 0->1 has limited capacity.
426+
gsfile, nodemap = generate_gossip_store([GenChannel(0, 1, capacity_sats=msat // 1000, forward=GenChannel.Half(propfee=10000)),
427+
GenChannel(0, 2, capacity_sats=msat // 1000, forward=GenChannel.Half(propfee=10000)),
428+
GenChannel(1, 3, capacity_sats=msat // 1000, forward=GenChannel.Half(propfee=10000)),
429+
GenChannel(2, 3, capacity_sats=msat // 1000, forward=GenChannel.Half(propfee=10000))])
430+
431+
# Set up l1 with this as the gossip_store
432+
shutil.copy(gsfile.name, os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store'))
433+
l1.start()
434+
435+
chan = only_one([c for c in l1.rpc.listchannels(source=nodemap[0])['channels'] if c['destination'] == nodemap[1]])
436+
l1.rpc.askrene_inform_channel(layer='test_layers',
437+
short_channel_id=chan['short_channel_id'],
438+
direction=chan['direction'],
439+
maximum_msat=max_msat)
440+
441+
routes = l1.rpc.getroutes(source=nodemap[0],
442+
destination=nodemap[3],
443+
amount_msat=msat,
444+
layers=['test_layers'],
445+
maxfee_msat=msat,
446+
final_cltv=99)['routes']
447+
assert len(routes) == 2
448+
for hop in routes[0]['path'] + routes[1]['path']:
449+
if hop['short_channel_id'] == chan['short_channel_id']:
450+
amount = hop['amount_msat']
451+
assert amount <= max_msat
452+
453+
454+
def test_mpp_pay2(node_factory, bitcoind):
455+
l1, l2, l3 = node_factory.get_nodes(3)
456+
l1.fundwallet(10_000_000)
457+
l2.fundwallet(10_000_000)
458+
l1.rpc.connect(l2.info['id'], 'localhost', port=l2.port)
459+
l2.rpc.connect(l3.info['id'], 'localhost', port=l3.port)
460+
461+
capacities = (100_000, 100_000, 200_000, 300_000, 400_000)
462+
for capacity in capacities:
463+
l1.rpc.fundchannel(l2.info["id"], capacity, mindepth=1)
464+
l2.rpc.fundchannel(l3.info["id"], capacity, mindepth=1)
465+
466+
bitcoind.generate_block(1, wait_for_mempool=2)
467+
sync_blockheight(bitcoind, [l1, l2])
468+
469+
bitcoind.generate_block(5)
470+
wait_for(lambda: len(l1.rpc.listchannels()["channels"]) == 2 * 2 * len(capacities))
471+
472+
routes = l1.rpc.getroutes(
473+
source=l1.info["id"],
474+
destination=l3.info["id"],
475+
amount_msat=800_000_000,
476+
layers=["auto.localchans", "auto.sourcefree"],
477+
maxfee_msat=50_000_000,
478+
final_cltv=10,
479+
)
480+
481+
# Don't exceed spendable_msat
482+
maxes = {}
483+
for chan in l1.rpc.listpeerchannels()['channels']:
484+
maxes["{}/{}".format(chan['short_channel_id'], chan['direction'])] = chan['spendable_msat']
485+
486+
for r in routes['routes']:
487+
for p in r['path']:
488+
scidd = "{}/{}".format(p['short_channel_id'], p['direction'])
489+
if scidd in maxes:
490+
assert p['amount_msat'] <= maxes[scidd]

0 commit comments

Comments
 (0)