renepay: bugfix finalized routes

Changelog-Fixed: renepay: finalized routes have to be processed and
determine the payment status even after the payment goes into the
background (no current command active). Not doing so leads to finalized
routes getting stuck in the payment internal data structure and their
associated HTLCs in the uncertainty network don't get released.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
This commit is contained in:
Lagrang3 2024-06-07 09:57:18 +01:00 committed by ShahanaFarooqui
parent 04bf0ae29d
commit cc9b8b0a19
3 changed files with 69 additions and 8 deletions

View file

@ -265,23 +265,28 @@ struct command *payment_command(struct payment *p)
return p->cmd_array[0];
}
struct command_result *payment_success(struct payment *payment,
const struct preimage *preimage TAKES)
void register_payment_success(struct payment *payment,
const struct preimage *preimage TAKES)
{
assert(payment);
assert(preimage);
payment->status = PAYMENT_SUCCESS;
payment->preimage = tal_free(payment->preimage);
if(taken(preimage))
if (taken(preimage))
payment->preimage = tal_steal(payment, preimage);
else
payment->preimage = tal_dup(payment, struct preimage, preimage);
}
struct command_result *payment_success(struct payment *payment,
const struct preimage *preimage TAKES)
{
register_payment_success(payment, preimage);
return payment_finish(payment);
}
struct command_result *payment_fail(struct payment *payment,
enum jsonrpc_errcode code, const char *fmt,
...)
void register_payment_fail(struct payment *payment, enum jsonrpc_errcode code,
const char *fmt, ...)
{
payment->status = PAYMENT_FAIL;
payment->error_code = code;
@ -291,6 +296,18 @@ struct command_result *payment_fail(struct payment *payment,
va_start(args, fmt);
payment->error_msg = tal_vfmt(payment, fmt, args);
va_end(args);
}
struct command_result *payment_fail(struct payment *payment,
enum jsonrpc_errcode code, const char *fmt,
...)
{
/* can't pass variadic arguments forward, so let's expand them. */
va_list args;
va_start(args, fmt);
const char *error_msg = tal_vfmt(tmpctx, fmt, args);
va_end(args);
register_payment_fail(payment, code, "%s", error_msg);
payment_note(payment, LOG_DBG, "Payment failed: %s",
payment->error_msg);

View file

@ -147,11 +147,19 @@ struct command *payment_command(struct payment *p);
/* get me the result of this payment, not necessarily a completed payment */
struct json_stream *payment_result(struct payment *p, struct command *cmd);
/* flag the payment as success and write the preimage as proof */
/* Flag the payment as success and write the preimage as proof. */
void register_payment_success(struct payment *payment,
const struct preimage *preimage TAKES);
/* Flag the payment as success and write the preimage as proof and end the
* payment execution. */
struct command_result *payment_success(struct payment *payment,
const struct preimage *preimage TAKES);
/* flag the payment as failed and write the reason */
/* Flag the payment as failed and write the reason. */
void register_payment_fail(struct payment *payment, enum jsonrpc_errcode code,
const char *fmt, ...);
/* Flag the payment as failed and write the reason and end the payment
* execution. */
struct command_result *payment_fail(struct payment *payment,
enum jsonrpc_errcode code, const char *fmt,
...);

View file

@ -50,7 +50,43 @@ static void routetracker_add_to_final(struct routetracker *routetracker,
{
tal_arr_expand(&routetracker->finalized_routes, route);
tal_steal(routetracker->finalized_routes, route);
struct payment *payment =
payment_map_get(pay_plugin->payment_map, route->key.payment_hash);
assert(payment);
if (payment->exec_state == INVALID_STATE) {
/* payment is offline, collect results now and set the payment
* state accordingly. */
assert(payment_commands_empty(payment));
assert(payment->status == PAYMENT_FAIL ||
payment->status == PAYMENT_SUCCESS);
struct preimage *payment_preimage = NULL;
enum jsonrpc_errcode final_error = LIGHTNINGD;
const char *final_msg = NULL;
/* Finalized routes must be processed and removed in order to
* free the uncertainty network's HTLCs. */
payment_collect_results(payment, &payment_preimage,
&final_error, &final_msg);
if (payment_preimage) {
/* If we have the preimage that means one succeed, we
* inmediately finish the payment. */
register_payment_success(payment,
take(payment_preimage));
return;
}
if (final_msg) {
/* We received a sendpay result with a final error
* message, we inmediately finish the payment. */
register_payment_fail(payment, final_error, "%s",
final_msg);
return;
}
}
}
static void route_success_register(struct routetracker *routetracker,
struct route *route)
{