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