From db145f575bf0ffd7936c677c7a31a2fdbdef6c1a Mon Sep 17 00:00:00 2001 From: trueptolemy Date: Tue, 27 Aug 2019 02:31:25 +0800 Subject: [PATCH] Fix: fundee can forget channel if it receives error during CHANNELD_AWAITING_LOCKIN --- lightningd/channel.c | 29 ++++++++++++++++++++++++++++- lightningd/channel.h | 3 +++ lightningd/peer_control.c | 15 ++++++++++++--- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 34c87779c..69c08b1f7 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -362,7 +362,7 @@ void channel_fail_permanent(struct channel *channel, const char *fmt, ...) struct channel_id cid; va_start(ap, fmt); - why = tal_vfmt(channel, fmt, ap); + why = tal_vfmt(tmpctx, fmt, ap); va_end(ap); log_unusual(channel->log, "Peer permanent failure in %s: %s", @@ -386,6 +386,33 @@ void channel_fail_permanent(struct channel *channel, const char *fmt, ...) tal_free(why); } +void channel_fail_forget(struct channel *channel, const char *fmt, ...) +{ + va_list ap; + char *why; + struct channel_id cid; + + assert(channel->funder == REMOTE && + channel->state == CHANNELD_AWAITING_LOCKIN); + va_start(ap, fmt); + why = tal_vfmt(tmpctx, fmt, ap); + va_end(ap); + + log_unusual(channel->log, "Peer permanent failure in %s: %s, " + "forget channel", + channel_state_name(channel), why); + + if (!channel->error) { + derive_channel_id(&cid, + &channel->funding_txid, + channel->funding_outnum); + channel->error = towire_errorfmt(channel, &cid, "%s", why); + } + + delete_channel(channel); + tal_free(why); +} + void channel_internal_error(struct channel *channel, const char *fmt, ...) { va_list ap; diff --git a/lightningd/channel.h b/lightningd/channel.h index f1dc8f6b7..bc609e77b 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -187,6 +187,9 @@ PRINTF_FMT(2,3) void channel_fail_reconnect_later(struct channel *channel, /* Channel has failed, give up on it. */ void channel_fail_permanent(struct channel *channel, const char *fmt, ...); +/* Forget the channel. This is only used for the case when we "receive" error + * during CHANNELD_AWAITING_LOCKIN if we are "fundee". */ +void channel_fail_forget(struct channel *channel, const char *fmt, ...); /* Permanent error, but due to internal problems, not peer. */ void channel_internal_error(struct channel *channel, const char *fmt, ...); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 03977275e..d14b1d910 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -441,9 +441,18 @@ void channel_errmsg(struct channel *channel, * - MUST fail the channel referred to by the error message, * if that channel is with the sending node. */ - channel_fail_permanent(channel, "%s: %s ERROR %s", - channel->owner->name, - err_for_them ? "sent" : "received", desc); + + /* We should immediately forget the channel if we receive error during + * CHANNELD_AWAITING_LOCKIN if we are fundee. */ + if (!err_for_them && channel->funder == REMOTE + && channel->state == CHANNELD_AWAITING_LOCKIN) + channel_fail_forget(channel, "%s: %s ERROR %s", + channel->owner->name, + err_for_them ? "sent" : "received", desc); + else + channel_fail_permanent(channel, "%s: %s ERROR %s", + channel->owner->name, + err_for_them ? "sent" : "received", desc); } struct peer_connected_hook_payload {