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 <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2020-08-05 13:26:32 +09:30
parent ffbb409b47
commit fa829f23db
6 changed files with 59 additions and 16 deletions

View File

@ -297,6 +297,18 @@ WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val,
return amount_msat_add(val, a, msatb); 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) bool amount_sat_eq(struct amount_sat a, struct amount_sat b)
{ {
return a.satoshis == b.satoshis; return a.satoshis == b.satoshis;
@ -417,6 +429,23 @@ struct amount_sat amount_sat(u64 satoshis)
return sat; 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, bool amount_msat_fee(struct amount_msat *fee,
struct amount_msat amt, struct amount_msat amt,
u32 fee_base_msat, u32 fee_base_msat,

View File

@ -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, WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val,
struct amount_sat a, struct amount_sat a,
struct amount_msat b); 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? */ /* Is a == b? */
bool amount_sat_eq(struct amount_sat a, struct amount_sat 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? */ /* Is msat == sat? */
bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat 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 /* Check whether this asset is actually the main / fee-paying asset of the
* current chain. */ * current chain. */
bool amount_asset_is_main(struct amount_asset *asset); bool amount_asset_is_main(struct amount_asset *asset);

View File

@ -650,14 +650,13 @@ static WARN_UNUSED_RESULT bool risk_add_fee(struct amount_msat *risk,
u32 delay, double riskfactor, u32 delay, double riskfactor,
u64 riskbias) u64 riskbias)
{ {
double r; struct amount_msat riskfee;
/* Won't overflow on add, just lose precision */ if (!amount_msat_scale(&riskfee, msat, riskfactor * delay))
r = (double)riskbias + riskfactor * delay * msat.millisatoshis + risk->millisatoshis; /* Raw: to double */
if (r > (double)UINT64_MAX)
return false; return false;
risk->millisatoshis = r; /* Raw: from double */ if (!amount_msat_add(&riskfee, riskfee, amount_msat(riskbias)))
return true; return false;
return amount_msat_add(risk, *risk, riskfee);
} }
/* Check that we can fit through this channel's indicated /* 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 * per block delay, which is close enough to zero to not break
* this algorithm, but still provide some bias towards * this algorithm, but still provide some bias towards
* low-delay routes. */ * 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. /* First, figure out if a short route is even possible.
* We set the cost function to ignore total, riskbias 1 and riskfactor * We set the cost function to ignore total, riskbias 1 and riskfactor

View File

@ -542,7 +542,7 @@ static struct route_info **select_inchan(const tal_t *ctx,
continue; continue;
} }
excess_frac = (double)excess.millisatoshis / capacity.millisatoshis; /* Raw: double fraction */ excess_frac = amount_msat_ratio(excess, capacity);
sample.route = &inchans[i]; sample.route = &inchans[i];
sample.weight = excess_frac; sample.weight = excess_frac;

View File

@ -348,8 +348,7 @@ static bool check_config_bounds(struct state *state,
/* We always set channel_reserve_satoshis to 1%, rounded down. */ /* We always set channel_reserve_satoshis to 1%, rounded down. */
static void set_reserve(struct state *state) static void set_reserve(struct state *state)
{ {
state->localconf.channel_reserve.satoshis /* Raw: rounding. */ state->localconf.channel_reserve = amount_sat_div(state->funding, 100);
= state->funding.satoshis / 100; /* Raw: rounding. */
/* BOLT #2: /* BOLT #2:
* *

View File

@ -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. */ /* Allow shadowroutes to consume up to 1/4th of our budget. */
d->constraints.cltv_budget = p->constraints.cltv_budget / 4; d->constraints.cltv_budget = p->constraints.cltv_budget / 4;
d->constraints.fee_budget = p->constraints.fee_budget; d->constraints.fee_budget
d->constraints.fee_budget.millisatoshis /= 4; /* Raw: msat division. */ = amount_msat_div(p->constraints.fee_budget, 4);
if (pseudorand(2) == 0) { if (pseudorand(2) == 0) {
return payment_continue(p); 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 /* Now adjust the constraints so we don't multiply them
* when splitting. */ * when splitting. */
multiplier = (double)c->amount.millisatoshis / (double)p->amount.millisatoshis; /* Raw: msat division. */ multiplier = amount_msat_ratio(c->amount, p->amount);
c->constraints.fee_budget.millisatoshis *= multiplier; /* Raw: Multiplication */ if (!amount_msat_scale(&c->constraints.fee_budget,
c->constraints.fee_budget,
multiplier))
abort(); /* multiplier < 1! */
payment_start(c); payment_start(c);
count++; count++;
} }
@ -2790,12 +2793,16 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
a->amount.millisatoshis = mid; /* Raw: split. */ a->amount.millisatoshis = mid; /* Raw: split. */
b->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); assert(multiplier >= 0.4 && multiplier < 0.6);
/* Adjust constraints since we don't want to double our /* Adjust constraints since we don't want to double our
* fee allowance when we split. */ * 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, ok = amount_msat_sub(&b->constraints.fee_budget,
pconstraints->fee_budget, pconstraints->fee_budget,