From 35f65c5d91c973fd4672b708bf95535c457fce7a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 13 Nov 2025 15:38:31 +1030 Subject: [PATCH] common: add amount_msat_deduct / amount_msat_deduct_sub. I added amount_msat_accumulate for the "a+=b" case, but I was struggling with a name for the subtractive equivalent. After some prompting, ChatGPT suggested deduct. Signed-off-by: Rusty Russell --- channeld/full_channel.c | 14 +++++++------- common/amount.c | 12 ++++++++++++ common/amount.h | 8 ++++++++ common/initial_commit_tx.c | 2 +- devtools/mkclose.c | 2 +- lightningd/invoice.c | 2 +- lightningd/peer_control.c | 16 ++++++++-------- lightningd/peer_htlcs.c | 3 +-- plugins/askrene/askrene.c | 2 +- plugins/askrene/mcf.c | 7 +++---- plugins/askrene/refine.c | 18 ++++++++---------- plugins/askrene/reserve.c | 2 +- plugins/bkpr/channelsapy.c | 6 ++---- plugins/bkpr/onchain_fee.c | 2 +- plugins/libplugin-pay.c | 15 ++++++--------- plugins/renepay/chan_extra.c | 8 ++++---- plugins/renepay/mcf.c | 2 +- plugins/renepay/mods.c | 2 +- plugins/renepay/routebuilder.c | 5 ++--- plugins/renepay/routetracker.c | 9 ++++----- tests/plugins/channeld_fakenet.c | 5 ++--- 21 files changed, 75 insertions(+), 67 deletions(-) diff --git a/channeld/full_channel.c b/channeld/full_channel.c index eca0ee522..c3df6ee66 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 0f1867369..cf872d0cb 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 11551b913..04965889b 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 07e3c8909..fb585513b 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 de51c7f64..d32aa2a6d 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 dc8239199..aa9546850 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 4b44384d9..e5fbc74ac 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 548a15c82..b64337505 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 d25fc4aed..8ed0ceabc 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 e41bfb057..3acf0a332 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 00ee4f75c..12743ebbc 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 738577fc2..de88091c2 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 f4fa55a04..898b3175c 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 6cdce78ab..8cfc0c136 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 58deb4d0a..3c8b9d604 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 931463ca5..d4ca30197 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 7d2f14903..8fdd067b4 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 30d6314a2..e6da2d108 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 4e9d15142..d4c940f77 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 2e8b9ba2b..b30a4a544 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 d56c5824f..c8281671b 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));