mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-22 08:34:20 +01:00
plugins/libplugin-pay.c: Make sure blockheight disagreement does not prevent all future progress.
Blockheight disagreement is signalled with a permanent failure at the end node, but is actually a transient failure.
This commit is contained in:
committed by
Christian Decker
parent
8769f9ed93
commit
f81611e551
@@ -721,12 +721,50 @@ static void report_tampering(struct payment *p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
failure_is_blockheight_disagreement(const struct payment *p,
|
||||||
|
u32 *blockheight)
|
||||||
|
{
|
||||||
|
struct amount_msat unused;
|
||||||
|
|
||||||
|
assert(p && p->result);
|
||||||
|
|
||||||
|
if (p->result->failcode == 17 /* Former final_expiry_too_soon */)
|
||||||
|
*blockheight = p->start_block + 1;
|
||||||
|
else if (!fromwire_incorrect_or_unknown_payment_details(
|
||||||
|
p->result->raw_message,
|
||||||
|
&unused, blockheight))
|
||||||
|
/* If it's incorrect_or_unknown_payment_details, that tells us
|
||||||
|
* what height they're at */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* If we are already at the desired blockheight there is no point in
|
||||||
|
* waiting, and it is likely just some other error. Notice that
|
||||||
|
* start_block gets set by the initial getinfo call for each
|
||||||
|
* attempt.*/
|
||||||
|
if (*blockheight <= p->start_block)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static struct command_result *
|
static struct command_result *
|
||||||
handle_final_failure(struct command *cmd,
|
handle_final_failure(struct command *cmd,
|
||||||
struct payment *p,
|
struct payment *p,
|
||||||
const struct node_id *final_id,
|
const struct node_id *final_id,
|
||||||
enum onion_type failcode)
|
enum onion_type failcode)
|
||||||
{
|
{
|
||||||
|
u32 unused;
|
||||||
|
|
||||||
|
/* Need to check for blockheight disagreement case here,
|
||||||
|
* otherwise we would set the abort flag too eagerly.
|
||||||
|
*/
|
||||||
|
if (failure_is_blockheight_disagreement(p, &unused)) {
|
||||||
|
plugin_log(p->plugin, LOG_DBG,
|
||||||
|
"Blockheight disagreement, not aborting.");
|
||||||
|
goto nonerror;
|
||||||
|
}
|
||||||
|
|
||||||
/* We use an exhaustive switch statement here so you get a compile
|
/* We use an exhaustive switch statement here so you get a compile
|
||||||
* warning when new ones are added, and can think about where they go */
|
* warning when new ones are added, and can think about where they go */
|
||||||
switch (failcode) {
|
switch (failcode) {
|
||||||
@@ -805,8 +843,10 @@ error:
|
|||||||
p->result->code = PAY_DESTINATION_PERM_FAIL;
|
p->result->code = PAY_DESTINATION_PERM_FAIL;
|
||||||
payment_root(p)->abort = true;
|
payment_root(p)->abort = true;
|
||||||
|
|
||||||
|
nonerror:
|
||||||
payment_fail(p, "%s", p->result->message);
|
payment_fail(p, "%s", p->result->message);
|
||||||
return command_still_pending(cmd);
|
return command_still_pending(cmd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2508,9 +2548,7 @@ static void waitblockheight_cb(void *d, struct payment *p)
|
|||||||
struct out_req *req;
|
struct out_req *req;
|
||||||
struct timeabs now = time_now();
|
struct timeabs now = time_now();
|
||||||
struct timerel remaining;
|
struct timerel remaining;
|
||||||
u32 blockheight = p->start_block;
|
u32 blockheight;
|
||||||
int failcode;
|
|
||||||
const u8 *raw_message;
|
|
||||||
if (p->step != PAYMENT_STEP_FAILED)
|
if (p->step != PAYMENT_STEP_FAILED)
|
||||||
return payment_continue(p);
|
return payment_continue(p);
|
||||||
|
|
||||||
@@ -2521,27 +2559,10 @@ static void waitblockheight_cb(void *d, struct payment *p)
|
|||||||
if (time_after(now, p->deadline))
|
if (time_after(now, p->deadline))
|
||||||
return payment_continue(p);
|
return payment_continue(p);
|
||||||
|
|
||||||
failcode = p->result->failcode;
|
|
||||||
raw_message = p->result->raw_message;
|
|
||||||
remaining = time_between(p->deadline, now);
|
remaining = time_between(p->deadline, now);
|
||||||
|
|
||||||
if (failcode == 17 /* Former final_expiry_too_soon */) {
|
/* *Was* it a blockheight disagreement that caused the failure? */
|
||||||
blockheight = p->start_block + 1;
|
if (!failure_is_blockheight_disagreement(p, &blockheight))
|
||||||
} else {
|
|
||||||
/* If it's incorrect_or_unknown_payment_details, that tells us
|
|
||||||
* what height they're at */
|
|
||||||
struct amount_msat unused;
|
|
||||||
const void *ptr = raw_message;
|
|
||||||
if (!fromwire_incorrect_or_unknown_payment_details(
|
|
||||||
ptr, &unused, &blockheight))
|
|
||||||
return payment_continue(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are already at the desired blockheight there is no point in
|
|
||||||
* waiting, and it is likely just some other error. Notice that
|
|
||||||
* start_block gets set by the initial getinfo call for each
|
|
||||||
* attempt.*/
|
|
||||||
if (blockheight <= p->start_block)
|
|
||||||
return payment_continue(p);
|
return payment_continue(p);
|
||||||
|
|
||||||
plugin_log(p->plugin, LOG_INFORM,
|
plugin_log(p->plugin, LOG_INFORM,
|
||||||
|
|||||||
Reference in New Issue
Block a user