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:
parent
cc96f2947a
commit
6307f7243e
32
rpcserver.go
32
rpcserver.go
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user