discovery: send channel announcements before node announcements.

According to BOLT#7, nodes will ignore node announcements
for nodes not found in any previous channel announcements.
This commit makes the discovery service send its known
channels before its known nodes when syncing the channel
graph with a peer.
This commit is contained in:
Johan T. Halseth 2017-07-14 21:41:46 +02:00 committed by Olaoluwa Osuntokun
parent ebbe6d7a10
commit 889a4eb48b

@ -439,8 +439,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []l
switch msg := nMsg.msg.(type) { switch msg := nMsg.msg.(type) {
// A new node announcement has arrived which either presents a new // A new node announcement has arrived which either presents new information
// node, or a node updating previously advertised information. // about a node in one of the channels we know about, or a updating
// previously advertised information.
case *lnwire.NodeAnnouncement: case *lnwire.NodeAnnouncement:
if nMsg.isRemote { if nMsg.isRemote {
if err := d.validateNodeAnn(msg); err != nil { if err := d.validateNodeAnn(msg); err != nil {
@ -453,6 +454,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []l
} }
node := &channeldb.LightningNode{ node := &channeldb.LightningNode{
HaveNodeAnnouncement: true,
LastUpdate: time.Unix(int64(msg.Timestamp), 0), LastUpdate: time.Unix(int64(msg.Timestamp), 0),
Addresses: msg.Addresses, Addresses: msg.Addresses,
PubKey: msg.NodeID, PubKey: msg.NodeID,
@ -537,6 +539,11 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []l
BitcoinKey2: msg.BitcoinKey2, BitcoinKey2: msg.BitcoinKey2,
AuthProof: proof, AuthProof: proof,
} }
// We will add the edge to the channel router. If the nodes
// present in this channel are not present in the database, a
// partial node will be added to represent each node while we
// wait for a node announcement.
if err := d.cfg.Router.AddEdge(edge); err != nil { if err := d.cfg.Router.AddEdge(edge); err != nil {
if routing.IsError(err, routing.ErrOutdated, if routing.IsError(err, routing.ErrOutdated,
routing.ErrIgnored) { routing.ErrIgnored) {
@ -896,30 +903,10 @@ func (d *AuthenticatedGossiper) synchronizeWithNode(syncReq *syncRequest) error
// containing all the messages to be sent to the target peer. // containing all the messages to be sent to the target peer.
var announceMessages []lnwire.Message var announceMessages []lnwire.Message
// First run through all the vertexes in the graph, retrieving the data // As peers are expecting channel announcements before node
// for the announcement we originally retrieved. // announcements, we first retrieve the initial announcement, as well as
var numNodes uint32 // the latest channel update announcement for both of the directed edges
if err := d.cfg.Router.ForEachNode(func(node *channeldb.LightningNode) error { // that make up each channel, and queue these to be sent to the peer.
ann := &lnwire.NodeAnnouncement{
Signature: node.AuthSig,
Timestamp: uint32(node.LastUpdate.Unix()),
Addresses: node.Addresses,
NodeID: node.PubKey,
Alias: lnwire.NewAlias(node.Alias),
Features: node.Features,
}
announceMessages = append(announceMessages, ann)
numNodes++
return nil
}); err != nil {
return err
}
// With the vertexes gathered, we'll no retrieve the initial
// announcement, as well as the latest channel update announcement for
// both of the directed infos that make up the channel.
var numEdges uint32 var numEdges uint32
if err := d.cfg.Router.ForEachChannel(func(chanInfo *channeldb.ChannelEdgeInfo, if err := d.cfg.Router.ForEachChannel(func(chanInfo *channeldb.ChannelEdgeInfo,
e1, e2 *channeldb.ChannelEdgePolicy) error { e1, e2 *channeldb.ChannelEdgePolicy) error {
@ -947,6 +934,32 @@ func (d *AuthenticatedGossiper) synchronizeWithNode(syncReq *syncRequest) error
return err return err
} }
// Run through all the vertexes in the graph, retrieving the data for
// the node announcements we originally retrieved.
var numNodes uint32
if err := d.cfg.Router.ForEachNode(func(node *channeldb.LightningNode) error {
// If this is a node we never received a node announcement for,
// we skip it.
if !node.HaveNodeAnnouncement {
return nil
}
ann := &lnwire.NodeAnnouncement{
Signature: node.AuthSig,
Timestamp: uint32(node.LastUpdate.Unix()),
Addresses: node.Addresses,
NodeID: node.PubKey,
Alias: lnwire.NewAlias(node.Alias),
Features: node.Features,
}
announceMessages = append(announceMessages, ann)
numNodes++
return nil
}); err != nil {
return err
}
log.Infof("Syncing channel graph state with %x, sending %v "+ log.Infof("Syncing channel graph state with %x, sending %v "+
"vertexes and %v edges", targetNode.SerializeCompressed(), "vertexes and %v edges", targetNode.SerializeCompressed(),
numNodes, numEdges) numNodes, numEdges)