mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 18:57:06 +01:00
pay: Make sendpay nonblocking.
This commit is contained in:
parent
bb4661f008
commit
1e4adb0359
4 changed files with 214 additions and 92 deletions
|
@ -10,7 +10,7 @@
|
||||||
#define JSONRPC2_METHOD_NOT_FOUND -32601
|
#define JSONRPC2_METHOD_NOT_FOUND -32601
|
||||||
#define JSONRPC2_INVALID_PARAMS -32602
|
#define JSONRPC2_INVALID_PARAMS -32602
|
||||||
|
|
||||||
/* Errors from `pay` and `sendpay` commands */
|
/* Errors from `pay`, `sendpay`, or `waitsendpay` commands */
|
||||||
#define PAY_IN_PROGRESS 200
|
#define PAY_IN_PROGRESS 200
|
||||||
#define PAY_RHASH_ALREADY_USED 201
|
#define PAY_RHASH_ALREADY_USED 201
|
||||||
#define PAY_UNPARSEABLE_ONION 202
|
#define PAY_UNPARSEABLE_ONION 202
|
||||||
|
@ -19,5 +19,7 @@
|
||||||
#define PAY_ROUTE_NOT_FOUND 205
|
#define PAY_ROUTE_NOT_FOUND 205
|
||||||
#define PAY_ROUTE_TOO_EXPENSIVE 206
|
#define PAY_ROUTE_TOO_EXPENSIVE 206
|
||||||
#define PAY_INVOICE_EXPIRED 207
|
#define PAY_INVOICE_EXPIRED 207
|
||||||
|
#define PAY_NO_SUCH_PAYMENT 208
|
||||||
|
#define PAY_UNSPECIFIED_ERROR 209
|
||||||
|
|
||||||
#endif /* !defined (LIGHTNING_LIGHTNINGD_JSONRPC_ERRORS_H) */
|
#endif /* !defined (LIGHTNING_LIGHTNINGD_JSONRPC_ERRORS_H) */
|
||||||
|
|
262
lightningd/pay.c
262
lightningd/pay.c
|
@ -4,6 +4,7 @@
|
||||||
#include <ccan/structeq/structeq.h>
|
#include <ccan/structeq/structeq.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <common/bolt11.h>
|
#include <common/bolt11.h>
|
||||||
|
#include <common/timeout.h>
|
||||||
#include <gossipd/gen_gossip_wire.h>
|
#include <gossipd/gen_gossip_wire.h>
|
||||||
#include <lightningd/chaintopology.h>
|
#include <lightningd/chaintopology.h>
|
||||||
#include <lightningd/jsonrpc.h>
|
#include <lightningd/jsonrpc.h>
|
||||||
|
@ -37,12 +38,12 @@ static void destroy_sendpay_command(struct sendpay_command *pc)
|
||||||
|
|
||||||
/* Owned by cxt; if cxt is deleted, then cb will
|
/* Owned by cxt; if cxt is deleted, then cb will
|
||||||
* no longer be called. */
|
* no longer be called. */
|
||||||
static struct sendpay_command *
|
static void
|
||||||
new_sendpay_command(const tal_t *cxt,
|
add_payment_waiter(const tal_t *cxt,
|
||||||
const struct sha256 *payment_hash,
|
const struct sha256 *payment_hash,
|
||||||
struct lightningd *ld,
|
struct lightningd *ld,
|
||||||
void (*cb)(const struct sendpay_result *, void*),
|
void (*cb)(const struct sendpay_result *, void*),
|
||||||
void *cbarg)
|
void *cbarg)
|
||||||
{
|
{
|
||||||
struct sendpay_command *pc = tal(cxt, struct sendpay_command);
|
struct sendpay_command *pc = tal(cxt, struct sendpay_command);
|
||||||
|
|
||||||
|
@ -51,7 +52,6 @@ new_sendpay_command(const tal_t *cxt,
|
||||||
pc->cbarg = cbarg;
|
pc->cbarg = cbarg;
|
||||||
list_add(&ld->sendpay_commands, &pc->list);
|
list_add(&ld->sendpay_commands, &pc->list);
|
||||||
tal_add_destructor(pc, destroy_sendpay_command);
|
tal_add_destructor(pc, destroy_sendpay_command);
|
||||||
return pc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller responsible for freeing ctx. */
|
/* Caller responsible for freeing ctx. */
|
||||||
|
@ -149,37 +149,6 @@ sendpay_result_simple_fail(const tal_t *ctx,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Immediately fail during send_payment call. */
|
|
||||||
static void sendpay_fail_now(void (*cb)(const struct sendpay_result *, void*),
|
|
||||||
void *cbarg,
|
|
||||||
int errorcode,
|
|
||||||
char const *details)
|
|
||||||
{
|
|
||||||
const tal_t *tmpctx = tal_tmpctx(NULL);
|
|
||||||
struct sendpay_result *result;
|
|
||||||
|
|
||||||
result = sendpay_result_simple_fail(tmpctx, errorcode, details);
|
|
||||||
|
|
||||||
cb(result, cbarg);
|
|
||||||
|
|
||||||
tal_free(tmpctx);
|
|
||||||
}
|
|
||||||
/* Immediately fail during send_payment call. */
|
|
||||||
static void
|
|
||||||
sendpay_succeed_now(void (*cb)(const struct sendpay_result*, void*),
|
|
||||||
void *cbarg,
|
|
||||||
const struct preimage *payment_preimage)
|
|
||||||
{
|
|
||||||
const tal_t *tmpctx = tal_tmpctx(NULL);
|
|
||||||
struct sendpay_result *result;
|
|
||||||
|
|
||||||
result = sendpay_result_success(tmpctx, payment_preimage);
|
|
||||||
|
|
||||||
cb(result, cbarg);
|
|
||||||
|
|
||||||
tal_free(tmpctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void payment_succeeded(struct lightningd *ld, struct htlc_out *hout,
|
void payment_succeeded(struct lightningd *ld, struct htlc_out *hout,
|
||||||
const struct preimage *rval)
|
const struct preimage *rval)
|
||||||
{
|
{
|
||||||
|
@ -496,17 +465,76 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
|
||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns false if we called callback directly, true if
|
/* Wait for a payment. If cxt is deleted, then cb will
|
||||||
* callback is scheduled for later.
|
* no longer be called.
|
||||||
*
|
* Return false if we called callback already, true if
|
||||||
* This call expects that if it calls the callback, then
|
* callback is scheduled for later. */
|
||||||
* the given context should have been freed. */
|
bool wait_payment(const tal_t *cxt,
|
||||||
bool send_payment(const tal_t *ctx,
|
struct lightningd *ld,
|
||||||
struct lightningd* ld,
|
const struct sha256 *payment_hash,
|
||||||
const struct sha256 *rhash,
|
void (*cb)(const struct sendpay_result *, void*),
|
||||||
const struct route_hop *route,
|
|
||||||
void (*cb)(const struct sendpay_result*, void*),
|
|
||||||
void *cbarg)
|
void *cbarg)
|
||||||
|
{
|
||||||
|
const tal_t *tmpctx = tal_tmpctx(cxt);
|
||||||
|
struct wallet_payment *payment;
|
||||||
|
struct sendpay_result *result;
|
||||||
|
char const *details;
|
||||||
|
bool cb_not_called;
|
||||||
|
|
||||||
|
payment = wallet_payment_by_hash(tmpctx, ld->wallet, payment_hash);
|
||||||
|
if (!payment) {
|
||||||
|
details = tal_fmt(tmpctx,
|
||||||
|
"Never attempted payment for '%s'",
|
||||||
|
type_to_string(tmpctx, struct sha256,
|
||||||
|
payment_hash));
|
||||||
|
result = sendpay_result_simple_fail(tmpctx,
|
||||||
|
PAY_NO_SUCH_PAYMENT,
|
||||||
|
details);
|
||||||
|
cb(result, cbarg);
|
||||||
|
cb_not_called = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (payment->status) {
|
||||||
|
case PAYMENT_PENDING:
|
||||||
|
add_payment_waiter(cxt, payment_hash, ld, cb, cbarg);
|
||||||
|
cb_not_called = true;
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
case PAYMENT_COMPLETE:
|
||||||
|
result = sendpay_result_success(tmpctx,
|
||||||
|
payment->payment_preimage);
|
||||||
|
cb(result, cbarg);
|
||||||
|
cb_not_called = false;
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
case PAYMENT_FAILED:
|
||||||
|
/* FIXME: store the failure and other failure data
|
||||||
|
* on the DB so that we can do something other than
|
||||||
|
* unspecified-error. */
|
||||||
|
result = sendpay_result_simple_fail(tmpctx,
|
||||||
|
PAY_UNSPECIFIED_ERROR,
|
||||||
|
"Payment already failed");
|
||||||
|
cb(result, cbarg);
|
||||||
|
cb_not_called = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Impossible. */
|
||||||
|
abort();
|
||||||
|
|
||||||
|
end:
|
||||||
|
tal_free(tmpctx);
|
||||||
|
return cb_not_called;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the result if available now, or NULL if the
|
||||||
|
* sendpay was deferred for later. */
|
||||||
|
struct sendpay_result *
|
||||||
|
send_payment(const tal_t *ctx,
|
||||||
|
struct lightningd* ld,
|
||||||
|
const struct sha256 *rhash,
|
||||||
|
const struct route_hop *route)
|
||||||
{
|
{
|
||||||
const u8 *onion;
|
const u8 *onion;
|
||||||
u8 sessionkey[32];
|
u8 sessionkey[32];
|
||||||
|
@ -523,6 +551,7 @@ bool send_payment(const tal_t *ctx,
|
||||||
struct short_channel_id *channels;
|
struct short_channel_id *channels;
|
||||||
struct routing_failure *fail;
|
struct routing_failure *fail;
|
||||||
struct channel *channel;
|
struct channel *channel;
|
||||||
|
struct sendpay_result *result;
|
||||||
|
|
||||||
/* Expiry for HTLCs is absolute. And add one to give some margin. */
|
/* Expiry for HTLCs is absolute. And add one to give some margin. */
|
||||||
base_expiry = get_block_height(ld->topology) + 1;
|
base_expiry = get_block_height(ld->topology) + 1;
|
||||||
|
@ -553,60 +582,57 @@ bool send_payment(const tal_t *ctx,
|
||||||
log_debug(ld->log, "send_payment: found previous");
|
log_debug(ld->log, "send_payment: found previous");
|
||||||
if (payment->status == PAYMENT_PENDING) {
|
if (payment->status == PAYMENT_PENDING) {
|
||||||
log_add(ld->log, "Payment is still in progress");
|
log_add(ld->log, "Payment is still in progress");
|
||||||
sendpay_fail_now(cb, cbarg, PAY_IN_PROGRESS,
|
tal_free(tmpctx);
|
||||||
"Payment is still in progress");
|
return sendpay_result_simple_fail(ctx,
|
||||||
return false;
|
PAY_IN_PROGRESS,
|
||||||
|
"Payment is still in progress");
|
||||||
}
|
}
|
||||||
if (payment->status == PAYMENT_COMPLETE) {
|
if (payment->status == PAYMENT_COMPLETE) {
|
||||||
log_add(ld->log, "... succeeded");
|
log_add(ld->log, "... succeeded");
|
||||||
/* Must match successful payment parameters. */
|
/* Must match successful payment parameters. */
|
||||||
if (payment->msatoshi != hop_data[n_hops-1].amt_forward) {
|
if (payment->msatoshi != hop_data[n_hops-1].amt_forward) {
|
||||||
char *msg = tal_fmt(tmpctx,
|
char *msg = tal_fmt(ctx,
|
||||||
"Already succeeded "
|
"Already succeeded "
|
||||||
"with amount %"PRIu64,
|
"with amount %"PRIu64,
|
||||||
payment->msatoshi);
|
payment->msatoshi);
|
||||||
sendpay_fail_now(cb, cbarg,
|
tal_free(tmpctx);
|
||||||
PAY_RHASH_ALREADY_USED,
|
return sendpay_result_simple_fail(ctx,
|
||||||
msg);
|
PAY_RHASH_ALREADY_USED,
|
||||||
return false;
|
msg);
|
||||||
}
|
}
|
||||||
if (!structeq(&payment->destination, &ids[n_hops-1])) {
|
if (!structeq(&payment->destination, &ids[n_hops-1])) {
|
||||||
char *msg = tal_fmt(tmpctx,
|
char *msg = tal_fmt(ctx,
|
||||||
"Already succeeded to %s",
|
"Already succeeded to %s",
|
||||||
type_to_string(tmpctx,
|
type_to_string(tmpctx,
|
||||||
struct pubkey,
|
struct pubkey,
|
||||||
&payment->destination));
|
&payment->destination));
|
||||||
sendpay_fail_now(cb, cbarg,
|
tal_free(tmpctx);
|
||||||
PAY_RHASH_ALREADY_USED,
|
return sendpay_result_simple_fail(ctx,
|
||||||
msg);
|
PAY_RHASH_ALREADY_USED,
|
||||||
return false;
|
msg);
|
||||||
}
|
}
|
||||||
sendpay_succeed_now(cb, cbarg,
|
result = sendpay_result_success(ctx,
|
||||||
payment->payment_preimage);
|
payment->payment_preimage);
|
||||||
return false;
|
tal_free(tmpctx);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
wallet_payment_delete(ld->wallet, rhash);
|
wallet_payment_delete(ld->wallet, rhash);
|
||||||
log_add(ld->log, "... retrying");
|
log_add(ld->log, "... retrying");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point we know there is no duplicate payment.
|
|
||||||
* Register it to the lightningd. Use the caller
|
|
||||||
* context, not our temporary context. */
|
|
||||||
new_sendpay_command(ctx, rhash, ld, cb, cbarg);
|
|
||||||
|
|
||||||
channel = active_channel_by_id(ld, &ids[0], NULL);
|
channel = active_channel_by_id(ld, &ids[0], NULL);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
/* Report routing failure to gossipd */
|
/* Report routing failure to gossipd */
|
||||||
fail = immediate_routing_failure(tmpctx, ld,
|
fail = immediate_routing_failure(ctx, ld,
|
||||||
WIRE_UNKNOWN_NEXT_PEER,
|
WIRE_UNKNOWN_NEXT_PEER,
|
||||||
&route[0].channel_id);
|
&route[0].channel_id);
|
||||||
report_routing_failure(ld->log, ld->gossip, fail);
|
report_routing_failure(ld->log, ld->gossip, fail);
|
||||||
|
|
||||||
/* Report routing failure to user */
|
/* Report routing failure to caller */
|
||||||
sendpay_route_failure(ld, rhash, true, fail, NULL,
|
tal_free(tmpctx);
|
||||||
"No connection to first "
|
return sendpay_result_route_failure(ctx, true, fail, NULL,
|
||||||
"peer found");
|
"No connection to first "
|
||||||
return false;
|
"peer found");
|
||||||
}
|
}
|
||||||
|
|
||||||
randombytes_buf(&sessionkey, sizeof(sessionkey));
|
randombytes_buf(&sessionkey, sizeof(sessionkey));
|
||||||
|
@ -624,15 +650,15 @@ bool send_payment(const tal_t *ctx,
|
||||||
rhash, onion, NULL, &hout);
|
rhash, onion, NULL, &hout);
|
||||||
if (failcode) {
|
if (failcode) {
|
||||||
/* Report routing failure to gossipd */
|
/* Report routing failure to gossipd */
|
||||||
fail = immediate_routing_failure(tmpctx, ld,
|
fail = immediate_routing_failure(ctx, ld,
|
||||||
failcode,
|
failcode,
|
||||||
&route[0].channel_id);
|
&route[0].channel_id);
|
||||||
report_routing_failure(ld->log, ld->gossip, fail);
|
report_routing_failure(ld->log, ld->gossip, fail);
|
||||||
|
|
||||||
/* Report routing failure to user */
|
/* Report routing failure to caller */
|
||||||
sendpay_route_failure(ld, rhash, true, fail, NULL,
|
tal_free(tmpctx);
|
||||||
"First peer not ready");
|
return sendpay_result_route_failure(ctx, true, fail, NULL,
|
||||||
return false;
|
"First peer not ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy channels used along the route. */
|
/* Copy channels used along the route. */
|
||||||
|
@ -657,7 +683,7 @@ bool send_payment(const tal_t *ctx,
|
||||||
wallet_payment_setup(ld->wallet, payment);
|
wallet_payment_setup(ld->wallet, payment);
|
||||||
|
|
||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
return true;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
|
@ -672,6 +698,7 @@ json_sendpay_success(struct command *cmd,
|
||||||
|
|
||||||
response = new_json_result(cmd);
|
response = new_json_result(cmd);
|
||||||
json_object_start(response, NULL);
|
json_object_start(response, NULL);
|
||||||
|
json_add_bool(response, "completed", true);
|
||||||
json_add_hex(response, "payment_preimage",
|
json_add_hex(response, "payment_preimage",
|
||||||
payment_preimage, sizeof(*payment_preimage));
|
payment_preimage, sizeof(*payment_preimage));
|
||||||
json_object_end(response);
|
json_object_end(response);
|
||||||
|
@ -693,6 +720,8 @@ static void json_sendpay_on_resolve(const struct sendpay_result *r,
|
||||||
switch (r->errorcode) {
|
switch (r->errorcode) {
|
||||||
case PAY_IN_PROGRESS:
|
case PAY_IN_PROGRESS:
|
||||||
case PAY_RHASH_ALREADY_USED:
|
case PAY_RHASH_ALREADY_USED:
|
||||||
|
case PAY_UNSPECIFIED_ERROR:
|
||||||
|
case PAY_NO_SUCH_PAYMENT:
|
||||||
data = NULL;
|
data = NULL;
|
||||||
msg = r->details;
|
msg = r->details;
|
||||||
break;
|
break;
|
||||||
|
@ -755,6 +784,8 @@ static void json_sendpay(struct command *cmd,
|
||||||
size_t n_hops;
|
size_t n_hops;
|
||||||
struct sha256 rhash;
|
struct sha256 rhash;
|
||||||
struct route_hop *route;
|
struct route_hop *route;
|
||||||
|
struct sendpay_result *r;
|
||||||
|
struct json_result *response;
|
||||||
|
|
||||||
if (!json_get_params(cmd, buffer, params,
|
if (!json_get_params(cmd, buffer, params,
|
||||||
"route", &routetok,
|
"route", &routetok,
|
||||||
|
@ -833,9 +864,18 @@ static void json_sendpay(struct command *cmd,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send_payment(cmd, cmd->ld, &rhash, route,
|
r = send_payment(cmd, cmd->ld, &rhash, route);
|
||||||
&json_sendpay_on_resolve, cmd))
|
if (r)
|
||||||
command_still_pending(cmd);
|
json_sendpay_on_resolve(r, cmd);
|
||||||
|
else {
|
||||||
|
response = new_json_result(cmd);
|
||||||
|
json_object_start(response, NULL);
|
||||||
|
json_add_string(response, "message",
|
||||||
|
"Monitor status with listpayments or waitsendpay");
|
||||||
|
json_add_bool(response, "completed", false);
|
||||||
|
json_object_end(response);
|
||||||
|
command_success(cmd, response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct json_command sendpay_command = {
|
static const struct json_command sendpay_command = {
|
||||||
|
@ -845,6 +885,60 @@ static const struct json_command sendpay_command = {
|
||||||
};
|
};
|
||||||
AUTODATA(json_command, &sendpay_command);
|
AUTODATA(json_command, &sendpay_command);
|
||||||
|
|
||||||
|
static void waitsendpay_timeout(struct command *cmd)
|
||||||
|
{
|
||||||
|
command_fail_detailed(cmd, PAY_IN_PROGRESS, NULL,
|
||||||
|
"Timed out while waiting");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void json_waitsendpay(struct command *cmd, const char *buffer,
|
||||||
|
const jsmntok_t *params)
|
||||||
|
{
|
||||||
|
jsmntok_t *rhashtok;
|
||||||
|
jsmntok_t *timeouttok;
|
||||||
|
struct sha256 rhash;
|
||||||
|
unsigned int timeout;
|
||||||
|
|
||||||
|
if (!json_get_params(cmd, buffer, params,
|
||||||
|
"payment_hash", &rhashtok,
|
||||||
|
"?timeout", &timeouttok,
|
||||||
|
NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!hex_decode(buffer + rhashtok->start,
|
||||||
|
rhashtok->end - rhashtok->start,
|
||||||
|
&rhash, sizeof(rhash))) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid sha256 hash",
|
||||||
|
rhashtok->end - rhashtok->start,
|
||||||
|
buffer + rhashtok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeouttok && !json_tok_number(buffer, timeouttok, &timeout)) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid number",
|
||||||
|
timeouttok->end - timeouttok->start,
|
||||||
|
buffer + timeouttok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wait_payment(cmd, cmd->ld, &rhash, &json_sendpay_on_resolve, cmd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (timeouttok)
|
||||||
|
new_reltimer(&cmd->ld->timers, cmd, time_from_sec(timeout),
|
||||||
|
&waitsendpay_timeout, cmd);
|
||||||
|
|
||||||
|
command_still_pending(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct json_command waitsendpay_command = {
|
||||||
|
"waitsendpay",
|
||||||
|
json_waitsendpay,
|
||||||
|
"Wait for payment attempt on {payment_hash} to succeed or fail, "
|
||||||
|
"but only up to {timeout} seconds."
|
||||||
|
};
|
||||||
|
AUTODATA(json_command, &waitsendpay_command);
|
||||||
|
|
||||||
static void json_listpayments(struct command *cmd, const char *buffer,
|
static void json_listpayments(struct command *cmd, const char *buffer,
|
||||||
const jsmntok_t *params)
|
const jsmntok_t *params)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,11 +40,27 @@ struct sendpay_result {
|
||||||
const char *details;
|
const char *details;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool send_payment(const tal_t *ctx,
|
/* Initiate a payment. Return NULL if the payment will be
|
||||||
|
* scheduled for later, or a result if the result is available
|
||||||
|
* immediately. If returning an immediate result, the returned
|
||||||
|
* object is allocated from the given context. Otherwise, the
|
||||||
|
* return context is ignored. */
|
||||||
|
struct sendpay_result *send_payment(const tal_t *ctx,
|
||||||
|
struct lightningd* ld,
|
||||||
|
const struct sha256 *rhash,
|
||||||
|
const struct route_hop *route);
|
||||||
|
/* Wait for a previous send_payment to complete in definite
|
||||||
|
* success or failure. If the given context is freed before
|
||||||
|
* the callback is called, then the callback will no longer
|
||||||
|
* be called.
|
||||||
|
*
|
||||||
|
* Return true if the payment is still pending on return, or
|
||||||
|
* false if the callback was already invoked before this
|
||||||
|
* function returned. */
|
||||||
|
bool wait_payment(const tal_t *ctx,
|
||||||
struct lightningd* ld,
|
struct lightningd* ld,
|
||||||
const struct sha256 *rhash,
|
const struct sha256 *payment_hash,
|
||||||
const struct route_hop *route,
|
void (*cb)(const struct sendpay_result *, void *cbarg),
|
||||||
void (*cb)(const struct sendpay_result*, void*),
|
|
||||||
void *cbarg);
|
void *cbarg);
|
||||||
|
|
||||||
void payment_succeeded(struct lightningd *ld, struct htlc_out *hout,
|
void payment_succeeded(struct lightningd *ld, struct htlc_out *hout,
|
||||||
|
|
|
@ -234,6 +234,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
|
||||||
double feepercent;
|
double feepercent;
|
||||||
bool fee_too_high;
|
bool fee_too_high;
|
||||||
struct json_result *data;
|
struct json_result *data;
|
||||||
|
struct sendpay_result *result;
|
||||||
|
|
||||||
fromwire_gossip_getroute_reply(reply, reply, &route);
|
fromwire_gossip_getroute_reply(reply, reply, &route);
|
||||||
|
|
||||||
|
@ -293,9 +294,18 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
|
||||||
++pay->sendpay_tries;
|
++pay->sendpay_tries;
|
||||||
|
|
||||||
log_route(pay, route);
|
log_route(pay, route);
|
||||||
send_payment(pay->try_parent,
|
|
||||||
pay->cmd->ld, &pay->payment_hash, route,
|
result = send_payment(pay->try_parent,
|
||||||
&json_pay_sendpay_resolve, pay);
|
pay->cmd->ld, &pay->payment_hash, route);
|
||||||
|
/* Resolved immediately? */
|
||||||
|
if (result)
|
||||||
|
json_pay_sendpay_resolve(result, pay);
|
||||||
|
/* Wait for resolution */
|
||||||
|
else
|
||||||
|
wait_payment(pay->try_parent,
|
||||||
|
pay->cmd->ld,
|
||||||
|
&pay->payment_hash,
|
||||||
|
&json_pay_sendpay_resolve, pay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start a payment attempt. Return true if deferred,
|
/* Start a payment attempt. Return true if deferred,
|
||||||
|
|
Loading…
Add table
Reference in a new issue