channeldb: don't return error from HasChannelEdge if single edge doesn't exist

This commit modifies the error propagating behavior within the
HasChannelEdge struct. Rather than exiting the function early when a
single edge isn’t found, we instead continue to also possibly retrieve
the second directional edge.

With this change, we avoid a potential infinite gossiping loop in the
routing package that would result if we’d seen one edge but not the
other. In this case the timestamps returned for *both* edges would
always be zero, causing the daemon to always accept and rebroadcast the
announcement putting all other connected lnd’s into the same loop.
This commit is contained in:
Olaoluwa Osuntokun 2016-12-30 16:35:23 -08:00
parent f7510cf1fc
commit 630afbdc93
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2

View File

@ -469,13 +469,17 @@ func (c *ChannelGraph) HasChannelEdge(chanID uint64) (time.Time, time.Time, bool
e1, e2, err := fetchEdges(edgeIndex, edges, nodes, e1, e2, err := fetchEdges(edgeIndex, edges, nodes,
channelID[:], c.db) channelID[:], c.db)
if err != nil { if err != nil {
// TODO(roasbeef): hack fix to return false until both return err
// edges are populated
return nil
} }
node1UpdateTime = e1.LastUpdate // As we may have only one of the edges populated, only set the
node2UpdateTime = e2.LastUpdate // update time if the edge was found in the database.
if e1 != nil {
node1UpdateTime = e1.LastUpdate
}
if e2 != nil {
node2UpdateTime = e2.LastUpdate
}
return nil return nil
}); err != nil { }); err != nil {
@ -1278,24 +1282,33 @@ func fetchEdges(edgeIndex *bolt.Bucket, edges *bolt.Bucket, nodes *bolt.Bucket,
} }
// The first node is contained within the first half of the // The first node is contained within the first half of the
// edge information. // edge information. We only propgate the error here and below if it's
// something other than edge non-existance.
node1Pub := edgeInfo[:33] node1Pub := edgeInfo[:33]
edge1, err := fetchChannelEdge(edges, chanID, node1Pub, nodes) edge1, err := fetchChannelEdge(edges, chanID, node1Pub, nodes)
if err != nil { if err != nil && err != ErrEdgeNotFound {
return nil, nil, err return nil, nil, err
} }
edge1.db = db
edge1.Node.db = db // As we may have a signle direction of the edge but not the other,
// only fill in the datbase pointers if the edge is found.
if edge1 != nil {
edge1.db = db
edge1.Node.db = db
}
// Similarly, the second node is contained within the latter // Similarly, the second node is contained within the latter
// half of the edge information. // half of the edge information.
node2Pub := edgeInfo[33:] node2Pub := edgeInfo[33:]
edge2, err := fetchChannelEdge(edges, chanID, node2Pub, nodes) edge2, err := fetchChannelEdge(edges, chanID, node2Pub, nodes)
if err != nil { if err != nil && err != ErrEdgeNotFound {
return nil, nil, err return nil, nil, err
} }
edge2.db = db
edge2.Node.db = db if edge2 != nil {
edge2.db = db
edge2.Node.db = db
}
return edge1, edge2, nil return edge1, edge2, nil
} }