pytest: demonstrate the weird 0 htlc_maximum_msat problem.
What changed, and why it matters
This commit adds a test case that demonstrates a bug in Core Lightning where a blinded payment path can be created with a zero htlc_maximum_msat value. This means the software sometimes generates payment invoices with a maximum payment size of zero, which could prevent payments from working. The test is marked as expected to fail because it only triggers under certain conditions related to gossip store ordering.
Treat this as a bug report test rather than a security fix. The commit only adds a test demonstrating the issue. A follow-up fix should investigate why htlc_maximum_msat can become zero in invoice_paths payinfo when a node without advertised addresses uses a fronting node, and make the computation deterministic regardless of gossip_store order.
Security signals we found
Non-deterministic test failure tied to gossip_store ordering
Zero-value htlc_maximum_msat in generated BOLT12 blinded payment path
Potential payment routing failure or invoice usability issue
Test marked xfail indicating known but not yet fixed bug
Evidence from the diff
The commit adds a pytest test_blinded_path_max in tests/test_pay.py that creates a 3-node line graph where the middle node (l2) has no advertised address. When l2 creates a BOLT12 offer and l1 fetches an invoice, l2 may use l1 or l3 as a fronting node for a blinded path. The bug occurs when the resulting invoice_paths payinfo contains htlc_maximum_msat = 0, which the test asserts should be greater than zero. The test is marked @pytest.mark.xfail and notes it only fails about half the time depending on gossip_store order, indicating a non-deterministic bug.
Changed components
tests/test_pay.pyBOLT12 blinded path / offer invoice generationgossip_store handling for htlc_maximum_msatInspect captured patch +12 / −0
diff --git a/tests/test_pay.py b/tests/test_pay.py
index 4b2cf800..b520ed52 100644
--- a/tests/test_pay.py
+++ b/tests/test_pay.py
@@ -7157,3 +7157,15 @@ def test_offer_currency_no_amount(node_factory):
l1 = node_factory.get_node()
with pytest.raises(RpcError, match="currency with no amount"):
l1.rpc.decode("lno1qcp4256ypgx9getnwss8vetrw3hhyuckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg")
+
+
+# Note: only fails half the time (when it chooses l3!)
+@pytest.mark.xfail
+def test_blinded_path_max(node_factory):
+ """We have a bug where we can create a invoice_blindedpay with 0 htlc_maximum_msat."""
+ l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True)
+
+ # l2, having no advertized address, will use l1 or l3 as fronting nodes.
+ offer = l2.rpc.offer('any')['bolt12']
+ inv = l1.rpc.fetchinvoice(offer, '10000msat')['invoice']
+ assert only_one(l1.rpc.decode(inv)['invoice_paths'])['payinfo']['htlc_maximum_msat'] > 0, f"bad paths for offer = {offer}, invoice = {inv}"
Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.