paymod: Add a deadline to the pay command and retry modifier

This commit is contained in:
Christian Decker
2020-06-11 11:38:41 +02:00
parent f557955515
commit 5601a1ab21
4 changed files with 83 additions and 1 deletions

View File

@@ -36,6 +36,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd,
/* Re-establish the unmodified constraints for our sub-payment. */
p->constraints = *parent->start_constraints;
p->deadline = parent->deadline;
} else {
assert(cmd != NULL);
p->partid = 0;
@@ -1317,10 +1318,21 @@ static inline void retry_step_cb(struct retry_mod_data *rd,
{
struct payment *subpayment;
struct retry_mod_data *rdata = payment_mod_retry_get_data(p);
struct timeabs now = time_now();
if (p->step != PAYMENT_STEP_FAILED)
return payment_continue(p);
if (time_after(now, p->deadline)) {
plugin_log(
p->plugin, LOG_INFORM,
"Payment deadline expired, not retrying (partial-)payment "
"%s/%d",
type_to_string(tmpctx, struct sha256, p->payment_hash),
p->partid);
return payment_continue(p);
}
/* If we failed to find a route, it's unlikely we can suddenly find a
* new one without any other changes, so it's time to give up. */
if (p->route == NULL)
@@ -1928,3 +1940,68 @@ static struct direct_pay_data *direct_pay_init(struct payment *p)
REGISTER_PAYMENT_MODIFIER(directpay, struct direct_pay_data *, direct_pay_init,
direct_pay_cb);
static struct command_result *waitblockheight_rpc_cb(struct command *cmd,
const char *buffer,
const jsmntok_t *toks,
struct payment *p)
{
struct payment *subpayment;
subpayment = payment_new(p, NULL, p, p->modifiers);
payment_start(subpayment);
payment_set_step(p, PAYMENT_STEP_RETRY);
subpayment->why =
tal_fmt(subpayment, "Retrying after waiting for blockchain sync.");
payment_continue(p);
return command_still_pending(cmd);
}
static void waitblockheight_cb(void *d, struct payment *p)
{
struct out_req *req;
struct timeabs now = time_now();
struct timerel remaining;
u32 blockheight;
int failcode;
const u8 *raw_message;
if (p->step != PAYMENT_STEP_FAILED)
return payment_continue(p);
/* If we don't have an error message to parse we can't wait for blockheight. */
if (p->result == NULL)
return payment_continue(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);
}
plugin_log(p->plugin, LOG_INFORM,
"Remote node appears to be on a longer chain, which causes "
"CLTV timeouts to be incorrect. Waiting up to %" PRIu64
" seconds to catch up to block %d before retrying.",
time_to_sec(remaining), blockheight);
req = jsonrpc_request_start(p->plugin, NULL, "waitblockheight",
waitblockheight_rpc_cb,
waitblockheight_rpc_cb, p);
json_add_u32(req->js, "blockheight", blockheight);
json_add_u32(req->js, "timeout", time_to_sec(remaining));
send_outreq(p->plugin, req);
}
REGISTER_PAYMENT_MODIFIER(waitblockheight, void *, NULL, waitblockheight_cb);