peer: reject remote closes with active HTLCs
In this commit, we follow up to the prior commit by ensuring we won't accept a co-op close request for a chennel with active HTLCs. When creating a chanCloser for the first time, we'll check the set of HTLC's and reject a request (by sending a wire error) if the target channel still as active HTLC's.
This commit is contained in:
parent
ecbeca5f29
commit
447a031435
27
peer.go
27
peer.go
@ -1438,9 +1438,14 @@ out:
|
|||||||
// closure process.
|
// closure process.
|
||||||
chanCloser, err := p.fetchActiveChanCloser(closeMsg.cid)
|
chanCloser, err := p.fetchActiveChanCloser(closeMsg.cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(roasbeef): send protocol error?
|
|
||||||
peerLog.Errorf("unable to respond to remote "+
|
peerLog.Errorf("unable to respond to remote "+
|
||||||
"close msg: %v", err)
|
"close msg: %v", err)
|
||||||
|
|
||||||
|
errMsg := &lnwire.Error{
|
||||||
|
ChanID: closeMsg.cid,
|
||||||
|
Data: lnwire.ErrorData(err.Error()),
|
||||||
|
}
|
||||||
|
p.queueMsg(errMsg, nil)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1520,11 +1525,21 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e
|
|||||||
// cooperative channel closure.
|
// cooperative channel closure.
|
||||||
chanCloser, ok := p.activeChanCloses[chanID]
|
chanCloser, ok := p.activeChanCloses[chanID]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// If we need to create a chan closer for the first time, then
|
||||||
|
// we'll check to ensure that the channel is even in the proper
|
||||||
|
// state to allow a co-op channel closure.
|
||||||
|
if len(channel.ActiveHtlcs()) != 0 {
|
||||||
|
return nil, fmt.Errorf("cannot co-op close " +
|
||||||
|
"channel w/ active htlcs")
|
||||||
|
}
|
||||||
|
|
||||||
// We'll create a valid closing state machine in order to
|
// We'll create a valid closing state machine in order to
|
||||||
// respond to the initiated cooperative channel closure.
|
// respond to the initiated cooperative channel closure.
|
||||||
deliveryAddr, err := p.genDeliveryScript()
|
deliveryAddr, err := p.genDeliveryScript()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
peerLog.Errorf("unable to gen delivery script: %v", err)
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("close addr unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order to begin fee negotiations, we'll first compute our
|
// In order to begin fee negotiations, we'll first compute our
|
||||||
@ -1532,8 +1547,9 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e
|
|||||||
// we weren't the ones that initiated the channel closure.
|
// we weren't the ones that initiated the channel closure.
|
||||||
feePerVSize, err := p.server.cc.feeEstimator.EstimateFeePerVSize(6)
|
feePerVSize, err := p.server.cc.feeEstimator.EstimateFeePerVSize(6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to query fee "+
|
peerLog.Errorf("unable to query fee estimator: %v", err)
|
||||||
"estimator: %v", err)
|
|
||||||
|
return nil, fmt.Errorf("unable to estimate fee")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll then convert the sat per weight to sat per k/w as this
|
// We'll then convert the sat per weight to sat per k/w as this
|
||||||
@ -1543,7 +1559,8 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e
|
|||||||
|
|
||||||
_, startingHeight, err := p.server.cc.chainIO.GetBestBlock()
|
_, startingHeight, err := p.server.cc.chainIO.GetBestBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
peerLog.Errorf("unable to obtain best block: %v", err)
|
||||||
|
return nil, fmt.Errorf("cannot obtain best block")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before we create the chan closer, we'll start a new
|
// Before we create the chan closer, we'll start a new
|
||||||
|
@ -1094,8 +1094,8 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
|
|||||||
// Before we attempt the cooperative channel closure, we'll
|
// Before we attempt the cooperative channel closure, we'll
|
||||||
// examine the channel to ensure that it doesn't have a
|
// examine the channel to ensure that it doesn't have a
|
||||||
// lingering HTLC.
|
// lingering HTLC.
|
||||||
if len(channel.localCommit.Htlcs) != 0 {
|
if len(channel.ActiveHtlcs()) != 0 {
|
||||||
return nil, fmt.Errorf("cannot co-op close channel " +
|
return fmt.Errorf("cannot co-op close channel " +
|
||||||
"with active htlcs")
|
"with active htlcs")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user