From c2a698069e0cea05100a6e1c412b5a90802a9677 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 19 Jun 2024 15:47:42 +0200 Subject: [PATCH] pay: Add an error code to the payments This allows us to directly returnan error code based on where we decided to abort, rather than attemtping to infer it from the parts. Changelog-Added: pay: The pay plugin now returns better error codes --- plugins/keysend.c | 1 + plugins/libplugin-pay.c | 10 ++++++---- plugins/libplugin-pay.h | 6 +++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/keysend.c b/plugins/keysend.c index b97bd8932..99d46c1bb 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -78,6 +78,7 @@ static void keysend_cb(struct keysend_data *d, struct payment *p) { p->result->failcode == WIRE_INVALID_ONION_PAYLOAD) { return payment_abort( p, + PAY_DESTINATION_PERM_FAIL, "Recipient %s reported an invalid payload, this " "usually means they don't support keysend.", fmt_node_id(tmpctx, p->route_destination)); diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index c7db43a50..aa4cc675f 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -97,6 +97,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd, p->aborterror = NULL; p->on_payment_success = NULL; p->on_payment_failure = NULL; + p->errorcode = 0; /* Copy over the relevant pieces of information. */ if (parent != NULL) { @@ -2158,7 +2159,7 @@ static void payment_finished(struct payment *p) } else if (p->aborterror != NULL) { /* We set an explicit toplevel error message, * so let's report that. */ - ret = jsonrpc_stream_fail(cmd, PAY_STOPPED_RETRYING, + ret = jsonrpc_stream_fail(cmd, p->errorcode, p->aborterror); payment_json_add_attempts(ret, "attempts", p); @@ -2318,7 +2319,7 @@ void payment_continue(struct payment *p) abort(); } -void payment_abort(struct payment *p, const char *fmt, ...) { +void payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt, ...) { va_list ap; struct payment *root = payment_root(p); payment_set_step(p, PAYMENT_STEP_FAILED); @@ -2945,6 +2946,7 @@ static void routehint_check_reachable(struct payment *p) payment_abort( p, + PAY_UNREACHABLE, "Destination %s is not reachable directly and " "all routehints were unusable.", fmt_node_id(tmpctx, p->route_destination)); @@ -3812,10 +3814,10 @@ static void route_exclusions_step_cb(struct route_exclusions_data *d, false, false, NULL, NULL); } else { if (node_id_eq(&e->u.node_id, p->route_destination)) { - payment_abort(p, "Payee is manually excluded"); + payment_abort(p, PAY_USER_ERROR, "Payee is manually excluded"); return; } else if (node_id_eq(&e->u.node_id, p->local_id)) { - payment_abort(p, "Payer is manually excluded"); + payment_abort(p, PAY_USER_ERROR, "Payer is manually excluded"); return; } diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index c2f918399..d7a987ab0 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -327,6 +327,10 @@ struct payment { /* A human readable error message that is used as a top-level * explanation if a payment is aborted. */ char *aborterror; + /* A numeric error code to return to JSON-RPC callers. Allows + * programmatically differentiate various errors, without + * having to parse the `p->aborterror` string. */ + u32 errorcode; /* How many blocks are we lagging behind the rest of the network? This needs to be taken into consideration when @@ -489,7 +493,7 @@ void payment_fail(struct payment *p, const char *fmt, ...) PRINTF_FMT(2,3); * they can, and sets the root failreason so we have a sensible error * message. The failreason is overwritten if it is already set, since * we probably know better what happened in the modifier.. */ -void payment_abort(struct payment *p, const char *fmt, ...) PRINTF_FMT(2,3); +void payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt, ...) PRINTF_FMT(3,4); struct payment *payment_root(struct payment *p); struct payment_tree_result payment_collect_result(struct payment *p);