mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
pay: Save and recover failure information.
Needed for particular race condition: client calls `sendpay` with intent to call `waitsendpay` later to get information, but the payment fails after `sendpay` returns but before client can invoke `waitsendpay`. This lets client know of information even if it manages to invoke `waitsendpay` "late".
This commit is contained in:
parent
693c718160
commit
411c9583a7
@ -448,16 +448,27 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
|
||||
}
|
||||
}
|
||||
|
||||
/* Save to DB */
|
||||
/* This may invalidated the payment structure returned, so
|
||||
* access to payment object should not be done after the
|
||||
* below call. */
|
||||
wallet_payment_set_status(ld->wallet, &hout->payment_hash,
|
||||
PAYMENT_FAILED, NULL);
|
||||
wallet_payment_set_failinfo(ld->wallet,
|
||||
&hout->payment_hash,
|
||||
fail ? NULL : hout->failuremsg,
|
||||
(fail && !retry_plausible),
|
||||
fail ? fail->erring_index : -1,
|
||||
fail ? fail->failcode : 0,
|
||||
fail ? &fail->erring_node : NULL,
|
||||
fail ? &fail->erring_channel : NULL,
|
||||
fail ? fail->channel_update : NULL);
|
||||
|
||||
/* Report to gossipd if we decided we should. */
|
||||
if (report_to_gossipd)
|
||||
report_routing_failure(ld->log, ld->gossip, fail);
|
||||
|
||||
|
||||
/* Report to client. */
|
||||
sendpay_route_failure(ld, &hout->payment_hash,
|
||||
retry_plausible, fail, hout->failuremsg,
|
||||
@ -480,6 +491,14 @@ bool wait_payment(const tal_t *cxt,
|
||||
struct sendpay_result *result;
|
||||
char const *details;
|
||||
bool cb_not_called;
|
||||
u8 *failonionreply;
|
||||
bool faildestperm;
|
||||
int failindex;
|
||||
enum onion_type failcode;
|
||||
struct pubkey *failnode;
|
||||
struct short_channel_id *failchannel;
|
||||
u8 *failupdate;
|
||||
struct routing_failure *fail;
|
||||
|
||||
payment = wallet_payment_by_hash(tmpctx, ld->wallet, payment_hash);
|
||||
if (!payment) {
|
||||
@ -509,12 +528,36 @@ bool wait_payment(const tal_t *cxt,
|
||||
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");
|
||||
/* Get error from DB */
|
||||
wallet_payment_get_failinfo(tmpctx, ld->wallet, payment_hash,
|
||||
&failonionreply,
|
||||
&faildestperm,
|
||||
&failindex,
|
||||
&failcode,
|
||||
&failnode,
|
||||
&failchannel,
|
||||
&failupdate);
|
||||
/* Old DB might not save failure information */
|
||||
if (!failonionreply && !failnode)
|
||||
result = sendpay_result_simple_fail(tmpctx,
|
||||
PAY_UNSPECIFIED_ERROR,
|
||||
"Payment failure reason unknown");
|
||||
else if (failonionreply) {
|
||||
/* failed to parse returned onion error */
|
||||
result = sendpay_result_route_failure(tmpctx, true, NULL, failonionreply, "reply from remote");
|
||||
} else {
|
||||
/* Parsed onion error, get its details */
|
||||
assert(failnode);
|
||||
assert(failchannel);
|
||||
fail = tal(tmpctx, struct routing_failure);
|
||||
fail->erring_index = failindex;
|
||||
fail->failcode = failcode;
|
||||
fail->erring_node = *failnode;
|
||||
fail->erring_channel = *failchannel;
|
||||
fail->channel_update = failupdate;
|
||||
result = sendpay_result_route_failure(tmpctx, !faildestperm, fail, NULL, "route failure");
|
||||
}
|
||||
|
||||
cb(result, cbarg);
|
||||
cb_not_called = false;
|
||||
goto end;
|
||||
|
Loading…
Reference in New Issue
Block a user