@@ -153,6 +153,29 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
153153 utils:: construct_blinded_hops ( secp_ctx, pks, tlvs, session_priv)
154154}
155155
156+ /// `None` if underflow or overflow occurs.
157+ fn amt_to_forward_msat ( inbound_amt_msat : u64 , payment_relay : & PaymentRelay ) -> Option < u64 > {
158+ let amt_to_fwd_numerator = inbound_amt_msat. checked_sub ( payment_relay. fee_base_msat as u64 )
159+ . and_then ( |a| a. checked_mul ( 1_000_000 ) )
160+ . and_then ( |a| a. checked_add ( 1_000_000 - 1 ) )
161+ . and_then ( |a| a. checked_add ( payment_relay. fee_proportional_millionths as u64 ) ) ;
162+ let amt_to_fwd_denominator = payment_relay. fee_proportional_millionths . checked_add ( 1_000_000 ) ;
163+ let mut amt_to_forward = match ( amt_to_fwd_numerator, amt_to_fwd_denominator) {
164+ ( Some ( num) , Some ( denom) ) => num / denom as u64 ,
165+ _ => return None ,
166+ } ;
167+ let fee_opt = amt_to_forward. checked_mul ( payment_relay. fee_proportional_millionths as u64 )
168+ . and_then ( |prop| ( prop / 1000000 ) . checked_add ( payment_relay. fee_base_msat as u64 ) ) ;
169+ let fee = if let Some ( f) = fee_opt { f } else { return None } ;
170+ if inbound_amt_msat - fee < amt_to_forward {
171+ // Rounding up the forwarded amount resulted in underpaying this node, so take an extra 1 msat
172+ // in fee to compensate.
173+ amt_to_forward -= 1 ;
174+ }
175+ debug_assert_eq ! ( amt_to_forward + fee, inbound_amt_msat) ;
176+ Some ( amt_to_forward)
177+ }
178+
156179pub ( super ) fn compute_payinfo (
157180 intermediate_nodes : & [ ( PublicKey , ForwardTlvs ) ] , payee_tlvs : & ReceiveTlvs
158181) -> Result < BlindedPayInfo , ( ) > {
@@ -185,28 +208,22 @@ pub(super) fn compute_payinfo(
185208 cltv_expiry_delta = cltv_expiry_delta. checked_add ( tlvs. payment_relay . cltv_expiry_delta ) . ok_or ( ( ) ) ?;
186209 }
187210
188- let mut htlc_minimum_msat = intermediate_nodes. first ( )
189- . map_or ( 0 , |( _, tlvs) | tlvs. payment_constraints . htlc_minimum_msat ) as u128 ;
190- for ( _, tlvs) in intermediate_nodes. iter ( ) . skip ( 1 ) {
191- let prop_fee = tlvs. payment_relay . fee_proportional_millionths as u128 ;
192- let base_fee = tlvs. payment_relay . fee_base_msat as u128 ;
193- let hop_fee = htlc_minimum_msat
194- . checked_mul ( prop_fee)
195- . and_then ( |prop_fee| ( prop_fee / 1_000_000 ) . checked_add ( base_fee) )
196- . ok_or ( ( ) ) ?;
197- htlc_minimum_msat = core:: cmp:: max (
198- htlc_minimum_msat. saturating_sub ( hop_fee) , tlvs. payment_constraints . htlc_minimum_msat as u128
199- ) ;
211+ let mut htlc_minimum_msat: u64 = 1 ;
212+ for ( _, tlvs) in intermediate_nodes. iter ( ) {
213+ htlc_minimum_msat = amt_to_forward_msat (
214+ core:: cmp:: max ( tlvs. payment_constraints . htlc_minimum_msat , htlc_minimum_msat) ,
215+ & tlvs. payment_relay
216+ ) . unwrap_or ( 1 ) ;
200217 }
201218 htlc_minimum_msat = core:: cmp:: max (
202- payee_tlvs. payment_constraints . htlc_minimum_msat as u128 , htlc_minimum_msat
219+ payee_tlvs. payment_constraints . htlc_minimum_msat , htlc_minimum_msat
203220 ) ;
204221
205222 Ok ( BlindedPayInfo {
206223 fee_base_msat : u32:: try_from ( curr_base_fee) . map_err ( |_| ( ) ) ?,
207224 fee_proportional_millionths : u32:: try_from ( curr_prop_mil) . map_err ( |_| ( ) ) ?,
208225 cltv_expiry_delta,
209- htlc_minimum_msat : u64 :: try_from ( htlc_minimum_msat ) . map_err ( |_| ( ) ) ? ,
226+ htlc_minimum_msat,
210227 htlc_maximum_msat : 21_000_000 * 100_000_000 * 1_000 , // TODO
211228 features : BlindedHopFeatures :: empty ( ) ,
212229 } )
@@ -271,7 +288,7 @@ mod tests {
271288 assert_eq ! ( blinded_payinfo. fee_base_msat, 201 ) ;
272289 assert_eq ! ( blinded_payinfo. fee_proportional_millionths, 1001 ) ;
273290 assert_eq ! ( blinded_payinfo. cltv_expiry_delta, 288 ) ;
274- assert_eq ! ( blinded_payinfo. htlc_minimum_msat, 1000 ) ;
291+ assert_eq ! ( blinded_payinfo. htlc_minimum_msat, 900 ) ;
275292 }
276293
277294 #[ test]
@@ -368,7 +385,8 @@ mod tests {
368385 htlc_minimum_msat : 1 ,
369386 } ,
370387 } ;
388+ let htlc_minimum_msat = 3798 ;
371389 let blinded_payinfo = super :: compute_payinfo ( & intermediate_nodes[ ..] , & recv_tlvs) . unwrap ( ) ;
372- assert_eq ! ( blinded_payinfo. htlc_minimum_msat, 4798 ) ;
390+ assert_eq ! ( blinded_payinfo. htlc_minimum_msat, htlc_minimum_msat ) ;
373391 }
374392}
0 commit comments