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);