|
3 | 3 | //! [`BlindedPath`]: crate::blinded_path::BlindedPath
|
4 | 4 |
|
5 | 5 | use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
|
6 |
| -use core::convert::TryFrom; |
7 | 6 | use crate::blinded_path::BlindedHop;
|
8 | 7 | use crate::blinded_path::utils;
|
9 | 8 | use crate::io;
|
@@ -165,21 +164,30 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
|
165 | 164 | pub(super) fn compute_payinfo(
|
166 | 165 | path: &[(PublicKey, BlindedPaymentTlvs)]
|
167 | 166 | ) -> Result<BlindedPayInfo, ()> {
|
168 |
| - let mut curr_base_fee: u128 = 0; |
169 |
| - let mut curr_prop_mil: u128 = 0; |
| 167 | + let mut curr_base_fee: u32 = 0; |
| 168 | + let mut curr_prop_mil: u32 = 0; |
170 | 169 | for (_, payment_tlvs) in path.iter().rev().skip(1) {
|
171 |
| - let next_base_fee = payment_tlvs.fee_base_msat() as u128; |
172 |
| - let next_prop_mil = payment_tlvs.fee_proportional_millionths() as u128; |
173 |
| - curr_base_fee = |
174 |
| - ((next_base_fee * 1_000_000 + (curr_base_fee * (1_000_000 + next_prop_mil))) + 1_000_000 - 1) |
175 |
| - / 1_000_000; |
176 |
| - curr_prop_mil = |
177 |
| - (((curr_prop_mil + next_prop_mil) * 1_000_000 + curr_prop_mil * next_prop_mil) + 1_000_000 - 1) |
178 |
| - / 1_000_000; |
| 170 | + let next_base_fee = payment_tlvs.fee_base_msat(); |
| 171 | + let next_prop_mil = payment_tlvs.fee_proportional_millionths(); |
| 172 | + // Use integer arithmetic to compute `ceil(a/b)` as `(a+b-1)/b` |
| 173 | + // ((next_base_fee * 1_000_000 + (curr_base_fee * (1_000_000 + next_prop_mil))) + 1_000_000 - 1) / 1_000_000 |
| 174 | + curr_base_fee = next_prop_mil.checked_add(1_000_000) |
| 175 | + .and_then(|f| f.checked_mul(curr_base_fee)) |
| 176 | + .and_then(|f| next_base_fee.checked_mul(1_000_000).and_then(|base| base.checked_add(f))) |
| 177 | + .and_then(|f| f.checked_add(1_000_000 - 1)) |
| 178 | + .map(|f| f / 1_000_000) |
| 179 | + .ok_or(())?; |
| 180 | + // (((curr_prop_mil + next_prop_mil) * 1_000_000 + curr_prop_mil * next_prop_mil) + 1_000_000 - 1) / 1_000_000 |
| 181 | + curr_prop_mil = curr_prop_mil.checked_add(next_prop_mil) |
| 182 | + .and_then(|f| f.checked_mul(1_000_000)) |
| 183 | + .and_then(|f| curr_prop_mil.checked_mul(next_prop_mil).and_then(|prop_mil| prop_mil.checked_add(f))) |
| 184 | + .and_then(|f| f.checked_add(1_000_000 - 1)) |
| 185 | + .map(|f| f / 1_000_000) |
| 186 | + .ok_or(())?; |
179 | 187 | }
|
180 | 188 | Ok(BlindedPayInfo {
|
181 |
| - fee_base_msat: u32::try_from(curr_base_fee).map_err(|_| ())?, |
182 |
| - fee_proportional_millionths: u32::try_from(curr_prop_mil).map_err(|_| ())?, |
| 189 | + fee_base_msat: curr_base_fee, |
| 190 | + fee_proportional_millionths: curr_prop_mil, |
183 | 191 | cltv_expiry_delta: path.iter().map(|(_, tlvs)| tlvs.cltv_expiry_delta())
|
184 | 192 | .try_fold(0u16, |acc, delta| acc.checked_add(delta)).ok_or(())?,
|
185 | 193 | htlc_minimum_msat: path.iter().map(|(_, tlvs)| tlvs.htlc_minimum_msat()).max().unwrap_or(0),
|
|
0 commit comments