Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .msggen.json
Original file line number Diff line number Diff line change
Expand Up @@ -1979,6 +1979,7 @@
"FetchinvoiceRequest": {
"FetchInvoice.amount_msat": 2,
"FetchInvoice.bip353": 10,
"FetchInvoice.bolt11": 11,
"FetchInvoice.offer": 1,
"FetchInvoice.payer_metadata": 9,
"FetchInvoice.payer_note": 8,
Expand Down Expand Up @@ -8108,6 +8109,10 @@
"added": "v25.02",
"deprecated": null
},
"FetchInvoice.bolt11": {
"added": "v26.09",
"deprecated": null
},
"FetchInvoice.changes": {
"added": "pre-v0.10.1",
"deprecated": null
Expand Down Expand Up @@ -15904,6 +15909,10 @@
"added": "pre-v0.10.1",
"deprecated": null
},
"onion_message_recv.onion_message.bolt11_invoice": {
"added": "v26.09",
"deprecated": null
},
"onion_message_recv.onion_message.invoice": {
"added": "pre-v0.10.1",
"deprecated": null
Expand Down Expand Up @@ -15972,6 +15981,10 @@
"added": "pre-v0.10.1",
"deprecated": null
},
"onion_message_recv_secret.onion_message.bolt11_invoice": {
"added": "v26.09",
"deprecated": null
},
"onion_message_recv_secret.onion_message.invoice": {
"added": "pre-v0.10.1",
"deprecated": null
Expand Down
1 change: 1 addition & 0 deletions cln-grpc/proto/node.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cln-grpc/src/convert.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions cln-rpc/src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ pub mod events{

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OnionMessageRecvOnionMessage {
#[serde(skip_serializing_if = "Option::is_none")]
pub bolt11_invoice: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub invoice: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -398,6 +400,8 @@ pub mod events{

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OnionMessageRecvSecretOnionMessage {
#[serde(skip_serializing_if = "Option::is_none")]
pub bolt11_invoice: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub invoice: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down
2 changes: 2 additions & 0 deletions cln-rpc/src/model.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions common/features.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ static const struct feature_style feature_styles[] = {
.copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT,
[NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT,
[CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT} },
{ OPT_BOLT11_REQUEST,
.copy_style = { [BOLT12_OFFER_FEATURE] = FEATURE_REPRESENT } },
};

struct dependency {
Expand Down
5 changes: 5 additions & 0 deletions common/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,9 @@ struct feature_set *feature_set_dup(const tal_t *ctx,

#define OPT_SHUTDOWN_WRONG_FUNDING 104

/* BOLT-fetch-bolt11 #9:
* | 2/3 | `option_bolt11_request` | Invoice request for a bolt11 invoice | 2 | | [BOLT #12][bolt12-bolt11-req] |
*/
#define OPT_BOLT11_REQUEST 2

#endif /* LIGHTNING_COMMON_FEATURES_H */
23 changes: 22 additions & 1 deletion contrib/msggen/msggen/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -13907,6 +13907,13 @@
],
"added": "v25.02"
},
"bolt11": {
"type": "boolean",
"description": [
"Indicates we should fetch a bolt11 invoice instead (EXPERIMENTAL)"
],
"added": "v26.09"
},
"dev_reply_path": {
"hidden": true
},
Expand All @@ -13925,7 +13932,7 @@
"invoice": {
"type": "string",
"description": [
"The BOLT12 invoice we fetched."
"The BOLT12 invoice we fetched (or BOLT11 if `bolt11` parameter was set)."
]
},
"changes": {
Expand Down Expand Up @@ -41747,6 +41754,13 @@
"BOLT #12 `invoice` payload."
]
},
"bolt11_invoice": {
"type": "string",
"added": "v26.09",
"description": [
"BOLT #11 invoice payload."
]
},
"invoice_error": {
"type": "hex",
"description": [
Expand Down Expand Up @@ -41932,6 +41946,13 @@
"BOLT #12 `invoice` payload."
]
},
"bolt11_invoice": {
"type": "string",
"added": "v26.09",
"description": [
"BOLT #11 invoice payload."
]
},
"invoice_error": {
"type": "hex",
"description": [
Expand Down
3 changes: 2 additions & 1 deletion contrib/pyln-client/pyln/client/lightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ def feerates(self, style, urgent=None, normal=None, slow=None):

def fetchinvoice(self, offer, amount_msat=None, quantity=None, recurrence_counter=None,
recurrence_start=None, recurrence_label=None, timeout=None, payer_note=None,
payer_metadata=None, bip353=None):
payer_metadata=None, bip353=None, bolt11=None):
"""
Fetch an invoice for an offer.
"""
Expand All @@ -767,6 +767,7 @@ def fetchinvoice(self, offer, amount_msat=None, quantity=None, recurrence_counte
"payer_note": payer_note,
"payer_metadata": payer_metadata,
"bip353": bip353,
"bolt11": bolt11,
}
return self.call("fetchinvoice", payload)

Expand Down
1,756 changes: 878 additions & 878 deletions contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion doc/schemas/fetchinvoice.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@
],
"added": "v25.02"
},
"bolt11": {
"type": "boolean",
"description": [
"Indicates we should fetch a bolt11 invoice instead (EXPERIMENTAL)"
],
"added": "v26.09"
},
"dev_reply_path": {
"hidden": true
},
Expand All @@ -94,7 +101,7 @@
"invoice": {
"type": "string",
"description": [
"The BOLT12 invoice we fetched."
"The BOLT12 invoice we fetched (or BOLT11 if `bolt11` parameter was set)."
]
},
"changes": {
Expand Down
7 changes: 7 additions & 0 deletions doc/schemas/hook/onion_message_recv.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@
"BOLT #12 `invoice` payload."
]
},
"bolt11_invoice": {
"type": "string",
"added": "v26.09",
"description": [
"BOLT #11 invoice payload."
]
},
"invoice_error": {
"type": "hex",
"description": [
Expand Down
7 changes: 7 additions & 0 deletions doc/schemas/hook/onion_message_recv_secret.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@
"BOLT #12 `invoice` payload."
]
},
"bolt11_invoice": {
"type": "string",
"added": "v26.09",
"description": [
"BOLT #11 invoice payload."
]
},
"invoice_error": {
"type": "hex",
"description": [
Expand Down
6 changes: 0 additions & 6 deletions lightningd/invoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,6 @@ static struct command_result *json_invoice(struct command *cmd,
struct jsonrpc_request *req;
struct plugin *plugin;
bool *hashonly;
const size_t inv_max_label_len = 128;
const jsmntok_t *dev_routes;

info = tal(cmd, struct invoice_info);
Expand All @@ -1151,11 +1150,6 @@ static struct command_result *json_invoice(struct command *cmd,
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"dev-routes requires --developer");

if (strlen(info->label->s) > inv_max_label_len) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Label '%s' over %zu bytes", info->label->s, inv_max_label_len);
}

if (strlen(desc_val) > BOLT11_FIELD_BYTE_LIMIT && !*hashonly) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Description greater than %d bytes "
Expand Down
5 changes: 5 additions & 0 deletions lightningd/onion_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ static void onion_message_serialize(struct onion_message_hook_payload *payload,
if (payload->om->invoice)
json_add_hex_talarr(stream, "invoice", payload->om->invoice);

if (payload->om->bolt11_invoice)
json_add_stringn(stream, "bolt11_invoice",
payload->om->bolt11_invoice,
tal_bytelen(payload->om->bolt11_invoice));

if (payload->om->invoice_error)
json_add_hex_talarr(stream, "invoice_error",
payload->om->invoice_error);
Expand Down
40 changes: 37 additions & 3 deletions plugins/fetchinvoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,20 +171,45 @@ static struct command_result *handle_invreq_response(struct command *cmd,
u64 *expected_amount;
const struct recurrence *recurrence;

invtok = json_get_member(buf, om, "invoice");
/* Handle bolt11 case separately */
const char *invfield = sent->invreq->invreq_bolt11 ? "bolt11_invoice" : "invoice";
invtok = json_get_member(buf, om, invfield);
if (!invtok) {
plugin_log(cmd->plugin, LOG_UNUSUAL,
"Neither invoice nor invoice_request_failed in reply %.*s",
"Neither %s nor invoice_request_failed in reply %.*s",
invfield,
json_tok_full_len(om),
json_tok_full(buf, om));
discard_result(command_fail(sent->cmd,
OFFER_BAD_INVREQ_REPLY,
"Neither invoice nor invoice_request_failed in reply %.*s",
"Neither %s nor invoice_request_failed in reply %.*s",
invfield,
json_tok_full_len(om),
json_tok_full(buf, om)));
return command_hook_success(cmd);
}

if (sent->invreq->invreq_bolt11) {
const char *bolt11, *err;

/* Sanity check that they sent us a valid reply */
bolt11 = json_strdup(tmpctx, buf, invtok);
if (!bolt11_decode(tmpctx, bolt11,
plugin_feature_set(cmd->plugin),
NULL,
chainparams,
&err)) {
badfield = tal_fmt(tmpctx, "invoice: %s", err);
goto badinv;
}
out = jsonrpc_stream_success(sent->cmd);
json_add_string(out, "invoice", bolt11);
json_object_start(out, "changes");
json_object_end(out);
discard_result(command_finished(sent->cmd, out));
return command_hook_success(cmd);
}

invbin = json_tok_bin_from_hex(cmd, buf, invtok);
cursor = invbin;
len = tal_bytelen(invbin);
Expand Down Expand Up @@ -929,6 +954,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
u32 *timeout;
u64 *quantity;
u32 *recurrence_counter, *recurrence_start;
bool *bolt11;

if (!param_check(cmd, buffer, params,
p_req("offer", param_offer, &sent->offer),
Expand All @@ -941,6 +967,7 @@ struct command_result *json_fetchinvoice(struct command *cmd,
p_opt("payer_note", param_string, &payer_note),
p_opt("payer_metadata", param_bin_from_hex, &payer_metadata),
p_opt("bip353", param_bip353, &bip353),
p_opt_def("bolt11", param_bool, &bolt11, false),
p_opt("dev_path_use_scidd", param_dev_scidd, &sent->dev_path_use_scidd),
p_opt("dev_reply_path", param_dev_reply_path, &sent->dev_reply_path),
NULL))
Expand Down Expand Up @@ -1148,6 +1175,13 @@ struct command_result *json_fetchinvoice(struct command *cmd,
strlen(payer_note),
0);

if (*bolt11) {
if (!feature_offered(invreq->offer_features, OPT_BOLT11_REQUEST))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Cannot request bolt11: offer does not implement it");
invreq->invreq_bolt11 = tal(invreq, struct tlv_invoice_request_invreq_bolt11);
}

/* If only checking, we're done now */
if (command_check_only(cmd))
return command_check_done(cmd);
Expand Down
Loading
Loading