diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 5251c06b2..72e5876ac 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -203,11 +203,14 @@ type Config struct { // notification for when it reconnects. NotifyWhenOffline func(peerPubKey [33]byte) <-chan struct{} - // SelfNodeAnnouncement is a function that fetches our own current node - // announcement, for use when determining whether we should update our - // peers about our presence on the network. If the refresh is true, a - // new and updated announcement will be returned. - SelfNodeAnnouncement func(refresh bool) (lnwire.NodeAnnouncement, error) + // FetchSelfAnnouncement retrieves our current node announcement, for + // use when determining whether we should update our peers about our + // presence in the network. + FetchSelfAnnouncement func() lnwire.NodeAnnouncement + + // UpdateSelfAnnouncement produces a new announcement for our node with + // an updated timestamp which can be broadcast to our peers. + UpdateSelfAnnouncement func() (lnwire.NodeAnnouncement, error) // ProofMatureDelta the number of confirmations which is needed before // exchange the channel announcement proofs. @@ -1660,12 +1663,7 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { } // We'll also check that our NodeAnnouncement is not too old. - currentNodeAnn, err := d.cfg.SelfNodeAnnouncement(false) - if err != nil { - return fmt.Errorf("unable to get current node announment: %v", - err) - } - + currentNodeAnn := d.cfg.FetchSelfAnnouncement() timestamp := time.Unix(int64(currentNodeAnn.Timestamp), 0) timeElapsed := now.Sub(timestamp) @@ -1673,7 +1671,7 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { // node announcement, refresh it and resend it. nodeAnnStr := "" if timeElapsed >= d.cfg.RebroadcastInterval { - newNodeAnn, err := d.cfg.SelfNodeAnnouncement(true) + newNodeAnn, err := d.cfg.UpdateSelfAnnouncement() if err != nil { return fmt.Errorf("unable to get refreshed node "+ "announcement: %v", err) diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index cc2fdef05..d364b80ec 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -775,7 +775,14 @@ func createTestCtx(t *testing.T, startHeight uint32) (*testCtx, error) { c := make(chan struct{}) return c }, - SelfNodeAnnouncement: func(bool) (lnwire.NodeAnnouncement, error) { + FetchSelfAnnouncement: func() lnwire.NodeAnnouncement { + return lnwire.NodeAnnouncement{ + Timestamp: testTimestamp, + } + }, + UpdateSelfAnnouncement: func() (lnwire.NodeAnnouncement, + error) { + return lnwire.NodeAnnouncement{ Timestamp: testTimestamp, }, nil @@ -1446,28 +1453,30 @@ func TestSignatureAnnouncementRetryAtStartup(t *testing.T) { return lnwire.ShortChannelID{}, fmt.Errorf("no peer alias") } + //nolint:lll gossiper := New(Config{ - Notifier: ctx.gossiper.cfg.Notifier, - Broadcast: ctx.gossiper.cfg.Broadcast, - NotifyWhenOnline: ctx.gossiper.reliableSender.cfg.NotifyWhenOnline, - NotifyWhenOffline: ctx.gossiper.reliableSender.cfg.NotifyWhenOffline, - SelfNodeAnnouncement: ctx.gossiper.cfg.SelfNodeAnnouncement, - Router: ctx.gossiper.cfg.Router, - TrickleDelay: trickleDelay, - RetransmitTicker: ticker.NewForce(retransmitDelay), - RebroadcastInterval: rebroadcastInterval, - ProofMatureDelta: proofMatureDelta, - WaitingProofStore: ctx.gossiper.cfg.WaitingProofStore, - MessageStore: ctx.gossiper.cfg.MessageStore, - RotateTicker: ticker.NewForce(DefaultSyncerRotationInterval), - HistoricalSyncTicker: ticker.NewForce(DefaultHistoricalSyncInterval), - NumActiveSyncers: 3, - MinimumBatchSize: 10, - SubBatchDelay: time.Second * 5, - IsAlias: isAlias, - SignAliasUpdate: signAliasUpdate, - FindBaseByAlias: findBaseByAlias, - GetAlias: getAlias, + Notifier: ctx.gossiper.cfg.Notifier, + Broadcast: ctx.gossiper.cfg.Broadcast, + NotifyWhenOnline: ctx.gossiper.reliableSender.cfg.NotifyWhenOnline, + NotifyWhenOffline: ctx.gossiper.reliableSender.cfg.NotifyWhenOffline, + FetchSelfAnnouncement: ctx.gossiper.cfg.FetchSelfAnnouncement, + UpdateSelfAnnouncement: ctx.gossiper.cfg.UpdateSelfAnnouncement, + Router: ctx.gossiper.cfg.Router, + TrickleDelay: trickleDelay, + RetransmitTicker: ticker.NewForce(retransmitDelay), + RebroadcastInterval: rebroadcastInterval, + ProofMatureDelta: proofMatureDelta, + WaitingProofStore: ctx.gossiper.cfg.WaitingProofStore, + MessageStore: ctx.gossiper.cfg.MessageStore, + RotateTicker: ticker.NewForce(DefaultSyncerRotationInterval), + HistoricalSyncTicker: ticker.NewForce(DefaultHistoricalSyncInterval), + NumActiveSyncers: 3, + MinimumBatchSize: 10, + SubBatchDelay: time.Second * 5, + IsAlias: isAlias, + SignAliasUpdate: signAliasUpdate, + FindBaseByAlias: findBaseByAlias, + GetAlias: getAlias, }, &keychain.KeyDescriptor{ PubKey: ctx.gossiper.selfKey, KeyLocator: ctx.gossiper.selfKeyLoc, diff --git a/funding/manager.go b/funding/manager.go index 3e72b896c..043ea4eb9 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -373,7 +373,8 @@ type Config struct { msg []byte, doubleHash bool) (*ecdsa.Signature, error) // CurrentNodeAnnouncement should return the latest, fully signed node - // announcement from the backing Lightning Network node. + // announcement from the backing Lightning Network node with a fresh + // timestamp. CurrentNodeAnnouncement func() (lnwire.NodeAnnouncement, error) // SendAnnouncement is used by the FundingManager to send announcement diff --git a/lnrpc/peersrpc/config_active.go b/lnrpc/peersrpc/config_active.go index 860e7627e..34da09699 100644 --- a/lnrpc/peersrpc/config_active.go +++ b/lnrpc/peersrpc/config_active.go @@ -18,7 +18,7 @@ import ( type Config struct { // GetNodeAnnouncement is used to send our retrieve the current // node announcement information. - GetNodeAnnouncement func() (lnwire.NodeAnnouncement, error) + GetNodeAnnouncement func() lnwire.NodeAnnouncement // ParseAddr parses an address from its string format to a net.Addr. ParseAddr func(addr string) (net.Addr, error) diff --git a/lnrpc/peersrpc/peers_server.go b/lnrpc/peersrpc/peers_server.go index 84516f7dc..5710f5fca 100644 --- a/lnrpc/peersrpc/peers_server.go +++ b/lnrpc/peersrpc/peers_server.go @@ -313,11 +313,7 @@ func (s *Server) UpdateNodeAnnouncement(_ context.Context, resp := &NodeAnnouncementUpdateResponse{} nodeModifiers := make([]netann.NodeAnnModifier, 0) - currentNodeAnn, err := s.cfg.GetNodeAnnouncement() - if err != nil { - return nil, fmt.Errorf("unable to get current node "+ - "announcement: %v", err) - } + currentNodeAnn := s.cfg.GetNodeAnnouncement() if len(req.FeatureUpdates) > 0 { features, ops, err := s.updateFeatures( diff --git a/netann/host_ann.go b/netann/host_ann.go index bc50289c1..767c3089c 100644 --- a/netann/host_ann.go +++ b/netann/host_ann.go @@ -168,15 +168,18 @@ func (h *HostAnnouncer) hostWatcher() { // NodeAnnUpdater describes a function that's able to update our current node // announcement on disk. It returns the updated node announcement given a set // of updates to be applied to the current node announcement. -type NodeAnnUpdater func(refresh bool, modifier ...NodeAnnModifier, +type NodeAnnUpdater func(modifier ...NodeAnnModifier, ) (lnwire.NodeAnnouncement, error) // IPAnnouncer is a factory function that generates a new function that uses // the passed annUpdater function to to announce new IP changes for a given // host. -func IPAnnouncer(annUpdater NodeAnnUpdater) func([]net.Addr, map[string]struct{}) error { +func IPAnnouncer(annUpdater NodeAnnUpdater) func([]net.Addr, + map[string]struct{}) error { + return func(newAddrs []net.Addr, oldAddrs map[string]struct{}) error { - _, err := annUpdater(true, func(currentNodeAnn *lnwire.NodeAnnouncement) { + _, err := annUpdater(func( + currentNodeAnn *lnwire.NodeAnnouncement) { // To ensure we don't duplicate any addresses, we'll // filter out the same of addresses we should no longer // advertise. diff --git a/peer/brontide.go b/peer/brontide.go index 82b11e310..08cad15de 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -263,8 +263,8 @@ type Config struct { // GenNodeAnnouncement is used to send our node announcement to the remote // on startup. - GenNodeAnnouncement func(bool, - ...netann.NodeAnnModifier) (lnwire.NodeAnnouncement, error) + GenNodeAnnouncement func(...netann.NodeAnnModifier) ( + lnwire.NodeAnnouncement, error) // PrunePersistentPeerConnection is used to remove all internal state // related to this peer in the server. @@ -1036,7 +1036,7 @@ func (p *Brontide) maybeSendNodeAnn(channels []*channeldb.OpenChannel) { return } - ourNodeAnn, err := p.cfg.GenNodeAnnouncement(false) + ourNodeAnn, err := p.cfg.GenNodeAnnouncement() if err != nil { p.log.Debugf("Unable to retrieve node announcement: %v", err) return diff --git a/rpcserver.go b/rpcserver.go index 528ca18d2..9cdcb9ee6 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -762,10 +762,6 @@ func (r *rpcServer) addDeps(s *server, macService *macaroons.Service, return s.featureMgr.Get(feature.SetInvoiceAmp) } - getNodeAnnouncement := func() (lnwire.NodeAnnouncement, error) { - return s.genNodeAnnouncement(false) - } - parseAddr := func(addr string) (net.Addr, error) { return parseAddr(addr, r.cfg.net) } @@ -786,7 +782,7 @@ func (r *rpcServer) addDeps(s *server, macService *macaroons.Service, routerBackend, s.nodeSigner, s.graphDB, s.chanStateDB, s.sweeper, tower, s.towerClient, s.anchorTowerClient, r.cfg.net.ResolveTCPAddr, genInvoiceFeatures, - genAmpInvoiceFeatures, getNodeAnnouncement, + genAmpInvoiceFeatures, s.getNodeAnnouncement, s.updateAndBrodcastSelfNode, parseAddr, rpcsLog, s.aliasMgr.GetPeerAlias, ) @@ -2910,11 +2906,8 @@ func (r *rpcServer) GetInfo(_ context.Context, // Check if external IP addresses were provided to lnd and use them // to set the URIs. - nodeAnn, err := r.server.genNodeAnnouncement(false) - if err != nil { - return nil, fmt.Errorf("unable to retrieve current fully signed "+ - "node announcement: %v", err) - } + nodeAnn := r.server.getNodeAnnouncement() + addrs := nodeAnn.Addresses uris := make([]string, len(addrs)) for i, addr := range addrs { diff --git a/server.go b/server.go index 97aad7a02..9957abbda 100644 --- a/server.go +++ b/server.go @@ -993,15 +993,18 @@ func newServer(cfg *Config, listenAddrs []net.Addr, } s.authGossiper = discovery.New(discovery.Config{ - Router: s.chanRouter, - Notifier: s.cc.ChainNotifier, - ChainHash: *s.cfg.ActiveNetParams.GenesisHash, - Broadcast: s.BroadcastMessage, - ChanSeries: chanSeries, - NotifyWhenOnline: s.NotifyWhenOnline, - NotifyWhenOffline: s.NotifyWhenOffline, - SelfNodeAnnouncement: func(refresh bool) (lnwire.NodeAnnouncement, error) { - return s.genNodeAnnouncement(refresh) + Router: s.chanRouter, + Notifier: s.cc.ChainNotifier, + ChainHash: *s.cfg.ActiveNetParams.GenesisHash, + Broadcast: s.BroadcastMessage, + ChanSeries: chanSeries, + NotifyWhenOnline: s.NotifyWhenOnline, + NotifyWhenOffline: s.NotifyWhenOffline, + FetchSelfAnnouncement: s.getNodeAnnouncement, + UpdateSelfAnnouncement: func() (lnwire.NodeAnnouncement, + error) { + + return s.genNodeAnnouncement() }, ProofMatureDelta: 0, TrickleDelay: time.Millisecond * time.Duration(cfg.TrickleDelay), @@ -1271,6 +1274,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, return ourPolicy, err } + //nolint:lll s.fundingMgr, err = funding.NewFundingManager(funding.Config{ NoWumboChans: !cfg.ProtocolOptions.Wumbo(), IDKey: nodeKeyDesc.PubKey, @@ -1283,8 +1287,10 @@ func newServer(cfg *Config, listenAddrs []net.Addr, Notifier: cc.ChainNotifier, FeeEstimator: cc.FeeEstimator, SignMessage: cc.MsgSigner.SignMessage, - CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement, error) { - return s.genNodeAnnouncement(true) + CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement, + error) { + + return s.genNodeAnnouncement() }, SendAnnouncement: s.authGossiper.ProcessLocalAnnouncement, NotifyWhenOnline: s.NotifyWhenOnline, @@ -2476,12 +2482,8 @@ out: // throughout the network. We'll only include addresses // that have a different IP from the previous one, as // the previous IP is no longer valid. - currentNodeAnn, err := s.genNodeAnnouncement(false) - if err != nil { - srvrLog.Debugf("Unable to retrieve current "+ - "node announcement: %v", err) - continue - } + currentNodeAnn := s.getNodeAnnouncement() + for _, addr := range currentNodeAnn.Addresses { host, _, err := net.SplitHostPort(addr.String()) if err != nil { @@ -2503,7 +2505,7 @@ out: // announcement with the updated addresses and broadcast // it to our peers. newNodeAnn, err := s.genNodeAnnouncement( - true, netann.NodeAnnSetAddrs(newAddrs), + netann.NodeAnnSetAddrs(newAddrs), ) if err != nil { srvrLog.Debugf("Unable to generate new node "+ @@ -2892,7 +2894,7 @@ func (s *server) createNewHiddenService() error { // Now that the onion service has been created, we'll add the onion // address it can be reached at to our list of advertised addresses. newNodeAnn, err := s.genNodeAnnouncement( - true, func(currentAnn *lnwire.NodeAnnouncement) { + func(currentAnn *lnwire.NodeAnnouncement) { currentAnn.Addresses = append(currentAnn.Addresses, addr) }, ) @@ -2942,20 +2944,22 @@ func (s *server) findChannel(node *btcec.PublicKey, chanID lnwire.ChannelID) ( return nil, fmt.Errorf("unable to find channel") } -// genNodeAnnouncement generates and returns the current fully signed node -// announcement. If refresh is true, then the time stamp of the announcement -// will be updated in order to ensure it propagates through the network. -func (s *server) genNodeAnnouncement(refresh bool, - modifiers ...netann.NodeAnnModifier) (lnwire.NodeAnnouncement, error) { - +// getNodeAnnouncement fetches the current, fully signed node announcement. +func (s *server) getNodeAnnouncement() lnwire.NodeAnnouncement { s.mu.Lock() defer s.mu.Unlock() - // If we don't need to refresh the announcement, then we can return a - // copy of our cached version. - if !refresh { - return *s.currentNodeAnn, nil - } + return *s.currentNodeAnn +} + +// genNodeAnnouncement generates and returns the current fully signed node +// announcement. The time stamp of the announcement will be updated in order +// to ensure it propagates through the network. +func (s *server) genNodeAnnouncement(modifiers ...netann.NodeAnnModifier) ( + lnwire.NodeAnnouncement, error) { + + s.mu.Lock() + defer s.mu.Unlock() // Always update the timestamp when refreshing to ensure the update // propagates. @@ -2966,8 +2970,7 @@ func (s *server) genNodeAnnouncement(refresh bool, modifier(s.currentNodeAnn) } - // Otherwise, we'll sign a new update after applying all of the passed - // modifiers. + // Sign a new update after applying all of the passed modifiers. err := netann.SignNodeAnnouncement( s.nodeSigner, s.identityKeyLoc, s.currentNodeAnn, ) @@ -2985,7 +2988,7 @@ func (s *server) genNodeAnnouncement(refresh bool, func (s *server) updateAndBrodcastSelfNode( modifiers ...netann.NodeAnnModifier) error { - newNodeAnn, err := s.genNodeAnnouncement(true, modifiers...) + newNodeAnn, err := s.genNodeAnnouncement(modifiers...) if err != nil { return fmt.Errorf("unable to generate new node "+ "announcement: %v", err) diff --git a/subrpcserver_config.go b/subrpcserver_config.go index 2723efaea..8de66d1ad 100644 --- a/subrpcserver_config.go +++ b/subrpcserver_config.go @@ -118,7 +118,7 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config, tcpResolver lncfg.TCPResolver, genInvoiceFeatures func() *lnwire.FeatureVector, genAmpInvoiceFeatures func() *lnwire.FeatureVector, - getNodeAnnouncement func() (lnwire.NodeAnnouncement, error), + getNodeAnnouncement func() lnwire.NodeAnnouncement, updateNodeAnnouncement func(modifiers ...netann.NodeAnnModifier) error, parseAddr func(addr string) (net.Addr, error), rpcLogger btclog.Logger,