Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid cascading failure: give up on incoming HTLCs in time if outgoing is stuck. #6378

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions lightningd/peer_htlcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1754,8 +1754,14 @@ void onchain_failed_our_htlc(const struct channel *channel,
} else if (hout->in) {
log_debug(channel->log, "HTLC id %"PRIu64" has incoming",
htlc->id);
local_fail_in_htlc(hout->in,
take(towire_permanent_channel_failure(NULL)));
/* Careful! We might have already timed out incoming
* HTLC in consider_failing_incoming */
if (hout->in->badonion == 0
&& !hout->in->failonion
&& !hout->in->preimage) {
local_fail_in_htlc(hout->in,
take(towire_permanent_channel_failure(NULL)));
}
Comment on lines +1761 to +1764
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here?

wallet_forwarded_payment_add(hout->key.channel->peer->ld->wallet,
hout->in, FORWARD_STYLE_TLV,
channel_scid_or_local_alias(channel), hout,
Expand Down Expand Up @@ -2661,6 +2667,43 @@ static u32 htlc_in_deadline(const struct lightningd *ld,
return hin->cltv_expiry - (ld->config.cltv_expiry_delta + 1)/2;
}

/* onchaind might fail to time out an HTLC: maybe fees spiked, or maybe
* it decided it wasn't worthwhile. This risks cascading failure if
* it was routed: the incoming peer will get upset with us, too.
*
* So, if we're within 3 blocks of this happening, we fail upstream.
* It's weird to do this by looking at hout, rather than hin, but
* there's a pointer from hout->hin and not vice versa (we don't
* normally need it). */
static void consider_failing_incoming(struct lightningd *ld,
u32 height,
struct htlc_out *hout)
{
/* Already failed or succeeded? */
if (hout->failmsg || hout->failonion || hout->preimage)
return;

/* Has no corresponding input we should be stressed about? */
if (!hout->in)
return;

/* Already done it once? */
if (hout->in->failonion)
return;

/* OK, if we're within 3 blocks of upstream getting upset, force it
* to fail without waiting for onchaind. */
if (height + 3 < hout->in->cltv_expiry)
return;
vincenzopalazzo marked this conversation as resolved.
Show resolved Hide resolved

log_unusual(hout->key.channel->log,
"Abandoning unresolved onchain HTLC at block %u"
" (expired at %u) to avoid peer closing incoming HTLC at block %u",
height, hout->cltv_expiry, hout->in->cltv_expiry);

local_fail_in_htlc(hout->in, take(towire_permanent_channel_failure(NULL)));
}

void htlcs_notify_new_block(struct lightningd *ld, u32 height)
{
bool removed;
Expand All @@ -2687,8 +2730,10 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height)
continue;

/* Peer on chain already? */
if (channel_on_chain(hout->key.channel))
if (channel_on_chain(hout->key.channel)) {
consider_failing_incoming(ld, height, hout);
continue;
}

/* Peer already failed, or we hit it? */
if (hout->key.channel->error)
Expand Down
1 change: 0 additions & 1 deletion tests/test_closing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3796,7 +3796,6 @@ def test_closing_anchorspend_htlc_tx_rbf(node_factory, bitcoind):
bitcoind.generate_block(1, needfeerate=4990)


@pytest.mark.xfail(strict=True)
@pytest.mark.developer("needs dev_disconnect")
@pytest.mark.parametrize("anchors", [False, True])
def test_htlc_no_force_close(node_factory, bitcoind, anchors):
Expand Down
Loading