htlcswitch: add new CloseType enum to account for all closure types
This commit is contained in:
parent
a5d9ce2fac
commit
93cbfdbd60
@ -7,18 +7,18 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ripemd160"
|
|
||||||
"github.com/lightningnetwork/lnd/routing"
|
|
||||||
"github.com/lightningnetwork/lnd/routing/rt/graph"
|
|
||||||
"github.com/btcsuite/fastsha256"
|
"github.com/btcsuite/fastsha256"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/rt/graph"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
|
"golang.org/x/crypto/ripemd160"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -184,6 +184,8 @@ func (h *htlcSwitch) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hswcLog.Tracef("Starting HTLC switch")
|
||||||
|
|
||||||
h.wg.Add(2)
|
h.wg.Add(2)
|
||||||
go h.networkAdmin()
|
go h.networkAdmin()
|
||||||
go h.htlcForwarder()
|
go h.htlcForwarder()
|
||||||
@ -198,6 +200,8 @@ func (h *htlcSwitch) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hswcLog.Infof("HLTC switch shutting down")
|
||||||
|
|
||||||
close(h.quit)
|
close(h.quit)
|
||||||
h.wg.Wait()
|
h.wg.Wait()
|
||||||
|
|
||||||
@ -480,7 +484,7 @@ func (h *htlcSwitch) handleRegisterLink(req *registerLinkMsg) {
|
|||||||
// this link leaves the interface empty, then the interface entry itself is
|
// this link leaves the interface empty, then the interface entry itself is
|
||||||
// also deleted.
|
// also deleted.
|
||||||
func (h *htlcSwitch) handleUnregisterLink(req *unregisterLinkMsg) {
|
func (h *htlcSwitch) handleUnregisterLink(req *unregisterLinkMsg) {
|
||||||
hswcLog.Infof("unregistering active link, interface=%v, chan_point=%v",
|
hswcLog.Debugf("unregistering active link, interface=%v, chan_point=%v",
|
||||||
hex.EncodeToString(req.chanInterface[:]), req.chanPoint)
|
hex.EncodeToString(req.chanInterface[:]), req.chanPoint)
|
||||||
|
|
||||||
chanInterface := req.chanInterface
|
chanInterface := req.chanInterface
|
||||||
@ -493,7 +497,7 @@ func (h *htlcSwitch) handleUnregisterLink(req *unregisterLinkMsg) {
|
|||||||
// links for this channel should be cleared.
|
// links for this channel should be cleared.
|
||||||
chansRemoved := make([]*wire.OutPoint, 0, len(links))
|
chansRemoved := make([]*wire.OutPoint, 0, len(links))
|
||||||
if req.chanPoint == nil {
|
if req.chanPoint == nil {
|
||||||
hswcLog.Infof("purging all active links for interface %v",
|
hswcLog.Debugf("purging all active links for interface %v",
|
||||||
hex.EncodeToString(chanInterface[:]))
|
hex.EncodeToString(chanInterface[:]))
|
||||||
|
|
||||||
for _, link := range links {
|
for _, link := range links {
|
||||||
@ -550,7 +554,7 @@ func (h *htlcSwitch) handleUnregisterLink(req *unregisterLinkMsg) {
|
|||||||
// * just have the interfaces index be keyed on hash160?
|
// * just have the interfaces index be keyed on hash160?
|
||||||
|
|
||||||
if len(links) == 0 {
|
if len(links) == 0 {
|
||||||
hswcLog.Infof("interface %v has no active links, destroying",
|
hswcLog.Debugf("interface %v has no active links, destroying",
|
||||||
hex.EncodeToString(chanInterface[:]))
|
hex.EncodeToString(chanInterface[:]))
|
||||||
h.interfaceMtx.Lock()
|
h.interfaceMtx.Lock()
|
||||||
delete(h.interfaces, chanInterface)
|
delete(h.interfaces, chanInterface)
|
||||||
@ -574,7 +578,7 @@ func (h *htlcSwitch) handleCloseLink(req *closeLinkReq) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hswcLog.Infof("requesting interface %v to close link %v",
|
hswcLog.Debugf("requesting interface %v to close link %v",
|
||||||
hex.EncodeToString(targetLink.peer.lightningID[:]), req.chanPoint)
|
hex.EncodeToString(targetLink.peer.lightningID[:]), req.chanPoint)
|
||||||
targetLink.peer.localCloseChanReqs <- req
|
targetLink.peer.localCloseChanReqs <- req
|
||||||
}
|
}
|
||||||
@ -650,11 +654,30 @@ func (h *htlcSwitch) UnregisterLink(remotePub *btcec.PublicKey, chanPoint *wire.
|
|||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
// closeChanReq represents a request to close a particular channel specified
|
// LinkCloseType is a enum which signals the type of channel closure the switch
|
||||||
// by its outpoint.
|
// should execute.
|
||||||
|
type LinkCloseType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CloseRegular indicates a regular cooperative channel closure should be attempted.
|
||||||
|
CloseRegular LinkCloseType = iota
|
||||||
|
|
||||||
|
// CloseForce indicates that the channel should be forcefully closed.
|
||||||
|
// This entails the broadcast of the commitment transaction directly on
|
||||||
|
// chain unilaterally.
|
||||||
|
CloseForce
|
||||||
|
|
||||||
|
// CloseBreach indicates that a channel breach has been dtected, and
|
||||||
|
// the link should immediately be marked as unavailable.
|
||||||
|
CloseBreach
|
||||||
|
)
|
||||||
|
|
||||||
|
// closeChanReq represents a request to close a particular channel specified by
|
||||||
|
// its outpoint.
|
||||||
type closeLinkReq struct {
|
type closeLinkReq struct {
|
||||||
chanPoint *wire.OutPoint
|
CloseType LinkCloseType
|
||||||
forceClose bool
|
|
||||||
|
chanPoint *wire.OutPoint
|
||||||
|
|
||||||
updates chan *lnrpc.CloseStatusUpdate
|
updates chan *lnrpc.CloseStatusUpdate
|
||||||
err chan error
|
err chan error
|
||||||
@ -663,18 +686,18 @@ type closeLinkReq struct {
|
|||||||
// CloseLink closes an active link targetted by it's channel point. Closing the
|
// CloseLink closes an active link targetted by it's channel point. Closing the
|
||||||
// link initiates a cooperative channel closure iff forceClose is false. If
|
// link initiates a cooperative channel closure iff forceClose is false. If
|
||||||
// forceClose is true, then a unilateral channel closure is executed.
|
// forceClose is true, then a unilateral channel closure is executed.
|
||||||
// TODO(roabeef): bool flag for timeout
|
// TODO(roasbeef): consolidate with UnregisterLink?
|
||||||
func (h *htlcSwitch) CloseLink(chanPoint *wire.OutPoint,
|
func (h *htlcSwitch) CloseLink(chanPoint *wire.OutPoint,
|
||||||
forceClose bool) (chan *lnrpc.CloseStatusUpdate, chan error) {
|
closeType LinkCloseType) (chan *lnrpc.CloseStatusUpdate, chan error) {
|
||||||
|
|
||||||
updateChan := make(chan *lnrpc.CloseStatusUpdate, 1)
|
updateChan := make(chan *lnrpc.CloseStatusUpdate, 1)
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
h.linkControl <- &closeLinkReq{
|
h.linkControl <- &closeLinkReq{
|
||||||
chanPoint: chanPoint,
|
CloseType: closeType,
|
||||||
forceClose: forceClose,
|
chanPoint: chanPoint,
|
||||||
updates: updateChan,
|
updates: updateChan,
|
||||||
err: errChan,
|
err: errChan,
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateChan, errChan
|
return updateChan, errChan
|
||||||
|
2
lnd.go
2
lnd.go
@ -68,7 +68,7 @@ func lndMain() error {
|
|||||||
defer chanDB.Close()
|
defer chanDB.Close()
|
||||||
|
|
||||||
// Next load btcd's TLS cert for the RPC connection. If a raw cert was
|
// Next load btcd's TLS cert for the RPC connection. If a raw cert was
|
||||||
// specified in the config, then we'll se that directly. Otherwise, we
|
// specified in the config, then we'll set that directly. Otherwise, we
|
||||||
// attempt to read the cert from the path specified in the config.
|
// attempt to read the cert from the path specified in the config.
|
||||||
var rpcCert []byte
|
var rpcCert []byte
|
||||||
if cfg.RawRPCCert != "" {
|
if cfg.RawRPCCert != "" {
|
||||||
|
58
peer.go
58
peer.go
@ -11,7 +11,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/routing/rt/graph"
|
|
||||||
"github.com/btcsuite/fastsha256"
|
"github.com/btcsuite/fastsha256"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
@ -19,6 +18,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/rt/graph"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/txscript"
|
"github.com/roasbeef/btcd/txscript"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
@ -778,15 +778,35 @@ func (p *peer) handleLocalClose(req *closeLinkReq) {
|
|||||||
channel := p.activeChannels[*req.chanPoint]
|
channel := p.activeChannels[*req.chanPoint]
|
||||||
p.activeChanMtx.RUnlock()
|
p.activeChanMtx.RUnlock()
|
||||||
|
|
||||||
if req.forceClose {
|
switch req.CloseType {
|
||||||
|
// A type of CloseForce indicates that the user has opted for
|
||||||
|
// unilaterally close the channel on-chain.
|
||||||
|
case CloseForce:
|
||||||
closingTxid, err = p.executeForceClose(channel)
|
closingTxid, err = p.executeForceClose(channel)
|
||||||
peerLog.Infof("Force closing ChannelPoint(%v) with txid: %v",
|
peerLog.Infof("Force closing ChannelPoint(%v) with txid: %v",
|
||||||
req.chanPoint, closingTxid)
|
req.chanPoint, closingTxid)
|
||||||
} else {
|
|
||||||
|
// A type of CloseRegular indicates that the user has opted to close
|
||||||
|
// out this channel on-chian, so we execute the cooperative channel
|
||||||
|
// closre workflow.
|
||||||
|
case CloseRegular:
|
||||||
closingTxid, err = p.executeCooperativeClose(channel)
|
closingTxid, err = p.executeCooperativeClose(channel)
|
||||||
peerLog.Infof("Attempting cooperative close of "+
|
peerLog.Infof("Attempting cooperative close of "+
|
||||||
"ChannelPoint(%v) with txid: %v", req.chanPoint,
|
"ChannelPoint(%v) with txid: %v", req.chanPoint,
|
||||||
closingTxid)
|
closingTxid)
|
||||||
|
|
||||||
|
// A type of CloseBreach indicates that the counter-party has breached
|
||||||
|
// the cahnnel therefore we need to clean up our local state.
|
||||||
|
case CloseBreach:
|
||||||
|
peerLog.Infof("ChannelPoint(%v) has been breached, wiping "+
|
||||||
|
"channel", req.chanPoint)
|
||||||
|
if err := wipeChannel(p, channel); err != nil {
|
||||||
|
peerLog.Infof("Unable to wipe channel after detected "+
|
||||||
|
"breach: %v", err)
|
||||||
|
req.err <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.err <- err
|
req.err <- err
|
||||||
@ -817,11 +837,10 @@ func (p *peer) handleLocalClose(req *closeLinkReq) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case height, ok := <-confNtfn.Confirmed:
|
case height, ok := <-confNtfn.Confirmed:
|
||||||
// In the case that the ChainNotifier is shutting
|
// In the case that the ChainNotifier is shutting down,
|
||||||
// down, all subscriber notification channels will be
|
// all subscriber notification channels will be closed,
|
||||||
// closed, generating a nil receive.
|
// generating a nil receive.
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO(roasbeef): check for nil elsewhere
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,10 +896,12 @@ func (p *peer) handleRemoteClose(req *lnwire.CloseRequest) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerLog.Infof("Broadcasting cooperative close tx: %v",
|
||||||
|
newLogClosure(func() string {
|
||||||
|
return spew.Sdump(closeTx)
|
||||||
|
}))
|
||||||
|
|
||||||
// Finally, broadcast the closure transaction, to the network.
|
// Finally, broadcast the closure transaction, to the network.
|
||||||
peerLog.Infof("Broadcasting cooperative close tx: %v", newLogClosure(func() string {
|
|
||||||
return spew.Sdump(closeTx)
|
|
||||||
}))
|
|
||||||
if err := p.server.lnwallet.PublishTransaction(closeTx); err != nil {
|
if err := p.server.lnwallet.PublishTransaction(closeTx); err != nil {
|
||||||
peerLog.Errorf("channel close tx from "+
|
peerLog.Errorf("channel close tx from "+
|
||||||
"ChannelPoint(%v) rejected: %v",
|
"ChannelPoint(%v) rejected: %v",
|
||||||
@ -910,20 +931,33 @@ func wipeChannel(p *peer, channel *lnwallet.LightningChannel) error {
|
|||||||
// longer active.
|
// longer active.
|
||||||
p.server.htlcSwitch.UnregisterLink(p.addr.IdentityKey, chanID)
|
p.server.htlcSwitch.UnregisterLink(p.addr.IdentityKey, chanID)
|
||||||
|
|
||||||
|
// Additionally, close up "down stream" link for the htlcManager which
|
||||||
|
// has been assigned to this channel. This servers the link between the
|
||||||
|
// htlcManager and the switch, signalling that the channel is no longer
|
||||||
|
// active.
|
||||||
p.htlcManMtx.RLock()
|
p.htlcManMtx.RLock()
|
||||||
|
|
||||||
|
// If the channel can't be found in the map, then this channel has
|
||||||
|
// already been wiped.
|
||||||
htlcWireLink, ok := p.htlcManagers[*chanID]
|
htlcWireLink, ok := p.htlcManagers[*chanID]
|
||||||
if !ok {
|
if !ok {
|
||||||
p.htlcManMtx.RUnlock()
|
p.htlcManMtx.RUnlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(htlcWireLink)
|
||||||
|
|
||||||
p.htlcManMtx.RUnlock()
|
p.htlcManMtx.RUnlock()
|
||||||
|
|
||||||
|
// Next, we remove the htlcManager from our internal map as the
|
||||||
|
// goroutine should have exited gracefully due to the channel closure
|
||||||
|
// above.
|
||||||
p.htlcManMtx.RLock()
|
p.htlcManMtx.RLock()
|
||||||
delete(p.htlcManagers, *chanID)
|
delete(p.htlcManagers, *chanID)
|
||||||
p.htlcManMtx.RUnlock()
|
p.htlcManMtx.RUnlock()
|
||||||
|
|
||||||
close(htlcWireLink)
|
// Finally, we purge the channel's state from the database, leaving a
|
||||||
|
// small summary for historical records.
|
||||||
if err := channel.DeleteState(); err != nil {
|
if err := channel.DeleteState(); err != nil {
|
||||||
peerLog.Errorf("Unable to delete ChannelPoint(%v) "+
|
peerLog.Errorf("Unable to delete ChannelPoint(%v) "+
|
||||||
"from db %v", chanID, err)
|
"from db %v", chanID, err)
|
||||||
|
12
rpcserver.go
12
rpcserver.go
@ -12,7 +12,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/routing/rt/graph"
|
|
||||||
"github.com/btcsuite/fastsha256"
|
"github.com/btcsuite/fastsha256"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
@ -20,6 +19,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/rt/graph"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/txscript"
|
"github.com/roasbeef/btcd/txscript"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
@ -367,7 +367,15 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
|
|||||||
rpcsLog.Tracef("[closechannel] request for ChannelPoint(%v)",
|
rpcsLog.Tracef("[closechannel] request for ChannelPoint(%v)",
|
||||||
targetChannelPoint)
|
targetChannelPoint)
|
||||||
|
|
||||||
updateChan, errChan := r.server.htlcSwitch.CloseLink(targetChannelPoint, force)
|
var closeType LinkCloseType
|
||||||
|
switch force {
|
||||||
|
case true:
|
||||||
|
closeType = CloseForce
|
||||||
|
case false:
|
||||||
|
closeType = CloseRegular
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChan, errChan := r.server.htlcSwitch.CloseLink(targetChannelPoint, closeType)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
|
Loading…
Reference in New Issue
Block a user