htlcswitch: add new CloseType enum to account for all closure types

This commit is contained in:
Olaoluwa Osuntokun 2016-11-28 18:44:14 -08:00
parent a5d9ce2fac
commit 93cbfdbd60
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
4 changed files with 97 additions and 32 deletions

@ -7,18 +7,18 @@ import (
"sync/atomic"
"time"
"golang.org/x/crypto/ripemd160"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/routing/rt/graph"
"github.com/btcsuite/fastsha256"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnrpc"
"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/wire"
"github.com/roasbeef/btcutil"
"golang.org/x/crypto/ripemd160"
)
const (
@ -184,6 +184,8 @@ func (h *htlcSwitch) Start() error {
return nil
}
hswcLog.Tracef("Starting HTLC switch")
h.wg.Add(2)
go h.networkAdmin()
go h.htlcForwarder()
@ -198,6 +200,8 @@ func (h *htlcSwitch) Stop() error {
return nil
}
hswcLog.Infof("HLTC switch shutting down")
close(h.quit)
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
// also deleted.
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)
chanInterface := req.chanInterface
@ -493,7 +497,7 @@ func (h *htlcSwitch) handleUnregisterLink(req *unregisterLinkMsg) {
// links for this channel should be cleared.
chansRemoved := make([]*wire.OutPoint, 0, len(links))
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[:]))
for _, link := range links {
@ -550,7 +554,7 @@ func (h *htlcSwitch) handleUnregisterLink(req *unregisterLinkMsg) {
// * just have the interfaces index be keyed on hash160?
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[:]))
h.interfaceMtx.Lock()
delete(h.interfaces, chanInterface)
@ -574,7 +578,7 @@ func (h *htlcSwitch) handleCloseLink(req *closeLinkReq) {
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)
targetLink.peer.localCloseChanReqs <- req
}
@ -650,11 +654,30 @@ func (h *htlcSwitch) UnregisterLink(remotePub *btcec.PublicKey, chanPoint *wire.
<-done
}
// closeChanReq represents a request to close a particular channel specified
// by its outpoint.
// LinkCloseType is a enum which signals the type of channel closure the switch
// 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 {
chanPoint *wire.OutPoint
forceClose bool
CloseType LinkCloseType
chanPoint *wire.OutPoint
updates chan *lnrpc.CloseStatusUpdate
err chan error
@ -663,18 +686,18 @@ type closeLinkReq struct {
// CloseLink closes an active link targetted by it's channel point. Closing the
// link initiates a cooperative channel closure iff forceClose is false. If
// 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,
forceClose bool) (chan *lnrpc.CloseStatusUpdate, chan error) {
closeType LinkCloseType) (chan *lnrpc.CloseStatusUpdate, chan error) {
updateChan := make(chan *lnrpc.CloseStatusUpdate, 1)
errChan := make(chan error, 1)
h.linkControl <- &closeLinkReq{
chanPoint: chanPoint,
forceClose: forceClose,
updates: updateChan,
err: errChan,
CloseType: closeType,
chanPoint: chanPoint,
updates: updateChan,
err: errChan,
}
return updateChan, errChan

2
lnd.go

@ -68,7 +68,7 @@ func lndMain() error {
defer chanDB.Close()
// 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.
var rpcCert []byte
if cfg.RawRPCCert != "" {

58
peer.go

@ -11,7 +11,6 @@ import (
"sync/atomic"
"time"
"github.com/lightningnetwork/lnd/routing/rt/graph"
"github.com/btcsuite/fastsha256"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lightning-onion"
@ -19,6 +18,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/rt/graph"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/txscript"
"github.com/roasbeef/btcd/wire"
@ -778,15 +778,35 @@ func (p *peer) handleLocalClose(req *closeLinkReq) {
channel := p.activeChannels[*req.chanPoint]
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)
peerLog.Infof("Force closing ChannelPoint(%v) with txid: %v",
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)
peerLog.Infof("Attempting cooperative close of "+
"ChannelPoint(%v) with txid: %v", req.chanPoint,
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 {
req.err <- err
@ -817,11 +837,10 @@ func (p *peer) handleLocalClose(req *closeLinkReq) {
select {
case height, ok := <-confNtfn.Confirmed:
// In the case that the ChainNotifier is shutting
// down, all subscriber notification channels will be
// closed, generating a nil receive.
// In the case that the ChainNotifier is shutting down,
// all subscriber notification channels will be closed,
// generating a nil receive.
if !ok {
// TODO(roasbeef): check for nil elsewhere
return
}
@ -877,10 +896,12 @@ func (p *peer) handleRemoteClose(req *lnwire.CloseRequest) {
return
}
peerLog.Infof("Broadcasting cooperative close tx: %v",
newLogClosure(func() string {
return spew.Sdump(closeTx)
}))
// 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 {
peerLog.Errorf("channel close tx from "+
"ChannelPoint(%v) rejected: %v",
@ -910,20 +931,33 @@ func wipeChannel(p *peer, channel *lnwallet.LightningChannel) error {
// longer active.
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()
// If the channel can't be found in the map, then this channel has
// already been wiped.
htlcWireLink, ok := p.htlcManagers[*chanID]
if !ok {
p.htlcManMtx.RUnlock()
return nil
}
close(htlcWireLink)
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()
delete(p.htlcManagers, *chanID)
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 {
peerLog.Errorf("Unable to delete ChannelPoint(%v) "+
"from db %v", chanID, err)

@ -12,7 +12,6 @@ import (
"sync"
"sync/atomic"
"github.com/lightningnetwork/lnd/routing/rt/graph"
"github.com/btcsuite/fastsha256"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lightning-onion"
@ -20,6 +19,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/rt/graph"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/txscript"
"github.com/roasbeef/btcd/wire"
@ -367,7 +367,15 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
rpcsLog.Tracef("[closechannel] request for ChannelPoint(%v)",
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:
for {