Skip to content

Commit 55e7fe9

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

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

tests/test_askrene.py

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

0 commit comments

Comments
 (0)