Skip to content

Commit

Permalink
JSON: allow any number of decimal points when parsing 'btc' suffix.
Browse files Browse the repository at this point in the history
I tried to fundchannel 0.01btc, and of course it wanted 8 decimals exactly.
If I can't get this right, it's probably a bad idea.

I still don't allow whole number of btc though, since that's probably a mistake
and you're not supposed to put that much in c-lightning yet :)

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Feb 23, 2019
1 parent 9f3627f commit f5dc8b9
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 69 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- lightning-cli: `help <cmd>` finds man pages even if `make install` not run.
- JSON API: `getroute`, `invoice`, `sendpay` and `pay` commands `msatoshi`
parameter can have suffixes `msat`, `sat` (optionally with 3 decimals) or `btc`
(with 8 or 11 decimals).
(with 1 to 11 decimal places).
- JSON API: `fundchannel` and `withdraw` commands `satoshi`
parameter can have suffixes `msat` (must end in `000`), `sat` or `btc`
(with 8 decimals).
(with 1 to 8 decimal places).
- JSON API: `decodepay`, `getroute`, `sendpay`, `pay`, `listpeers`, `listfunds`, `listchannels` and
all invoice commands now return an `amount_msat` field which has an `msat` suffix.
- JSON API: `listfunds` `channels` now has `_msat` fields for each existing raw amount field, with `msat` suffix.
Expand Down
64 changes: 28 additions & 36 deletions common/amount.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ static bool breakup(const char *str, size_t slen,
return true;
}

static bool from_number(u64 *res, const char *s, size_t len, u64 multipler)
static bool from_number(u64 *res, const char *s, size_t len, int tens_factor)
{
if (len == 0)
return false;
Expand All @@ -118,19 +118,25 @@ static bool from_number(u64 *res, const char *s, size_t len, u64 multipler)
return false;
*res += s[i] - '0';
}
if (mul_overflows_u64(*res, multipler))
return false;
*res *= multipler;
while (tens_factor > 0) {
if (mul_overflows_u64(*res, 10))
return false;
*res *= 10;
tens_factor--;
}
return true;
}

static bool from_numbers(u64 *res,
const char *s1, size_t len1, u64 multipler1,
const char *s2, size_t len2, u64 multipler2)
const char *s1, size_t len1, int tens_factor,
const char *s2, size_t len2)
{
u64 p1, p2;
if (!from_number(&p1, s1, len1, multipler1)
|| !from_number(&p2, s2, len2, multipler2))
if (len2 > tens_factor)
return false;

if (!from_number(&p1, s1, len1, tens_factor)
|| !from_number(&p2, s2, len2, tens_factor - len2))
return false;

if (add_overflows_u64(p1, p2))
Expand All @@ -144,8 +150,7 @@ static bool from_numbers(u64 *res,
* [0-9]+ => millisatoshi.
* [0-9]+msat => millisatoshi.
* [0-9]+sat => *1000 -> millisatopshi.
* [0-9]+.[0-9]{8}btc => *1000 -> millisatoshi.
* [0-9]+.[0-9]{11}btc => millisatoshi.
* [0-9]+.[0-9]{1,11}btc => millisatoshi.
*/
bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen)
{
Expand All @@ -158,33 +163,23 @@ bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen)
return false;

if (!post_decimal_ptr && !suffix_ptr)
return from_number(&msat->millisatoshis, s, whole_number_len, 1);
return from_number(&msat->millisatoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "msat"))
return from_number(&msat->millisatoshis, s, whole_number_len, 1);
return from_number(&msat->millisatoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "sat"))
return from_number(&msat->millisatoshis, s, whole_number_len,
MSAT_PER_SAT);
if (post_decimal_ptr && post_decimal_len == 8
&& memeqstr(suffix_ptr, suffix_len, "btc"))
return from_numbers(&msat->millisatoshis,
s, whole_number_len,
MSAT_PER_BTC,
post_decimal_ptr, post_decimal_len,
MSAT_PER_SAT);
if (post_decimal_ptr && post_decimal_len == 11
&& memeqstr(suffix_ptr, suffix_len, "btc"))
return from_number(&msat->millisatoshis, s, whole_number_len, 3);
if (post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "btc"))
return from_numbers(&msat->millisatoshis,
s, whole_number_len,
MSAT_PER_BTC,
post_decimal_ptr, post_decimal_len, 1);
s, whole_number_len, 11,
post_decimal_ptr, post_decimal_len);
return false;
}

/* Valid strings:
* [0-9]+ => satoshi.
* [0-9]+sat => satoshi.
* [0-9]+000msat => satoshi.
* [0-9]+.[0-9]{8}btc => satoshi.
* [0-9]+.[0-9]{1,8}btc => satoshi.
*/
bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen)
{
Expand All @@ -197,21 +192,18 @@ bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen)
return false;

if (!post_decimal_ptr && !suffix_ptr)
return from_number(&sat->satoshis, s, whole_number_len, 1);
return from_number(&sat->satoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "sat"))
return from_number(&sat->satoshis, s, whole_number_len, 1);
return from_number(&sat->satoshis, s, whole_number_len, 0);
if (!post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "msat")) {
if (!memends(s, whole_number_len, "000", strlen("000")))
return false;
return from_number(&sat->satoshis, s, whole_number_len - 3, 1);
return from_number(&sat->satoshis, s, whole_number_len - 3, 0);
}
if (post_decimal_ptr && post_decimal_len == 8
&& memeqstr(suffix_ptr, suffix_len, "btc"))
if (post_decimal_ptr && memeqstr(suffix_ptr, suffix_len, "btc"))
return from_numbers(&sat->satoshis,
s, whole_number_len,
SAT_PER_BTC,
post_decimal_ptr, post_decimal_len,
1);
s, whole_number_len, 8,
post_decimal_ptr, post_decimal_len);

return false;
}
Expand Down
5 changes: 2 additions & 3 deletions common/amount.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,15 @@ const char *fmt_amount_sat(const tal_t *ctx, const struct amount_sat *sat);
* [0-9]+ => millisatoshi.
* [0-9]+msat => millisatoshi.
* [0-9]+sat => *1000 -> millisatopshi.
* [0-9]+.[0-9]{8}btc => *1000 -> millisatoshi.
* [0-9]+.[0-9]{11}btc => millisatoshi.
* [0-9]+.[0-9]{1,11}btc => millisatoshi.
*/
bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen);

/* Valid strings:
* [0-9]+ => satoshi.
* [0-9]+sat => satoshi.
* [0-9]+000msat => satoshi.
* [0-9]+.[0-9]{8}btc => satoshi.
* [0-9]+.[0-9]{1,8}btc => satoshi.
*/
bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen);

Expand Down
24 changes: 19 additions & 5 deletions common/test/run-amount.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,19 @@ int main(void)
PASS_MSAT(&msat, "0.00000000000btc", 0);
PASS_MSAT(&msat, "0.00000001btc", 1000);
PASS_MSAT(&msat, "0.00000000001btc", 1);
PASS_MSAT(&msat, "1.2btc", 120000000000);
PASS_MSAT(&msat, "1.23btc", 123000000000);
PASS_MSAT(&msat, "1.234btc", 123400000000);
PASS_MSAT(&msat, "1.2345btc", 123450000000);
PASS_MSAT(&msat, "1.23456btc", 123456000000);
PASS_MSAT(&msat, "1.234567btc", 123456700000);
PASS_MSAT(&msat, "1.2345678btc", 123456780000);
PASS_MSAT(&msat, "1.23456789btc", 123456789000);
PASS_MSAT(&msat, "1.234567890btc", 123456789000);
PASS_MSAT(&msat, "1.2345678901btc", 123456789010);
PASS_MSAT(&msat, "1.23456789012btc", 123456789012);
FAIL_MSAT(&msat, "1btc");
FAIL_MSAT(&msat, "1.0000000btc");
FAIL_MSAT(&msat, "1.000000000btc");
FAIL_MSAT(&msat, "1.000000000000btc");
FAIL_MSAT(&msat, "-1.23456789btc");
FAIL_MSAT(&msat, "-1.23456789012btc");

Expand Down Expand Up @@ -95,10 +103,16 @@ int main(void)
PASS_SAT(&sat, "0.00000001btc", 1);
FAIL_SAT(&sat, "0.00000000001btc");
PASS_SAT(&sat, "1.23456789btc", 123456789);
FAIL_SAT(&sat, "1.23456789012btc");
PASS_SAT(&sat, "1.2btc", 120000000);
PASS_SAT(&sat, "1.23btc", 123000000);
PASS_SAT(&sat, "1.234btc", 123400000);
PASS_SAT(&sat, "1.2345btc", 123450000);
PASS_SAT(&sat, "1.23456btc", 123456000);
PASS_SAT(&sat, "1.234567btc", 123456700);
PASS_SAT(&sat, "1.2345678btc", 123456780);
PASS_SAT(&sat, "1.23456789btc", 123456789);
FAIL_SAT(&sat, "1.234567890btc");
FAIL_SAT(&sat, "1btc");
FAIL_SAT(&sat, "1.0000000btc");
FAIL_SAT(&sat, "1.000000000btc");
FAIL_SAT(&sat, "-1.23456789btc");

/* Overflowingly big. */
Expand Down
6 changes: 3 additions & 3 deletions doc/lightning-fundchannel.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-fundchannel
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 02/18/2019
.\" Date: 02/23/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-FUNDCHANN" "7" "02/18/2019" "\ \&" "\ \&"
.TH "LIGHTNING\-FUNDCHANN" "7" "02/23/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand Down Expand Up @@ -38,7 +38,7 @@ The \fBfundchannel\fR RPC command opens a payment channel with a peer by committ
.sp
\fIid\fR is the peer id obtained from \fBconnect\fR\&.
.sp
\fIsatoshi\fR is the amount in satoshis taken from the internal wallet to fund the channel\&. The string \fIall\fR can be used to specify all available funds (or 16777215 satoshi if more is available)\&. Otherwise, it is in satoshi precision; it can be a whole number, a whole number ending in \fIsat\fR, a whole number ending in \fI000msat\fR, or a number with 8 decimal places ending in \fIbtc\fR\&. The value cannot be less than the dust limit, currently set to 546, nor more than 16777215 satoshi\&.
\fIsatoshi\fR is the amount in satoshis taken from the internal wallet to fund the channel\&. The string \fIall\fR can be used to specify all available funds (or 16777215 satoshi if more is available)\&. Otherwise, it is in satoshi precision; it can be a whole number, a whole number ending in \fIsat\fR, a whole number ending in \fI000msat\fR, or a number with 1 to 8 decimal places ending in \fIbtc\fR\&. The value cannot be less than the dust limit, currently set to 546, nor more than 16777215 satoshi\&.
.sp
\fIfeerate\fR is an optional feerate used for the opening transaction and as initial feerate for commitment and HTLC transactions\&. It can be one of the strings \fIurgent\fR, \fInormal\fR or \fIslow\fR to use lightningd\(cqs internal estimates: \fInormal\fR is the default\&.
.sp
Expand Down
2 changes: 1 addition & 1 deletion doc/lightning-fundchannel.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ for the channel.

'satoshi' is the amount in satoshis taken from the internal wallet to fund the channel.
The string 'all' can be used to specify all available funds (or 16777215 satoshi if more is available).
Otherwise, it is in satoshi precision; it can be a whole number, a whole number ending in 'sat', a whole number ending in '000msat', or a number with 8 decimal places ending in 'btc'.
Otherwise, it is in satoshi precision; it can be a whole number, a whole number ending in 'sat', a whole number ending in '000msat', or a number with 1 to 8 decimal places ending in 'btc'.
The value cannot be less than the dust limit, currently set to 546, nor more
than 16777215 satoshi.

Expand Down
6 changes: 3 additions & 3 deletions doc/lightning-invoice.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-invoice
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 02/18/2019
.\" Date: 02/23/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-INVOICE" "7" "02/18/2019" "\ \&" "\ \&"
.TH "LIGHTNING\-INVOICE" "7" "02/23/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand Down Expand Up @@ -36,7 +36,7 @@ lightning-invoice \- Command for accepting payments\&.
.sp
The \fBinvoice\fR RPC command creates the expectation of a payment of a given amount of milli\-satoshi: it returns a unique token which another lightning daemon can use to pay this invoice\&. This token includes a \fIroute hint\fR description of an incoming channel with capacity to pay the invoice, if any exists\&.
.sp
The \fImsatoshi\fR parameter can be the string "any", which creates an invoice that can be paid with any amount\&. Otherwise it is in millisatoshi precision; it can be a whole number, or a whole number ending in \fImsat\fR or \fIsat\fR, or a number with three decimal places ending in \fIsat\fR, or a number with 8 or 11 decimal places ending in \fIbtc\fR\&.
The \fImsatoshi\fR parameter can be the string "any", which creates an invoice that can be paid with any amount\&. Otherwise it is in millisatoshi precision; it can be a whole number, or a whole number ending in \fImsat\fR or \fIsat\fR, or a number with three decimal places ending in \fIsat\fR, or a number with 1 to 11 decimal places ending in \fIbtc\fR\&.
.sp
The \fIlabel\fR must be a unique string or number (which is treated as a string, so "01" is different from "1"); it is never revealed to other nodes on the lightning network, but it can be used to query the status of this invoice\&.
.sp
Expand Down
2 changes: 1 addition & 1 deletion doc/lightning-invoice.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The 'msatoshi' parameter can be the string "any", which creates an invoice
that can be paid with any amount. Otherwise it is in millisatoshi
precision; it can be a whole number, or a whole number ending in 'msat' or
'sat', or a number with three decimal places ending in 'sat', or a number
with 8 or 11 decimal places ending in 'btc'.
with 1 to 11 decimal places ending in 'btc'.

The 'label' must be a unique string or number (which is treated as a
string, so "01" is different from "1"); it is never revealed to other
Expand Down
6 changes: 3 additions & 3 deletions doc/lightning-pay.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-pay
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 02/18/2019
.\" Date: 02/23/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-PAY" "7" "02/18/2019" "\ \&" "\ \&"
.TH "LIGHTNING\-PAY" "7" "02/23/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand All @@ -34,7 +34,7 @@ lightning-pay \- Command for sending a payment to a BOLT11 invoice
\fBpay\fR \fIbolt11\fR [\fImsatoshi\fR] [\fIdescription\fR] [\fIriskfactor\fR] [\fImaxfeepercent\fR] [\fIretry_for\fR] [\fImaxdelay\fR] [\fIexemptfee\fR]
.SH "DESCRIPTION"
.sp
The \fBpay\fR RPC command attempts to find a route to the given destination, and send the funds it asks for\&. If the \fIbolt11\fR does not contain an amount, \fImsatoshi\fR is required, otherwise if it is specified it must be \fInull\fR\&. \fImsatoshi\fR is in millisatoshi precision; it can be a whole number, or a whole number with suffix \fImsat\fR, \fIsat\fR, or \fIbtc\fR, or a three decimal point number with suffix \fIsat\fR, or an 8 or 11 decimal point number postfixed by \fIbtc\fR\&.
The \fBpay\fR RPC command attempts to find a route to the given destination, and send the funds it asks for\&. If the \fIbolt11\fR does not contain an amount, \fImsatoshi\fR is required, otherwise if it is specified it must be \fInull\fR\&. \fImsatoshi\fR is in millisatoshi precision; it can be a whole number, or a whole number with suffix \fImsat\fR or \fIsat\fR, or a three decimal point number with suffix \fIsat\fR, or an 1 to 11 decimal point number suffixed by \fIbtc\fR\&.
.sp
If \fIbolt11\fR contains a description hash (\fIh\fR field) \fIdescription\fR is required, otherwise it is unused\&. The \fIriskfactor\fR is described in detail in lightning\-getroute(7), and defaults to 10\&. The \fImaxfeepercent\fR limits the money paid in fees, and defaults to 0\&.5\&. The maxfeepercent\*(Aq is a percentage of the amount that is to be paid\&. The `exemptfee option can be used for tiny payments which would be dominated by the fee leveraged by forwarding nodes\&. Setting exemptfee allows the maxfeepercent check to be skipped on fees that are smaller than exemptfee (default: 5000 millisatoshi)\&.
.sp
Expand Down
6 changes: 3 additions & 3 deletions doc/lightning-pay.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ The *pay* RPC command attempts to find a route to the given destination,
and send the funds it asks for. If the 'bolt11' does not contain an amount,
'msatoshi' is required, otherwise if it is specified it must be 'null'.
'msatoshi' is in millisatoshi precision; it can be a whole number, or
a whole number with suffix 'msat', 'sat', or 'btc', or a three decimal
point number with suffix 'sat', or an 8 or 11 decimal point number
postfixed by 'btc'.
a whole number with suffix 'msat' or 'sat', or a three decimal
point number with suffix 'sat', or an 1 to 11 decimal point number
suffixed by 'btc'.

If 'bolt11' contains a description hash ('h' field) 'description' is
required, otherwise it is unused. The 'riskfactor' is described in detail
Expand Down
6 changes: 3 additions & 3 deletions doc/lightning-sendpay.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-sendpay
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 02/18/2019
.\" Date: 02/23/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-SENDPAY" "7" "02/18/2019" "\ \&" "\ \&"
.TH "LIGHTNING\-SENDPAY" "7" "02/23/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand Down Expand Up @@ -42,7 +42,7 @@ The response will occur when the payment is on its way to the destination\&. The
.sp
The \fIdescription\fR parameter, if provided, will be returned in \fIwaitsendpay\fR and \fIlistpayments\fR results\&.
.sp
The \fImsatoshi\fR amount, if provided, is the amount that will be recorded as the target payment value\&. If not specified, it will be the final amount to the destination\&. If specified, then the final amount at the destination must be from the specified \fImsatoshi\fR to twice the specified \fImsatoshi\fR, inclusive\&. This is intended to obscure payments by overpaying slightly at the destination; the actual target payment is what should be specified as the \fImsatoshi\fR argument\&. \fImsatoshi\fR is in millisatoshi precision; it can be a whole number, or a whole number ending in \fImsat\fR or \fIsat\fR, or a number with three decimal places ending in \fIsat\fR, or a number with 8 or 11 decimal places ending in \fIbtc\fR\&.
The \fImsatoshi\fR amount, if provided, is the amount that will be recorded as the target payment value\&. If not specified, it will be the final amount to the destination\&. If specified, then the final amount at the destination must be from the specified \fImsatoshi\fR to twice the specified \fImsatoshi\fR, inclusive\&. This is intended to obscure payments by overpaying slightly at the destination; the actual target payment is what should be specified as the \fImsatoshi\fR argument\&. \fImsatoshi\fR is in millisatoshi precision; it can be a whole number, or a whole number ending in \fImsat\fR or \fIsat\fR, or a number with three decimal places ending in \fIsat\fR, or a number with 1 to 11 decimal places ending in \fIbtc\fR\&.
.sp
Once a payment has succeeded, calls to \fBsendpay\fR with the same \fIpayment_hash\fR but a different \fImsatoshi\fR or destination will fail; this prevents accidental multiple payments\&. Calls to \fBsendpay\fR with the same \fIpayment_hash\fR, \fImsatoshi\fR, and destination as a previous successful payment (even if a different route) will return immediately with success\&.
.SH "RETURN VALUE"
Expand Down
4 changes: 2 additions & 2 deletions doc/lightning-sendpay.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ the destination;
the actual target payment is what should be specified as the
'msatoshi' argument. 'msatoshi' is in millisatoshi precision; it can
be a whole number, or a whole number ending in 'msat' or 'sat', or a
number with three decimal places ending in 'sat', or a number with 8
or 11 decimal places ending in 'btc'.
number with three decimal places ending in 'sat', or a number with 1
to 11 decimal places ending in 'btc'.


Once a payment has succeeded, calls to *sendpay* with the same 'payment_hash'
Expand Down
Loading

0 comments on commit f5dc8b9

Please sign in to comment.