xpay: add flag for "includefees"
What changed, and why it matters
This commit adds a new optional flag called 'includefees' to the xpay plugin in Core Lightning. When enabled, it tells the routing system that the sender wants the payment amount to include any routing fees, rather than having fees deducted from the recipient's amount. This is a feature addition, not a bug fix or security patch. There is no indication in the commit that it addresses a security vulnerability.
No security action required. Treat as normal feature review. If auditing, verify that the 'auto.include_fees' layer is correctly interpreted by the routing subsystem and that user-facing documentation matches the new behavior.
Security signals we found
No security-relevant signals present in commit message or diff
Feature addition: new optional payment flag
No validation, authorization, or cryptographic changes
No memory safety, bounds checking, or input sanitization changes
Evidence from the diff
The patch introduces an ‘includefees’ boolean to the xpay payment struct and exposes it as a parameter. When set, it adds the ‘auto.include_fees’ layer string to the route request sent to the underlying routing plugin. The default behavior remains unchanged (false), and existing call sites pass false explicitly. The change is additive and does not modify existing fee logic or validation paths.
Changed components
plugins/xpay/xpay.cInspect captured patch +13 / −1
diff --git a/plugins/xpay/xpay.c b/plugins/xpay/xpay.c
index 0fb5ff5c..2a74906a 100644
--- a/plugins/xpay/xpay.c
+++ b/plugins/xpay/xpay.c
@@ -151,6 +151,9 @@ struct payment {
/* When did we start? */
struct timeabs start_time;
+ /* sender pays for fees */
+ bool includefees;
+
/* Are we to add a shadow route? */
bool use_shadow;
};
@@ -1869,6 +1872,8 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
json_add_string(req->js, NULL, payment->layers[i]);
for (size_t i = 0; i < tal_count(xpay->user_layers); i++)
json_add_string(req->js, NULL, xpay->user_layers[i]);
+ if (payment->includefees)
+ json_add_string(req->js, NULL, "auto.include_fees");
json_array_end(req->js);
json_add_amount_msat(req->js, "maxfee_msat", maxfee);
json_add_u32(req->js, "final_cltv", payment->final_cltv);
@@ -2159,7 +2164,7 @@ static struct command_result *check_offer_payable(struct command *cmd,
}
struct xpay_params {
- struct amount_msat *msat, *maxfee, *partial;
+ struct amount_msat *msat, *maxfee, *partial, *includefees_msat;
const char **layers;
unsigned int retryfor;
u32 maxdelay;
@@ -2298,6 +2303,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
xparams->bip353 = NULL;
xparams->payer_note = payer_note;
xparams->label = label;
+ xparams->includefees_msat = NULL;
return do_fetchinvoice(cmd, invstring, xparams);
}
@@ -2325,6 +2331,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
xparams->bip353 = invstring;
xparams->payer_note = payer_note;
xparams->label = label;
+ xparams->includefees_msat = NULL;
req = jsonrpc_request_start(cmd, "fetchbip353",
bip353_fetched,
@@ -2370,6 +2377,7 @@ static struct payment *new_payment(const tal_t *ctx,
const struct json_escape *label,
const struct sha256 *localinvreqid,
bool as_pay,
+ bool includefees,
const char **err)
{
struct xpay *xpay = xpay_of(cmd->plugin);
@@ -2392,6 +2400,7 @@ static struct payment *new_payment(const tal_t *ctx,
payment->destination = *destination;
payment->payment_hash = *payment_hash;
payment->mpp_amount = mpp_amount;
+ payment->includefees = includefees;
if (partial) {
payment->amount = *partial;
if (amount_msat_greater(*partial, payment->mpp_amount)) {
@@ -2521,6 +2530,7 @@ static struct command_result *xpay_core(struct command *cmd,
label,
localinvreqid,
as_pay,
+ false,
&err);
if (!payment)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
@@ -2611,6 +2621,7 @@ static struct command_result *xpay_core(struct command *cmd,
label,
localinvreqid,
as_pay,
+ false,
&err);
if (!payment)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
@@ -2829,6 +2840,7 @@ static struct command_result *json_xkeysend(struct command *cmd,
label,
NULL,
false,
+ false,
&err);
if (!payment)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
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.