@@ -20,7 +20,7 @@ use crate::ln::msgs;
20
20
use crate :: ln:: msgs:: ChannelMessageHandler ;
21
21
use crate :: ln:: onion_utils;
22
22
use crate :: ln:: onion_utils:: INVALID_ONION_BLINDING ;
23
- use crate :: ln:: outbound_payment:: Retry ;
23
+ use crate :: ln:: outbound_payment:: { Retry , IDEMPOTENCY_TIMEOUT_TICKS } ;
24
24
use crate :: offers:: invoice:: BlindedPayInfo ;
25
25
use crate :: prelude:: * ;
26
26
use crate :: routing:: router:: { Payee , PaymentParameters , RouteParameters } ;
@@ -1062,3 +1062,73 @@ fn blinded_path_retries() {
1062
1062
_ => panic ! ( )
1063
1063
}
1064
1064
}
1065
+
1066
+ #[ test]
1067
+ fn min_htlc ( ) {
1068
+ // The min htlc of a blinded path is the max (htlc_min - following_fees) along the path. Make sure
1069
+ // the payment succeeds when we calculate the min htlc this way.
1070
+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
1071
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
1072
+ let mut node_1_cfg = test_default_channel_config ( ) ;
1073
+ node_1_cfg. channel_handshake_config . our_htlc_minimum_msat = 2000 ;
1074
+ node_1_cfg. channel_config . forwarding_fee_base_msat = 1000 ;
1075
+ node_1_cfg. channel_config . forwarding_fee_proportional_millionths = 100_000 ;
1076
+ let mut node_2_cfg = test_default_channel_config ( ) ;
1077
+ node_2_cfg. channel_handshake_config . our_htlc_minimum_msat = 5000 ;
1078
+ node_2_cfg. channel_config . forwarding_fee_base_msat = 200 ;
1079
+ node_2_cfg. channel_config . forwarding_fee_proportional_millionths = 150_000 ;
1080
+ let mut node_3_cfg = test_default_channel_config ( ) ;
1081
+ node_3_cfg. channel_handshake_config . our_htlc_minimum_msat = 2000 ;
1082
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , Some ( node_1_cfg) , Some ( node_2_cfg) , Some ( node_3_cfg) ] ) ;
1083
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
1084
+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
1085
+ let chan_1_2 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) ;
1086
+ let chan_2_3 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 1_000_000 , 0 ) ;
1087
+
1088
+ let min_htlc_msat = {
1089
+ // The min htlc for this setup is nodes[2]'s htlc_minimum_msat minus the
1090
+ // following fees.
1091
+ let post_base_fee = chan_2_3. 1 . contents . htlc_minimum_msat - chan_2_3. 0 . contents . fee_base_msat as u64 ;
1092
+ let prop_fee = chan_2_3. 0 . contents . fee_proportional_millionths as u64 ;
1093
+ ( post_base_fee * 1_000_000 + 1_000_000 + prop_fee - 1 ) / ( prop_fee + 1_000_000 )
1094
+ } ;
1095
+ let ( payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash ( & nodes[ 3 ] , Some ( min_htlc_msat) , None ) ;
1096
+ let mut route_params = get_blinded_route_parameters (
1097
+ min_htlc_msat, payment_secret, chan_1_2. 1 . contents . htlc_minimum_msat ,
1098
+ chan_1_2. 1 . contents . htlc_maximum_msat , vec ! [ nodes[ 1 ] . node. get_our_node_id( ) ,
1099
+ nodes[ 2 ] . node. get_our_node_id( ) , nodes[ 3 ] . node. get_our_node_id( ) ] ,
1100
+ & [ & chan_1_2. 0 . contents , & chan_2_3. 0 . contents ] , & chanmon_cfgs[ 3 ] . keys_manager ) ;
1101
+ assert_eq ! ( min_htlc_msat,
1102
+ route_params. payment_params. payee. blinded_route_hints( ) [ 0 ] . 0 . htlc_minimum_msat) ;
1103
+
1104
+ nodes[ 0 ] . node . send_payment ( payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) , route_params. clone ( ) , Retry :: Attempts ( 0 ) ) . unwrap ( ) ;
1105
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
1106
+ pass_along_route ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ] ] , min_htlc_msat, payment_hash, payment_secret) ;
1107
+ claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ] , payment_preimage) ;
1108
+
1109
+ // Paying 1 less than the min fails.
1110
+ for _ in 0 ..IDEMPOTENCY_TIMEOUT_TICKS + 1 {
1111
+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
1112
+ }
1113
+ if let Payee :: Blinded { ref mut route_hints, .. } = route_params. payment_params . payee {
1114
+ route_hints[ 0 ] . 0 . htlc_minimum_msat -= 1 ;
1115
+ } else { panic ! ( ) }
1116
+ route_params. final_value_msat -= 1 ;
1117
+ nodes[ 0 ] . node . send_payment ( payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 0 ) ) . unwrap ( ) ;
1118
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
1119
+
1120
+ let mut payment_event_0_1 = {
1121
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
1122
+ assert_eq ! ( events. len( ) , 1 ) ;
1123
+ let ev = remove_first_msg_event_to_node ( & nodes[ 1 ] . node . get_our_node_id ( ) , & mut events) ;
1124
+ SendEvent :: from_event ( ev)
1125
+ } ;
1126
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event_0_1. msgs [ 0 ] ) ;
1127
+ check_added_monitors ! ( nodes[ 1 ] , 0 ) ;
1128
+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 0 ] , & payment_event_0_1. commitment_msg , true , true ) ;
1129
+ let mut updates = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
1130
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & updates. update_fail_htlcs [ 0 ] ) ;
1131
+ do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 1 ] , & updates. commitment_signed , false , false ) ;
1132
+ expect_payment_failed_conditions ( & nodes[ 0 ] , payment_hash, false ,
1133
+ PaymentFailedConditions :: new ( ) . expected_htlc_error_data ( INVALID_ONION_BLINDING , & [ 0 ; 32 ] ) ) ;
1134
+ }
0 commit comments