Merge pull request #2921 from cfromknecht/skip-unknown-edges

channeldb/graph: skip unknown edges in FetchChanInfos
This commit is contained in:
Olaoluwa Osuntokun 2019-04-10 17:18:13 -07:00 committed by GitHub
commit 58aa32035c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 46 deletions

@ -1636,9 +1636,11 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, endHeight uint32) ([]uint
return chanIDs, nil return chanIDs, nil
} }
// FetchChanInfos returns the set of channel edges that correspond to the // FetchChanInfos returns the set of channel edges that correspond to the passed
// passed channel ID's. This can be used to respond to peer queries that are // channel ID's. If an edge is the query is unknown to the database, it will
// seeking to fill in gaps in their view of the channel graph. // skipped and the result will contain only those edges that exist at the time
// of the query. This can be used to respond to peer queries that are seeking to
// fill in gaps in their view of the channel graph.
func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) { func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
// TODO(roasbeef): sort cids? // TODO(roasbeef): sort cids?
@ -1664,11 +1666,16 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
for _, cid := range chanIDs { for _, cid := range chanIDs {
byteOrder.PutUint64(cidBytes[:], cid) byteOrder.PutUint64(cidBytes[:], cid)
// First, we'll fetch the static edge information. // First, we'll fetch the static edge information. If
// the edge is unknown, we will skip the edge and
// continue gathering all known edges.
edgeInfo, err := fetchChanEdgeInfo( edgeInfo, err := fetchChanEdgeInfo(
edgeIndex, cidBytes[:], edgeIndex, cidBytes[:],
) )
if err != nil { switch {
case err == ErrEdgeNotFound:
continue
case err != nil:
return err return err
} }
edgeInfo.db = c.db edgeInfo.db = c.db
@ -3058,36 +3065,6 @@ func (c *ChannelGraph) NewChannelEdgePolicy() *ChannelEdgePolicy {
return &ChannelEdgePolicy{db: c.db} return &ChannelEdgePolicy{db: c.db}
} }
// MarkEdgeZombie marks an edge as a zombie within the graph's zombie index.
// The public keys should represent the node public keys of the two parties
// involved in the edge.
func (c *ChannelGraph) MarkEdgeZombie(chanID uint64, pubKey1,
pubKey2 [33]byte) error {
c.cacheMu.Lock()
defer c.cacheMu.Unlock()
err := c.db.Update(func(tx *bbolt.Tx) error {
edges := tx.Bucket(edgeBucket)
if edges == nil {
return ErrGraphNoEdgesFound
}
zombieIndex, err := edges.CreateBucketIfNotExists(zombieBucket)
if err != nil {
return err
}
return markEdgeZombie(zombieIndex, chanID, pubKey1, pubKey2)
})
if err != nil {
return err
}
c.rejectCache.remove(chanID)
c.chanCache.remove(chanID)
return nil
}
// markEdgeZombie marks an edge as a zombie within our zombie index. The public // markEdgeZombie marks an edge as a zombie within our zombie index. The public
// keys should represent the node public keys of the two parties involved in the // keys should represent the node public keys of the two parties involved in the
// edge. // edge.

@ -1750,9 +1750,8 @@ func TestFilterKnownChanIDs(t *testing.T) {
if err := graph.AddChannelEdge(&channel); err != nil { if err := graph.AddChannelEdge(&channel); err != nil {
t.Fatalf("unable to create channel edge: %v", err) t.Fatalf("unable to create channel edge: %v", err)
} }
if err := graph.MarkEdgeZombie( err := graph.DeleteChannelEdge(&channel.ChannelPoint)
chanID.ToUint64(), node1.PubKeyBytes, node2.PubKeyBytes, if err != nil {
); err != nil {
t.Fatalf("unable to mark edge zombie: %v", err) t.Fatalf("unable to mark edge zombie: %v", err)
} }
@ -2006,6 +2005,24 @@ func TestFetchChanInfos(t *testing.T) {
edgeQuery = append(edgeQuery, chanID.ToUint64()) edgeQuery = append(edgeQuery, chanID.ToUint64())
} }
// Add an additional edge that does not exist. The query should skip
// this channel and return only infos for the edges that exist.
edgeQuery = append(edgeQuery, 500)
// Add an another edge to the query that has been marked as a zombie
// edge. The query should also skip this channel.
zombieChan, zombieChanID := createEdge(
666, 0, 0, 0, node1, node2,
)
if err := graph.AddChannelEdge(&zombieChan); err != nil {
t.Fatalf("unable to create channel edge: %v", err)
}
err = graph.DeleteChannelEdge(&zombieChan.ChannelPoint)
if err != nil {
t.Fatalf("unable to delete and mark edge zombie: %v", err)
}
edgeQuery = append(edgeQuery, zombieChanID.ToUint64())
// We'll now attempt to query for the range of channel ID's we just // We'll now attempt to query for the range of channel ID's we just
// inserted into the database. We should get the exact same set of // inserted into the database. We should get the exact same set of
// edges back. // edges back.
@ -2846,20 +2863,28 @@ func TestGraphZombieIndex(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to create test vertex: %v", err) t.Fatalf("unable to create test vertex: %v", err)
} }
edge, _, _ := createChannelEdge(db, node1, node2)
// If the graph is not aware of the edge, then it should not be a // Swap the nodes if the second's pubkey is smaller than the first.
// zombie. // Without this, the comparisons at the end will fail probabilistically.
if bytes.Compare(node2.PubKeyBytes[:], node1.PubKeyBytes[:]) < 0 {
node1, node2 = node2, node1
}
edge, _, _ := createChannelEdge(db, node1, node2)
if err := graph.AddChannelEdge(edge); err != nil {
t.Fatalf("unable to create channel edge: %v", err)
}
// Since the edge is known the graph and it isn't a zombie, IsZombieEdge
// should not report the channel as a zombie.
isZombie, _, _ := graph.IsZombieEdge(edge.ChannelID) isZombie, _, _ := graph.IsZombieEdge(edge.ChannelID)
if isZombie { if isZombie {
t.Fatal("expected edge to not be marked as zombie") t.Fatal("expected edge to not be marked as zombie")
} }
// If we mark the edge as a zombie, then we should expect to see it // If we delete the edge and mark it as a zombie, then we should expect
// within the index. // to see it within the index.
err = graph.MarkEdgeZombie( err = graph.DeleteChannelEdge(&edge.ChannelPoint)
edge.ChannelID, node1.PubKeyBytes, node2.PubKeyBytes,
)
if err != nil { if err != nil {
t.Fatalf("unable to mark edge as zombie: %v", err) t.Fatalf("unable to mark edge as zombie: %v", err)
} }