xpay: more accurately reflect pay when xpay-handle-pay is set.

Note that the slight code reorder changes the JSON order, which is generally
undefined, but our doc checker is very strict!

Changelog-Changed: `xpay` now gives the same JSON success return as documented by `pay` when `xpay-handle-pay` is set.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7923
This commit is contained in:
Rusty Russell
2024-12-15 10:53:05 +10:30
parent 428c76068c
commit d26ea6673d
5 changed files with 54 additions and 25 deletions

View File

@@ -36428,10 +36428,10 @@
},
"response": {
"payment_preimage": "paymentpreimgxp1010101010101010101010101010101010101010101010101",
"failed_parts": 0,
"successful_parts": 1,
"amount_msat": 10000,
"amount_sent_msat": 10002
"amount_sent_msat": 10002,
"failed_parts": 0,
"successful_parts": 1
}
},
{
@@ -36444,10 +36444,10 @@
},
"response": {
"payment_preimage": "paymentpreimgxp2020202020202020202020202020202020202020202020202",
"failed_parts": 0,
"successful_parts": 1,
"amount_msat": 1000,
"amount_sent_msat": 1000
"amount_sent_msat": 1000,
"failed_parts": 0,
"successful_parts": 1
}
}
]

View File

@@ -540,8 +540,7 @@ command, so they invoices can also be paid onchain.
* **xpay-handle-pay**=*BOOL* [plugin `xpay`, *dynamic*]
Setting this makes `xpay` intercept simply `pay` commands (default `false`). Note that the
response will be different from the normal pay command, however.
Setting this makes `xpay` intercept simply `pay` commands (default `false`).
### Networking options

View File

@@ -132,10 +132,10 @@
},
"response": {
"payment_preimage": "paymentpreimgxp1010101010101010101010101010101010101010101010101",
"failed_parts": 0,
"successful_parts": 1,
"amount_msat": 10000,
"amount_sent_msat": 10002
"amount_sent_msat": 10002,
"failed_parts": 0,
"successful_parts": 1
}
},
{
@@ -148,10 +148,10 @@
},
"response": {
"payment_preimage": "paymentpreimgxp2020202020202020202020202020202020202020202020202",
"failed_parts": 0,
"successful_parts": 1,
"amount_msat": 1000,
"amount_sent_msat": 1000
"amount_sent_msat": 1000,
"failed_parts": 0,
"successful_parts": 1
}
}
]

View File

@@ -111,6 +111,11 @@ struct payment {
/* Requests currently outstanding */
struct out_req **requests;
/* Are we pretending to be "pay"? */
bool pay_compat;
/* When did we start? */
struct timeabs start_time;
};
/* One step in a path. */
@@ -374,11 +379,19 @@ static void payment_succeeded(struct payment *payment,
if (payment->cmd) {
js = jsonrpc_stream_success(payment->cmd);
json_add_preimage(js, "payment_preimage", preimage);
json_add_u64(js, "failed_parts", payment->num_failures);
json_add_u64(js, "successful_parts",
payment->total_num_attempts - payment->num_failures);
json_add_amount_msat(js, "amount_msat", payment->amount);
json_add_amount_msat(js, "amount_sent_msat", total_sent(payment, attempt));
/* Pay's schema expects these fields */
if (payment->pay_compat) {
json_add_u64(js, "parts", payment->total_num_attempts);
json_add_sha256(js, "payment_hash", &payment->payment_hash);
json_add_string(js, "status", "complete");
json_add_u64(js, "created_at", (u64)payment->start_time.ts.tv_sec);
} else {
json_add_u64(js, "failed_parts", payment->num_failures);
json_add_u64(js, "successful_parts",
payment->total_num_attempts - payment->num_failures);
}
was_pending(command_finished(payment->cmd, js));
payment->cmd = NULL;
}
@@ -1436,9 +1449,10 @@ preapproveinvoice_succeed(struct command *cmd,
return populate_private_layer(cmd, payment);
}
static struct command_result *json_xpay(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
static struct command_result *json_xpay_core(struct command *cmd,
const char *buffer,
const jsmntok_t *params,
bool as_pay)
{
struct xpay *xpay = xpay_of(cmd->plugin);
struct amount_msat *msat, *maxfee, *partial;
@@ -1468,6 +1482,8 @@ static struct command_result *json_xpay(struct command *cmd,
payment->requests = tal_arr(payment, struct out_req *, 0);
payment->prior_results = tal_strdup(payment, "");
payment->deadline = timemono_add(time_mono(), time_from_sec(*retryfor));
payment->start_time = time_now();
payment->pay_compat = as_pay;
if (bolt12_has_prefix(payment->invstring)) {
struct gossmap *gossmap = get_gossmap(xpay);
@@ -1595,6 +1611,20 @@ static struct command_result *json_xpay(struct command *cmd,
return send_outreq(req);
}
static struct command_result *json_xpay(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
{
return json_xpay_core(cmd, buffer, params, false);
}
static struct command_result *json_xpay_as_pay(struct command *cmd,
const char *buffer,
const jsmntok_t *params)
{
return json_xpay_core(cmd, buffer, params, true);
}
static struct command_result *getchaininfo_done(struct command *aux_cmd,
const char *method,
const char *buf,
@@ -1727,6 +1757,10 @@ static const struct plugin_command commands[] = {
"xpay",
json_xpay,
},
{
"xpay-as-pay",
json_xpay_as_pay,
},
};
static struct command_result *handle_block_added(struct command *cmd,
@@ -1930,7 +1964,7 @@ static struct command_result *handle_rpc_command(struct command *cmd,
json_object_start(response, "replace");
json_add_string(response, "jsonrpc", "2.0");
json_add_tok(response, "id", id_tok, buf);
json_add_string(response, "method", "xpay");
json_add_string(response, "method", "xpay-as-pay");
json_object_start(response, "params");
json_add_tok(response, "invstring", bolt11, buf);
if (amount_msat)

View File

@@ -368,10 +368,6 @@ def test_xpay_takeover(node_factory, executor):
l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True,
opts={'xpay-handle-pay': True})
# xpay does NOT look like pay!
l1.rpc.jsonschemas = {}
l2.rpc.jsonschemas = {}
# Simple bolt11/bolt12 payment.
inv = l3.rpc.invoice(100000, "test_xpay_takeover1", "test_xpay_takeover1")['bolt11']
l1.rpc.pay(inv)