mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-04 03:03:51 +01:00
payalgo: Throttle pay command if failure is due to blockheight disagreement.
This commit is contained in:
parent
ef34efa93f
commit
1f6008689d
1 changed files with 49 additions and 2 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <ccan/time/time.h>
|
#include <ccan/time/time.h>
|
||||||
#include <common/bolt11.h>
|
#include <common/bolt11.h>
|
||||||
|
#include <common/timeout.h>
|
||||||
#include <common/type_to_string.h>
|
#include <common/type_to_string.h>
|
||||||
#include <gossipd/gen_gossip_wire.h>
|
#include <gossipd/gen_gossip_wire.h>
|
||||||
#include <gossipd/routing.h>
|
#include <gossipd/routing.h>
|
||||||
|
@ -122,14 +123,49 @@ static void json_pay_failure(struct pay *pay,
|
||||||
command_fail_detailed(pay->cmd, r->errorcode, data, "%s", msg);
|
command_fail_detailed(pay->cmd, r->errorcode, data, "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine if we should delay before retrying. Return a reason
|
||||||
|
* string, or NULL if we will not retry */
|
||||||
|
static const char *should_delay_retry(const tal_t *ctx,
|
||||||
|
const struct sendpay_result *r)
|
||||||
|
{
|
||||||
|
/* The routing failures WIRE_EXPIRY_TOO_FAR, WIRE_EXPIRY_TOO_SOON,
|
||||||
|
* and WIRE_FINAL_EXPIRY_TOO_SOON may arise due to disagreement
|
||||||
|
* between the peers about what the block heights are. So
|
||||||
|
* delay for those before retrying. */
|
||||||
|
if (!r->succeeded && r->errorcode == PAY_TRY_OTHER_ROUTE) {
|
||||||
|
switch (r->routing_failure->failcode) {
|
||||||
|
case WIRE_EXPIRY_TOO_FAR:
|
||||||
|
case WIRE_EXPIRY_TOO_SOON:
|
||||||
|
case WIRE_FINAL_EXPIRY_TOO_SOON:
|
||||||
|
return tal_fmt(ctx,
|
||||||
|
"Possible blockheight disagreement "
|
||||||
|
"(%s from peer)",
|
||||||
|
onion_type_name(r->routing_failure->failcode));
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Do nothing */ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start a payment attempt. */
|
/* Start a payment attempt. */
|
||||||
static bool json_pay_try(struct pay *pay);
|
static bool json_pay_try(struct pay *pay);
|
||||||
|
|
||||||
|
/* Used when delaying. */
|
||||||
|
static void do_pay_try(struct pay *pay)
|
||||||
|
{
|
||||||
|
log_info(pay->cmd->ld->log, "pay(%p): Try another route", pay);
|
||||||
|
json_pay_try(pay);
|
||||||
|
}
|
||||||
|
|
||||||
/* Call when sendpay returns to us. */
|
/* Call when sendpay returns to us. */
|
||||||
static void json_pay_sendpay_resolve(const struct sendpay_result *r,
|
static void json_pay_sendpay_resolve(const struct sendpay_result *r,
|
||||||
void *vpay)
|
void *vpay)
|
||||||
{
|
{
|
||||||
struct pay *pay = (struct pay *) vpay;
|
struct pay *pay = (struct pay *) vpay;
|
||||||
|
char const *why;
|
||||||
|
|
||||||
/* If we succeed, hurray */
|
/* If we succeed, hurray */
|
||||||
if (r->succeeded) {
|
if (r->succeeded) {
|
||||||
|
@ -148,8 +184,19 @@ static void json_pay_sendpay_resolve(const struct sendpay_result *r,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info(pay->cmd->ld->log, "pay(%p): Try another route", pay);
|
/* Should retry here, question is whether to retry now or later */
|
||||||
json_pay_try(pay);
|
|
||||||
|
why = should_delay_retry(pay->try_parent, r);
|
||||||
|
if (why) {
|
||||||
|
log_info(pay->cmd->ld->log,
|
||||||
|
"pay(%p): Delay before retry: %s", pay, why);
|
||||||
|
/* Delay for 3 seconds if needed. FIXME: random
|
||||||
|
* exponential backoff */
|
||||||
|
new_reltimer(&pay->cmd->ld->timers, pay->try_parent,
|
||||||
|
time_from_sec(3),
|
||||||
|
&do_pay_try, pay);
|
||||||
|
} else
|
||||||
|
do_pay_try(pay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generates a string describing the route. Route should be a
|
/* Generates a string describing the route. Route should be a
|
||||||
|
|
Loading…
Add table
Reference in a new issue