Skip to content

Commit 4199c2a

Browse files
committed
askrene: add test for reservation leaks
Changelog-None. Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
1 parent 2dc03f4 commit 4199c2a

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

tests/test_askrene.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,3 +1473,63 @@ def test_simple_dummy_channel(node_factory):
14731473
final_cltv=5,
14741474
layers=["mylayer"],
14751475
)
1476+
1477+
1478+
def test_reservations_leak(node_factory, executor):
1479+
l1, l2, l3, l4, l5, l6 = node_factory.get_nodes(
1480+
6,
1481+
opts=[
1482+
{"fee-base": 0, "fee-per-satoshi": 0},
1483+
{"fee-base": 0, "fee-per-satoshi": 0},
1484+
{
1485+
"fee-base": 0,
1486+
"fee-per-satoshi": 0,
1487+
"plugin": os.path.join(os.getcwd(), "tests/plugins/hold_htlcs.py"),
1488+
},
1489+
{"fee-base": 0, "fee-per-satoshi": 0},
1490+
{"fee-base": 0, "fee-per-satoshi": 0},
1491+
{"fee-base": 1000, "fee-per-satoshi": 0},
1492+
],
1493+
)
1494+
1495+
# There must be a common non-local channel in both payment paths.
1496+
# With a local channel we cannot trigger the reservation leak because we
1497+
# reserve slightly different amounts locally due to HTLC onchain costs.
1498+
node_factory.join_nodes([l1, l2, l4, l6, l3], wait_for_announce=True)
1499+
node_factory.join_nodes([l1, l2, l4, l5], wait_for_announce=True)
1500+
1501+
# Use offers instead of bolt11 because we are going to pay through a blinded
1502+
# path and trigger a fake channel collision between both payments.
1503+
offer1 = l3.rpc.offer("any")["bolt12"]
1504+
offer2 = l5.rpc.offer("any")["bolt12"]
1505+
1506+
inv1 = l1.rpc.fetchinvoice(offer1, "100sat")["invoice"]
1507+
inv2 = l1.rpc.fetchinvoice(offer2, "101sat")["invoice"]
1508+
1509+
# Initiate the first payment that has a delay.
1510+
fut = executor.submit(l1.rpc.xpay, (inv1))
1511+
1512+
# Wait for the first payment to reserve the path.
1513+
l1.daemon.wait_for_log(r"json_askrene_reserve called")
1514+
1515+
# A second payment starts.
1516+
l1.rpc.xpay(inv2)
1517+
l1.daemon.wait_for_log(r"json_askrene_unreserve called")
1518+
1519+
l3.daemon.wait_for_log(r"Holding onto an incoming htlc for 10 seconds")
1520+
1521+
# There is a payment pending therefore we expect reservations.
1522+
reservations = l1.rpc.askrene_listreservations()
1523+
assert reservations != {"reservations": []}
1524+
1525+
l3.daemon.wait_for_log(r"htlc_accepted hook called")
1526+
fut.result()
1527+
l1.daemon.wait_for_log(r"json_askrene_unreserve called")
1528+
1529+
# The first payment has finished we expect no reservations.
1530+
reservations = l1.rpc.askrene_listreservations()
1531+
assert reservations == {"reservations": []}
1532+
1533+
# We shouldn't fail askrene-unreserve. If it does it means something went
1534+
# wrong.
1535+
assert l1.daemon.is_in_log("askrene-unreserve failed") is None

0 commit comments

Comments
 (0)