@@ -1046,6 +1046,9 @@ mod tests {
1046
1046
use bitcoin:: secp256k1:: PublicKey ;
1047
1047
use lightning:: routing:: router:: Route ;
1048
1048
use mockall:: mock;
1049
+ use std:: time:: Duration ;
1050
+ use tokio:: sync:: oneshot;
1051
+ use tokio:: time:: timeout;
1049
1052
1050
1053
/// Creates a test channel policy with its maximum HTLC size set to half of the in flight limit of the channel.
1051
1054
/// The minimum HTLC size is hardcoded to 2 so that we can fall beneath this value with a 1 msat htlc.
@@ -1506,4 +1509,268 @@ mod tests {
1506
1509
PaymentOutcome :: InsufficientBalance
1507
1510
) ) ;
1508
1511
}
1512
+
1513
+ /// Contains elements required to test dispatch_payment functionality.
1514
+ struct DispatchPaymentTestKit < ' a > {
1515
+ graph : SimGraph ,
1516
+ nodes : Vec < PublicKey > ,
1517
+ routing_graph : NetworkGraph < & ' a WrappedLog > ,
1518
+ shutdown : triggered:: Trigger ,
1519
+ }
1520
+
1521
+ impl < ' a > DispatchPaymentTestKit < ' a > {
1522
+ /// Creates a test graph with a set of nodes connected by three channels, with all the capacity of the channel
1523
+ /// on the side of the first node. For example, if called with capacity = 100 it will set up the following
1524
+ /// network:
1525
+ /// Alice (100) --- (0) Bob (100) --- (0) Carol (100) --- (0) Dave
1526
+ ///
1527
+ /// The nodes pubkeys in this chain of channels are provided in-order for easy access.
1528
+ async fn new ( capacity : u64 ) -> Self {
1529
+ let ( shutdown, _listener) = triggered:: trigger ( ) ;
1530
+ let channels = create_simulated_channels ( 3 , capacity) ;
1531
+
1532
+ // Collect pubkeys in-order, pushing the last node on separately because they don't have an outgoing
1533
+ // channel (they are not node_1 in any channel, only node_2).
1534
+ let mut nodes = channels
1535
+ . iter ( )
1536
+ . map ( |c| c. node_1 . policy . pubkey )
1537
+ . collect :: < Vec < PublicKey > > ( ) ;
1538
+ nodes. push ( channels. last ( ) . unwrap ( ) . node_2 . policy . pubkey ) ;
1539
+
1540
+ let kit = DispatchPaymentTestKit {
1541
+ graph : SimGraph :: new ( channels. clone ( ) , shutdown. clone ( ) )
1542
+ . expect ( "could not create test graph" ) ,
1543
+ nodes,
1544
+ routing_graph : populate_network_graph ( channels) . unwrap ( ) ,
1545
+ shutdown,
1546
+ } ;
1547
+
1548
+ // Assert that our channel balance is all on the side of the channel opener when we start up.
1549
+ assert_eq ! (
1550
+ kit. channel_balances( ) . await ,
1551
+ vec![ ( capacity, 0 ) , ( capacity, 0 ) , ( capacity, 0 ) ]
1552
+ ) ;
1553
+
1554
+ kit
1555
+ }
1556
+
1557
+ /// Returns a vector of local/remote channel balances for channels in the network.
1558
+ async fn channel_balances ( & self ) -> Vec < ( u64 , u64 ) > {
1559
+ let mut balances = vec ! [ ] ;
1560
+
1561
+ // We can't iterate through our hashmap of channels in-order, so we take advantage of our short channel id
1562
+ // being the index in our chain of channels. This allows us to look up channels in-order.
1563
+ let chan_count = self . graph . channels . lock ( ) . await . len ( ) ;
1564
+
1565
+ for i in 0 ..chan_count {
1566
+ let chan_lock = self . graph . channels . lock ( ) . await ;
1567
+ let channel = chan_lock. get ( & ShortChannelID :: from ( i as u64 ) ) . unwrap ( ) ;
1568
+
1569
+ // Take advantage of our test setup, which always makes node_1 the channel initiator to get our
1570
+ // "in order" balances for the chain of channels.
1571
+ balances. push ( (
1572
+ channel. node_1 . local_balance_msat ,
1573
+ channel. node_2 . local_balance_msat ,
1574
+ ) ) ;
1575
+ }
1576
+
1577
+ balances
1578
+ }
1579
+
1580
+ // Sends a test payment from source to destination and waits for the payment to complete, returning the route
1581
+ // used.
1582
+ async fn send_test_payemnt (
1583
+ & mut self ,
1584
+ source : PublicKey ,
1585
+ dest : PublicKey ,
1586
+ amt : u64 ,
1587
+ ) -> Route {
1588
+ let route = find_payment_route ( & source, dest, amt, & self . routing_graph ) . unwrap ( ) ;
1589
+
1590
+ let ( sender, receiver) = oneshot:: channel ( ) ;
1591
+ self . graph
1592
+ . dispatch_payment ( source, route. clone ( ) , PaymentHash { 0 : [ 1 ; 32 ] } , sender) ;
1593
+
1594
+ // Assert that we receive from the channel or fail.
1595
+ assert ! ( timeout( Duration :: from_millis( 10 ) , receiver) . await . is_ok( ) ) ;
1596
+
1597
+ route
1598
+ }
1599
+
1600
+ // Sets the balance on the channel to the tuple provided, used to arrange liquidity for testing.
1601
+ async fn set_channel_balance ( & mut self , scid : & ShortChannelID , balance : ( u64 , u64 ) ) {
1602
+ let mut channels_lock = self . graph . channels . lock ( ) . await ;
1603
+ let channel = channels_lock. get_mut ( scid) . unwrap ( ) ;
1604
+
1605
+ channel. node_1 . local_balance_msat = balance. 0 ;
1606
+ channel. node_2 . local_balance_msat = balance. 1 ;
1607
+
1608
+ assert ! ( channel. sanity_check( ) . is_ok( ) ) ;
1609
+ }
1610
+ }
1611
+
1612
+ /// Tests dispatch of a successfully settled payment across a test network of simulated channels:
1613
+ /// Alice --- Bob --- Carol --- Dave
1614
+ #[ tokio:: test]
1615
+ async fn test_successful_dispatch ( ) {
1616
+ let chan_capacity = 500_000_000 ;
1617
+ let mut test_kit = DispatchPaymentTestKit :: new ( chan_capacity) . await ;
1618
+
1619
+ // Send a payment that should succeed from Alice -> Dave.
1620
+ let mut amt = 20_000 ;
1621
+ let route = test_kit
1622
+ . send_test_payemnt ( test_kit. nodes [ 0 ] , test_kit. nodes [ 3 ] , amt)
1623
+ . await ;
1624
+
1625
+ let route_total = amt + route. get_total_fees ( ) ;
1626
+ let hop_1_amt = amt + route. paths [ 0 ] . hops [ 1 ] . fee_msat ;
1627
+
1628
+ // The sending node should have pushed the amount + total fee to the intermediary.
1629
+ let alice_to_bob = ( chan_capacity - route_total, route_total) ;
1630
+ // The middle hop should include fees for the outgoing link.
1631
+ let mut bob_to_carol = ( chan_capacity - hop_1_amt, hop_1_amt) ;
1632
+ // The receiving node should have the payment amount pushed to them.
1633
+ let carol_to_dave = ( chan_capacity - amt, amt) ;
1634
+
1635
+ let mut expected_balances = vec ! [ alice_to_bob, bob_to_carol, carol_to_dave] ;
1636
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1637
+
1638
+ // Next, we'll test the case where a payment fails on the first hop. This is an edge case in our state
1639
+ // machine, so we want to specifically hit it. To do this, we'll try to send double the amount that we just
1640
+ // pushed to Dave back to Bob, expecting a failure on Dave's outgoing link due to insufficient liquidity.
1641
+ let _ = test_kit
1642
+ . send_test_payemnt ( test_kit. nodes [ 3 ] , test_kit. nodes [ 1 ] , amt * 2 )
1643
+ . await ;
1644
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1645
+
1646
+ // Now, test a successful single-hop payment from Bob -> Carol. We'll do this twice, so that we can drain all
1647
+ // the liquidity on Bob's side (to prepare for a multi-hop failure test). Our pathfinding only allows us to
1648
+ // use 50% of the channel's capacity, so we need to do two payments.
1649
+ amt = bob_to_carol. 0 / 2 ;
1650
+ let _ = test_kit
1651
+ . send_test_payemnt ( test_kit. nodes [ 1 ] , test_kit. nodes [ 2 ] , amt)
1652
+ . await ;
1653
+
1654
+ bob_to_carol = ( bob_to_carol. 0 / 2 , bob_to_carol. 1 + amt) ;
1655
+ expected_balances = vec ! [ alice_to_bob, bob_to_carol, carol_to_dave] ;
1656
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1657
+
1658
+ // When we push this amount a second time, all the liquidity should be moved to Carol's end.
1659
+ let _ = test_kit
1660
+ . send_test_payemnt ( test_kit. nodes [ 1 ] , test_kit. nodes [ 2 ] , amt)
1661
+ . await ;
1662
+ bob_to_carol = ( 0 , chan_capacity) ;
1663
+ expected_balances = vec ! [ alice_to_bob, bob_to_carol, carol_to_dave] ;
1664
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1665
+
1666
+ // Finally, we'll test a multi-hop failure by trying to send from Alice -> Dave. Since Bob's liquidity is
1667
+ // drained, we expect a failure and unchanged balances along the route.
1668
+ let _ = test_kit
1669
+ . send_test_payemnt ( test_kit. nodes [ 0 ] , test_kit. nodes [ 3 ] , 20_000 )
1670
+ . await ;
1671
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1672
+
1673
+ test_kit. shutdown . trigger ( ) ;
1674
+ test_kit. graph . wait_for_shutdown ( ) . await ;
1675
+ }
1676
+
1677
+ /// Tests successful dispatch of a multi-hop payment.
1678
+ #[ tokio:: test]
1679
+ async fn test_successful_multi_hop ( ) {
1680
+ let chan_capacity = 500_000_000 ;
1681
+ let mut test_kit = DispatchPaymentTestKit :: new ( chan_capacity) . await ;
1682
+
1683
+ // Send a payment that should succeed from Alice -> Dave.
1684
+ let amt = 20_000 ;
1685
+ let route = test_kit
1686
+ . send_test_payemnt ( test_kit. nodes [ 0 ] , test_kit. nodes [ 3 ] , amt)
1687
+ . await ;
1688
+
1689
+ let route_total = amt + route. get_total_fees ( ) ;
1690
+ let hop_1_amt = amt + route. paths [ 0 ] . hops [ 1 ] . fee_msat ;
1691
+
1692
+ let expected_balances = vec ! [
1693
+ // The sending node should have pushed the amount + total fee to the intermediary.
1694
+ ( chan_capacity - route_total, route_total) ,
1695
+ // The middle hop should include fees for the outgoing link.
1696
+ ( chan_capacity - hop_1_amt, hop_1_amt) ,
1697
+ // The receiving node should have the payment amount pushed to them.
1698
+ ( chan_capacity - amt, amt) ,
1699
+ ] ;
1700
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1701
+
1702
+ test_kit. shutdown . trigger ( ) ;
1703
+ test_kit. graph . wait_for_shutdown ( ) . await ;
1704
+ }
1705
+
1706
+ /// Tests success and failure for single hop payments, which are an edge case in our state machine.
1707
+ #[ tokio:: test]
1708
+ async fn test_single_hop_payments ( ) {
1709
+ let chan_capacity = 500_000_000 ;
1710
+ let mut test_kit = DispatchPaymentTestKit :: new ( chan_capacity) . await ;
1711
+
1712
+ // Send a single hop payment from Alice -> Bob, it will succeed because Alice has all the liquidity.
1713
+ let amt = 150_000 ;
1714
+ let _ = test_kit
1715
+ . send_test_payemnt ( test_kit. nodes [ 0 ] , test_kit. nodes [ 1 ] , amt)
1716
+ . await ;
1717
+
1718
+ let expected_balances = vec ! [
1719
+ ( chan_capacity - amt, amt) ,
1720
+ ( chan_capacity, 0 ) ,
1721
+ ( chan_capacity, 0 ) ,
1722
+ ] ;
1723
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1724
+
1725
+ // Send a single hop payment from Dave -> Carol that will fail due to lack of liquidity, balances should be
1726
+ // unchanged.
1727
+ let _ = test_kit
1728
+ . send_test_payemnt ( test_kit. nodes [ 3 ] , test_kit. nodes [ 2 ] , amt)
1729
+ . await ;
1730
+
1731
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1732
+
1733
+ test_kit. shutdown . trigger ( ) ;
1734
+ test_kit. graph . wait_for_shutdown ( ) . await ;
1735
+ }
1736
+
1737
+ /// Tests failing back of multi-hop payments at various failure indexes.
1738
+ #[ tokio:: test]
1739
+ async fn test_multi_hop_faiulre ( ) {
1740
+ let chan_capacity = 500_000_000 ;
1741
+ let mut test_kit = DispatchPaymentTestKit :: new ( chan_capacity) . await ;
1742
+
1743
+ // Drain liquidity between Bob and Carol to force failures on Bob's outgoing linke.
1744
+ test_kit
1745
+ . set_channel_balance ( & ShortChannelID :: from ( 1 ) , ( 0 , chan_capacity) )
1746
+ . await ;
1747
+
1748
+ let mut expected_balances =
1749
+ vec ! [ ( chan_capacity, 0 ) , ( 0 , chan_capacity) , ( chan_capacity, 0 ) ] ;
1750
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1751
+
1752
+ // Send a payment from Alice -> Dave which we expect to fail leaving balances unaffected.
1753
+ let amt = 150_000 ;
1754
+ let _ = test_kit
1755
+ . send_test_payemnt ( test_kit. nodes [ 0 ] , test_kit. nodes [ 3 ] , amt)
1756
+ . await ;
1757
+
1758
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1759
+
1760
+ // Push liquidity to Dave so that we can send a payment which will fail on Bob's outgoing link, leaving
1761
+ // balances unaffected.
1762
+ expected_balances[ 2 ] = ( 0 , chan_capacity) ;
1763
+ test_kit
1764
+ . set_channel_balance ( & ShortChannelID :: from ( 2 ) , ( 0 , chan_capacity) )
1765
+ . await ;
1766
+
1767
+ let _ = test_kit
1768
+ . send_test_payemnt ( test_kit. nodes [ 3 ] , test_kit. nodes [ 0 ] , amt)
1769
+ . await ;
1770
+
1771
+ assert_eq ! ( test_kit. channel_balances( ) . await , expected_balances) ;
1772
+
1773
+ test_kit. shutdown . trigger ( ) ;
1774
+ test_kit. graph . wait_for_shutdown ( ) . await ;
1775
+ }
1509
1776
}
0 commit comments