rpc: ensure db is updated on force close if no outputs to sweep

This commit fixes an issue where if a party force closing a channel,
doesn’t have a non-dust balance, nor any outgoing HTLC’s, then the
channel would never be marked as fully closed within the database.

We ensure that this case is addressed, by inserting a checking to
determine if we have any funds to sweep, marking the channel fully
closed on initial commitment transaction confirmation if not.
This commit is contained in:
Olaoluwa Osuntokun 2017-08-04 18:29:14 -07:00
parent cc96f2947a
commit 6307f7243e
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2

@ -621,7 +621,7 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
// With the necessary indexes cleaned up, we'll now force close // With the necessary indexes cleaned up, we'll now force close
// the channel. // the channel.
closingTxid, err := r.forceCloseChan(channel) closingTxid, closeSummary, err := r.forceCloseChan(channel)
if err != nil { if err != nil {
rpcsLog.Errorf("unable to force close transaction: %v", err) rpcsLog.Errorf("unable to force close transaction: %v", err)
return err return err
@ -629,7 +629,7 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
// With the transaction broadcast, we send our first update to // With the transaction broadcast, we send our first update to
// the client. // the client.
updateChan = make(chan *lnrpc.CloseStatusUpdate, 1) updateChan = make(chan *lnrpc.CloseStatusUpdate, 2)
updateChan <- &lnrpc.CloseStatusUpdate{ updateChan <- &lnrpc.CloseStatusUpdate{
Update: &lnrpc.CloseStatusUpdate_ClosePending{ Update: &lnrpc.CloseStatusUpdate_ClosePending{
ClosePending: &lnrpc.PendingUpdate{ ClosePending: &lnrpc.PendingUpdate{
@ -652,10 +652,21 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
}, },
}, },
} }
// If we didn't have an output active on the
// commitment transaction, and had no outgoing
// HTLC's then we can mark the channels as
// closed as there are no funds to be swept.
if closeSummary.SelfOutputSignDesc == nil &&
len(closeSummary.HtlcResolutions) == 0 {
err := r.server.chanDB.MarkChanFullyClosed(chanPoint)
if err != nil {
rpcsLog.Errorf("unable to "+
"mark channel as closed: %v", err)
return
}
}
}) })
// TODO(roasbeef): utxo nursery marks as fully closed
} else { } else {
// Otherwise, the caller has requested a regular interactive // Otherwise, the caller has requested a regular interactive
// cooperative channel closure. So we'll forward the request to // cooperative channel closure. So we'll forward the request to
@ -731,12 +742,13 @@ func (r *rpcServer) fetchActiveChannel(chanPoint wire.OutPoint) (*lnwallet.Light
// commitment transaction has been broadcast, a struct describing the final // commitment transaction has been broadcast, a struct describing the final
// state of the channel is sent to the utxoNursery in order to ultimately sweep // state of the channel is sent to the utxoNursery in order to ultimately sweep
// the immature outputs. // the immature outputs.
func (r *rpcServer) forceCloseChan(channel *lnwallet.LightningChannel) (*chainhash.Hash, error) { func (r *rpcServer) forceCloseChan(channel *lnwallet.LightningChannel) (*chainhash.Hash, *lnwallet.ForceCloseSummary, error) {
// Execute a unilateral close shutting down all further channel // Execute a unilateral close shutting down all further channel
// operation. // operation.
closeSummary, err := channel.ForceClose() closeSummary, err := channel.ForceClose()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
closeTx := closeSummary.CloseTx closeTx := closeSummary.CloseTx
@ -749,7 +761,7 @@ func (r *rpcServer) forceCloseChan(channel *lnwallet.LightningChannel) (*chainha
return spew.Sdump(closeTx) return spew.Sdump(closeTx)
})) }))
if err := r.server.cc.wallet.PublishTransaction(closeTx); err != nil { if err := r.server.cc.wallet.PublishTransaction(closeTx); err != nil {
return nil, err return nil, nil, err
} }
// Now that the closing transaction has been broadcast successfully, // Now that the closing transaction has been broadcast successfully,
@ -769,14 +781,14 @@ func (r *rpcServer) forceCloseChan(channel *lnwallet.LightningChannel) (*chainha
IsPending: true, IsPending: true,
} }
if err := channel.DeleteState(closeInfo); err != nil { if err := channel.DeleteState(closeInfo); err != nil {
return nil, err return nil, nil, err
} }
// Send the closed channel summary over to the utxoNursery in order to // Send the closed channel summary over to the utxoNursery in order to
// have its outputs swept back into the wallet once they're mature. // have its outputs swept back into the wallet once they're mature.
r.server.utxoNursery.IncubateOutputs(closeSummary) r.server.utxoNursery.IncubateOutputs(closeSummary)
return &txid, nil return &txid, closeSummary, nil
} }
// GetInfo serves a request to the "getinfo" RPC call. This call returns // GetInfo serves a request to the "getinfo" RPC call. This call returns