From ecbeca5f29888c0f429b4284feab8b421031e785 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 30 Mar 2018 12:51:01 -0700 Subject: [PATCH] rpc: disallow attempting a co-op close of a channel with active HTLCs In this commit, we fix a bug that at times could cause any dangling HTLC's to be sent to miner's fees if a user attempted to close out a channel cooperatively that still had pending HTLC's. We'll first prevent this at the RPC level by rejecting any attempts to trigger a co-op channel closure while a channel still have dangling HTLC's. --- rpcserver.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 244795d85..798cfcea4 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -996,20 +996,19 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, // TODO(roasbeef): if force and peer online then don't force? + // First, we'll fetch the channel as is, as we'll need to examine it + // regardless of if this is a force close or not. + channel, err := r.fetchActiveChannel(*chanPoint) + if err != nil { + return err + } + channel.Stop() + // If a force closure was requested, then we'll handle all the details // around the creation and broadcast of the unilateral closure // transaction here rather than going to the switch as we don't require // interaction from the peer. if force { - // As the first part of the force closure, we first fetch the - // channel from the database, then execute a direct force - // closure broadcasting our current commitment transaction. - channel, err := r.fetchActiveChannel(*chanPoint) - if err != nil { - return err - } - channel.Stop() - _, bestHeight, err := r.server.cc.chainIO.GetBestBlock() if err != nil { return err @@ -1092,6 +1091,14 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, } } + // Before we attempt the cooperative channel closure, we'll + // examine the channel to ensure that it doesn't have a + // lingering HTLC. + if len(channel.localCommit.Htlcs) != 0 { + return nil, fmt.Errorf("cannot co-op close channel " + + "with active htlcs") + } + // Otherwise, the caller has requested a regular interactive // cooperative channel closure. So we'll forward the request to // the htlc switch which will handle the negotiation and