Browse Source

amount: correctly parse amount strings we generate

This:
	- Allows `.*btc` amounts (without post-decimal)
	- Avoids creating decimals when amount is 0 btc
	- Corrects our handling of the suffixes (memeqstr would
	  sometimes return false because of null-termination)

Changelog-Fixed: We are now able to parse any amount string (XXXmsat, XX.XXXbtc, ..) we create.

Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
travis-experimental
Antoine Poinsot 4 years ago
committed by Christian Decker
parent
commit
ae4dc231c1
  1. 32
      common/amount.c
  2. 2
      common/test/run-amount.c

32
common/amount.c

@ -33,6 +33,9 @@ const char *fmt_amount_msat_btc(const tal_t *ctx,
const struct amount_msat *msat, const struct amount_msat *msat,
bool append_unit) bool append_unit)
{ {
if (msat->millisatoshis == 0)
return tal_fmt(ctx, append_unit ? "0btc" : "0");
return tal_fmt(ctx, "%"PRIu64".%011"PRIu64"%s", return tal_fmt(ctx, "%"PRIu64".%011"PRIu64"%s",
msat->millisatoshis / MSAT_PER_BTC, msat->millisatoshis / MSAT_PER_BTC,
msat->millisatoshis % MSAT_PER_BTC, msat->millisatoshis % MSAT_PER_BTC,
@ -49,6 +52,9 @@ const char *fmt_amount_sat_btc(const tal_t *ctx,
const struct amount_sat *sat, const struct amount_sat *sat,
bool append_unit) bool append_unit)
{ {
if (sat->satoshis == 0)
return tal_fmt(ctx, append_unit ? "0btc" : "0");
return tal_fmt(ctx, "%"PRIu64".%08"PRIu64"%s", return tal_fmt(ctx, "%"PRIu64".%08"PRIu64"%s",
sat->satoshis / SAT_PER_BTC, sat->satoshis / SAT_PER_BTC,
sat->satoshis % SAT_PER_BTC, sat->satoshis % SAT_PER_BTC,
@ -80,7 +86,8 @@ static bool breakup(const char *str, size_t slen,
*suffix_len = 0; *suffix_len = 0;
for (i = 0;; i++) { for (i = 0;; i++) {
if (i >= slen) /* The string may be null-terminated. */
if (i >= slen || str[i] == '\0')
return i != 0; return i != 0;
if (cisdigit(str[i])) if (cisdigit(str[i]))
(*whole_number_len)++; (*whole_number_len)++;
@ -93,7 +100,7 @@ static bool breakup(const char *str, size_t slen,
*post_decimal_ptr = str + i; *post_decimal_ptr = str + i;
for (;; i++) { for (;; i++) {
/* True if > 0 decimals. */ /* True if > 0 decimals. */
if (i >= slen) if (i >= slen || str[i] == '\0')
return str + i != *post_decimal_ptr; return str + i != *post_decimal_ptr;
if (cisdigit(str[i])) if (cisdigit(str[i]))
(*post_decimal_len)++; (*post_decimal_len)++;
@ -168,14 +175,18 @@ bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen)
if (!post_decimal_ptr && !suffix_ptr) if (!post_decimal_ptr && !suffix_ptr)
return from_number(&msat->millisatoshis, s, whole_number_len, 0); return from_number(&msat->millisatoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "msat")) if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat"))
return from_number(&msat->millisatoshis, s, whole_number_len, 0); return from_number(&msat->millisatoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "sat")) if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat"))
return from_number(&msat->millisatoshis, s, whole_number_len, 3); return from_number(&msat->millisatoshis, s, whole_number_len, 3);
if (post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "btc")) if (memstarts_str(suffix_ptr, suffix_len, "btc")) {
if (post_decimal_len > 0)
return from_numbers(&msat->millisatoshis, return from_numbers(&msat->millisatoshis,
s, whole_number_len, 11, s, whole_number_len, 11,
post_decimal_ptr, post_decimal_len); post_decimal_ptr, post_decimal_len);
return from_number(&msat->millisatoshis, s, whole_number_len, 11);
}
return false; return false;
} }
@ -198,21 +209,24 @@ bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen)
if (!post_decimal_ptr && !suffix_ptr) if (!post_decimal_ptr && !suffix_ptr)
return from_number(&sat->satoshis, s, whole_number_len, 0); return from_number(&sat->satoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "sat")) if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat"))
return from_number(&sat->satoshis, s, whole_number_len, 0); return from_number(&sat->satoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "msat")) { if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat")) {
if (!memends(s, whole_number_len, "000", strlen("000"))) { if (!memends(s, whole_number_len, "000", strlen("000"))) {
if (memeqstr(s, whole_number_len, "0")) if (memstarts_str(s, whole_number_len, "0"))
return from_number(&sat->satoshis, s, return from_number(&sat->satoshis, s,
whole_number_len, 0); whole_number_len, 0);
return false; return false;
} }
return from_number(&sat->satoshis, s, whole_number_len - 3, 0); return from_number(&sat->satoshis, s, whole_number_len - 3, 0);
} }
if (post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "btc")) if (memstarts_str(suffix_ptr, suffix_len, "btc")) {
if (post_decimal_len > 0)
return from_numbers(&sat->satoshis, return from_numbers(&sat->satoshis,
s, whole_number_len, 8, s, whole_number_len, 8,
post_decimal_ptr, post_decimal_len); post_decimal_ptr, post_decimal_len);
return from_number(&sat->satoshis, s, whole_number_len, 8);
}
return false; return false;
} }

2
common/test/run-amount.c

@ -128,7 +128,6 @@ int main(void)
PASS_MSAT(&msat, "1.234567890btc", 123456789000); PASS_MSAT(&msat, "1.234567890btc", 123456789000);
PASS_MSAT(&msat, "1.2345678901btc", 123456789010); PASS_MSAT(&msat, "1.2345678901btc", 123456789010);
PASS_MSAT(&msat, "1.23456789012btc", 123456789012); PASS_MSAT(&msat, "1.23456789012btc", 123456789012);
FAIL_MSAT(&msat, "1btc");
FAIL_MSAT(&msat, "1.000000000000btc"); FAIL_MSAT(&msat, "1.000000000000btc");
FAIL_MSAT(&msat, "-1.23456789btc"); FAIL_MSAT(&msat, "-1.23456789btc");
FAIL_MSAT(&msat, "-1.23456789012btc"); FAIL_MSAT(&msat, "-1.23456789012btc");
@ -177,7 +176,6 @@ int main(void)
PASS_SAT(&sat, "1.2345678btc", 123456780); PASS_SAT(&sat, "1.2345678btc", 123456780);
PASS_SAT(&sat, "1.23456789btc", 123456789); PASS_SAT(&sat, "1.23456789btc", 123456789);
FAIL_SAT(&sat, "1.234567890btc"); FAIL_SAT(&sat, "1.234567890btc");
FAIL_SAT(&sat, "1btc");
FAIL_SAT(&sat, "-1.23456789btc"); FAIL_SAT(&sat, "-1.23456789btc");
/* Overflowingly big. */ /* Overflowingly big. */

Loading…
Cancel
Save