nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

amount.c (15250B)


      1 #include "../config.h"
      2 #include "ccan/mem/mem.h"
      3 #include "ccan/tal/str/str.h"
      4 #include "amount.h"
      5 #include "overflows.h"
      6 #include <assert.h>
      7 #include <inttypes.h>
      8 
      9 bool amount_sat_to_msat(struct amount_msat *msat,
     10             struct amount_sat sat)
     11 {
     12     if (mul_overflows_u64(sat.satoshis, MSAT_PER_SAT))
     13         return false;
     14     msat->millisatoshis = sat.satoshis * MSAT_PER_SAT;
     15     return true;
     16 }
     17 
     18 bool amount_msat_to_sat(struct amount_sat *sat,
     19             struct amount_msat msat)
     20 {
     21     if (msat.millisatoshis % MSAT_PER_SAT)
     22         return false;
     23     sat->satoshis = msat.millisatoshis / MSAT_PER_SAT;
     24     return true;
     25 }
     26 
     27 
     28 /* You can always truncate millisatoshis->satoshis. */
     29 struct amount_sat amount_msat_to_sat_round_down(struct amount_msat msat)
     30 {
     31     struct amount_sat sat;
     32 
     33     sat.satoshis = msat.millisatoshis / MSAT_PER_SAT;
     34     return sat;
     35 }
     36 
     37 /* Different formatting by amounts: btc, sat and msat */
     38 const char *fmt_amount_msat_btc(const tal_t *ctx,
     39                 struct amount_msat msat,
     40                 bool append_unit)
     41 {
     42     if (msat.millisatoshis == 0)
     43         return tal_fmt(ctx, append_unit ? "0btc" : "0");
     44 
     45     return tal_fmt(ctx, "%"PRIu64".%011"PRIu64"%s",
     46                msat.millisatoshis / MSAT_PER_BTC,
     47                msat.millisatoshis % MSAT_PER_BTC,
     48                append_unit ? "btc" : "");
     49 }
     50 
     51 const char *fmt_amount_msat(const tal_t *ctx, struct amount_msat msat)
     52 {
     53     return tal_fmt(ctx, "%"PRIu64"msat", msat.millisatoshis);
     54 }
     55 
     56 const char *fmt_amount_sat_btc(const tal_t *ctx,
     57                    struct amount_sat sat,
     58                    bool append_unit)
     59 {
     60     if (sat.satoshis == 0)
     61         return tal_fmt(ctx, append_unit ? "0btc" : "0");
     62 
     63     return tal_fmt(ctx, "%"PRIu64".%08"PRIu64"%s",
     64                sat.satoshis / SAT_PER_BTC,
     65                sat.satoshis % SAT_PER_BTC,
     66                append_unit ? "btc" : "");
     67 }
     68 
     69 const char *fmt_amount_sat(const tal_t *ctx, struct amount_sat sat)
     70 {
     71     return tal_fmt(ctx, "%"PRIu64"sat", sat.satoshis);
     72 }
     73 
     74 static bool breakup(const char *str, size_t slen,
     75             /* Length of first numeric part. */
     76             size_t *whole_number_len,
     77             /* Pointer to post-decimal part, or NULL */
     78             const char **post_decimal_ptr,
     79             size_t *post_decimal_len,
     80             /* Pointer to suffix, or NULL */
     81             const char **suffix_ptr,
     82             size_t *suffix_len)
     83 {
     84     size_t i;
     85 
     86     *whole_number_len = 0;
     87     *post_decimal_len = 0;
     88     *post_decimal_ptr = NULL;
     89     *suffix_ptr = NULL;
     90     *suffix_len = 0;
     91 
     92     for (i = 0;; i++) {
     93         /* The string may be null-terminated. */
     94         if (i >= slen || str[i] == '\0')
     95             return i != 0;
     96         if (cisdigit(str[i]))
     97             (*whole_number_len)++;
     98         else
     99             break;
    100     }
    101 
    102     if (str[i] == '.') {
    103         i++;
    104         *post_decimal_ptr = str + i;
    105         for (;; i++) {
    106             /* True if > 0 decimals. */
    107             if (i >= slen || str[i] == '\0')
    108                 return str + i != *post_decimal_ptr;
    109             if (cisdigit(str[i]))
    110                 (*post_decimal_len)++;
    111             else
    112                 break;
    113         }
    114     }
    115 
    116     *suffix_ptr = str + i;
    117     *suffix_len = slen - i;
    118     return true;
    119 }
    120 
    121 static bool from_number(u64 *res, const char *s, size_t len, int tens_factor)
    122 {
    123     if (len == 0)
    124         return false;
    125 
    126     *res = 0;
    127     for (size_t i = 0; i < len; i++) {
    128         if (mul_overflows_u64(*res, 10))
    129             return false;
    130         *res *= 10;
    131         assert(cisdigit(s[i]));
    132         if (add_overflows_u64(*res, s[i] - '0'))
    133             return false;
    134         *res += s[i] - '0';
    135     }
    136     while (tens_factor > 0) {
    137         if (mul_overflows_u64(*res, 10))
    138             return false;
    139         *res *= 10;
    140         tens_factor--;
    141     }
    142     return true;
    143 }
    144 
    145 static bool from_numbers(u64 *res,
    146              const char *s1, size_t len1, int tens_factor,
    147              const char *s2, size_t len2)
    148 {
    149     u64 p1, p2;
    150     if (len2 > tens_factor)
    151         return false;
    152 
    153     if (!from_number(&p1, s1, len1, tens_factor)
    154         || !from_number(&p2, s2, len2, tens_factor - (int)len2))
    155         return false;
    156 
    157     if (add_overflows_u64(p1, p2))
    158         return false;
    159 
    160     *res = p1 + p2;
    161     return true;
    162 }
    163 
    164 /* Valid strings:
    165  *  [0-9]+ => millisatoshi.
    166  *  [0-9]+msat => millisatoshi.
    167  *  [0-9]+sat => *1000 -> millisatoshi.
    168  *  [0-9]+.[0-9]{1,11}btc => millisatoshi.
    169  */
    170 bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen)
    171 {
    172     size_t whole_number_len, post_decimal_len, suffix_len;
    173     const char *post_decimal_ptr, *suffix_ptr;
    174 
    175     if (!breakup(s, slen, &whole_number_len,
    176              &post_decimal_ptr, &post_decimal_len,
    177              &suffix_ptr, &suffix_len))
    178         return false;
    179 
    180     if (!post_decimal_ptr && !suffix_ptr)
    181         return from_number(&msat->millisatoshis, s, whole_number_len, 0);
    182     if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat"))
    183         return from_number(&msat->millisatoshis, s, whole_number_len, 0);
    184     if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat"))
    185         return from_number(&msat->millisatoshis, s, whole_number_len, 3);
    186     if (memstarts_str(suffix_ptr, suffix_len, "btc")) {
    187         if (post_decimal_len > 0)
    188             return from_numbers(&msat->millisatoshis,
    189                         s, whole_number_len, 11,
    190                         post_decimal_ptr, post_decimal_len);
    191         return from_number(&msat->millisatoshis, s, whole_number_len, 11);
    192     }
    193 
    194     return false;
    195 }
    196 
    197 /* Valid strings:
    198  *  [0-9]+ => satoshi.
    199  *  [0-9]+sat => satoshi.
    200  *  [0-9]+000msat => satoshi.
    201  *  0msat => 0 satoshi
    202  *  [0-9]+.[0-9]{1,8}btc => satoshi.
    203  */
    204 bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen)
    205 {
    206     size_t whole_number_len, post_decimal_len, suffix_len;
    207     const char *post_decimal_ptr, *suffix_ptr;
    208 
    209     if (!breakup(s, slen, &whole_number_len,
    210              &post_decimal_ptr, &post_decimal_len,
    211              &suffix_ptr, &suffix_len))
    212         return false;
    213 
    214     if (!post_decimal_ptr && !suffix_ptr)
    215         return from_number(&sat->satoshis, s, whole_number_len, 0);
    216     if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat"))
    217         return from_number(&sat->satoshis, s, whole_number_len, 0);
    218     if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat")) {
    219         if (!memends(s, whole_number_len, "000", strlen("000"))) {
    220             if (memstarts_str(s, whole_number_len, "0"))
    221                 return from_number(&sat->satoshis, s,
    222                            whole_number_len, 0);
    223             return false;
    224         }
    225         return from_number(&sat->satoshis, s, whole_number_len - 3, 0);
    226     }
    227     if (memstarts_str(suffix_ptr, suffix_len, "btc")) {
    228         if (post_decimal_len > 0)
    229             return from_numbers(&sat->satoshis,
    230                         s, whole_number_len, 8,
    231                         post_decimal_ptr, post_decimal_len);
    232         return from_number(&sat->satoshis, s, whole_number_len, 8);
    233     }
    234 
    235     return false;
    236 }
    237 
    238 WARN_UNUSED_RESULT bool amount_msat_add(struct amount_msat *val,
    239                     struct amount_msat a,
    240                     struct amount_msat b)
    241 {
    242     if (add_overflows_u64(a.millisatoshis, b.millisatoshis))
    243         return false;
    244 
    245     val->millisatoshis = a.millisatoshis + b.millisatoshis;
    246     return true;
    247 }
    248 
    249 WARN_UNUSED_RESULT bool amount_msat_sub(struct amount_msat *val,
    250                     struct amount_msat a,
    251                     struct amount_msat b)
    252 {
    253     if (a.millisatoshis < b.millisatoshis)
    254         return false;
    255 
    256     val->millisatoshis = a.millisatoshis - b.millisatoshis;
    257     return true;
    258 }
    259 
    260 WARN_UNUSED_RESULT bool amount_sat_add(struct amount_sat *val,
    261                        struct amount_sat a,
    262                        struct amount_sat b)
    263 {
    264     if (add_overflows_u64(a.satoshis, b.satoshis))
    265         return false;
    266 
    267     val->satoshis = a.satoshis + b.satoshis;
    268     return true;
    269 }
    270 
    271 WARN_UNUSED_RESULT bool amount_sat_sub(struct amount_sat *val,
    272                        struct amount_sat a,
    273                        struct amount_sat b)
    274 {
    275     if (a.satoshis < b.satoshis)
    276         return false;
    277 
    278     val->satoshis = a.satoshis - b.satoshis;
    279     return true;
    280 }
    281 
    282 WARN_UNUSED_RESULT bool amount_msat_sub_sat(struct amount_msat *val,
    283                         struct amount_msat a,
    284                         struct amount_sat b)
    285 {
    286     struct amount_msat msatb;
    287 
    288     if (!amount_sat_to_msat(&msatb, b))
    289         return false;
    290 
    291     return amount_msat_sub(val, a, msatb);
    292 }
    293 
    294 WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val,
    295                         struct amount_sat a,
    296                         struct amount_msat b)
    297 {
    298     struct amount_msat msata;
    299 
    300     if (!amount_sat_to_msat(&msata, a))
    301         return false;
    302 
    303     return amount_msat_sub(val, msata, b);
    304 }
    305 
    306 WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val,
    307                         struct amount_msat a,
    308                         struct amount_sat b)
    309 {
    310     struct amount_msat msatb;
    311 
    312     if (!amount_sat_to_msat(&msatb, b))
    313         return false;
    314 
    315     return amount_msat_add(val, a, msatb);
    316 }
    317 
    318 WARN_UNUSED_RESULT bool amount_msat_scale(struct amount_msat *val,
    319                       struct amount_msat msat,
    320                       double scale)
    321 {
    322     double scaled = msat.millisatoshis * scale;
    323 
    324     /* If mantissa is < 64 bits, a naive "if (scaled >
    325      * UINT64_MAX)" doesn't work.  Stick to powers of 2. */
    326     if (scaled >= (double)((u64)1 << 63) * 2)
    327         return false;
    328     val->millisatoshis = scaled;
    329     return true;
    330 }
    331 
    332 WARN_UNUSED_RESULT bool amount_sat_scale(struct amount_sat *val,
    333                      struct amount_sat sat,
    334                      double scale)
    335 {
    336     double scaled = sat.satoshis * scale;
    337 
    338     /* If mantissa is < 64 bits, a naive "if (scaled >
    339      * UINT64_MAX)" doesn't work.  Stick to powers of 2. */
    340     if (scaled >= (double)((u64)1 << 63) * 2)
    341         return false;
    342     val->satoshis = scaled;
    343     return true;
    344 }
    345 
    346 bool amount_sat_eq(struct amount_sat a, struct amount_sat b)
    347 {
    348     return a.satoshis == b.satoshis;
    349 }
    350 
    351 bool amount_sat_zero(struct amount_sat a)
    352 {
    353     return a.satoshis == 0;
    354 }
    355 
    356 bool amount_msat_zero(struct amount_msat a)
    357 {
    358     return a.millisatoshis == 0;
    359 }
    360 
    361 bool amount_msat_eq(struct amount_msat a, struct amount_msat b)
    362 {
    363     return a.millisatoshis == b.millisatoshis;
    364 }
    365 
    366 bool amount_sat_greater(struct amount_sat a, struct amount_sat b)
    367 {
    368     return a.satoshis > b.satoshis;
    369 }
    370 
    371 bool amount_msat_greater(struct amount_msat a, struct amount_msat b)
    372 {
    373     return a.millisatoshis > b.millisatoshis;
    374 }
    375 
    376 bool amount_sat_greater_eq(struct amount_sat a, struct amount_sat b)
    377 {
    378     return a.satoshis >= b.satoshis;
    379 }
    380 
    381 bool amount_msat_greater_eq(struct amount_msat a, struct amount_msat b)
    382 {
    383     return a.millisatoshis >= b.millisatoshis;
    384 }
    385 
    386 bool amount_sat_less(struct amount_sat a, struct amount_sat b)
    387 {
    388     return a.satoshis < b.satoshis;
    389 }
    390 
    391 bool amount_msat_less(struct amount_msat a, struct amount_msat b)
    392 {
    393     return a.millisatoshis < b.millisatoshis;
    394 }
    395 
    396 bool amount_sat_less_eq(struct amount_sat a, struct amount_sat b)
    397 {
    398     return a.satoshis <= b.satoshis;
    399 }
    400 
    401 bool amount_msat_less_eq(struct amount_msat a, struct amount_msat b)
    402 {
    403     return a.millisatoshis <= b.millisatoshis;
    404 }
    405 
    406 bool amount_msat_greater_sat(struct amount_msat msat, struct amount_sat sat)
    407 {
    408     struct amount_msat msat_from_sat;
    409 
    410     if (!amount_sat_to_msat(&msat_from_sat, sat))
    411         return false;
    412     return msat.millisatoshis > msat_from_sat.millisatoshis;
    413 }
    414 
    415 bool amount_msat_greater_eq_sat(struct amount_msat msat, struct amount_sat sat)
    416 {
    417     struct amount_msat msat_from_sat;
    418 
    419     if (!amount_sat_to_msat(&msat_from_sat, sat))
    420         return false;
    421     return msat.millisatoshis >= msat_from_sat.millisatoshis;
    422 }
    423 
    424 bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat)
    425 {
    426     struct amount_msat msat_from_sat;
    427 
    428     if (!amount_sat_to_msat(&msat_from_sat, sat))
    429         return false;
    430     return msat.millisatoshis < msat_from_sat.millisatoshis;
    431 }
    432 
    433 bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat)
    434 {
    435     struct amount_msat msat_from_sat;
    436 
    437     if (!amount_sat_to_msat(&msat_from_sat, sat))
    438         return false;
    439     return msat.millisatoshis <= msat_from_sat.millisatoshis;
    440 }
    441 
    442 bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat)
    443 {
    444     struct amount_msat msat_from_sat;
    445 
    446     if (!amount_sat_to_msat(&msat_from_sat, sat))
    447         return false;
    448 
    449     return msat.millisatoshis == msat_from_sat.millisatoshis;
    450 }
    451 
    452 bool amount_msat_to_u32(struct amount_msat msat, u32 *millisatoshis)
    453 {
    454     if (amount_msat_greater_eq(msat, AMOUNT_MSAT(0x100000000)))
    455         return false;
    456     *millisatoshis = (u32)msat.millisatoshis;
    457     return true;
    458 }
    459 
    460 struct amount_msat amount_msat(u64 millisatoshis)
    461 {
    462     struct amount_msat msat;
    463 
    464     msat.millisatoshis = millisatoshis;
    465     return msat;
    466 }
    467 
    468 struct amount_sat amount_sat(u64 satoshis)
    469 {
    470     struct amount_sat sat;
    471 
    472     sat.satoshis = satoshis;
    473     return sat;
    474 }
    475 
    476 double amount_msat_ratio(struct amount_msat a, struct amount_msat b)
    477 {
    478     return (double)a.millisatoshis / b.millisatoshis;
    479 }
    480 
    481 struct amount_msat amount_msat_div(struct amount_msat msat, u64 div)
    482 {
    483     msat.millisatoshis /= div;
    484     return msat;
    485 }
    486 
    487 struct amount_sat amount_sat_div(struct amount_sat sat, u64 div)
    488 {
    489     sat.satoshis /= div;
    490     return sat;
    491 }
    492 
    493 bool amount_msat_fee(struct amount_msat *fee,
    494              struct amount_msat amt,
    495              u32 fee_base_msat,
    496              u32 fee_proportional_millionths)
    497 {
    498     struct amount_msat fee_base, fee_prop;
    499 
    500     /* BOLT #7:
    501      *
    502      *   - SHOULD accept HTLCs that pay a fee equal to or greater than:
    503      *    - fee_base_msat + ( amount_to_forward * fee_proportional_millionths / 1000000 )
    504      */
    505     fee_base.millisatoshis = fee_base_msat;
    506 
    507     if (mul_overflows_u64(amt.millisatoshis, fee_proportional_millionths))
    508         return false;
    509     fee_prop.millisatoshis = amt.millisatoshis * fee_proportional_millionths
    510         / 1000000;
    511 
    512     return amount_msat_add(fee, fee_base, fee_prop);
    513 }
    514 
    515 bool amount_msat_add_fee(struct amount_msat *amt,
    516              u32 fee_base_msat,
    517              u32 fee_proportional_millionths)
    518 {
    519     struct amount_msat fee;
    520 
    521     if (!amount_msat_fee(&fee, *amt,
    522                  fee_base_msat, fee_proportional_millionths))
    523         return false;
    524     return amount_msat_add(amt, *amt, fee);
    525 }
    526 
    527 struct amount_sat amount_tx_fee(u32 fee_per_kw, size_t weight)
    528 {
    529     struct amount_sat fee;
    530 
    531     /* If this overflows, weight must be > 2^32, which is not a real tx */
    532     assert(!mul_overflows_u64(fee_per_kw, weight));
    533     fee.satoshis = (u64)fee_per_kw * weight / 1000;
    534 
    535     return fee;
    536 }
    537 
    538 /*
    539 struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max)
    540 {
    541     struct amount_msat msat;
    542 
    543     msat.millisatoshis = fromwire_u64(cursor, max);
    544     return msat;
    545 }
    546 
    547 struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max)
    548 {
    549     struct amount_sat sat;
    550 
    551     sat.satoshis = fromwire_u64(cursor, max);
    552     return sat;
    553 }
    554 
    555 void towire_amount_msat(u8 **pptr, const struct amount_msat msat)
    556 {
    557     towire_u64(pptr, msat.millisatoshis);
    558 }
    559 
    560 void towire_amount_sat(u8 **pptr, const struct amount_sat sat)
    561 {
    562     towire_u64(pptr, sat.satoshis);
    563 }
    564 
    565 
    566 */