mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +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
|
/* This may invalidated the payment structure returned, so
|
||||||
* access to payment object should not be done after the
|
* access to payment object should not be done after the
|
||||||
* below call. */
|
* below call. */
|
||||||
wallet_payment_set_status(ld->wallet, &hout->payment_hash,
|
wallet_payment_set_status(ld->wallet, &hout->payment_hash,
|
||||||
PAYMENT_FAILED, NULL);
|
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. */
|
/* Report to gossipd if we decided we should. */
|
||||||
if (report_to_gossipd)
|
if (report_to_gossipd)
|
||||||
report_routing_failure(ld->log, ld->gossip, fail);
|
report_routing_failure(ld->log, ld->gossip, fail);
|
||||||
|
|
||||||
|
|
||||||
/* Report to client. */
|
/* Report to client. */
|
||||||
sendpay_route_failure(ld, &hout->payment_hash,
|
sendpay_route_failure(ld, &hout->payment_hash,
|
||||||
retry_plausible, fail, hout->failuremsg,
|
retry_plausible, fail, hout->failuremsg,
|
||||||
@ -480,6 +491,14 @@ bool wait_payment(const tal_t *cxt,
|
|||||||
struct sendpay_result *result;
|
struct sendpay_result *result;
|
||||||
char const *details;
|
char const *details;
|
||||||
bool cb_not_called;
|
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);
|
payment = wallet_payment_by_hash(tmpctx, ld->wallet, payment_hash);
|
||||||
if (!payment) {
|
if (!payment) {
|
||||||
@ -509,12 +528,36 @@ bool wait_payment(const tal_t *cxt,
|
|||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
case PAYMENT_FAILED:
|
case PAYMENT_FAILED:
|
||||||
/* FIXME: store the failure and other failure data
|
/* Get error from DB */
|
||||||
* on the DB so that we can do something other than
|
wallet_payment_get_failinfo(tmpctx, ld->wallet, payment_hash,
|
||||||
* unspecified-error. */
|
&failonionreply,
|
||||||
|
&faildestperm,
|
||||||
|
&failindex,
|
||||||
|
&failcode,
|
||||||
|
&failnode,
|
||||||
|
&failchannel,
|
||||||
|
&failupdate);
|
||||||
|
/* Old DB might not save failure information */
|
||||||
|
if (!failonionreply && !failnode)
|
||||||
result = sendpay_result_simple_fail(tmpctx,
|
result = sendpay_result_simple_fail(tmpctx,
|
||||||
PAY_UNSPECIFIED_ERROR,
|
PAY_UNSPECIFIED_ERROR,
|
||||||
"Payment already failed");
|
"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(result, cbarg);
|
||||||
cb_not_called = false;
|
cb_not_called = false;
|
||||||
goto end;
|
goto end;
|
||||||
|
Loading…
Reference in New Issue
Block a user