mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 01:36:24 +01:00
lnrpc/peers: handle feature bit changes in updateNodeAnnouncement
This commit is contained in:
parent
76196db70e
commit
ae2aa5671f
5 changed files with 171 additions and 1 deletions
|
@ -141,6 +141,11 @@ func (m *Manager) GetRaw(set Set) *lnwire.RawFeatureVector {
|
|||
return lnwire.NewRawFeatureVector()
|
||||
}
|
||||
|
||||
// SetRaw sets a new raw feature vector for the given set.
|
||||
func (m *Manager) SetRaw(set Set, raw *lnwire.RawFeatureVector) {
|
||||
m.fsets[set] = raw
|
||||
}
|
||||
|
||||
// Get returns a feature vector for the passed set. If no set is known, an empty
|
||||
// feature vector is returned.
|
||||
func (m *Manager) Get(set Set) *lnwire.FeatureVector {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"sync/atomic"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/lightningnetwork/lnd/feature"
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
|
@ -241,6 +242,68 @@ func (s *Server) updateAddresses(currentAddresses []net.Addr,
|
|||
return newAddrs, ops, nil
|
||||
}
|
||||
|
||||
// updateFeatures computes the new raw SetNodeAnn after executing the update
|
||||
// actions.
|
||||
func (s *Server) updateFeatures(currentfeatures *lnwire.RawFeatureVector,
|
||||
updates []*UpdateFeatureAction) (*lnwire.RawFeatureVector,
|
||||
*lnrpc.Op, error) {
|
||||
|
||||
ops := &lnrpc.Op{Entity: "features"}
|
||||
raw := currentfeatures.Clone()
|
||||
|
||||
for _, update := range updates {
|
||||
bit := lnwire.FeatureBit(update.FeatureBit)
|
||||
|
||||
switch update.Action {
|
||||
case UpdateAction_ADD:
|
||||
if raw.IsSet(bit) {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"invalid add action for bit %v, "+
|
||||
"bit is already set",
|
||||
update.FeatureBit,
|
||||
)
|
||||
}
|
||||
raw.Set(bit)
|
||||
ops.Actions = append(
|
||||
ops.Actions,
|
||||
fmt.Sprintf("%s set", lnwire.Features[bit]),
|
||||
)
|
||||
|
||||
case UpdateAction_REMOVE:
|
||||
if !raw.IsSet(bit) {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"invalid remove action for bit %v, "+
|
||||
"bit is already unset",
|
||||
update.FeatureBit,
|
||||
)
|
||||
}
|
||||
raw.Unset(bit)
|
||||
ops.Actions = append(
|
||||
ops.Actions,
|
||||
fmt.Sprintf("%s unset", lnwire.Features[bit]),
|
||||
)
|
||||
|
||||
default:
|
||||
return nil, nil, fmt.Errorf(
|
||||
"invalid update action (%v) for bit %v",
|
||||
update.Action,
|
||||
update.FeatureBit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate our new SetNodeAnn.
|
||||
fv := lnwire.NewFeatureVector(raw, lnwire.Features)
|
||||
if err := feature.ValidateDeps(fv); err != nil {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"invalid feature set (SetNodeAnn): %v",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
return raw, ops, nil
|
||||
}
|
||||
|
||||
// UpdateNodeAnnouncement allows the caller to update the node parameters
|
||||
// and broadcasts a new version of the node announcement to its peers.
|
||||
func (s *Server) UpdateNodeAnnouncement(_ context.Context,
|
||||
|
@ -256,7 +319,21 @@ func (s *Server) UpdateNodeAnnouncement(_ context.Context,
|
|||
"announcement: %v", err)
|
||||
}
|
||||
|
||||
// TODO(positiveblue): apply feature bit modifications
|
||||
if len(req.FeatureUpdates) > 0 {
|
||||
features, ops, err := s.updateFeatures(
|
||||
currentNodeAnn.Features,
|
||||
req.FeatureUpdates,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error trying to update node "+
|
||||
"features: %w", err)
|
||||
}
|
||||
resp.Ops = append(resp.Ops, ops)
|
||||
nodeModifiers = append(
|
||||
nodeModifiers,
|
||||
netann.NodeAnnSetFeatures(features),
|
||||
)
|
||||
}
|
||||
|
||||
if req.Color != "" {
|
||||
color, err := lncfg.ParseHexColor(req.Color)
|
||||
|
|
|
@ -841,6 +841,15 @@ func testUpdateNodeAnnouncement(net *lntest.NetworkHarness, t *harnessTest) {
|
|||
)
|
||||
}
|
||||
|
||||
// This feature bit is used to test that our endpoint sets/unsets
|
||||
// feature bits properly. If the current FeatureBit is set by default
|
||||
// update this one for another one unset by default at random.
|
||||
featureBit := lnrpc.FeatureBit_WUMBO_CHANNELS_REQ
|
||||
featureIdx := uint32(featureBit)
|
||||
if _, ok := resp.Features[featureIdx]; ok {
|
||||
t.Fatalf("unexpected feature bit enabled by default")
|
||||
}
|
||||
|
||||
defaultDaveNodeAnn := &lnrpc.NodeUpdate{
|
||||
Alias: resp.Alias,
|
||||
Color: resp.Color,
|
||||
|
@ -912,16 +921,25 @@ func testUpdateNodeAnnouncement(net *lntest.NetworkHarness, t *harnessTest) {
|
|||
},
|
||||
}
|
||||
|
||||
updateFeatureActions := []*peersrpc.UpdateFeatureAction{
|
||||
{
|
||||
Action: peersrpc.UpdateAction_ADD,
|
||||
FeatureBit: featureBit,
|
||||
},
|
||||
}
|
||||
|
||||
nodeAnnReq := &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
Alias: newAlias,
|
||||
Color: newColor,
|
||||
AddressUpdates: updateAddressActions,
|
||||
FeatureUpdates: updateFeatureActions,
|
||||
}
|
||||
|
||||
response, err := dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
|
||||
require.NoError(t.t, err, "unable to update dave's node announcement")
|
||||
|
||||
expectedOps := map[string]int{
|
||||
"features": 1,
|
||||
"color": 1,
|
||||
"alias": 1,
|
||||
"addresses": 3,
|
||||
|
@ -951,6 +969,63 @@ func testUpdateNodeAnnouncement(net *lntest.NetworkHarness, t *harnessTest) {
|
|||
aliceSub, dave.PubKeyStr, newDaveNodeAnn, t,
|
||||
)
|
||||
|
||||
// Check that the feature bit was set correctly.
|
||||
resp, err = dave.GetInfo(ctxt, nodeInfoReq)
|
||||
require.NoError(t.t, err, "unable to get dave's information")
|
||||
|
||||
if _, ok := resp.Features[featureIdx]; !ok {
|
||||
t.Fatalf("failed to set feature bit")
|
||||
}
|
||||
|
||||
// Check that we cannot set a feature bit that is already set.
|
||||
nodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
FeatureUpdates: updateFeatureActions,
|
||||
}
|
||||
|
||||
_, err = dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
|
||||
require.Error(
|
||||
t.t, err, "missing expected error: cannot set a feature bit "+
|
||||
"that is already set",
|
||||
)
|
||||
|
||||
// Check that we can unset feature bits.
|
||||
updateFeatureActions = []*peersrpc.UpdateFeatureAction{
|
||||
{
|
||||
Action: peersrpc.UpdateAction_REMOVE,
|
||||
FeatureBit: featureBit,
|
||||
},
|
||||
}
|
||||
|
||||
nodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
FeatureUpdates: updateFeatureActions,
|
||||
}
|
||||
|
||||
response, err = dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
|
||||
require.NoError(t.t, err, "unable to update dave's node announcement")
|
||||
|
||||
expectedOps = map[string]int{
|
||||
"features": 1,
|
||||
}
|
||||
assertUpdateNodeAnnouncementResponse(t, response, expectedOps)
|
||||
|
||||
resp, err = dave.GetInfo(ctxt, nodeInfoReq)
|
||||
require.NoError(t.t, err, "unable to get dave's information")
|
||||
|
||||
if _, ok := resp.Features[featureIdx]; ok {
|
||||
t.Fatalf("failed to unset feature bit")
|
||||
}
|
||||
|
||||
// Check that we cannot unset a feature bit that is already unset.
|
||||
nodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
FeatureUpdates: updateFeatureActions,
|
||||
}
|
||||
|
||||
_, err = dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
|
||||
require.Error(
|
||||
t.t, err, "missing expected error: cannot unset a feature bit "+
|
||||
"that is already unset",
|
||||
)
|
||||
|
||||
// Close the channel between Bob and Dave.
|
||||
closeChannelAndAssert(t, net, net.Bob, chanPoint, false)
|
||||
}
|
||||
|
|
|
@ -38,6 +38,14 @@ func NodeAnnSetColor(newColor color.RGBA) func(*lnwire.NodeAnnouncement) {
|
|||
}
|
||||
}
|
||||
|
||||
// NodeAnnSetFeatures is a functional option that allows updating the features of
|
||||
// the given node announcement.
|
||||
func NodeAnnSetFeatures(features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement) {
|
||||
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
||||
nodeAnn.Features = features
|
||||
}
|
||||
}
|
||||
|
||||
// NodeAnnSetTimestamp is a functional option that sets the timestamp of the
|
||||
// announcement to the current time, or increments it if the timestamp is
|
||||
// already in the future.
|
||||
|
|
|
@ -2771,6 +2771,11 @@ func (s *server) updateAndBrodcastSelfNode(
|
|||
return fmt.Errorf("can't set self node: %v", err)
|
||||
}
|
||||
|
||||
// Update the feature bits for the SetNodeAnn in case they changed.
|
||||
s.featureMgr.SetRaw(
|
||||
feature.SetNodeAnn, selfNode.Features.RawFeatureVector,
|
||||
)
|
||||
|
||||
// Finally, propagate it to the nodes in the network.
|
||||
err = s.BroadcastMessage(nil, &newNodeAnn)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Reference in a new issue