From 4c2dcc7af570e574391436f2d62e33f7bf5a568b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 5 Aug 2020 13:26:32 +0930 Subject: [PATCH] amount: add amount_msat_scale, amount_msat_ratio, amount_{msat,sat}_div It's not all that rare to do these operations, and requiring annotations for it is a little painful. Signed-off-by: Rusty Russell --- common/amount.c | 29 +++++++++++++++++++++++++++++ common/amount.h | 9 +++++++++ gossipd/routing.c | 13 ++++++------- lightningd/invoice.c | 2 +- openingd/openingd.c | 3 +-- plugins/libplugin-pay.c | 19 +++++++++++++------ 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/common/amount.c b/common/amount.c index 4ddde7abc0ca..508a0322ef7e 100644 --- a/common/amount.c +++ b/common/amount.c @@ -297,6 +297,18 @@ WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, return amount_msat_add(val, a, msatb); } +WARN_UNUSED_RESULT bool amount_msat_scale(struct amount_msat *val, + struct amount_msat sat, + double scale) +{ + double scaled = sat.millisatoshis * scale; + + if (scaled > UINT64_MAX) + return false; + val->millisatoshis = scaled; + return true; +} + bool amount_sat_eq(struct amount_sat a, struct amount_sat b) { return a.satoshis == b.satoshis; @@ -417,6 +429,23 @@ struct amount_sat amount_sat(u64 satoshis) return sat; } +double amount_msat_ratio(struct amount_msat a, struct amount_msat b) +{ + return (double)a.millisatoshis / b.millisatoshis; +} + +struct amount_msat amount_msat_div(struct amount_msat msat, u64 div) +{ + msat.millisatoshis /= div; + return msat; +} + +struct amount_sat amount_sat_div(struct amount_sat sat, u64 div) +{ + sat.satoshis /= div; + return sat; +} + bool amount_msat_fee(struct amount_msat *fee, struct amount_msat amt, u32 fee_base_msat, diff --git a/common/amount.h b/common/amount.h index 38df4c60b9e1..6a5f60699dab 100644 --- a/common/amount.h +++ b/common/amount.h @@ -80,6 +80,12 @@ WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val, struct amount_sat a, struct amount_msat b); +WARN_UNUSED_RESULT bool amount_msat_scale(struct amount_msat *val, + struct amount_msat msat, + double scale); + +struct amount_msat amount_msat_div(struct amount_msat msat, u64 div); +struct amount_sat amount_sat_div(struct amount_sat sat, u64 div); /* Is a == b? */ bool amount_sat_eq(struct amount_sat a, struct amount_sat b); @@ -112,6 +118,9 @@ bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat); /* Is msat == sat? */ bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat); +/* a / b */ +double amount_msat_ratio(struct amount_msat a, struct amount_msat b); + /* Check whether this asset is actually the main / fee-paying asset of the * current chain. */ bool amount_asset_is_main(struct amount_asset *asset); diff --git a/gossipd/routing.c b/gossipd/routing.c index e76c586a4d3c..15704a43fb5a 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -650,14 +650,13 @@ static WARN_UNUSED_RESULT bool risk_add_fee(struct amount_msat *risk, u32 delay, double riskfactor, u64 riskbias) { - double r; + struct amount_msat riskfee; - /* Won't overflow on add, just lose precision */ - r = (double)riskbias + riskfactor * delay * msat.millisatoshis + risk->millisatoshis; /* Raw: to double */ - if (r > (double)UINT64_MAX) + if (!amount_msat_scale(&riskfee, msat, riskfactor * delay)) return false; - risk->millisatoshis = r; /* Raw: from double */ - return true; + if (!amount_msat_add(&riskfee, riskfee, amount_msat(riskbias))) + return false; + return amount_msat_add(risk, *risk, riskfee); } /* Check that we can fit through this channel's indicated @@ -1209,7 +1208,7 @@ find_shorter_route(const tal_t *ctx, struct routing_state *rstate, * per block delay, which is close enough to zero to not break * this algorithm, but still provide some bias towards * low-delay routes. */ - riskfactor = (double)1.0 / msat.millisatoshis; /* Raw: inversion */ + riskfactor = amount_msat_ratio(AMOUNT_MSAT(1), msat); /* First, figure out if a short route is even possible. * We set the cost function to ignore total, riskbias 1 and riskfactor diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 08fb5dbfc005..f91fe9386f8f 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -542,7 +542,7 @@ static struct route_info **select_inchan(const tal_t *ctx, continue; } - excess_frac = (double)excess.millisatoshis / capacity.millisatoshis; /* Raw: double fraction */ + excess_frac = amount_msat_ratio(excess, capacity); sample.route = &inchans[i]; sample.weight = excess_frac; diff --git a/openingd/openingd.c b/openingd/openingd.c index a86e520471b9..c5e78d51845c 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -348,8 +348,7 @@ static bool check_config_bounds(struct state *state, /* We always set channel_reserve_satoshis to 1%, rounded down. */ static void set_reserve(struct state *state) { - state->localconf.channel_reserve.satoshis /* Raw: rounding. */ - = state->funding.satoshis / 100; /* Raw: rounding. */ + state->localconf.channel_reserve = amount_sat_div(state->funding, 100); /* BOLT #2: * diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 94861b1c6226..5b6fe84b07b1 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -2313,8 +2313,8 @@ static void shadow_route_cb(struct shadow_route_data *d, /* Allow shadowroutes to consume up to 1/4th of our budget. */ d->constraints.cltv_budget = p->constraints.cltv_budget / 4; - d->constraints.fee_budget = p->constraints.fee_budget; - d->constraints.fee_budget.millisatoshis /= 4; /* Raw: msat division. */ + d->constraints.fee_budget + = amount_msat_div(p->constraints.fee_budget, 4); if (pseudorand(2) == 0) { return payment_continue(p); @@ -2672,8 +2672,11 @@ static void presplit_cb(struct presplit_mod_data *d, struct payment *p) /* Now adjust the constraints so we don't multiply them * when splitting. */ - multiplier = (double)c->amount.millisatoshis / (double)p->amount.millisatoshis; /* Raw: msat division. */ - c->constraints.fee_budget.millisatoshis *= multiplier; /* Raw: Multiplication */ + multiplier = amount_msat_ratio(c->amount, p->amount); + if (!amount_msat_scale(&c->constraints.fee_budget, + c->constraints.fee_budget, + multiplier)) + abort(); /* multiplier < 1! */ payment_start(c); count++; } @@ -2790,12 +2793,16 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme a->amount.millisatoshis = mid; /* Raw: split. */ b->amount.millisatoshis -= mid; /* Raw: split. */ - double multiplier = (double)a->amount.millisatoshis / (double)p->amount.millisatoshis; /* Raw: msat division */ + double multiplier = amount_msat_ratio(a->amount, + p->amount); assert(multiplier >= 0.4 && multiplier < 0.6); /* Adjust constraints since we don't want to double our * fee allowance when we split. */ - a->constraints.fee_budget.millisatoshis = pconstraints->fee_budget.millisatoshis * multiplier; /* Raw: msat multiplication. */ + if (!amount_msat_scale(&a->constraints.fee_budget, + pconstraints->fee_budget, + multiplier)) + abort(); ok = amount_msat_sub(&b->constraints.fee_budget, pconstraints->fee_budget,