chancloser: deny co-op close initiated by the chan initiator for frozen chans
This commit is contained in:
parent
c85f6bb364
commit
1ac7550e3f
@ -347,6 +347,21 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b
|
|||||||
"instead have %v", spew.Sdump(msg))
|
"instead have %v", spew.Sdump(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As we're the responder to this shutdown (the other party
|
||||||
|
// wants to close), we'll check if this is a frozen channel or
|
||||||
|
// not. If the channel is frozen as we were also the initiator
|
||||||
|
// of the channel opening, then we'll deny their close attempt.
|
||||||
|
chanInitiator := c.cfg.channel.IsInitiator()
|
||||||
|
if !chanInitiator && c.cfg.channel.State().ChanType.IsFrozen() &&
|
||||||
|
c.negotiationHeight < c.cfg.channel.State().ThawHeight {
|
||||||
|
|
||||||
|
return nil, false, fmt.Errorf("initiator attempting "+
|
||||||
|
"to co-op close frozen ChannelPoint(%v) "+
|
||||||
|
"(current_height=%v, thaw_height=%v)",
|
||||||
|
c.chanPoint, c.negotiationHeight,
|
||||||
|
c.cfg.channel.State().ThawHeight)
|
||||||
|
}
|
||||||
|
|
||||||
// If the remote node opened the channel with option upfront shutdown
|
// If the remote node opened the channel with option upfront shutdown
|
||||||
// script, check that the script they provided matches.
|
// script, check that the script they provided matches.
|
||||||
if err := maybeMatchScript(
|
if err := maybeMatchScript(
|
||||||
@ -382,7 +397,7 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b
|
|||||||
|
|
||||||
// We'll also craft our initial close proposal in order to keep
|
// We'll also craft our initial close proposal in order to keep
|
||||||
// the negotiation moving, but only if we're the negotiator.
|
// the negotiation moving, but only if we're the negotiator.
|
||||||
if c.cfg.channel.IsInitiator() {
|
if chanInitiator {
|
||||||
closeSigned, err := c.proposeCloseSigned(c.idealFeeSat)
|
closeSigned, err := c.proposeCloseSigned(c.idealFeeSat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
|
28
rpcserver.go
28
rpcserver.go
@ -1470,8 +1470,8 @@ func extractOpenChannelMinConfs(in *lnrpc.OpenChannelRequest) (int32, error) {
|
|||||||
|
|
||||||
// newFundingShimAssembler returns a new fully populated
|
// newFundingShimAssembler returns a new fully populated
|
||||||
// chanfunding.CannedAssembler using a FundingShim obtained from an RPC caller.
|
// chanfunding.CannedAssembler using a FundingShim obtained from an RPC caller.
|
||||||
func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim,
|
func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, initiator bool,
|
||||||
initiator bool, keyRing keychain.KeyRing) (chanfunding.Assembler, error) {
|
keyRing keychain.KeyRing) (chanfunding.Assembler, error) {
|
||||||
|
|
||||||
// Perform some basic sanity checks to ensure that all the expected
|
// Perform some basic sanity checks to ensure that all the expected
|
||||||
// fields are populated.
|
// fields are populated.
|
||||||
@ -1545,8 +1545,9 @@ func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim,
|
|||||||
// With all the parts assembled, we can now make the canned assembler
|
// With all the parts assembled, we can now make the canned assembler
|
||||||
// to pass into the wallet.
|
// to pass into the wallet.
|
||||||
return chanfunding.NewCannedAssembler(
|
return chanfunding.NewCannedAssembler(
|
||||||
0, *chanPoint, btcutil.Amount(chanPointShim.Amt),
|
chanPointShim.ThawHeight, *chanPoint,
|
||||||
&localKeyDesc, remoteKey, initiator,
|
btcutil.Amount(chanPointShim.Amt), &localKeyDesc,
|
||||||
|
remoteKey, initiator,
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1956,15 +1957,25 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a frozen channel, then we only allow the close to proceed
|
||||||
|
// if we were the responder to this channel.
|
||||||
|
_, bestHeight, err := r.server.cc.chainIO.GetBestBlock()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if channel.State().ChanType.IsFrozen() && channel.IsInitiator() &&
|
||||||
|
uint32(bestHeight) < channel.State().ThawHeight {
|
||||||
|
|
||||||
|
return fmt.Errorf("cannot co-op close frozen channel as "+
|
||||||
|
"initiator until height=%v, (current_height=%v)",
|
||||||
|
channel.State().ThawHeight, bestHeight)
|
||||||
|
}
|
||||||
|
|
||||||
// If a force closure was requested, then we'll handle all the details
|
// If a force closure was requested, then we'll handle all the details
|
||||||
// around the creation and broadcast of the unilateral closure
|
// around the creation and broadcast of the unilateral closure
|
||||||
// transaction here rather than going to the switch as we don't require
|
// transaction here rather than going to the switch as we don't require
|
||||||
// interaction from the peer.
|
// interaction from the peer.
|
||||||
if force {
|
if force {
|
||||||
_, bestHeight, err := r.server.cc.chainIO.GetBestBlock()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// As we're force closing this channel, as a precaution, we'll
|
// As we're force closing this channel, as a precaution, we'll
|
||||||
// ensure that the switch doesn't continue to see this channel
|
// ensure that the switch doesn't continue to see this channel
|
||||||
@ -3179,6 +3190,7 @@ func createRPCOpenChannel(r *rpcServer, graph *channeldb.ChannelGraph,
|
|||||||
RemoteChanReserveSat: int64(dbChannel.RemoteChanCfg.ChanReserve),
|
RemoteChanReserveSat: int64(dbChannel.RemoteChanCfg.ChanReserve),
|
||||||
StaticRemoteKey: commitmentType == lnrpc.CommitmentType_STATIC_REMOTE_KEY,
|
StaticRemoteKey: commitmentType == lnrpc.CommitmentType_STATIC_REMOTE_KEY,
|
||||||
CommitmentType: commitmentType,
|
CommitmentType: commitmentType,
|
||||||
|
ThawHeight: dbChannel.ThawHeight,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, htlc := range localCommit.Htlcs {
|
for i, htlc := range localCommit.Htlcs {
|
||||||
|
Loading…
Reference in New Issue
Block a user