Browse Source

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.
v0.9.0.1
ZmnSCPxj jxPCSnmZ 5 years ago
committed by Christian Decker
parent
commit
c93a0a5eed
  1. 65
      plugins/libplugin-pay.c

65
plugins/libplugin-pay.c

@ -723,12 +723,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 *
handle_final_failure(struct command *cmd,
struct payment *p,
const struct node_id *final_id,
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
* warning when new ones are added, and can think about where they go */
switch (failcode) {
@ -807,8 +845,10 @@ error:
p->result->code = PAY_DESTINATION_PERM_FAIL;
payment_root(p)->abort = true;
nonerror:
payment_fail(p, "%s", p->result->message);
return command_still_pending(cmd);
}
@ -2471,9 +2511,7 @@ static void waitblockheight_cb(void *d, struct payment *p)
struct out_req *req;
struct timeabs now = time_now();
struct timerel remaining;
u32 blockheight = p->start_block;
int failcode;
const u8 *raw_message;
u32 blockheight;
if (p->step != PAYMENT_STEP_FAILED)
return payment_continue(p);
@ -2484,27 +2522,10 @@ static void waitblockheight_cb(void *d, struct payment *p)
if (time_after(now, p->deadline))
return payment_continue(p);
failcode = p->result->failcode;
raw_message = p->result->raw_message;
remaining = time_between(p->deadline, now);
if (failcode == 17 /* Former final_expiry_too_soon */) {
blockheight = p->start_block + 1;
} 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)
/* *Was* it a blockheight disagreement that caused the failure? */
if (!failure_is_blockheight_disagreement(p, &blockheight))
return payment_continue(p);
plugin_log(p->plugin, LOG_INFORM,

Loading…
Cancel
Save