From adf6b8619f8de4bae35fd06116a01047167d030e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 3 Sep 2018 21:58:48 -0700 Subject: [PATCH] peer: dispatch gossip sync in peer start This commit moves the gossip sync dispatch such that it is more tightly coupled to the life cycle of the peer. In testing, I noticed that the gossip syncer needs to be dispatched before the first gossip messages come across the wire. The prior spawn location in the server happens after starting all of the peer's goroutines, which could permit an ordering where the gossip syncer has not yet been registered. The new location registers the gossip syncer within the read handler such that the call is blocks before any messages are read. --- peer.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/peer.go b/peer.go index c1afa0ed1..a45263265 100644 --- a/peer.go +++ b/peer.go @@ -320,6 +320,43 @@ func (p *peer) Start() error { return nil } +// initGossipSync initializes either a gossip syncer or an initial routing +// dump, depending on the negotiated synchronization method. +func (p *peer) initGossipSync() { + switch { + + // 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): + srvrLog.Infof("Negotiated chan series queries with %x", + p.pubKeyBytes[:]) + + // We'll only request channel updates from the remote peer if + // its enabled in the config, or we're already getting updates + // from enough peers. + // + // TODO(roasbeef): craft s.t. we only get updates from a few + // peers + recvUpdates := !cfg.NoChanUpdates + + // Register the this peer's for gossip syncer with the gossiper. + // This is blocks synchronously to ensure the gossip syncer is + // registered with the gossiper before attempting to read + // messages from the remote peer. + p.server.authGossiper.InitSyncState(p, recvUpdates) + + // If the remote peer has the initial sync feature bit set, then we'll + // being the synchronization protocol to exchange authenticated channel + // graph edges/vertexes, but only if they don't know of the new gossip + // queries. + case p.remoteLocalFeatures.HasFeature(lnwire.InitialRoutingSync): + srvrLog.Infof("Requesting full table sync with %x", + p.pubKeyBytes[:]) + + go p.server.authGossiper.SynchronizeNode(p) + } +} + // QuitSignal is a method that should return a channel which will be sent upon // or closed once the backing peer exits. This allows callers using the // interface to cancel any processing in the event the backing implementation @@ -877,6 +914,14 @@ func (p *peer) readHandler() { p.Disconnect(err) }) + // Initialize our negotiated gossip sync method before reading + // messages off the wire. When using gossip queries, this ensures + // a gossip syncer is active by the time query messages arrive. + // + // TODO(conner): have peer store gossip syncer directly and bypass + // gossiper? + p.initGossipSync() + discStream := newDiscMsgStream(p) discStream.Start() defer discStream.Stop()