test_lnpeer: add more tests, combining forwarding and hold invoices
This commit is contained in:
@@ -500,6 +500,18 @@ class TestPeer(ElectrumTestCase):
|
|||||||
await w.network.channel_db.stopped_event.wait()
|
await w.network.channel_db.stopped_event.wait()
|
||||||
w.network.channel_db = None
|
w.network.channel_db = None
|
||||||
|
|
||||||
|
def prepare_recipient(self, w2, payment_hash, test_hold_invoice, test_failure):
|
||||||
|
if not test_hold_invoice and not test_failure:
|
||||||
|
return
|
||||||
|
preimage = bytes.fromhex(w2.preimages.pop(payment_hash.hex()))
|
||||||
|
if test_hold_invoice:
|
||||||
|
async def cb(payment_hash):
|
||||||
|
if not test_failure:
|
||||||
|
w2.save_preimage(payment_hash, preimage)
|
||||||
|
else:
|
||||||
|
raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'')
|
||||||
|
w2.register_hold_invoice(payment_hash, cb)
|
||||||
|
|
||||||
|
|
||||||
class TestPeerDirect(TestPeer):
|
class TestPeerDirect(TestPeer):
|
||||||
|
|
||||||
@@ -700,8 +712,8 @@ class TestPeerDirect(TestPeer):
|
|||||||
async def _test_simple_payment(
|
async def _test_simple_payment(
|
||||||
self,
|
self,
|
||||||
test_trampoline: bool,
|
test_trampoline: bool,
|
||||||
test_failure:bool=False,
|
|
||||||
test_hold_invoice=False,
|
test_hold_invoice=False,
|
||||||
|
test_failure=False,
|
||||||
test_bundle=False,
|
test_bundle=False,
|
||||||
test_bundle_timeout=False
|
test_bundle_timeout=False
|
||||||
):
|
):
|
||||||
@@ -717,16 +729,7 @@ class TestPeerDirect(TestPeer):
|
|||||||
else:
|
else:
|
||||||
raise PaymentFailure()
|
raise PaymentFailure()
|
||||||
lnaddr, pay_req = self.prepare_invoice(w2)
|
lnaddr, pay_req = self.prepare_invoice(w2)
|
||||||
payment_hash = lnaddr.paymenthash
|
self.prepare_recipient(w2, lnaddr.paymenthash, test_hold_invoice, test_failure)
|
||||||
if test_failure or test_hold_invoice:
|
|
||||||
preimage = bytes.fromhex(w2.preimages.pop(payment_hash.hex()))
|
|
||||||
if test_hold_invoice:
|
|
||||||
async def cb(payment_hash):
|
|
||||||
if not test_failure:
|
|
||||||
w2.save_preimage(payment_hash, preimage)
|
|
||||||
else:
|
|
||||||
raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'')
|
|
||||||
w2.register_hold_invoice(payment_hash, cb)
|
|
||||||
|
|
||||||
if test_bundle:
|
if test_bundle:
|
||||||
lnaddr2, pay_req2 = self.prepare_invoice(w2)
|
lnaddr2, pay_req2 = self.prepare_invoice(w2)
|
||||||
@@ -1681,26 +1684,32 @@ class TestPeerForwarding(TestPeer):
|
|||||||
bob_forwarding=True,
|
bob_forwarding=True,
|
||||||
mpp_invoice=True,
|
mpp_invoice=True,
|
||||||
disable_trampoline_receiving=False,
|
disable_trampoline_receiving=False,
|
||||||
|
test_hold_invoice=False,
|
||||||
|
test_failure=False,
|
||||||
):
|
):
|
||||||
|
alice_w = graph.workers['alice']
|
||||||
|
bob_w = graph.workers['bob']
|
||||||
|
dave_w = graph.workers['dave']
|
||||||
if mpp_invoice:
|
if mpp_invoice:
|
||||||
graph.workers['dave'].features |= LnFeatures.BASIC_MPP_OPT
|
dave_w.features |= LnFeatures.BASIC_MPP_OPT
|
||||||
if disable_trampoline_receiving:
|
if disable_trampoline_receiving:
|
||||||
graph.workers['dave'].features &= ~LnFeatures.OPTION_TRAMPOLINE_ROUTING_OPT_ELECTRUM
|
dave_w.features &= ~LnFeatures.OPTION_TRAMPOLINE_ROUTING_OPT_ELECTRUM
|
||||||
if not bob_forwarding:
|
if not bob_forwarding:
|
||||||
graph.workers['bob'].enable_htlc_forwarding = False
|
bob_w.enable_htlc_forwarding = False
|
||||||
if alice_uses_trampoline:
|
if alice_uses_trampoline:
|
||||||
await self._activate_trampoline(graph.workers['alice'])
|
await self._activate_trampoline(alice_w)
|
||||||
else:
|
else:
|
||||||
assert graph.workers['alice'].network.channel_db is not None
|
assert alice_w.network.channel_db is not None
|
||||||
lnaddr, pay_req = self.prepare_invoice(graph.workers['dave'], include_routing_hints=True, amount_msat=amount_to_pay)
|
lnaddr, pay_req = self.prepare_invoice(dave_w, include_routing_hints=True, amount_msat=amount_to_pay)
|
||||||
self.assertEqual(PR_UNPAID, graph.workers['dave'].get_payment_status(lnaddr.paymenthash))
|
self.prepare_recipient(dave_w, lnaddr.paymenthash, test_hold_invoice, test_failure)
|
||||||
result, log = await graph.workers['alice'].pay_invoice(pay_req, attempts=attempts)
|
self.assertEqual(PR_UNPAID, dave_w.get_payment_status(lnaddr.paymenthash))
|
||||||
|
result, log = await alice_w.pay_invoice(pay_req, attempts=attempts)
|
||||||
if not bob_forwarding:
|
if not bob_forwarding:
|
||||||
# reset to previous state, sleep 2s so that the second htlc can time out
|
# reset to previous state, sleep 2s so that the second htlc can time out
|
||||||
graph.workers['bob'].enable_htlc_forwarding = True
|
graph.workers['bob'].enable_htlc_forwarding = True
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
if result:
|
if result:
|
||||||
self.assertEqual(PR_PAID, graph.workers['dave'].get_payment_status(lnaddr.paymenthash))
|
self.assertEqual(PR_PAID, dave_w.get_payment_status(lnaddr.paymenthash))
|
||||||
raise PaymentDone()
|
raise PaymentDone()
|
||||||
elif len(log) == 1 and log[0].failure_msg.code == OnionFailureCode.MPP_TIMEOUT:
|
elif len(log) == 1 and log[0].failure_msg.code == OnionFailureCode.MPP_TIMEOUT:
|
||||||
raise PaymentTimeout()
|
raise PaymentTimeout()
|
||||||
@@ -1720,6 +1729,11 @@ class TestPeerForwarding(TestPeer):
|
|||||||
with self.assertRaises(PaymentDone):
|
with self.assertRaises(PaymentDone):
|
||||||
await self._run_mpp(graph, {})
|
await self._run_mpp(graph, {})
|
||||||
|
|
||||||
|
async def test_payment_multipart_with_hold_invoice(self):
|
||||||
|
graph = self.prepare_chans_and_peers_in_graph(self.GRAPH_DEFINITIONS['square_graph'])
|
||||||
|
with self.assertRaises(PaymentDone):
|
||||||
|
await self._run_mpp(graph, {'test_hold_invoice': True})
|
||||||
|
|
||||||
async def test_payment_multipart_with_timeout(self):
|
async def test_payment_multipart_with_timeout(self):
|
||||||
graph = self.prepare_chans_and_peers_in_graph(self.GRAPH_DEFINITIONS['square_graph'])
|
graph = self.prepare_chans_and_peers_in_graph(self.GRAPH_DEFINITIONS['square_graph'])
|
||||||
with self.assertRaises(PaymentTimeout):
|
with self.assertRaises(PaymentTimeout):
|
||||||
@@ -1801,8 +1815,12 @@ class TestPeerForwarding(TestPeer):
|
|||||||
async def _run_trampoline_payment(
|
async def _run_trampoline_payment(
|
||||||
self, graph, *,
|
self, graph, *,
|
||||||
include_routing_hints=True,
|
include_routing_hints=True,
|
||||||
|
test_hold_invoice=False,
|
||||||
|
test_failure=False,
|
||||||
attempts=2):
|
attempts=2):
|
||||||
|
|
||||||
|
dave_w = graph.workers['dave']
|
||||||
|
|
||||||
async def pay(lnaddr, pay_req):
|
async def pay(lnaddr, pay_req):
|
||||||
self.assertEqual(PR_UNPAID, graph.workers['dave'].get_payment_status(lnaddr.paymenthash))
|
self.assertEqual(PR_UNPAID, graph.workers['dave'].get_payment_status(lnaddr.paymenthash))
|
||||||
result, log = await graph.workers['alice'].pay_invoice(pay_req, attempts=attempts)
|
result, log = await graph.workers['alice'].pay_invoice(pay_req, attempts=attempts)
|
||||||
@@ -1820,7 +1838,8 @@ class TestPeerForwarding(TestPeer):
|
|||||||
await group.spawn(peer.htlc_switch())
|
await group.spawn(peer.htlc_switch())
|
||||||
for peer in peers:
|
for peer in peers:
|
||||||
await peer.initialized
|
await peer.initialized
|
||||||
lnaddr, pay_req = self.prepare_invoice(graph.workers['dave'], include_routing_hints=include_routing_hints)
|
lnaddr, pay_req = self.prepare_invoice(dave_w, include_routing_hints=include_routing_hints)
|
||||||
|
self.prepare_recipient(dave_w, lnaddr.paymenthash, test_hold_invoice, test_failure)
|
||||||
await group.spawn(pay(lnaddr, pay_req))
|
await group.spawn(pay(lnaddr, pay_req))
|
||||||
|
|
||||||
peers = graph.peers.values()
|
peers = graph.peers.values()
|
||||||
@@ -1859,6 +1878,16 @@ class TestPeerForwarding(TestPeer):
|
|||||||
graph = self.create_square_graph(direct=False, test_mpp_consolidation=True, is_legacy=True)
|
graph = self.create_square_graph(direct=False, test_mpp_consolidation=True, is_legacy=True)
|
||||||
await self._run_trampoline_payment(graph)
|
await self._run_trampoline_payment(graph)
|
||||||
|
|
||||||
|
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)
|
||||||
|
await self._run_trampoline_payment(graph, test_hold_invoice=True)
|
||||||
|
|
||||||
|
async def test_trampoline_mpp_consolidation_with_hold_invoice_failure(self):
|
||||||
|
with self.assertRaises(NoPathFound):
|
||||||
|
graph = self.create_square_graph(direct=False, test_mpp_consolidation=True, is_legacy=True)
|
||||||
|
await self._run_trampoline_payment(graph, test_hold_invoice=True, test_failure=True)
|
||||||
|
|
||||||
async def test_payment_trampoline_legacy(self):
|
async def test_payment_trampoline_legacy(self):
|
||||||
with self.assertRaises(PaymentDone):
|
with self.assertRaises(PaymentDone):
|
||||||
graph = self.create_square_graph(direct=False, is_legacy=True)
|
graph = self.create_square_graph(direct=False, is_legacy=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user