common: add amount_msat_deduct / amount_msat_deduct_sub.
What changed, and why it matters
This commit is a straightforward code cleanup: it introduces two new helper functions, amount_msat_deduct and amount_msat_deduct_sat, which are shorthand for 'subtract this amount from itself' (like a -= b). It then replaces many existing calls of the longer form amount_msat_sub(&x, x, y) with the shorter amount_msat_deduct(&x, y). There is no change in behavior, no bug fix, and no security relevance in the diff itself.
No security action required. This is a non-functional refactor. Normal code-review approval is sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change adds in-place subtraction wrappers in common/amount.c and common/amount.h and mechanically refactors callers across channeld, common, lightningd, plugins, devtools, and tests to use the new API. The underlying arithmetic (amount_msat_sub / amount_msat_sub_sat) remains identical; only the call site syntax is simplified. No overflow/underflow checks, return values, or arithmetic semantics are altered.
Changed components
common/amount.ccommon/amount.hInspect captured patch +75 / −67
diff --git a/channeld/full_channel.c b/channeld/full_channel.c
index eca0ee52..c3df6ee6 100644
--- a/channeld/full_channel.c
+++ b/channeld/full_channel.c
@@ -416,7 +416,7 @@ static bool get_room_above_reserve(const struct channel *channel,
return false;
}
- if (!amount_msat_sub_sat(remainder, *remainder, reserve)) {
+ if (!amount_msat_deduct_sat(remainder, reserve)) {
status_debug("%s cannot afford htlc: would make balance %s"
" below reserve %s",
side_to_str(side),
@@ -504,7 +504,7 @@ static bool htlc_dust(const struct channel *channel,
side, &trim_rmvd))
return false;
- return amount_msat_sub(trim_total, *trim_total, trim_rmvd);
+ return amount_msat_deduct(trim_total, trim_rmvd);
}
/*
@@ -773,7 +773,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
*/
if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx)
&& channel->opener == sender
- && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660)))
+ && !amount_msat_deduct_sat(&remainder, AMOUNT_SAT(660)))
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
if (channel->opener== sender) {
@@ -805,7 +805,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx)
&& channel->opener != sender
- && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660)))
+ && !amount_msat_deduct_sat(&remainder, AMOUNT_SAT(660)))
return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED;
/* Should be able to afford both their own commit tx
@@ -1257,12 +1257,12 @@ u32 approx_max_feerate(const struct channel *channel)
* `to_remote`).
*/
if ((option_anchor_outputs || option_anchors_zero_fee_htlc_tx)
- && !amount_msat_sub_sat(&avail, avail, AMOUNT_SAT(660))) {
+ && !amount_msat_deduct_sat(&avail, AMOUNT_SAT(660))) {
avail = AMOUNT_MSAT(0);
} else {
/* We should never go below reserve. */
- if (!amount_msat_sub_sat(&avail, avail,
- channel->config[!channel->opener].channel_reserve))
+ if (!amount_msat_deduct_sat(&avail,
+ channel->config[!channel->opener].channel_reserve))
avail = AMOUNT_MSAT(0);
}
diff --git a/common/amount.c b/common/amount.c
index 0f186736..cf872d0c 100644
--- a/common/amount.c
+++ b/common/amount.c
@@ -263,6 +263,18 @@ WARN_UNUSED_RESULT bool amount_msat_accumulate(struct amount_msat *a,
return amount_msat_add(a, *a, b);
}
+WARN_UNUSED_RESULT bool amount_msat_deduct(struct amount_msat *a,
+ struct amount_msat b)
+{
+ return amount_msat_sub(a, *a, b);
+}
+
+WARN_UNUSED_RESULT bool amount_msat_deduct_sat(struct amount_msat *a,
+ struct amount_sat b)
+{
+ return amount_msat_sub_sat(a, *a, b);
+}
+
WARN_UNUSED_RESULT bool amount_msat_sub(struct amount_msat *val,
struct amount_msat a,
struct amount_msat b)
diff --git a/common/amount.h b/common/amount.h
index 11551b91..04965889 100644
--- a/common/amount.h
+++ b/common/amount.h
@@ -105,6 +105,14 @@ WARN_UNUSED_RESULT bool amount_sat_add_sat_s64(struct amount_sat *val,
WARN_UNUSED_RESULT bool amount_msat_accumulate(struct amount_msat *a,
struct amount_msat b);
+/* a -= b */
+WARN_UNUSED_RESULT bool amount_msat_deduct(struct amount_msat *a,
+ struct amount_msat b);
+
+/* a -= b */
+WARN_UNUSED_RESULT bool amount_msat_deduct_sat(struct amount_msat *a,
+ struct amount_sat b);
+
/* returns floor(msat/div) */
struct amount_msat amount_msat_div(struct amount_msat msat, u64 div);
diff --git a/common/initial_commit_tx.c b/common/initial_commit_tx.c
index 07e3c890..fb585513 100644
--- a/common/initial_commit_tx.c
+++ b/common/initial_commit_tx.c
@@ -40,7 +40,7 @@ bool try_subtract_fee(enum side opener, enum side side,
else
opener_amount = other;
- if (amount_msat_sub_sat(opener_amount, *opener_amount, base_fee))
+ if (amount_msat_deduct_sat(opener_amount, base_fee))
return true;
*opener_amount = AMOUNT_MSAT(0);
diff --git a/devtools/mkclose.c b/devtools/mkclose.c
index de51c7f6..d32aa2a6 100644
--- a/devtools/mkclose.c
+++ b/devtools/mkclose.c
@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
if (option_anchor_outputs && !amount_sat_add(&fee, fee, AMOUNT_SAT(660)))
errx(1, "Can't afford anchors");
- if (!amount_msat_sub_sat(&local_msat, local_msat, fee))
+ if (!amount_msat_deduct_sat(&local_msat, fee))
errx(1, "Can't afford fee %s",
fmt_amount_sat(NULL, fee));
if (!amount_sat_sub_msat(&remote_msat, funding_amount, local_msat))
diff --git a/lightningd/invoice.c b/lightningd/invoice.c
index dc823919..aa954685 100644
--- a/lightningd/invoice.c
+++ b/lightningd/invoice.c
@@ -571,7 +571,7 @@ static struct route_info **select_inchan(const tal_t *ctx,
candidates[i].c->our_config.channel_reserve,
candidates[i].c->channel_info.their_config.channel_reserve)
|| !amount_sat_to_msat(&capacity, candidates[i].c->funding_sats)
- || !amount_msat_sub_sat(&capacity, capacity, cumulative_reserve)) {
+ || !amount_msat_deduct_sat(&capacity, cumulative_reserve)) {
log_broken(ld->log, "Channel %s capacity overflow!",
fmt_short_channel_id(tmpctx, *candidates[i].c->scid));
continue;
diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c
index 4b44384d..e5fbc74a 100644
--- a/lightningd/peer_control.c
+++ b/lightningd/peer_control.c
@@ -721,7 +721,7 @@ static void subtract_offered_htlcs(const struct channel *channel,
hout = htlc_out_map_next(ld->htlcs_out, &outi)) {
if (hout->key.channel != channel)
continue;
- if (!amount_msat_sub(amount, *amount, hout->msat))
+ if (!amount_msat_deduct(amount, hout->msat))
*amount = AMOUNT_MSAT(0);
}
}
@@ -738,7 +738,7 @@ static void subtract_received_htlcs(const struct channel *channel,
hin = htlc_in_map_next(ld->htlcs_in, &ini)) {
if (hin->key.channel != channel)
continue;
- if (!amount_msat_sub(amount, *amount, hin->msat))
+ if (!amount_msat_deduct(amount, hin->msat))
*amount = AMOUNT_MSAT(0);
}
}
@@ -759,9 +759,9 @@ struct amount_msat channel_amount_spendable(const struct channel *channel)
/* If we're opener, subtract txfees we'll need to spend this */
if (channel->opener == LOCAL) {
- if (!amount_msat_sub_sat(&spendable, spendable,
- commit_txfee(channel, spendable,
- LOCAL)))
+ if (!amount_msat_deduct_sat(&spendable,
+ commit_txfee(channel, spendable,
+ LOCAL)))
return AMOUNT_MSAT(0);
}
@@ -803,9 +803,9 @@ struct amount_msat channel_amount_receivable(const struct channel *channel)
/* If they're opener, subtract txfees they'll need to spend this */
if (channel->opener == REMOTE) {
- if (!amount_msat_sub_sat(&receivable, receivable,
- commit_txfee(channel,
- receivable, REMOTE)))
+ if (!amount_msat_deduct_sat(&receivable,
+ commit_txfee(channel,
+ receivable, REMOTE)))
return AMOUNT_MSAT(0);
}
diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c
index 548a15c8..b6433750 100644
--- a/lightningd/peer_htlcs.c
+++ b/lightningd/peer_htlcs.c
@@ -2006,8 +2006,7 @@ static void remove_htlc_out(struct channel *channel, struct htlc_out *hout)
const struct channel_coin_mvt *mvt;
struct amount_msat oldamt = channel->our_msat;
/* We paid for this HTLC, so deduct balance. */
- if (!amount_msat_sub(&channel->our_msat, channel->our_msat,
- hout->msat)) {
+ if (!amount_msat_deduct(&channel->our_msat, hout->msat)) {
channel_internal_error(channel,
"Underflow our_msat %s - HTLC %s",
fmt_amount_msat(tmpctx,
diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c
index d25fc4ae..8ed0ceab 100644
--- a/plugins/askrene/askrene.c
+++ b/plugins/askrene/askrene.c
@@ -1057,7 +1057,7 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd,
if (!reserve_accumulate(askrene->reserved, scidd, amount))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Amount overflow with reserves");
- if (!amount_msat_sub(amount, *amount, AMOUNT_MSAT(1)))
+ if (!amount_msat_deduct(amount, AMOUNT_MSAT(1)))
*amount = AMOUNT_MSAT(0);
if (command_check_only(cmd))
return command_check_done(cmd);
diff --git a/plugins/askrene/mcf.c b/plugins/askrene/mcf.c
index e41bfb05..3acf0a33 100644
--- a/plugins/askrene/mcf.c
+++ b/plugins/askrene/mcf.c
@@ -345,7 +345,7 @@ static double pickhardt_richter_probability(struct amount_msat low,
struct amount_msat all_states, good_states;
if (amount_msat_greater_eq(amount, high))
return 0.0;
- if (!amount_msat_sub(&amount, amount, low))
+ if (!amount_msat_deduct(&amount, low))
return 1.0;
if (!amount_msat_sub(&all_states, high, low))
abort(); // we expect high > low
@@ -1587,9 +1587,8 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
}
}
- if (!amount_msat_sub(&feebudget, feebudget, all_fees) ||
- !amount_msat_sub(&amount_to_deliver, amount_to_deliver,
- all_deliver)) {
+ if (!amount_msat_deduct(&feebudget, all_fees) ||
+ !amount_msat_deduct(&amount_to_deliver, all_deliver)) {
error_message =
rq_log(ctx, rq, LOG_BROKEN,
"%s: unexpected arithmetic operation "
diff --git a/plugins/askrene/refine.c b/plugins/askrene/refine.c
index 00ee4f75..12743ebb 100644
--- a/plugins/askrene/refine.c
+++ b/plugins/askrene/refine.c
@@ -372,10 +372,10 @@ static struct amount_msat remove_excess(struct flow **flows,
/* Remove the smaller parts if they deliver less than the
* excess. */
for (int i = tal_count(*flows_index) - 1; i >= 0; i--) {
- if (!amount_msat_sub(&excess, excess,
+ if (!amount_msat_deduct(&excess,
flows[(*flows_index)[i]]->delivers))
break;
- if (!amount_msat_sub(&all_deliver, all_deliver,
+ if (!amount_msat_deduct(&all_deliver,
flows[(*flows_index)[i]]->delivers))
abort();
tal_arr_remove(flows_index, i);
@@ -397,21 +397,19 @@ static struct amount_msat remove_excess(struct flow **flows,
/* rounding errors: don't remove more than excess */
remove = amount_msat_min(remove, excess);
- if (!amount_msat_sub(&excess, excess, remove))
+ if (!amount_msat_deduct(&excess, remove))
abort();
- if (!amount_msat_sub(&all_deliver, all_deliver, remove) ||
- !amount_msat_sub(&flows[(*flows_index)[i]]->delivers,
- flows[(*flows_index)[i]]->delivers,
- remove))
+ if (!amount_msat_deduct(&all_deliver, remove) ||
+ !amount_msat_deduct(&flows[(*flows_index)[i]]->delivers,
+ remove))
abort();
}
/* any rounding error left, take it from the first */
assert(tal_count(*flows_index) > 0);
- if (!amount_msat_sub(&all_deliver, all_deliver, excess) ||
- !amount_msat_sub(&flows[(*flows_index)[0]]->delivers,
- flows[(*flows_index)[0]]->delivers, excess))
+ if (!amount_msat_deduct(&all_deliver, excess) ||
+ !amount_msat_deduct(&flows[(*flows_index)[0]]->delivers, excess))
abort();
return all_deliver;
}
diff --git a/plugins/askrene/reserve.c b/plugins/askrene/reserve.c
index 738577fc..de88091c 100644
--- a/plugins/askrene/reserve.c
+++ b/plugins/askrene/reserve.c
@@ -103,7 +103,7 @@ void reserve_sub(const struct reserve_htable *reserved,
for (r = reserve_htable_getfirst(reserved, scidd, &rit);
r;
r = reserve_htable_getnext(reserved, scidd, &rit)) {
- if (!amount_msat_sub(amount, *amount, r->rhop.amount))
+ if (!amount_msat_deduct(amount, r->rhop.amount))
*amount = AMOUNT_MSAT(0);
}
}
diff --git a/plugins/bkpr/channelsapy.c b/plugins/bkpr/channelsapy.c
index f4fa55a0..898b3175 100644
--- a/plugins/bkpr/channelsapy.c
+++ b/plugins/bkpr/channelsapy.c
@@ -126,11 +126,9 @@ static void fillin_apy_acct_details(const struct bkpr *bkpr,
/* If there is any push_out or lease_fees_out, we subtract
* from starting balance */
- ok = amount_msat_sub(&apy->our_start_bal, apy->our_start_bal,
- apy->push_out);
+ ok = amount_msat_deduct(&apy->our_start_bal, apy->push_out);
assert(ok);
- ok = amount_msat_sub(&apy->our_start_bal, apy->our_start_bal,
- apy->lease_out);
+ ok = amount_msat_deduct(&apy->our_start_bal, apy->lease_out);
assert(ok);
/* we add values in to starting balance */
diff --git a/plugins/bkpr/onchain_fee.c b/plugins/bkpr/onchain_fee.c
index 6cdce78a..8cfc0c13 100644
--- a/plugins/bkpr/onchain_fee.c
+++ b/plugins/bkpr/onchain_fee.c
@@ -288,7 +288,7 @@ static void insert_chain_fees_diff(struct command *cmd,
if (!amount_msat_accumulate(¤t_amt, ofs[i]->credit))
plugin_err(cmd->plugin, "Overflow when adding onchain fees");
- if (!amount_msat_sub(¤t_amt, current_amt, ofs[i]->debit))
+ if (!amount_msat_deduct(¤t_amt, ofs[i]->debit))
plugin_err(cmd->plugin, "Underflow when subtracting onchain fees");
if (ofs[i]->update_count > max_update_count)
max_update_count = ofs[i]->update_count;
diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c
index 58deb4d0..3c8b9d60 100644
--- a/plugins/libplugin-pay.c
+++ b/plugins/libplugin-pay.c
@@ -483,7 +483,7 @@ payment_constraints_update(struct payment_constraints *cons,
return false;
/* amount_msat_sub performs a check before actually subtracting. */
- if (!amount_msat_sub(&cons->fee_budget, cons->fee_budget, delta_fee))
+ if (!amount_msat_deduct(&cons->fee_budget, delta_fee))
return false;
cons->cltv_budget -= delta_cltv;
@@ -572,9 +572,8 @@ static bool payment_chanhints_apply_route(struct payment *p)
curhint->local->htlc_budget--;
}
- if (!amount_msat_sub(&curhint->estimated_capacity,
- curhint->estimated_capacity,
- curhop->amount)) {
+ if (!amount_msat_deduct(&curhint->estimated_capacity,
+ curhop->amount)) {
/* Given our preemptive test
* above, this should never
* happen either. */
@@ -1448,7 +1447,7 @@ handle_intermediate_failure(struct command *cmd,
* work. This allows us to then allow on equality, this is for
* example necessary for local channels where exact matches
* should be allowed. */
- if (!amount_msat_sub(&estimated, estimated, AMOUNT_MSAT(1)))
+ if (!amount_msat_deduct(&estimated, AMOUNT_MSAT(1)))
abort();
/* These are an indication that the capacity was insufficient,
@@ -3408,10 +3407,8 @@ static struct command_result *shadow_route_listchannels(struct command *cmd,
* destination could otherwise cause the route to be too
* expensive, while really being ok. If any of these fail then
* the above checks are insufficient. */
- if (!amount_msat_sub(&d->constraints.fee_budget,
- d->constraints.fee_budget, best_fee) ||
- !amount_msat_sub(&p->constraints.fee_budget,
- p->constraints.fee_budget, best_fee))
+ if (!amount_msat_deduct(&d->constraints.fee_budget, best_fee) ||
+ !amount_msat_deduct(&p->constraints.fee_budget, best_fee))
paymod_err(p,
"Could not update fee constraints "
"for shadow route extension. "
diff --git a/plugins/renepay/chan_extra.c b/plugins/renepay/chan_extra.c
index 931463ca..d4ca3019 100644
--- a/plugins/renepay/chan_extra.c
+++ b/plugins/renepay/chan_extra.c
@@ -128,7 +128,7 @@ enum renepay_errorcode channel_liquidity(struct amount_msat *liquidity,
if (!h)
return RENEPAY_CHANNEL_NOT_FOUND;
struct amount_msat value_liquidity = h->known_max;
- if (!amount_msat_sub(&value_liquidity, value_liquidity, h->htlc_total))
+ if (!amount_msat_deduct(&value_liquidity, h->htlc_total))
return RENEPAY_AMOUNT_OVERFLOW;
*liquidity = value_liquidity;
return RENEPAY_NOERROR;
@@ -616,12 +616,12 @@ double edge_probability(struct amount_msat min, struct amount_msat max,
goto function_fail;
// in_flight cannot be greater than max
- if (!amount_msat_sub(&B, B, in_flight))
+ if (!amount_msat_deduct(&B, in_flight))
goto function_fail;
struct amount_msat A = min; // = MAX(0,min-in_flight);
- if (!amount_msat_sub(&A, A, in_flight))
+ if (!amount_msat_deduct(&A, in_flight))
A = AMOUNT_MSAT(0);
struct amount_msat denominator; // = B-A
@@ -655,7 +655,7 @@ chan_extra_remove_htlc(struct chan_extra_map *chan_extra_map,
if (h->num_htlcs <= 0)
return RENEPAY_PRECONDITION_ERROR;
- if (!amount_msat_sub(&h->htlc_total, h->htlc_total, amount))
+ if (!amount_msat_deduct(&h->htlc_total, amount))
return RENEPAY_AMOUNT_OVERFLOW;
h->num_htlcs--;
return RENEPAY_NOERROR;
diff --git a/plugins/renepay/mcf.c b/plugins/renepay/mcf.c
index 7d2f1490..8fdd067b 100644
--- a/plugins/renepay/mcf.c
+++ b/plugins/renepay/mcf.c
@@ -1440,7 +1440,7 @@ get_flow_paths(const tal_t *ctx, const struct gossmap *gossmap,
// substract the excess of msats for not having msat
// accuracy
struct amount_msat delivered = amount_msat(delta*1000);
- if (!amount_msat_sub(&delivered, delivered, excess)) {
+ if (!amount_msat_deduct(&delivered, excess)) {
if (fail)
*fail = tal_fmt(
ctx, "unable to substract excess");
diff --git a/plugins/renepay/mods.c b/plugins/renepay/mods.c
index 30d6314a..e6da2d10 100644
--- a/plugins/renepay/mods.c
+++ b/plugins/renepay/mods.c
@@ -680,7 +680,7 @@ static struct command_result *compute_routes_cb(struct payment *payment)
__func__);
/* Remaining fee budget. */
- if (!amount_msat_sub(&feebudget, feebudget, fees_spent))
+ if (!amount_msat_deduct(&feebudget, fees_spent))
feebudget = AMOUNT_MSAT(0);
/* How much are we still trying to send? */
diff --git a/plugins/renepay/routebuilder.c b/plugins/renepay/routebuilder.c
index 4e9d1514..d4c940f7 100644
--- a/plugins/renepay/routebuilder.c
+++ b/plugins/renepay/routebuilder.c
@@ -364,7 +364,7 @@ struct route **get_routes(const tal_t *ctx,
}
// update the fee budget
- if (!amount_msat_sub(&feebudget, feebudget, fee)) {
+ if (!amount_msat_deduct(&feebudget, fee)) {
// should never happen
tal_report_error(
ctx, ecode, fail, PLUGIN_ERROR,
@@ -377,8 +377,7 @@ struct route **get_routes(const tal_t *ctx,
}
// update the amount that we deliver
- if (!amount_msat_sub(&amount_to_deliver,
- amount_to_deliver, delivering)) {
+ if (!amount_msat_deduct(&amount_to_deliver, delivering)) {
// should never happen
tal_report_error(
ctx, ecode, fail, PLUGIN_ERROR,
diff --git a/plugins/renepay/routetracker.c b/plugins/renepay/routetracker.c
index 2e8b9ba2..b30a4a54 100644
--- a/plugins/renepay/routetracker.c
+++ b/plugins/renepay/routetracker.c
@@ -330,11 +330,10 @@ void payment_collect_results(struct payment *payment,
*final_msg = tal_strdup(tmpctx, r->final_msg);
}
- if (!amount_msat_sub(&payment->total_delivering,
- payment->total_delivering,
- route_delivers(r)) ||
- !amount_msat_sub(&payment->total_sent, payment->total_sent,
- route_sends(r))) {
+ if (!amount_msat_deduct(&payment->total_delivering,
+ route_delivers(r)) ||
+ !amount_msat_deduct(&payment->total_sent,
+ route_sends(r))) {
plugin_err(pay_plugin->plugin,
"%s: routes do not add up to "
"payment total amount.",
diff --git a/tests/plugins/channeld_fakenet.c b/tests/plugins/channeld_fakenet.c
index d56c5824..c8281671 100644
--- a/tests/plugins/channeld_fakenet.c
+++ b/tests/plugins/channeld_fakenet.c
@@ -657,9 +657,8 @@ static struct amount_msat calc_capacity(struct info *info,
if (!short_channel_id_dir_eq(&info->reservations[i]->scidd, scidd))
continue;
/* We should never use more that we have! */
- if (!amount_msat_sub(&dynamic_capacity,
- dynamic_capacity,
- info->reservations[i]->amount))
+ if (!amount_msat_deduct(&dynamic_capacity,
+ info->reservations[i]->amount))
abort();
status_debug("... minus reservation %s",
fmt_amount_msat(tmpctx, info->reservations[i]->amount));
Why this scored 15/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.