Skip to content

Commit 1f36f97

Browse files
f fix min htlc calc
1 parent e92c61c commit 1f36f97

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

lightning/src/blinded_path/payment.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
156179
pub(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

Comments
 (0)