Skip to content

Commit

Permalink
lightningd: refactor payment failed.
Browse files Browse the repository at this point in the history
Don't assume we have an outgoing HTLC at this level.

Note that previously we didn't save the failed onion unless it was
unparsable: we keep that both for space savings and because our
`waitsendpay` logic assumes that when it fetches from the db if
there's a failonion it was unparsable!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Oct 22, 2024
1 parent c439589 commit ba92a56
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 38 deletions.
63 changes: 31 additions & 32 deletions lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,6 @@ immediate_routing_failure(const tal_t *ctx,
static struct routing_failure*
local_routing_failure(const tal_t *ctx,
const struct lightningd *ld,
const struct htlc_out *hout,
enum onion_wire failcode,
const struct wallet_payment *payment)
{
Expand All @@ -435,9 +434,6 @@ local_routing_failure(const tal_t *ctx,

routing_failure->msg = NULL;

log_debug(hout->key.channel->log, "local_routing_failure: %u (%s)",
routing_failure->failcode,
onion_wire_name(routing_failure->failcode));
return routing_failure;
}

Expand Down Expand Up @@ -545,28 +541,32 @@ remote_routing_failure(const tal_t *ctx,
return routing_failure;
}

void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
void payment_failed(struct lightningd *ld,
struct logger *log,
const struct sha256 *payment_hash,
u64 partid, u64 groupid,
const struct onionreply *failonion,
const u8 *failmsg,
const char *localfail)
{
struct wallet_payment *payment;
struct routing_failure* fail = NULL;
const char *failstr;
enum jsonrpc_errcode pay_errcode;
const u8 *failmsg;
int origin_index;

payment = wallet_payment_by_hash(tmpctx, ld->wallet,
&hout->payment_hash,
hout->partid, hout->groupid);
payment_hash,
partid, groupid);

#ifdef COMPAT_V052
/* Prior to "pay: delete HTLC when we delete payment." we would
* delete a payment on retry, but leave the HTLC. */
if (!payment) {
log_unusual(hout->key.channel->log,
log_unusual(log,
"No payment for %s:"
" was this an old database?",
fmt_sha256(tmpctx, &hout->payment_hash));
fmt_sha256(tmpctx, payment_hash));
return;
}
#else
Expand All @@ -578,10 +578,12 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
if (localfail) {
/* Use temporary_channel_failure if failmsg has it */
enum onion_wire failcode;
failcode = fromwire_peektype(hout->failmsg);
failcode = fromwire_peektype(failmsg);

fail = local_routing_failure(tmpctx, ld, hout, failcode,
payment);
fail = local_routing_failure(tmpctx, ld, failcode, payment);
log_debug(log, "local_routing_failure: %u (%s)",
fail->failcode,
onion_wire_name(fail->failcode));
failstr = localfail;
pay_errcode = PAY_TRY_OTHER_ROUTE;
} else if (payment->path_secrets == NULL) {
Expand All @@ -593,11 +595,10 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
pay_errcode = PAY_UNPARSEABLE_ONION;
fail = NULL;
failstr = NULL;
} else if (hout->failmsg) {
} else if (failmsg) {
/* This can happen when a direct peer told channeld it's a
* malformed onion using update_fail_malformed_htlc. */
failstr = "local failure";
failmsg = hout->failmsg;
origin_index = 0;
pay_errcode = PAY_TRY_OTHER_ROUTE;
goto use_failmsg;
Expand All @@ -609,12 +610,11 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,

failmsg = unwrap_onionreply(tmpctx, path_secrets,
tal_count(path_secrets),
hout->failonion, &origin_index);
failonion, &origin_index);
if (!failmsg) {
log_info(hout->key.channel->log,
"htlc %"PRIu64" failed with bad reply (%s)",
hout->key.id,
tal_hex(tmpctx, hout->failonion->contents));
log_info(log,
"htlc failed with bad reply (%s)",
tal_hex(tmpctx, failonion->contents));
/* Cannot record failure. */
fail = NULL;
pay_errcode = PAY_UNPARSEABLE_ONION;
Expand All @@ -623,28 +623,27 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,

use_failmsg:
failcode = fromwire_peektype(failmsg);
log_info(hout->key.channel->log,
"htlc %"PRIu64" "
"failed from %ith node "
log_info(log,
"htlc failed from %ith node "
"with code 0x%04x (%s)",
hout->key.id,
origin_index,
failcode, onion_wire_name(failcode));
fail = remote_routing_failure(tmpctx, ld,
payment, failmsg,
origin_index,
hout->key.channel->log,
log,
&pay_errcode);
}
}

wallet_payment_set_status(ld->wallet, &hout->payment_hash,
hout->partid, hout->groupid,
wallet_payment_set_status(ld->wallet, payment_hash,
partid, groupid,
PAYMENT_FAILED, NULL);
wallet_payment_set_failinfo(ld->wallet,
&hout->payment_hash,
hout->partid,
fail ? NULL : hout->failonion,
payment_hash,
partid,
/* We only save failonion if it's unparseable */
fail ? NULL : failonion,
pay_errcode == PAY_DESTINATION_PERM_FAIL,
fail ? fail->erring_index : -1,
fail ? fail->failcode : 0,
Expand All @@ -654,8 +653,8 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
failstr,
fail ? fail->channel_dir : 0);

tell_waiters_failed(ld, &hout->payment_hash, payment, pay_errcode,
hout->failonion, fail, failstr);
tell_waiters_failed(ld, payment_hash, payment, pay_errcode,
failonion, fail, failstr);
}

/* Wait for a payment. If cmd is deleted, then wait_payment()
Expand Down
9 changes: 7 additions & 2 deletions lightningd/pay.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ void payment_succeeded(struct lightningd *ld,
u64 partid, u64 groupid,
const struct preimage *rval);

/* hout->failmsg or hout->failonion must be set. */
void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
/* failmsg or failonion must be set. */
void payment_failed(struct lightningd *ld,
struct logger *log,
const struct sha256 *payment_hash,
u64 partid, u64 groupid,
const struct onionreply *failonion,
const u8 *failmsg,
const char *localfail);

/* This json will be also used in 'sendpay_success' notifictaion. */
Expand Down
28 changes: 24 additions & 4 deletions lightningd/peer_htlcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,14 @@ static void fail_out_htlc(struct htlc_out *hout, const char *localfail)
assert(hout->failmsg || hout->failonion);

if (hout->am_origin) {
payment_failed(hout->key.channel->peer->ld, hout, localfail);
payment_failed(hout->key.channel->peer->ld,
hout->key.channel->log,
&hout->payment_hash,
hout->partid,
hout->groupid,
hout->failonion,
hout->failmsg,
localfail);
} else if (hout->in) {
const struct onionreply *failonion;

Expand Down Expand Up @@ -598,8 +605,14 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds UNU
char *localfail = tal_fmt(msg, "%s: %s",
onion_wire_name(fromwire_peektype(failmsg)),
failurestr);
payment_failed(ld, hout, localfail);

payment_failed(ld,
hout->key.channel->log,
&hout->payment_hash,
hout->partid,
hout->groupid,
hout->failonion,
hout->failmsg,
localfail);
} else if (hout->in) {
struct onionreply *failonion;
struct short_channel_id scid;
Expand Down Expand Up @@ -1783,7 +1796,14 @@ void onchain_failed_our_htlc(const struct channel *channel,
char *localfail = tal_fmt(channel, "%s: %s",
onion_wire_name(WIRE_PERMANENT_CHANNEL_FAILURE),
why);
payment_failed(ld, hout, localfail);
payment_failed(ld,
hout->key.channel->log,
&hout->payment_hash,
hout->partid,
hout->groupid,
hout->failonion,
hout->failmsg,
localfail);
tal_free(localfail);
} else if (hout->in) {
struct short_channel_id scid = channel_scid_or_local_alias(channel);
Expand Down

0 comments on commit ba92a56

Please sign in to comment.