async def pay(pay_req): with self.subTest(msg="bad path: edges do not chain together"): path = [ PathEdge(node_id=graph.w_c.node_keypair.pubkey, short_channel_id=graph.chan_ab.short_channel_id), PathEdge(node_id=graph.w_d.node_keypair.pubkey, short_channel_id=graph.chan_bd.short_channel_id) ] result, log = await graph.w_a._pay(pay_req, full_path=path) self.assertFalse(result) self.assertTrue( isinstance(log[0].exception, LNPathInconsistent)) with self.subTest( msg="bad path: last node id differs from invoice pubkey"): path = [ PathEdge(node_id=graph.w_b.node_keypair.pubkey, short_channel_id=graph.chan_ab.short_channel_id) ] result, log = await graph.w_a._pay(pay_req, full_path=path) self.assertFalse(result) self.assertTrue( isinstance(log[0].exception, LNPathInconsistent)) with self.subTest(msg="good path"): path = [ PathEdge(node_id=graph.w_b.node_keypair.pubkey, short_channel_id=graph.chan_ab.short_channel_id), PathEdge(node_id=graph.w_d.node_keypair.pubkey, short_channel_id=graph.chan_bd.short_channel_id) ] result, log = await graph.w_a._pay(pay_req, full_path=path) self.assertTrue(result) self.assertEqual( [edge.short_channel_id for edge in path], [edge.short_channel_id for edge in log[0].route]) raise PaymentDone()
def test_find_path_for_payment(self): self.prepare_graph() amount_to_send = 100000 path = self.path_finder.find_path_for_payment( nodeA=node('a'), nodeB=node('e'), invoice_amount_msat=amount_to_send) self.assertEqual([ PathEdge(start_node=node('a'), end_node=node('b'), short_channel_id=channel(3)), PathEdge(start_node=node('b'), end_node=node('e'), short_channel_id=channel(2)), ], path) route = self.path_finder.create_route_from_path(path) self.assertEqual(node('b'), route[0].node_id) self.assertEqual(channel(3), route[0].short_channel_id) self.cdb.stop() asyncio.run_coroutine_threadsafe(self.cdb.stopped_event.wait(), self.asyncio_loop).result()
def test_find_path_for_payment(self): class fake_network: config = self.config asyncio_loop = asyncio.get_event_loop() trigger_callback = lambda *args: None register_callback = lambda *args: None interface = None fake_network.channel_db = lnrouter.ChannelDB(fake_network()) fake_network.channel_db.data_loaded.set() cdb = fake_network.channel_db path_finder = lnrouter.LNPathFinder(cdb) self.assertEqual(cdb.num_channels, 0) cdb.add_channel_announcement( { 'node_id_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'node_id_2': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02cccccccccccccccccccccccccccccccc', 'short_channel_id': bfh('0000000000000001'), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) self.assertEqual(cdb.num_channels, 1) cdb.add_channel_announcement( { 'node_id_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'short_channel_id': bfh('0000000000000002'), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'short_channel_id': bfh('0000000000000003'), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'len': b'\x00\x00', 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02cccccccccccccccccccccccccccccccc', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_1': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd', 'short_channel_id': bfh('0000000000000004'), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'len': b'\x00\x00', 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02dddddddddddddddddddddddddddddddd', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'bitcoin_key_1': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'short_channel_id': bfh('0000000000000005'), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'len': b'\x00\x00', 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd', 'short_channel_id': bfh('0000000000000006'), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'len': b'\x00\x00', 'features': b'' }, trusted=True) o = lambda i: i.to_bytes(8, "big") cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(99), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(999), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(99999999), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': o(10), 'htlc_minimum_msat': o(250), 'fee_base_msat': o(100), 'fee_proportional_millionths': o(150), 'chain_hash': QtumTestnet.rev_genesis_bytes(), 'timestamp': b'\x00\x00\x00\x00' }) path = path_finder.find_path_for_payment( b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 100000) self.assertEqual([ PathEdge(node_id=b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', short_channel_id=bfh('0000000000000003')), PathEdge(node_id=b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', short_channel_id=bfh('0000000000000002')), ], path) start_node = b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' route = path_finder.create_route_from_path(path, start_node) self.assertEqual(b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', route[0].node_id) self.assertEqual(bfh('0000000000000003'), route[0].short_channel_id) # need to duplicate tear_down here, as we also need to wait for the sql thread to stop self.asyncio_loop.call_soon_threadsafe(self._stop_loop.set_result, 1) self._loop_thread.join(timeout=1) cdb.sql_thread.join(timeout=1)
def test_find_path_for_payment(self): class fake_network: config = self.config asyncio_loop = asyncio.get_event_loop() trigger_callback = lambda *args: None register_callback = lambda *args: None interface = None fake_network.channel_db = lnrouter.ChannelDB(fake_network()) fake_network.channel_db.data_loaded.set() cdb = fake_network.channel_db path_finder = lnrouter.LNPathFinder(cdb) self.assertEqual(cdb.num_channels, 0) cdb.add_channel_announcement( { 'node_id_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'node_id_2': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02cccccccccccccccccccccccccccccccc', 'short_channel_id': bfh('0000000000000001'), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) self.assertEqual(cdb.num_channels, 1) cdb.add_channel_announcement( { 'node_id_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'bitcoin_key_1': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'short_channel_id': bfh('0000000000000002'), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'short_channel_id': bfh('0000000000000003'), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02cccccccccccccccccccccccccccccccc', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_1': b'\x02cccccccccccccccccccccccccccccccc', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd', 'short_channel_id': bfh('0000000000000004'), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02dddddddddddddddddddddddddddddddd', 'node_id_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'bitcoin_key_1': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_2': b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'short_channel_id': bfh('0000000000000005'), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) cdb.add_channel_announcement( { 'node_id_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'node_id_2': b'\x02dddddddddddddddddddddddddddddddd', 'bitcoin_key_1': b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bitcoin_key_2': b'\x02dddddddddddddddddddddddddddddddd', 'short_channel_id': bfh('0000000000000006'), 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'len': 0, 'features': b'' }, trusted=True) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000001'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 99, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000002'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000003'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000004'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000005'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 999, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x00', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 99999999, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) cdb.add_channel_update({ 'short_channel_id': bfh('0000000000000006'), 'message_flags': b'\x00', 'channel_flags': b'\x01', 'cltv_expiry_delta': 10, 'htlc_minimum_msat': 250, 'fee_base_msat': 100, 'fee_proportional_millionths': 150, 'chain_hash': BitcoinTestnet.rev_genesis_bytes(), 'timestamp': 0 }) path = path_finder.find_path_for_payment( nodeA=b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nodeB=b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', invoice_amount_msat=100000) self.assertEqual([ PathEdge(start_node=b'\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', end_node=b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', short_channel_id=bfh('0000000000000003')), PathEdge(start_node=b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', end_node=b'\x02eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', short_channel_id=bfh('0000000000000002')), ], path) route = path_finder.create_route_from_path(path) self.assertEqual(b'\x02bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', route[0].node_id) self.assertEqual(bfh('0000000000000003'), route[0].short_channel_id) cdb.stop() asyncio.run_coroutine_threadsafe(cdb.stopped_event.wait(), self.asyncio_loop).result()