|
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;
|
@@ -172,21 +171,30 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
|
172 | 171 | pub(super) fn compute_payinfo(
|
173 | 172 | path: &[(PublicKey, BlindedPaymentTlvs)]
|
174 | 173 | ) -> Result<BlindedPayInfo, ()> {
|
175 |
| - let mut curr_base_fee: u128 = 0; |
176 |
| - let mut curr_prop_mil: u128 = 0; |
| 174 | + let mut curr_base_fee: u32 = 0; |
| 175 | + let mut curr_prop_mil: u32 = 0; |
177 | 176 | for (_, payment_tlvs) in path.iter().rev().skip(1) {
|
178 |
| - let next_base_fee = payment_tlvs.fee_base_msat() as u128; |
179 |
| - let next_prop_mil = payment_tlvs.fee_proportional_millionths() as u128; |
180 |
| - curr_base_fee = |
181 |
| - ((next_base_fee * 1_000_000 + (curr_base_fee * (1_000_000 + next_prop_mil))) + 1_000_000 - 1) |
182 |
| - / 1_000_000; |
183 |
| - curr_prop_mil = |
184 |
| - (((curr_prop_mil + next_prop_mil) * 1_000_000 + curr_prop_mil * next_prop_mil) + 1_000_000 - 1) |
185 |
| - / 1_000_000; |
| 177 | + let next_base_fee = payment_tlvs.fee_base_msat(); |
| 178 | + let next_prop_mil = payment_tlvs.fee_proportional_millionths(); |
| 179 | + // Use integer arithmetic to compute `ceil(a/b)` as `(a+b-1)/b` |
| 180 | + // ((next_base_fee * 1_000_000 + (curr_base_fee * (1_000_000 + next_prop_mil))) + 1_000_000 - 1) / 1_000_000 |
| 181 | + curr_base_fee = next_prop_mil.checked_add(1_000_000) |
| 182 | + .and_then(|f| f.checked_mul(curr_base_fee)) |
| 183 | + .and_then(|f| next_base_fee.checked_mul(1_000_000).and_then(|base| base.checked_add(f))) |
| 184 | + .and_then(|f| f.checked_add(1_000_000 - 1)) |
| 185 | + .map(|f| f / 1_000_000) |
| 186 | + .ok_or(())?; |
| 187 | + // (((curr_prop_mil + next_prop_mil) * 1_000_000 + curr_prop_mil * next_prop_mil) + 1_000_000 - 1) / 1_000_000 |
| 188 | + curr_prop_mil = curr_prop_mil.checked_add(next_prop_mil) |
| 189 | + .and_then(|f| f.checked_mul(1_000_000)) |
| 190 | + .and_then(|f| curr_prop_mil.checked_mul(next_prop_mil).and_then(|prop_mil| prop_mil.checked_add(f))) |
| 191 | + .and_then(|f| f.checked_add(1_000_000 - 1)) |
| 192 | + .map(|f| f / 1_000_000) |
| 193 | + .ok_or(())?; |
186 | 194 | }
|
187 | 195 | Ok(BlindedPayInfo {
|
188 |
| - fee_base_msat: u32::try_from(curr_base_fee).map_err(|_| ())?, |
189 |
| - fee_proportional_millionths: u32::try_from(curr_prop_mil).map_err(|_| ())?, |
| 196 | + fee_base_msat: curr_base_fee, |
| 197 | + fee_proportional_millionths: curr_prop_mil, |
190 | 198 | cltv_expiry_delta: path.iter().map(|(_, tlvs)| tlvs.cltv_expiry_delta())
|
191 | 199 | .try_fold(0u16, |acc, delta| acc.checked_add(delta)).ok_or(())?,
|
192 | 200 | htlc_minimum_msat: path.iter().map(|(_, tlvs)| tlvs.htlc_minimum_msat()).max().unwrap_or(0),
|
|
0 commit comments