diff --git a/channeldb/graph.go b/channeldb/graph.go index 25c59f5f714..68d5b87c98e 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -1513,10 +1513,10 @@ func (c *ChannelGraph) NodeUpdatesInHorizon(startTime, endTime time.Time) ([]Lig } // FilterKnownChanIDs takes a set of channel IDs and return the subset of chan -// ID's that we don't know of in the passed set. In other words, we perform a -// set difference of our set of chan ID's and the ones passed in. This method -// can be used by callers to determine the set of channels ta peer knows of -// that we don't. +// ID's that we don't know and are not known zombies of the passed set. In other +// words, we perform a set difference of our set of chan ID's and the ones +// passed in. This method can be used by callers to determine the set of +// channels another peer knows of that we don't. func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) { var newChanIDs []uint64 @@ -1530,15 +1530,31 @@ func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) { return ErrGraphNoEdgesFound } + // Fetch the zombie index, it may not exist if no edges have + // ever been marked as zombies. If the index has been + // initialized, we will use it later to skip known zombie edges. + zombieIndex := edges.Bucket(zombieBucket) + // We'll run through the set of chanIDs and collate only the // set of channel that are unable to be found within our db. var cidBytes [8]byte for _, cid := range chanIDs { byteOrder.PutUint64(cidBytes[:], cid) - if v := edgeIndex.Get(cidBytes[:]); v == nil { - newChanIDs = append(newChanIDs, cid) + // If the edge is already known, skip it. + if v := edgeIndex.Get(cidBytes[:]); v != nil { + continue } + + // If the edge is a known zombie, skip it. + if zombieIndex != nil { + isZombie, _, _ := isZombieEdge(zombieIndex, cid) + if isZombie { + continue + } + } + + newChanIDs = append(newChanIDs, cid) } return nil diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index f8df644876c..c2ae2ab2ccd 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -1741,6 +1741,24 @@ func TestFilterKnownChanIDs(t *testing.T) { chanIDs = append(chanIDs, chanID.ToUint64()) } + const numZombies = 5 + zombieIDs := make([]uint64, 0, numZombies) + for i := 0; i < numZombies; i++ { + channel, chanID := createEdge( + uint32(i*10+1), 0, 0, 0, node1, node2, + ) + if err := graph.AddChannelEdge(&channel); err != nil { + t.Fatalf("unable to create channel edge: %v", err) + } + if err := graph.MarkEdgeZombie( + chanID.ToUint64(), node1.PubKeyBytes, node2.PubKeyBytes, + ); err != nil { + t.Fatalf("unable to mark edge zombie: %v", err) + } + + zombieIDs = append(zombieIDs, chanID.ToUint64()) + } + queryCases := []struct { queryIDs []uint64 @@ -1751,6 +1769,11 @@ func TestFilterKnownChanIDs(t *testing.T) { { queryIDs: chanIDs, }, + // If we attempt to filter out all zombies that we know of, the + // response should be the empty set. + { + queryIDs: zombieIDs, + }, // If we query for a set of ID's that we didn't insert, we // should get the same set back.