Skip to content

Commit

Permalink
lightningd: don't print nasty message when onchaind fails partially-f…
Browse files Browse the repository at this point in the history
…ailed HTLC

1. We set an outgoing htlc's `failonion` when we get a commitment_signed.
2. We don't transfer it to the corresponding incoming HTLC until we send
   commitment_signed and receive revoke_and_ack (meaning, outgoing htlc is
   completely dead).
3. If between these steps we go onchain, onchaind (after 3 blocks) tells us
   to fail the HTLC.
4. hout->failonion is set, but hout->hin has not been failed yet.  We
   do a sanity check and print a nasty message, and fail it with
   WIRE_PERMANENT_CHANNEL_FAILURE instead of relaying the error.

So handle this case explicitly.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Jun 27, 2022
1 parent 353361a commit 517828a
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 2 deletions.
12 changes: 12 additions & 0 deletions lightningd/peer_htlcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,18 @@ void onchain_failed_our_htlc(const struct channel *channel,
return;
}

/* We can have hout->failonion (which gets set when we process the
* received commitment_signed), but not failed hin yet, because the peer
* hadn't revoke_and_acked our own commitment without that htlc. */
if (hout->failonion && hout->in
&& hout->in->badonion == 0
&& !hout->in->failonion
&& !hout->in->preimage) {
log_debug(channel->log, "HTLC out %"PRIu64" can now fail HTLC upstream!",
htlc->id);
fail_in_htlc(hout->in, hout->failonion);
}

/* Don't fail twice (or if already succeeded)! */
if (hout->failonion || hout->failmsg || hout->preimage) {
log_debug(channel->log, "HTLC id %"PRIu64" failonion = %p, failmsg = %p, preimage = %p",
Expand Down
3 changes: 1 addition & 2 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -5267,7 +5267,6 @@ def test_pay_bolt11_metadata(node_factory, bitcoind):
l2.daemon.wait_for_log("Unexpected payment_metadata {}".format(b'this is metadata'.hex()))


@pytest.mark.xfail(strict=True)
@pytest.mark.developer("needs to dev-disconnect")
def test_pay_middle_fail(node_factory, bitcoind, executor):
"""Test the case where a HTLC is failed, but not on peer's side, then
Expand Down Expand Up @@ -5308,5 +5307,5 @@ def test_pay_middle_fail(node_factory, bitcoind, executor):
bitcoind.generate_block(3, wait_for_mempool=1)

# And that will fail upstream
with pytest.raises(RpcError, match=r'WIRE_PERMANENT_CHANNEL_FAILURE'):
with pytest.raises(RpcError, match=r'WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS'):
l1.rpc.waitsendpay('00' * 32)

0 comments on commit 517828a

Please sign in to comment.