Merge pull request #1905 from halseth/fundinglocked-htlc-mismatch

Defer channel restoration until after channel active check.
This commit is contained in:
Olaoluwa Osuntokun 2018-09-28 16:34:18 -07:00 committed by GitHub
commit c508365bcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 55 deletions

View File

@ -26,7 +26,6 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing"
)
@ -2315,7 +2314,7 @@ func (p *mockPeer) SendMessage(_ bool, msgs ...lnwire.Message) error {
return nil
}
func (p *mockPeer) AddNewChannel(_ *lnwallet.LightningChannel, _ <-chan struct{}) error {
func (p *mockPeer) AddNewChannel(_ *channeldb.OpenChannel, _ <-chan struct{}) error {
return nil
}
func (p *mockPeer) WipeChannel(_ *wire.OutPoint) error { return nil }

View File

@ -267,7 +267,7 @@ type fundingConfig struct {
// FindChannel queries the database for the channel with the given
// channel ID.
FindChannel func(chanID lnwire.ChannelID) (*lnwallet.LightningChannel, error)
FindChannel func(chanID lnwire.ChannelID) (*channeldb.OpenChannel, error)
// TempChanIDSeed is a cryptographically random string of bytes that's
// used as a seed to generate pending channel ID's.
@ -2323,10 +2323,9 @@ func (f *fundingManager) handleFundingLocked(fmsg *fundingLockedMsg) {
// If the RemoteNextRevocation is non-nil, it means that we have
// already processed fundingLocked for this channel, so ignore.
if channel.RemoteNextRevocation() != nil {
if channel.RemoteNextRevocation != nil {
fndgLog.Infof("Received duplicate fundingLocked for "+
"ChannelID(%v), ignoring.", chanID)
channel.Stop()
return
}
@ -2334,10 +2333,9 @@ func (f *fundingManager) handleFundingLocked(fmsg *fundingLockedMsg) {
// need to create the next commitment state for the remote party. So
// we'll insert that into the channel now before passing it along to
// other sub-systems.
err = channel.InitNextRevocation(fmsg.msg.NextPerCommitmentPoint)
err = channel.InsertNextRevocation(fmsg.msg.NextPerCommitmentPoint)
if err != nil {
fndgLog.Errorf("unable to insert next commitment point: %v", err)
channel.Stop()
return
}
@ -2361,8 +2359,7 @@ func (f *fundingManager) handleFundingLocked(fmsg *fundingLockedMsg) {
if err := fmsg.peer.AddNewChannel(channel, f.quit); err != nil {
fndgLog.Errorf("Unable to add new channel %v with peer %x: %v",
fmsg.peer.IdentityKey().SerializeCompressed(),
*channel.ChanPoint, err)
channel.Stop()
channel.FundingOutpoint, err)
}
}

View File

@ -178,13 +178,13 @@ func (n *testNode) QuitSignal() <-chan struct{} {
return n.shutdownChannel
}
func (n *testNode) AddNewChannel(channel *lnwallet.LightningChannel,
func (n *testNode) AddNewChannel(channel *channeldb.OpenChannel,
quit <-chan struct{}) error {
done := make(chan struct{})
errChan := make(chan error)
msg := &newChannelMsg{
channel: channel,
done: done,
err: errChan,
}
select {
@ -194,12 +194,11 @@ func (n *testNode) AddNewChannel(channel *lnwallet.LightningChannel,
}
select {
case <-done:
case err := <-errChan:
return err
case <-quit:
return ErrFundingManagerShuttingDown
}
return nil
}
func init() {
@ -304,7 +303,8 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
return lnwire.NodeAnnouncement{}, nil
},
TempChanIDSeed: chanIDSeed,
FindChannel: func(chanID lnwire.ChannelID) (*lnwallet.LightningChannel, error) {
FindChannel: func(chanID lnwire.ChannelID) (
*channeldb.OpenChannel, error) {
dbChannels, err := cdb.FetchAllChannels()
if err != nil {
return nil, err
@ -312,10 +312,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
for _, channel := range dbChannels {
if chanID.IsChanPoint(&channel.FundingOutpoint) {
return lnwallet.NewLightningChannel(
signer,
nil,
channel)
return channel, nil
}
}
@ -992,14 +989,14 @@ func assertHandleFundingLocked(t *testing.T, alice, bob *testNode) {
// They should both send the new channel state to their peer.
select {
case c := <-alice.newChannels:
close(c.done)
close(c.err)
case <-time.After(time.Second * 15):
t.Fatalf("alice did not send new channel to peer")
}
select {
case c := <-bob.newChannels:
close(c.done)
close(c.err)
case <-time.After(time.Second * 15):
t.Fatalf("bob did not send new channel to peer")
}

View File

@ -1477,7 +1477,8 @@ func (m *mockPeer) SendMessage(sync bool, msgs ...lnwire.Message) error {
}
return nil
}
func (m *mockPeer) AddNewChannel(_ *lnwallet.LightningChannel, _ <-chan struct{}) error {
func (m *mockPeer) AddNewChannel(_ *channeldb.OpenChannel,
_ <-chan struct{}) error {
return nil
}
func (m *mockPeer) WipeChannel(*wire.OutPoint) error {

View File

@ -543,7 +543,7 @@ func (s *mockServer) Address() net.Addr {
return nil
}
func (s *mockServer) AddNewChannel(channel *lnwallet.LightningChannel,
func (s *mockServer) AddNewChannel(channel *channeldb.OpenChannel,
cancel <-chan struct{}) error {
return nil

View File

@ -5,7 +5,7 @@ import (
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
)
@ -19,7 +19,7 @@ type Peer interface {
// AddNewChannel adds a new channel to the peer. The channel should fail
// to be added if the cancel channel is closed.
AddNewChannel(channel *lnwallet.LightningChannel, cancel <-chan struct{}) error
AddNewChannel(channel *channeldb.OpenChannel, cancel <-chan struct{}) error
// WipeChannel removes the channel uniquely identified by its channel
// point from all indexes associated with the peer.

74
peer.go
View File

@ -59,12 +59,12 @@ type outgoingMsg struct {
errChan chan error // MUST be buffered.
}
// newChannelMsg packages an lnwallet.LightningChannel with a channel that
// allows the receiver of the request to report when the funding transaction
// has been confirmed and the channel creation process completed.
// newChannelMsg packages a channeldb.OpenChannel with a channel that allows
// the receiver of the request to report when the funding transaction has been
// confirmed and the channel creation process completed.
type newChannelMsg struct {
channel *lnwallet.LightningChannel
done chan struct{}
channel *channeldb.OpenChannel
err chan error
}
// closeMsgs is a wrapper struct around any wire messages that deal with the
@ -1522,9 +1522,9 @@ out:
// funding workflow. We'll initialize the necessary local
// state, and notify the htlc switch of a new link.
case newChanReq := <-p.newChannels:
chanPoint := newChanReq.channel.ChannelPoint()
chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
newChan := newChanReq.channel
chanPoint := &newChan.FundingOutpoint
chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
// Make sure this channel is not already active.
p.activeChanMtx.Lock()
@ -1533,8 +1533,7 @@ out:
"ignoring.", chanPoint)
p.activeChanMtx.Unlock()
close(newChanReq.done)
newChanReq.channel.Stop()
close(newChanReq.err)
// If we're being sent a new channel, and our
// existing channel doesn't have the next
@ -1548,7 +1547,7 @@ out:
"FundingLocked for ChannelPoint(%v)",
chanPoint)
nextRevoke := newChan.RemoteNextRevocation()
nextRevoke := newChan.RemoteNextRevocation
err := currentChan.InitNextRevocation(nextRevoke)
if err != nil {
peerLog.Errorf("unable to init chan "+
@ -1562,7 +1561,21 @@ out:
// If not already active, we'll add this channel to the
// set of active channels, so we can look it up later
// easily according to its channel ID.
p.activeChannels[chanID] = newChan
lnChan, err := lnwallet.NewLightningChannel(
p.server.cc.signer, p.server.witnessBeacon,
newChan,
)
if err != nil {
p.activeChanMtx.Unlock()
err := fmt.Errorf("unable to create "+
"LightningChannel: %v", err)
peerLog.Errorf(err.Error())
newChanReq.err <- err
continue
}
p.activeChannels[chanID] = lnChan
p.activeChanMtx.Unlock()
peerLog.Infof("New channel active ChannelPoint(%v) "+
@ -1574,15 +1587,24 @@ out:
// TODO(roasbeef): panic on below?
_, currentHeight, err := p.server.cc.chainIO.GetBestBlock()
if err != nil {
peerLog.Errorf("unable to get best block: %v", err)
err := fmt.Errorf("unable to get best "+
"block: %v", err)
peerLog.Errorf(err.Error())
lnChan.Stop()
newChanReq.err <- err
continue
}
chainEvents, err := p.server.chainArb.SubscribeChannelEvents(
*chanPoint,
)
if err != nil {
peerLog.Errorf("unable to subscribe to chain "+
"events: %v", err)
err := fmt.Errorf("unable to subscribe to "+
"chain events: %v", err)
peerLog.Errorf(err.Error())
lnChan.Stop()
newChanReq.err <- err
continue
}
@ -1591,7 +1613,7 @@ out:
// forwarded. For fees we'll use the default values, as
// they currently are always set to the default values
// at initial channel creation.
fwdMinHtlc := newChan.FwdMinHtlc()
fwdMinHtlc := lnChan.FwdMinHtlc()
defaultPolicy := p.server.cc.routingPolicy
forwardingPolicy := &htlcswitch.ForwardingPolicy{
MinHTLC: fwdMinHtlc,
@ -1602,16 +1624,21 @@ out:
// Create the link and add it to the switch.
err = p.addLink(
chanPoint, newChan, forwardingPolicy,
chanPoint, lnChan, forwardingPolicy,
chainEvents, currentHeight, false,
)
if err != nil {
peerLog.Errorf("can't register new channel "+
err := fmt.Errorf("can't register new channel "+
"link(%v) with NodeKey(%x)", chanPoint,
p.PubKey())
peerLog.Errorf(err.Error())
lnChan.Stop()
newChanReq.err <- err
continue
}
close(newChanReq.done)
close(newChanReq.err)
// We've just received a local request to close an active
// channel. If will either kick of a cooperative channel
@ -2171,13 +2198,13 @@ func (p *peer) Address() net.Addr {
// added if the cancel channel is closed.
//
// NOTE: Part of the lnpeer.Peer interface.
func (p *peer) AddNewChannel(channel *lnwallet.LightningChannel,
func (p *peer) AddNewChannel(channel *channeldb.OpenChannel,
cancel <-chan struct{}) error {
newChanDone := make(chan struct{})
errChan := make(chan error, 1)
newChanMsg := &newChannelMsg{
channel: channel,
done: newChanDone,
err: errChan,
}
select {
@ -2191,12 +2218,11 @@ func (p *peer) AddNewChannel(channel *lnwallet.LightningChannel,
// We pause here to wait for the peer to recognize the new channel
// before we close the channel barrier corresponding to the channel.
select {
case <-newChanDone:
case err := <-errChan:
return err
case <-p.quit:
return ErrPeerExiting
}
return nil
}
// StartTime returns the time at which the connection was established if the

View File

@ -743,7 +743,9 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
},
NotifyWhenOnline: s.NotifyWhenOnline,
TempChanIDSeed: chanIDSeed,
FindChannel: func(chanID lnwire.ChannelID) (*lnwallet.LightningChannel, error) {
FindChannel: func(chanID lnwire.ChannelID) (
*channeldb.OpenChannel, error) {
dbChannels, err := chanDB.FetchAllChannels()
if err != nil {
return nil, err
@ -751,10 +753,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
for _, channel := range dbChannels {
if chanID.IsChanPoint(&channel.FundingOutpoint) {
return lnwallet.NewLightningChannel(
cc.signer, s.witnessBeacon,
channel,
)
return channel, nil
}
}