|
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