multi: merge local+global features from remote peer
This commit is contained in:
parent
6c86075354
commit
16318c5a41
@ -56,10 +56,10 @@ func (p *mockPeer) Address() net.Addr { return nil }
|
||||
func (p *mockPeer) QuitSignal() <-chan struct{} {
|
||||
return p.quit
|
||||
}
|
||||
func (p *mockPeer) LocalGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (p *mockPeer) LocalFeatures() *lnwire.FeatureVector {
|
||||
return nil
|
||||
}
|
||||
func (p *mockPeer) RemoteGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (p *mockPeer) RemoteFeatures() *lnwire.FeatureVector {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1205,10 +1205,10 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
||||
// negotiated the new tweakless commitment format. This is only the
|
||||
// case if *both* us and the remote peer are signaling the proper
|
||||
// feature bit.
|
||||
localTweakless := fmsg.peer.LocalGlobalFeatures().HasFeature(
|
||||
localTweakless := fmsg.peer.LocalFeatures().HasFeature(
|
||||
lnwire.StaticRemoteKeyOptional,
|
||||
)
|
||||
remoteTweakless := fmsg.peer.RemoteGlobalFeatures().HasFeature(
|
||||
remoteTweakless := fmsg.peer.RemoteFeatures().HasFeature(
|
||||
lnwire.StaticRemoteKeyOptional,
|
||||
)
|
||||
tweaklessCommitment := localTweakless && remoteTweakless
|
||||
@ -2780,10 +2780,10 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
// negotiated the new tweakless commitment format. This is only the
|
||||
// case if *both* us and the remote peer are signaling the proper
|
||||
// feature bit.
|
||||
localTweakless := msg.peer.LocalGlobalFeatures().HasFeature(
|
||||
localTweakless := msg.peer.LocalFeatures().HasFeature(
|
||||
lnwire.StaticRemoteKeyOptional,
|
||||
)
|
||||
remoteTweakless := msg.peer.RemoteGlobalFeatures().HasFeature(
|
||||
remoteTweakless := msg.peer.RemoteFeatures().HasFeature(
|
||||
lnwire.StaticRemoteKeyOptional,
|
||||
)
|
||||
tweaklessCommitment := localTweakless && remoteTweakless
|
||||
|
@ -184,11 +184,11 @@ func (n *testNode) QuitSignal() <-chan struct{} {
|
||||
return n.shutdownChannel
|
||||
}
|
||||
|
||||
func (n *testNode) LocalGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (n *testNode) LocalFeatures() *lnwire.FeatureVector {
|
||||
return lnwire.NewFeatureVector(nil, nil)
|
||||
}
|
||||
|
||||
func (n *testNode) RemoteGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (n *testNode) RemoteFeatures() *lnwire.FeatureVector {
|
||||
return lnwire.NewFeatureVector(nil, nil)
|
||||
}
|
||||
|
||||
|
@ -1653,10 +1653,10 @@ func (m *mockPeer) IdentityKey() *btcec.PublicKey {
|
||||
func (m *mockPeer) Address() net.Addr {
|
||||
return nil
|
||||
}
|
||||
func (m *mockPeer) LocalGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (m *mockPeer) LocalFeatures() *lnwire.FeatureVector {
|
||||
return nil
|
||||
}
|
||||
func (m *mockPeer) RemoteGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (m *mockPeer) RemoteFeatures() *lnwire.FeatureVector {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -607,11 +607,11 @@ func (s *mockServer) WipeChannel(*wire.OutPoint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *mockServer) LocalGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (s *mockServer) LocalFeatures() *lnwire.FeatureVector {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *mockServer) RemoteGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (s *mockServer) RemoteFeatures() *lnwire.FeatureVector {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -47,15 +47,14 @@ type Peer interface {
|
||||
// implementation exits.
|
||||
QuitSignal() <-chan struct{}
|
||||
|
||||
// LocalGlobalFeatures returns the set of global features that has been
|
||||
// advertised by the local peer. This allows sub-systems that use this
|
||||
// LocalFeatures returns the set of features that has been advertised by
|
||||
// the us to the remote peer. This allows sub-systems that use this
|
||||
// interface to gate their behavior off the set of negotiated feature
|
||||
// bits.
|
||||
LocalGlobalFeatures() *lnwire.FeatureVector
|
||||
LocalFeatures() *lnwire.FeatureVector
|
||||
|
||||
// RemoteGlobalFeatures returns the set of global features that has
|
||||
// been advertised by the remote peer. This allows sub-systems that use
|
||||
// this interface to gate their behavior off the set of negotiated
|
||||
// feature bits.
|
||||
RemoteGlobalFeatures() *lnwire.FeatureVector
|
||||
// RemoteFeatures returns the set of features that has been advertised
|
||||
// by the remote peer. This allows sub-systems that use this interface
|
||||
// to gate their behavior off the set of negotiated feature bits.
|
||||
RemoteFeatures() *lnwire.FeatureVector
|
||||
}
|
||||
|
@ -143,6 +143,17 @@ func NewRawFeatureVector(bits ...FeatureBit) *RawFeatureVector {
|
||||
return fv
|
||||
}
|
||||
|
||||
// Merges sets all feature bits in other on the receiver's feature vector.
|
||||
func (fv *RawFeatureVector) Merge(other *RawFeatureVector) error {
|
||||
for bit := range other.features {
|
||||
err := fv.SafeSet(bit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clone makes a copy of a feature vector.
|
||||
func (fv *RawFeatureVector) Clone() *RawFeatureVector {
|
||||
newFeatures := NewRawFeatureVector()
|
||||
|
@ -7,20 +7,26 @@ import "io"
|
||||
// diagnosis where features are incompatible. Each node MUST wait to receive
|
||||
// init before sending any other messages.
|
||||
type Init struct {
|
||||
// GlobalFeatures is feature vector which affects HTLCs and thus are
|
||||
// also advertised to other nodes.
|
||||
// GlobalFeatures is a legacy feature vector used for backwards
|
||||
// compatibility with older nodes. Any features defined here should be
|
||||
// merged with those presented in Features.
|
||||
GlobalFeatures *RawFeatureVector
|
||||
|
||||
// LocalFeatures is feature vector which only affect the protocol
|
||||
// between two nodes.
|
||||
LocalFeatures *RawFeatureVector
|
||||
// Features is a feature vector containing a the features supported by
|
||||
// the remote node.
|
||||
//
|
||||
// NOTE: Older nodes may place some features in GlobalFeatures, but all
|
||||
// new features are to be added in Features. When handling an Init
|
||||
// message, any GlobalFeatures should be merged into the unified
|
||||
// Features field.
|
||||
Features *RawFeatureVector
|
||||
}
|
||||
|
||||
// NewInitMessage creates new instance of init message object.
|
||||
func NewInitMessage(gf *RawFeatureVector, lf *RawFeatureVector) *Init {
|
||||
func NewInitMessage(gf *RawFeatureVector, f *RawFeatureVector) *Init {
|
||||
return &Init{
|
||||
GlobalFeatures: gf,
|
||||
LocalFeatures: lf,
|
||||
Features: f,
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +41,7 @@ var _ Message = (*Init)(nil)
|
||||
func (msg *Init) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&msg.GlobalFeatures,
|
||||
&msg.LocalFeatures,
|
||||
&msg.Features,
|
||||
)
|
||||
}
|
||||
|
||||
@ -46,7 +52,7 @@ func (msg *Init) Decode(r io.Reader, pver uint32) error {
|
||||
func (msg *Init) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
msg.GlobalFeatures,
|
||||
msg.LocalFeatures,
|
||||
msg.Features,
|
||||
)
|
||||
}
|
||||
|
||||
|
63
peer.go
63
peer.go
@ -205,13 +205,9 @@ type peer struct {
|
||||
// an htlc where we don't offer an htlc anymore.
|
||||
outgoingCltvRejectDelta uint32
|
||||
|
||||
// remoteLocalFeatures is the local feature vector received from the
|
||||
// peer during the connection handshake.
|
||||
remoteLocalFeatures *lnwire.FeatureVector
|
||||
|
||||
// remoteGlobalFeatures is the global feature vector received from the
|
||||
// peer during the connection handshake.
|
||||
remoteGlobalFeatures *lnwire.FeatureVector
|
||||
// remoteFeatures is the feature vector received from the peer during
|
||||
// the connection handshake.
|
||||
remoteFeatures *lnwire.FeatureVector
|
||||
|
||||
// failedChannels is a set that tracks channels we consider `failed`.
|
||||
// This is a temporary measure until we have implemented real failure
|
||||
@ -407,7 +403,7 @@ func (p *peer) initGossipSync() {
|
||||
|
||||
// If the remote peer knows of the new gossip queries feature, then
|
||||
// we'll create a new gossipSyncer in the AuthenticatedGossiper for it.
|
||||
case p.remoteLocalFeatures.HasFeature(lnwire.GossipQueriesOptional):
|
||||
case p.remoteFeatures.HasFeature(lnwire.GossipQueriesOptional):
|
||||
srvrLog.Infof("Negotiated chan series queries with %x",
|
||||
p.pubKeyBytes[:])
|
||||
|
||||
@ -2395,54 +2391,55 @@ func (p *peer) WipeChannel(chanPoint *wire.OutPoint) error {
|
||||
// handleInitMsg handles the incoming init message which contains global and
|
||||
// local features vectors. If feature vectors are incompatible then disconnect.
|
||||
func (p *peer) handleInitMsg(msg *lnwire.Init) error {
|
||||
p.remoteLocalFeatures = lnwire.NewFeatureVector(
|
||||
msg.LocalFeatures, lnwire.LocalFeatures,
|
||||
)
|
||||
p.remoteGlobalFeatures = lnwire.NewFeatureVector(
|
||||
msg.GlobalFeatures, lnwire.GlobalFeatures,
|
||||
// First, merge any features from the legacy global features field into
|
||||
// those presented in the local features fields.
|
||||
err := msg.Features.Merge(msg.GlobalFeatures)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to merge legacy global featues: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// Then, finalize the remote feature vector providing the flatteneed
|
||||
// feature bit namespace.
|
||||
p.remoteFeatures = lnwire.NewFeatureVector(
|
||||
msg.Features, lnwire.Features,
|
||||
)
|
||||
|
||||
// Now that we have their features loaded, we'll ensure that they
|
||||
// didn't set any required bits that we don't know of.
|
||||
unknownLocalFeatures := p.remoteLocalFeatures.UnknownRequiredFeatures()
|
||||
if len(unknownLocalFeatures) > 0 {
|
||||
err := fmt.Errorf("Peer set unknown local feature bits: %v",
|
||||
unknownLocalFeatures)
|
||||
return err
|
||||
}
|
||||
unknownGlobalFeatures := p.remoteGlobalFeatures.UnknownRequiredFeatures()
|
||||
if len(unknownGlobalFeatures) > 0 {
|
||||
err := fmt.Errorf("Peer set unknown global feature bits: %v",
|
||||
unknownGlobalFeatures)
|
||||
unknownFeatures := p.remoteFeatures.UnknownRequiredFeatures()
|
||||
if len(unknownFeatures) > 0 {
|
||||
err := fmt.Errorf("peer set unknown feature bits: %v",
|
||||
unknownFeatures)
|
||||
return err
|
||||
}
|
||||
|
||||
// Now that we know we understand their requirements, we'll check to
|
||||
// see if they don't support anything that we deem to be mandatory.
|
||||
switch {
|
||||
case !p.remoteLocalFeatures.HasFeature(lnwire.DataLossProtectRequired):
|
||||
case !p.remoteFeatures.HasFeature(lnwire.DataLossProtectRequired):
|
||||
return fmt.Errorf("data loss protection required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LocalGlobalFeatures returns the set of global features that has been
|
||||
// advertised by the local node. This allows sub-systems that use this
|
||||
// interface to gate their behavior off the set of negotiated feature bits.
|
||||
// LocalFeatures returns the set of global features that has been advertised by
|
||||
// the local node. This allows sub-systems that use this interface to gate their
|
||||
// behavior off the set of negotiated feature bits.
|
||||
//
|
||||
// NOTE: Part of the lnpeer.Peer interface.
|
||||
func (p *peer) LocalGlobalFeatures() *lnwire.FeatureVector {
|
||||
func (p *peer) LocalFeatures() *lnwire.FeatureVector {
|
||||
return p.features
|
||||
}
|
||||
|
||||
// RemoteGlobalFeatures returns the set of global features that has been
|
||||
// advertised by the remote node. This allows sub-systems that use this
|
||||
// interface to gate their behavior off the set of negotiated feature bits.
|
||||
// RemoteFeatures returns the set of global features that has been advertised by
|
||||
// the remote node. This allows sub-systems that use this interface to gate
|
||||
// their behavior off the set of negotiated feature bits.
|
||||
//
|
||||
// NOTE: Part of the lnpeer.Peer interface.
|
||||
func (p *peer) RemoteGlobalFeatures() *lnwire.FeatureVector {
|
||||
return p.remoteGlobalFeatures
|
||||
func (p *peer) RemoteFeatures() *lnwire.FeatureVector {
|
||||
return p.remoteFeatures
|
||||
}
|
||||
|
||||
// sendInitMsg sends init message to remote peer which contains our currently
|
||||
|
Loading…
Reference in New Issue
Block a user