@@ -153,6 +153,29 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
153
153
utils:: construct_blinded_hops ( secp_ctx, pks, tlvs, session_priv)
154
154
}
155
155
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
+
156
179
pub ( super ) fn compute_payinfo (
157
180
intermediate_nodes : & [ ( PublicKey , ForwardTlvs ) ] , payee_tlvs : & ReceiveTlvs
158
181
) -> Result < BlindedPayInfo , ( ) > {
@@ -185,28 +208,22 @@ pub(super) fn compute_payinfo(
185
208
cltv_expiry_delta = cltv_expiry_delta. checked_add ( tlvs. payment_relay . cltv_expiry_delta ) . ok_or ( ( ) ) ?;
186
209
}
187
210
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 ) ;
200
217
}
201
218
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
203
220
) ;
204
221
205
222
Ok ( BlindedPayInfo {
206
223
fee_base_msat : u32:: try_from ( curr_base_fee) . map_err ( |_| ( ) ) ?,
207
224
fee_proportional_millionths : u32:: try_from ( curr_prop_mil) . map_err ( |_| ( ) ) ?,
208
225
cltv_expiry_delta,
209
- htlc_minimum_msat : u64 :: try_from ( htlc_minimum_msat ) . map_err ( |_| ( ) ) ? ,
226
+ htlc_minimum_msat,
210
227
htlc_maximum_msat : 21_000_000 * 100_000_000 * 1_000 , // TODO
211
228
features : BlindedHopFeatures :: empty ( ) ,
212
229
} )
@@ -271,7 +288,7 @@ mod tests {
271
288
assert_eq ! ( blinded_payinfo. fee_base_msat, 201 ) ;
272
289
assert_eq ! ( blinded_payinfo. fee_proportional_millionths, 1001 ) ;
273
290
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 ) ;
275
292
}
276
293
277
294
#[ test]
@@ -368,7 +385,8 @@ mod tests {
368
385
htlc_minimum_msat : 1 ,
369
386
} ,
370
387
} ;
388
+ let htlc_minimum_msat = 3798 ;
371
389
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 ) ;
373
391
}
374
392
}
0 commit comments