mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-22 00:24:19 +01:00
invoice: don't allow zero-value invoices.
You can't pay them anyway, and at least one person used 0 instead of "any". Closes: #3808 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Changed: JSON-RPC: `invoice` no longer accepts zero amounts (did you mean "any"?)
This commit is contained in:
2
doc/lightning-invoice.7
generated
2
doc/lightning-invoice.7
generated
@@ -16,7 +16,7 @@ invoice, if any exists\.
|
|||||||
|
|
||||||
|
|
||||||
The \fImsatoshi\fR parameter can be the string "any", which creates an
|
The \fImsatoshi\fR parameter can be the string "any", which creates an
|
||||||
invoice that can be paid with any amount\. Otherwise it is in
|
invoice that can be paid with any amount\. Otherwise it is a positive value in
|
||||||
millisatoshi precision; it can be a whole number, or a whole number
|
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
|
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\.
|
in \fIsat\fR, or a number with 1 to 11 decimal places ending in \fIbtc\fR\.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ lightning daemon can use to pay this invoice. This token includes a
|
|||||||
invoice, if any exists.
|
invoice, if any exists.
|
||||||
|
|
||||||
The *msatoshi* parameter can be the string "any", which creates an
|
The *msatoshi* parameter can be the string "any", which creates an
|
||||||
invoice that can be paid with any amount. Otherwise it is in
|
invoice that can be paid with any amount. Otherwise it is a positive value in
|
||||||
millisatoshi precision; it can be a whole number, or a whole number
|
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
|
ending in *msat* or *sat*, or a number with three decimal places ending
|
||||||
in *sat*, or a number with 1 to 11 decimal places ending in *btc*.
|
in *sat*, or a number with 1 to 11 decimal places ending in *btc*.
|
||||||
|
|||||||
@@ -826,22 +826,24 @@ static struct route_info **unpack_routes(const tal_t *ctx,
|
|||||||
}
|
}
|
||||||
#endif /* DEVELOPER */
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
static struct command_result *param_msat_or_any(struct command *cmd,
|
static struct command_result *param_positive_msat_or_any(struct command *cmd,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *buffer,
|
const char *buffer,
|
||||||
const jsmntok_t *tok,
|
const jsmntok_t *tok,
|
||||||
struct amount_msat **msat)
|
struct amount_msat **msat)
|
||||||
{
|
{
|
||||||
if (json_tok_streq(buffer, tok, "any")) {
|
if (json_tok_streq(buffer, tok, "any")) {
|
||||||
*msat = NULL;
|
*msat = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*msat = tal(cmd, struct amount_msat);
|
*msat = tal(cmd, struct amount_msat);
|
||||||
if (parse_amount_msat(*msat, buffer + tok->start, tok->end - tok->start))
|
if (parse_amount_msat(*msat, buffer + tok->start, tok->end - tok->start)
|
||||||
|
&& !amount_msat_eq(**msat, AMOUNT_MSAT(0)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
"'%s' should be millisatoshis or 'any', not '%.*s'",
|
"'%s' should be positive millisatoshis or 'any',"
|
||||||
|
" not '%.*s'",
|
||||||
name,
|
name,
|
||||||
tok->end - tok->start,
|
tok->end - tok->start,
|
||||||
buffer + tok->start);
|
buffer + tok->start);
|
||||||
@@ -963,7 +965,7 @@ static struct command_result *json_invoice(struct command *cmd,
|
|||||||
info->cmd = cmd;
|
info->cmd = cmd;
|
||||||
|
|
||||||
if (!param(cmd, buffer, params,
|
if (!param(cmd, buffer, params,
|
||||||
p_req("msatoshi", param_msat_or_any, &msatoshi_val),
|
p_req("msatoshi", param_positive_msat_or_any, &msatoshi_val),
|
||||||
p_req("label", param_label, &info->label),
|
p_req("label", param_label, &info->label),
|
||||||
p_req("description", param_escaped_string, &desc_val),
|
p_req("description", param_escaped_string, &desc_val),
|
||||||
p_opt_def("expiry", param_time, &expiry, 3600*24*7),
|
p_opt_def("expiry", param_time, &expiry, 3600*24*7),
|
||||||
|
|||||||
@@ -59,6 +59,26 @@ def test_invoice(node_factory, chainparams):
|
|||||||
l2.rpc.invoice(4294967295, 'inv3', '?')
|
l2.rpc.invoice(4294967295, 'inv3', '?')
|
||||||
|
|
||||||
|
|
||||||
|
def test_invoice_zeroval(node_factory):
|
||||||
|
"""A zero value invoice is unpayable, did you mean 'any'?"""
|
||||||
|
l1 = node_factory.get_node()
|
||||||
|
|
||||||
|
with pytest.raises(RpcError, match=r"positive .* not '0'"):
|
||||||
|
l1.rpc.invoice(0, 'inv', '?')
|
||||||
|
|
||||||
|
with pytest.raises(RpcError, match=r"positive .* not '0msat'"):
|
||||||
|
l1.rpc.invoice('0msat', 'inv', '?')
|
||||||
|
|
||||||
|
with pytest.raises(RpcError, match=r"positive .* not '0sat'"):
|
||||||
|
l1.rpc.invoice('0sat', 'inv', '?')
|
||||||
|
|
||||||
|
with pytest.raises(RpcError, match=r"positive .* not '0.00000000btc'"):
|
||||||
|
l1.rpc.invoice('0.00000000btc', 'inv', '?')
|
||||||
|
|
||||||
|
with pytest.raises(RpcError, match=r"positive .* not '0.00000000000btc'"):
|
||||||
|
l1.rpc.invoice('0.00000000000btc', 'inv', '?')
|
||||||
|
|
||||||
|
|
||||||
def test_invoice_weirdstring(node_factory):
|
def test_invoice_weirdstring(node_factory):
|
||||||
l1 = node_factory.get_node()
|
l1 = node_factory.get_node()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user