@@ -1561,6 +1561,133 @@ fn do_test_intercepted_payment(test: InterceptTest) {
1561
1561
}
1562
1562
}
1563
1563
1564
+ #[ test]
1565
+ fn accept_underpaying_htlcs_config ( ) {
1566
+ do_accept_underpaying_htlcs_config ( 1 ) ;
1567
+ do_accept_underpaying_htlcs_config ( 2 ) ;
1568
+ do_accept_underpaying_htlcs_config ( 3 ) ;
1569
+ }
1570
+
1571
+ fn do_accept_underpaying_htlcs_config ( num_mpp_parts : usize ) {
1572
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
1573
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
1574
+ let mut intercept_forwards_config = test_default_channel_config ( ) ;
1575
+ intercept_forwards_config. accept_intercept_htlcs = true ;
1576
+ let mut underpay_config = test_default_channel_config ( ) ;
1577
+ underpay_config. channel_config . accept_underpaying_htlcs = true ;
1578
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , Some ( intercept_forwards_config) , Some ( underpay_config) ] ) ;
1579
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
1580
+
1581
+ let mut chan_ids = Vec :: new ( ) ;
1582
+ for _ in 0 ..num_mpp_parts {
1583
+ let _ = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000 , 0 ) ;
1584
+ let channel_id = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 2_000_000 , 0 ) . 0 . channel_id ;
1585
+ chan_ids. push ( channel_id) ;
1586
+ }
1587
+
1588
+ // Send the initial payment.
1589
+ let amt_msat = 900_000 ;
1590
+ let skimmed_fee_msat = 20 ;
1591
+ let mut route_hints = Vec :: new ( ) ;
1592
+ for _ in 0 ..num_mpp_parts {
1593
+ route_hints. push ( RouteHint ( vec ! [ RouteHintHop {
1594
+ src_node_id: nodes[ 1 ] . node. get_our_node_id( ) ,
1595
+ short_channel_id: nodes[ 1 ] . node. get_intercept_scid( ) ,
1596
+ fees: RoutingFees {
1597
+ base_msat: 1000 ,
1598
+ proportional_millionths: 0 ,
1599
+ } ,
1600
+ cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA ,
1601
+ htlc_minimum_msat: None ,
1602
+ htlc_maximum_msat: Some ( amt_msat / num_mpp_parts as u64 + 5 ) ,
1603
+ } ] ) ) ;
1604
+ }
1605
+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 2 ] . node . get_our_node_id ( ) , TEST_FINAL_CLTV )
1606
+ . with_route_hints ( route_hints) . unwrap ( )
1607
+ . with_bolt11_features ( nodes[ 2 ] . node . invoice_features ( ) ) . unwrap ( ) ;
1608
+ let route_params = RouteParameters {
1609
+ payment_params,
1610
+ final_value_msat : amt_msat,
1611
+ } ;
1612
+ let ( payment_hash, payment_secret) = nodes[ 2 ] . node . create_inbound_payment ( Some ( amt_msat) , 60 * 60 , None ) . unwrap ( ) ;
1613
+ nodes[ 0 ] . node . send_payment ( payment_hash, RecipientOnionFields :: secret_only ( payment_secret) ,
1614
+ PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 0 ) ) . unwrap ( ) ;
1615
+ check_added_monitors ! ( nodes[ 0 ] , num_mpp_parts) ; // one monitor per path
1616
+ let mut events: Vec < SendEvent > = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) . into_iter ( ) . map ( |e| SendEvent :: from_event ( e) ) . collect ( ) ;
1617
+ assert_eq ! ( events. len( ) , num_mpp_parts) ;
1618
+
1619
+ // Forward the intercepted payments.
1620
+ for ( idx, ev) in events. into_iter ( ) . enumerate ( ) {
1621
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & ev. msgs [ 0 ] ) ;
1622
+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 0 ] , & ev. commitment_msg , false , true ) ;
1623
+
1624
+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
1625
+ assert_eq ! ( events. len( ) , 1 ) ;
1626
+ let ( intercept_id, expected_outbound_amt_msat) = match events[ 0 ] {
1627
+ crate :: events:: Event :: HTLCIntercepted {
1628
+ intercept_id, expected_outbound_amount_msat, payment_hash : pmt_hash, ..
1629
+ } => {
1630
+ assert_eq ! ( pmt_hash, payment_hash) ;
1631
+ ( intercept_id, expected_outbound_amount_msat)
1632
+ } ,
1633
+ _ => panic ! ( )
1634
+ } ;
1635
+ nodes[ 1 ] . node . forward_intercepted_htlc ( intercept_id, & chan_ids[ idx] ,
1636
+ nodes[ 2 ] . node . get_our_node_id ( ) , expected_outbound_amt_msat - skimmed_fee_msat) . unwrap ( ) ;
1637
+ expect_pending_htlcs_forwardable ! ( nodes[ 1 ] ) ;
1638
+ let payment_event = {
1639
+ {
1640
+ let mut added_monitors = nodes[ 1 ] . chain_monitor . added_monitors . lock ( ) . unwrap ( ) ;
1641
+ assert_eq ! ( added_monitors. len( ) , 1 ) ;
1642
+ added_monitors. clear ( ) ;
1643
+ }
1644
+ let mut events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1645
+ assert_eq ! ( events. len( ) , 1 ) ;
1646
+ SendEvent :: from_event ( events. remove ( 0 ) )
1647
+ } ;
1648
+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
1649
+ do_commitment_signed_dance ( & nodes[ 2 ] , & nodes[ 1 ] , & payment_event. commitment_msg , false , true ) ;
1650
+ if idx == num_mpp_parts - 1 {
1651
+ expect_pending_htlcs_forwardable ! ( nodes[ 2 ] ) ;
1652
+ }
1653
+ }
1654
+
1655
+ // Claim the payment and check that the skimmed fee is as expected.
1656
+ let payment_preimage = nodes[ 2 ] . node . get_payment_preimage ( payment_hash, payment_secret) . unwrap ( ) ;
1657
+ let events = nodes[ 2 ] . node . get_and_clear_pending_events ( ) ;
1658
+ assert_eq ! ( events. len( ) , 1 ) ;
1659
+ match events[ 0 ] {
1660
+ crate :: events:: Event :: PaymentClaimable {
1661
+ ref payment_hash, ref purpose, amount_msat, counterparty_skimmed_fee_msat, receiver_node_id, ..
1662
+ } => {
1663
+ assert_eq ! ( payment_hash, payment_hash) ;
1664
+ assert_eq ! ( amt_msat - skimmed_fee_msat * num_mpp_parts as u64 , amount_msat) ;
1665
+ assert_eq ! ( skimmed_fee_msat * num_mpp_parts as u64 , counterparty_skimmed_fee_msat) ;
1666
+ assert_eq ! ( nodes[ 2 ] . node. get_our_node_id( ) , receiver_node_id. unwrap( ) ) ;
1667
+ match purpose {
1668
+ crate :: events:: PaymentPurpose :: InvoicePayment { payment_preimage : ev_payment_preimage,
1669
+ payment_secret : ev_payment_secret, .. } =>
1670
+ {
1671
+ assert_eq ! ( payment_preimage, ev_payment_preimage. unwrap( ) ) ;
1672
+ assert_eq ! ( payment_secret, * ev_payment_secret) ;
1673
+ } ,
1674
+ _ => panic ! ( ) ,
1675
+ }
1676
+ } ,
1677
+ _ => panic ! ( "Unexpected event" ) ,
1678
+ }
1679
+ let mut expected_paths_vecs = Vec :: new ( ) ;
1680
+ let mut expected_paths = Vec :: new ( ) ;
1681
+ for _ in 0 ..num_mpp_parts { expected_paths_vecs. push ( vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) ) ; }
1682
+ for i in 0 ..num_mpp_parts { expected_paths. push ( & expected_paths_vecs[ i] [ ..] ) ; }
1683
+ let total_fee_msat = do_claim_payment_along_route_with_extra_penultimate_hop_fees (
1684
+ & nodes[ 0 ] , & expected_paths[ ..] , & vec ! [ skimmed_fee_msat as u32 ; num_mpp_parts] [ ..] , false ,
1685
+ payment_preimage) ;
1686
+ // The sender doesn't know that the penultimate hop took an extra fee.
1687
+ expect_payment_sent ( & nodes[ 0 ] , payment_preimage,
1688
+ Some ( Some ( total_fee_msat - skimmed_fee_msat * num_mpp_parts as u64 ) ) , true ) ;
1689
+ }
1690
+
1564
1691
#[ derive( PartialEq ) ]
1565
1692
enum AutoRetry {
1566
1693
Success ,
0 commit comments