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