tests: lnpeer: test_trampoline_mpp_consolidation_forwarding_amount
What changed, and why it matters
This commit only adds a new automated test to Electrum's Lightning networking code. It does not change any production code, fix a bug, or introduce a vulnerability. The test checks that in a specific multi-part trampoline payment scenario, an intermediate node (Bob) does not forward more money to the next hop than he received from the previous hop. It is a regression test to help catch a potential bug in the future, not a patch for an existing security issue.
No action required. This is a test-only addition with no security relevance in the commit itself.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds test_trampoline_mpp_consolidation_forwarding_amount to tests/test_lnpeer.py. The test constructs a four-node trampoline route (alice→bob→carol→dave) with MPP consolidation enabled, runs one payment attempt, and asserts that the sum of HTLC amounts Bob sent to Carol is strictly less than the sum Bob received from Alice. This is a sanity/regression test; no lnpeer/lnworker logic is modified.
Changed components
tests/test_lnpeer.pyInspect captured patch +19 / −0
diff --git a/tests/test_lnpeer.py b/tests/test_lnpeer.py
index 97813f5..1ea9ae0 100644
--- a/tests/test_lnpeer.py
+++ b/tests/test_lnpeer.py
@@ -2394,6 +2394,25 @@ class TestPeerForwarding(TestPeer):
graph = self.create_square_graph(direct=False, test_mpp_consolidation=True, is_legacy=True)
await self._run_trampoline_payment(graph)
+ async def test_trampoline_mpp_consolidation_forwarding_amount(self):
+ """sanity check that bob is forwarding less than he is receiving"""
+ # alice->bob->carol->dave
+ graph = self.create_square_graph(direct=False, test_mpp_consolidation=True, is_legacy=True)
+ # bump alices trampoline fee level so the first payment succeeds and the htlc sums can be compared usefully below.
+ alice = graph.workers['alice']
+ alice.config.INITIAL_TRAMPOLINE_FEE_LEVEL = 6
+ with self.assertRaises(PaymentDone):
+ await self._run_trampoline_payment(graph, attempts=1)
+
+ # assert bob hasn't forwarded more than he received
+ bob_alice_channel = graph.channels[('bob', 'alice')]
+ htlcs_bob_received_from_alice = bob_alice_channel.hm.all_htlcs_ever()
+ bob_carol_channel = graph.channels[('bob', 'carol')]
+ htlcs_bob_sent_to_carol = bob_carol_channel.hm.all_htlcs_ever()
+ sum_bob_received = sum(htlc.amount_msat for (direction, htlc) in htlcs_bob_received_from_alice)
+ sum_bob_sent = sum(htlc.amount_msat for (direction, htlc) in htlcs_bob_sent_to_carol)
+ assert sum_bob_sent < sum_bob_received, f"{sum_bob_sent=} > {sum_bob_received=}"
+
async def test_trampoline_mpp_consolidation_with_hold_invoice(self):
with self.assertRaises(PaymentDone):
graph = self.create_square_graph(direct=False, test_mpp_consolidation=True, is_legacy=True)
Why this scored 15/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.