fee_rate: fix mul_by_weight to use ceil not floor
What changed, and why it matters
This commit fixes a rounding bug in a Bitcoin fee calculation. The code previously rounded the fee rate down to the nearest whole number before multiplying by transaction weight, which could cause the calculated fee to be slightly too low. After the fix, it rounds up, ensuring the fee is always sufficient. A too-low fee could cause a transaction to be rejected by the Bitcoin network or get stuck unconfirmed.
Review callers of mul_by_weight to confirm no other rounding assumptions are violated. Ensure tests cover edge cases where floor/ceil divergence matters. Consider whether this change affects any consensus-critical or wallet fee-estimation code paths. No immediate emergency action is indicated, but the fix should be included in the next release.
Security signals we found
Rounding direction changed from floor to ceil in fee computation
Potential for computed fee to be slightly below required amount before fix
Transaction fee insufficiency can lead to network rejection or delayed confirmation
No explicit security advisory or CVE referenced in commit
Evidence from the diff
In units/src/fee_rate/mod.rs, the mul_by_weight method on FeeRate was changed from to_sat_per_kwu_floor() to to_sat_per_kwu_ceil(). The method computes fee = fee_rate * weight / 1000. Using floor on the per-kwu rate before multiplication and then ceil on the final division could still produce a fee one satoshi short of the true required amount. The fix ensures the intermediate rate is rounded up, so the final fee is never below the mathematically correct value. This is a correctness fix for fee computation in a Bitcoin library.
Changed components
units/src/fee_rate/mod.rsFeeRate::mul_by_weightAmount/NumOpResult fee computationInspect captured patch +1 / −1
diff --git a/units/src/fee_rate/mod.rs b/units/src/fee_rate/mod.rs
index 7afa7473..5d814a99 100644
--- a/units/src/fee_rate/mod.rs
+++ b/units/src/fee_rate/mod.rs
@@ -215,7 +215,7 @@ impl FeeRate {
/// enough instead of falling short if rounded down.
pub const fn mul_by_weight(self, weight: Weight) -> NumOpResult<Amount> {
let wu = weight.to_wu();
- if let Some(fee_kwu) = self.to_sat_per_kwu_floor().checked_mul(wu) {
+ if let Some(fee_kwu) = self.to_sat_per_kwu_ceil().checked_mul(wu) {
let fee = fee_kwu.div_ceil(1_000);
if let Ok(fee_amount) = Amount::from_sat(fee) {
return NumOpResult::Valid(fee_amount);
Why this scored 51/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.