mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
pay: Do not clobber error messages if we fail decoding a bolt11
We were automatically falling back to bolt12 decoding, clobbering the fail message. Ultimately resulting in confusing error messages (expected prefix lni but got lnbtrc). Now we first determine which decoding we're trying to do, and then only decode accordingly. Changelog-Fixed: pay: Report the correct decoding error if bolt11 parsing fails.
This commit is contained in:
committed by
Rusty Russell
parent
ea92466025
commit
40e9d60ce0
@@ -1973,6 +1973,7 @@ static struct command_result *json_paymod(struct command *cmd,
|
|||||||
u64 invexpiry;
|
u64 invexpiry;
|
||||||
struct sha256 *local_offer_id;
|
struct sha256 *local_offer_id;
|
||||||
const struct tlv_invoice *b12;
|
const struct tlv_invoice *b12;
|
||||||
|
bool is_b12;
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
bool *use_shadow;
|
bool *use_shadow;
|
||||||
#endif
|
#endif
|
||||||
@@ -2003,31 +2004,45 @@ static struct command_result *json_paymod(struct command *cmd,
|
|||||||
p = payment_new(cmd, cmd, NULL /* No parent */, paymod_mods);
|
p = payment_new(cmd, cmd, NULL /* No parent */, paymod_mods);
|
||||||
p->invstring = tal_steal(p, b11str);
|
p->invstring = tal_steal(p, b11str);
|
||||||
|
|
||||||
b11 = bolt11_decode(cmd, b11str, plugin_feature_set(cmd->plugin),
|
is_b12 = strlen(b11str) > 3 &&
|
||||||
NULL, chainparams, &fail);
|
(strstarts(b11str, "lni") || strstarts(b11str, "lno") ||
|
||||||
if (b11) {
|
strstarts(b11str, "lnr"));
|
||||||
|
|
||||||
|
b11 = bolt11_decode(cmd, b11str, plugin_feature_set(cmd->plugin), NULL,
|
||||||
|
chainparams, &fail);
|
||||||
|
if (!is_b12) {
|
||||||
|
if (b11 == NULL)
|
||||||
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
|
"Invalid bolt11: %s", fail);
|
||||||
invmsat = b11->msat;
|
invmsat = b11->msat;
|
||||||
invexpiry = b11->timestamp + b11->expiry;
|
invexpiry = b11->timestamp + b11->expiry;
|
||||||
|
|
||||||
p->destination = tal_dup(p, struct node_id, &b11->receiver_id);
|
p->destination = tal_dup(p, struct node_id, &b11->receiver_id);
|
||||||
p->destination_has_tlv = feature_offered(b11->features,
|
p->destination_has_tlv =
|
||||||
OPT_VAR_ONION);
|
feature_offered(b11->features, OPT_VAR_ONION);
|
||||||
p->payment_hash = tal_dup(p, struct sha256, &b11->payment_hash);
|
p->payment_hash = tal_dup(p, struct sha256, &b11->payment_hash);
|
||||||
p->payment_secret = b11->payment_secret
|
p->payment_secret =
|
||||||
|
b11->payment_secret
|
||||||
? tal_dup(p, struct secret, b11->payment_secret)
|
? tal_dup(p, struct secret, b11->payment_secret)
|
||||||
: NULL;
|
: NULL;
|
||||||
p->routes = tal_steal(p, b11->routes);
|
p->routes = tal_steal(p, b11->routes);
|
||||||
p->min_final_cltv_expiry = b11->min_final_cltv_expiry;
|
p->min_final_cltv_expiry = b11->min_final_cltv_expiry;
|
||||||
p->features = tal_steal(p, b11->features);
|
p->features = tal_steal(p, b11->features);
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (feature_offered(b11->features, OPT_VAR_ONION)
|
if (feature_offered(b11->features, OPT_VAR_ONION) &&
|
||||||
&& !b11->payment_secret)
|
!b11->payment_secret)
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail(
|
||||||
|
cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
"Invalid bolt11:"
|
"Invalid bolt11:"
|
||||||
" sets feature var_onion with no secret");
|
" sets feature var_onion with no secret");
|
||||||
} else if ((b12 = invoice_decode(cmd, b11str, strlen(b11str),
|
} else {
|
||||||
|
b12 = invoice_decode(cmd, b11str, strlen(b11str),
|
||||||
plugin_feature_set(cmd->plugin),
|
plugin_feature_set(cmd->plugin),
|
||||||
chainparams, &fail)) != NULL) {
|
chainparams, &fail);
|
||||||
|
if (b12 == NULL)
|
||||||
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
|
"Invalid bolt12: %s", fail);
|
||||||
|
|
||||||
if (!exp_offers)
|
if (!exp_offers)
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
"experimental-offers disabled");
|
"experimental-offers disabled");
|
||||||
@@ -2051,13 +2066,13 @@ static struct command_result *json_paymod(struct command *cmd,
|
|||||||
|
|
||||||
/* FIXME: gossmap should store as pubkey32 */
|
/* FIXME: gossmap should store as pubkey32 */
|
||||||
p->destination = tal(p, struct node_id);
|
p->destination = tal(p, struct node_id);
|
||||||
gossmap_guess_node_id(get_gossmap(cmd->plugin),
|
gossmap_guess_node_id(get_gossmap(cmd->plugin), b12->node_id,
|
||||||
b12->node_id,
|
|
||||||
p->destination);
|
p->destination);
|
||||||
p->destination_has_tlv = true;
|
p->destination_has_tlv = true;
|
||||||
p->payment_hash = tal_dup(p, struct sha256, b12->payment_hash);
|
p->payment_hash = tal_dup(p, struct sha256, b12->payment_hash);
|
||||||
if (b12->recurrence_counter && !label)
|
if (b12->recurrence_counter && !label)
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail(
|
||||||
|
cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
"recurring invoice requires a label");
|
"recurring invoice requires a label");
|
||||||
/* FIXME payment_secret should be signature! */
|
/* FIXME payment_secret should be signature! */
|
||||||
{
|
{
|
||||||
@@ -2066,7 +2081,8 @@ static struct command_result *json_paymod(struct command *cmd,
|
|||||||
p->payment_secret = tal(p, struct secret);
|
p->payment_secret = tal(p, struct secret);
|
||||||
merkle_tlv(b12->fields, &merkle);
|
merkle_tlv(b12->fields, &merkle);
|
||||||
memcpy(p->payment_secret, &merkle, sizeof(merkle));
|
memcpy(p->payment_secret, &merkle, sizeof(merkle));
|
||||||
BUILD_ASSERT(sizeof(*p->payment_secret) == sizeof(merkle));
|
BUILD_ASSERT(sizeof(*p->payment_secret) ==
|
||||||
|
sizeof(merkle));
|
||||||
}
|
}
|
||||||
p->routes = NULL;
|
p->routes = NULL;
|
||||||
/* FIXME: paths! */
|
/* FIXME: paths! */
|
||||||
@@ -2081,16 +2097,15 @@ static struct command_result *json_paymod(struct command *cmd,
|
|||||||
* `seconds_from_timestamp`.
|
* `seconds_from_timestamp`.
|
||||||
* - otherwise:
|
* - otherwise:
|
||||||
* - MUST reject the invoice if the current time since
|
* - MUST reject the invoice if the current time since
|
||||||
* 1970-01-01 UTC is greater than `timestamp` plus 7200.
|
* 1970-01-01 UTC is greater than `timestamp` plus
|
||||||
|
* 7200.
|
||||||
*/
|
*/
|
||||||
if (b12->relative_expiry)
|
if (b12->relative_expiry)
|
||||||
invexpiry = *b12->timestamp + *b12->relative_expiry;
|
invexpiry = *b12->timestamp + *b12->relative_expiry;
|
||||||
else
|
else
|
||||||
invexpiry = *b12->timestamp + BOLT12_DEFAULT_REL_EXPIRY;
|
invexpiry = *b12->timestamp + BOLT12_DEFAULT_REL_EXPIRY;
|
||||||
p->local_offer_id = tal_steal(p, local_offer_id);
|
p->local_offer_id = tal_steal(p, local_offer_id);
|
||||||
} else
|
}
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
|
||||||
"Invalid bolt11: %s", fail);
|
|
||||||
|
|
||||||
if (time_now().ts.tv_sec > invexpiry)
|
if (time_now().ts.tv_sec > invexpiry)
|
||||||
return command_fail(cmd, PAY_INVOICE_EXPIRED, "Invoice expired");
|
return command_fail(cmd, PAY_INVOICE_EXPIRED, "Invoice expired");
|
||||||
|
|||||||
Reference in New Issue
Block a user