plugins/fetchinvoice: allow send_message() to say "don't expect a reply"
What changed, and why it matters
This is a small, preparatory code change in Core Lightning's invoice-fetching plugin. It lets the plugin send a message without asking the recipient to send a reply back. The change itself does not fix a bug or close a security hole; it adds a capability that will be used later for canceling recurring invoice requests. There is no direct security impact visible in this commit.
No immediate action required. Treat as routine feature/refactoring commit. Monitor follow-up commits that use the new `want_reply=false` path for `invreq_recurrence_cancel` to ensure the no-reply behavior is handled safely and does not introduce message-handling or state-management bugs.
Security signals we found
No security-relevant bug fix or hardening is present in the diff.
The change only makes an existing reply-path construction conditional on a new boolean flag.
All current callers explicitly request a reply, preserving prior behavior.
Commit message frames the change as feature preparation, not as a security fix.
Evidence from the diff
The commit modifies plugins/fetchinvoice.c to add a want_reply boolean to the send_message() helper and the establish_paths state. When want_reply is false, the code skips adding a reply_path to the final onion message TLV. Existing callers that expect replies (invoice requests and invoice delivery) pass true. The commit message states this is groundwork for future invreq_recurrence_cancel invoice requests, which do not need a reply. No vulnerability is patched and no security-sensitive logic is altered beyond making the reply-path optional.
Changed components
plugins/fetchinvoice.csend_message() helperestablish_path_done()onion message reply-path constructionInspect captured patch +14 / −8
diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c
index 0d875fd8..4965f1ea 100644
--- a/plugins/fetchinvoice.c
+++ b/plugins/fetchinvoice.c
@@ -497,6 +497,8 @@ struct establishing_paths {
int which_blinded_path;
struct sent *sent;
struct tlv_onionmsg_tlv *final_tlv;
+ /* Do we want a reply? */
+ bool want_reply;
struct command_result *(*done)(struct command *cmd,
const char *method UNUSED,
const char *buf UNUSED,
@@ -526,12 +528,14 @@ static struct command_result *establish_path_done(struct command *cmd,
assert(tal_count(path) > 0);
/* Add reply path to final_tlv (it already contains invoice_request/invoice) */
- final_tlv->reply_path = make_reply_path(final_tlv, cmd->plugin, sent, path, sent->reply_secret);
+ if (epaths->want_reply) {
+ final_tlv->reply_path = make_reply_path(final_tlv, cmd->plugin, sent, path, sent->reply_secret);
- /* Replace first hop with scidd if they said to */
- if (sent->dev_path_use_scidd)
- sciddir_or_pubkey_from_scidd(&final_tlv->reply_path->first_node_id,
- sent->dev_path_use_scidd);
+ /* Replace first hop with scidd if they said to */
+ if (sent->dev_path_use_scidd)
+ sciddir_or_pubkey_from_scidd(&final_tlv->reply_path->first_node_id,
+ sent->dev_path_use_scidd);
+ }
/* Put in list so we recognize reply onion message. Note: because
* onion message notification comes from a different fd than the one
@@ -608,6 +612,7 @@ static struct command_result *try_establish(struct command *cmd,
static struct command_result *send_message(struct command *cmd,
struct sent *sent,
+ bool want_reply,
struct tlv_onionmsg_tlv *final_tlv STEALS,
struct command_result *(*done)
(struct command *cmd,
@@ -622,6 +627,7 @@ static struct command_result *send_message(struct command *cmd,
epaths->sent = sent;
epaths->final_tlv = tal_steal(epaths, final_tlv);
epaths->done = done;
+ epaths->want_reply = want_reply;
return try_establish(cmd, epaths);
}
@@ -762,7 +768,7 @@ static struct command_result *invreq_done(struct command *cmd,
payload->invoice_request = tal_arr(payload, u8, 0);
towire_tlv_invoice_request(&payload->invoice_request, sent->invreq);
- return send_message(cmd, sent, payload, sendonionmsg_done);
+ return send_message(cmd, sent, true, payload, sendonionmsg_done);
}
static struct command_result *param_dev_scidd(struct command *cmd, const char *name,
@@ -1222,7 +1228,7 @@ static struct command_result *createinvoice_done(struct command *cmd,
payload->invoice = tal_arr(payload, u8, 0);
towire_tlv_invoice(&payload->invoice, sent->inv);
- return send_message(cmd, sent, payload, prepare_inv_timeout);
+ return send_message(cmd, sent, true, payload, prepare_inv_timeout);
}
static struct command_result *sign_invoice(struct command *cmd,
@@ -1515,5 +1521,5 @@ struct command_result *json_dev_rawrequest(struct command *cmd,
payload->invoice_request = tal_arr(payload, u8, 0);
towire_tlv_invoice_request(&payload->invoice_request, sent->invreq);
- return send_message(cmd, sent, payload, sendonionmsg_done);
+ return send_message(cmd, sent, true, payload, sendonionmsg_done);
}
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.