channeldb+discovery: use timestamps to maybe revive zombie
This commit is contained in:
5 files changed
+212
-53
No files matched your search
+40
-8
@@ -2086,10 +2086,12 @@ func (c *ChannelGraph) NodeUpdatesInHorizon(startTime,
|
||||
// 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) {
|
||||
func (c *ChannelGraph) FilterKnownChanIDs(chansInfo []ChannelUpdateInfo,
|
||||
isZombieChan func(time.Time, time.Time) bool) ([]uint64, error) {
|
||||
|
||||
var newChanIDs []uint64
|
||||
|
||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||
err := kvdb.Update(c.db, func(tx kvdb.RwTx) error {
|
||||
edges := tx.ReadBucket(edgeBucket)
|
||||
if edges == nil {
|
||||
return ErrGraphNoEdgesFound
|
||||
@@ -2107,8 +2109,9 @@ func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) {
|
||||
// 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)
|
||||
for _, info := range chansInfo {
|
||||
scid := info.ShortChannelID.ToUint64()
|
||||
byteOrder.PutUint64(cidBytes[:], scid)
|
||||
|
||||
// If the edge is already known, skip it.
|
||||
if v := edgeIndex.Get(cidBytes[:]); v != nil {
|
||||
@@ -2117,13 +2120,37 @@ func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) {
|
||||
|
||||
// If the edge is a known zombie, skip it.
|
||||
if zombieIndex != nil {
|
||||
isZombie, _, _ := isZombieEdge(zombieIndex, cid)
|
||||
if isZombie {
|
||||
isZombie, _, _ := isZombieEdge(
|
||||
zombieIndex, scid,
|
||||
)
|
||||
|
||||
isStillZombie := isZombieChan(
|
||||
info.Node1UpdateTimestamp,
|
||||
info.Node2UpdateTimestamp,
|
||||
)
|
||||
|
||||
switch {
|
||||
// If the edge is a known zombie and if we
|
||||
// would still consider it a zombie given the
|
||||
// latest update timestamps, then we skip this
|
||||
// channel.
|
||||
case isZombie && isStillZombie:
|
||||
continue
|
||||
|
||||
// Otherwise, if we have marked it as a zombie
|
||||
// but the latest update timestamps could bring
|
||||
// it back from the dead, then we mark it alive,
|
||||
// and we let it be added to the set of IDs to
|
||||
// query our peer for.
|
||||
case isZombie && !isStillZombie:
|
||||
err := c.markEdgeLive(tx, scid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newChanIDs = append(newChanIDs, cid)
|
||||
newChanIDs = append(newChanIDs, scid)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -2134,7 +2161,12 @@ func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) {
|
||||
// If we don't know of any edges yet, then we'll return the entire set
|
||||
// of chan IDs specified.
|
||||
case err == ErrGraphNoEdgesFound:
|
||||
return chanIDs, nil
|
||||
ogChanIDs := make([]uint64, len(chansInfo))
|
||||
for i, info := range chansInfo {
|
||||
ogChanIDs[i] = info.ShortChannelID.ToUint64()
|
||||
}
|
||||
|
||||
return ogChanIDs, nil
|
||||
|
||||
case err != nil:
|
||||
return nil, err
|
||||
|
||||
+85
-21
@@ -1928,14 +1928,32 @@ func TestFilterKnownChanIDs(t *testing.T) {
|
||||
graph, err := MakeTestGraph(t)
|
||||
require.NoError(t, err, "unable to make test database")
|
||||
|
||||
isZombieUpdate := func(updateTime1 time.Time,
|
||||
updateTime2 time.Time) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
var (
|
||||
scid1 = lnwire.ShortChannelID{BlockHeight: 1}
|
||||
scid2 = lnwire.ShortChannelID{BlockHeight: 2}
|
||||
scid3 = lnwire.ShortChannelID{BlockHeight: 3}
|
||||
)
|
||||
|
||||
// If we try to filter out a set of channel ID's before we even know of
|
||||
// any channels, then we should get the entire set back.
|
||||
preChanIDs := []uint64{1, 2, 3, 4}
|
||||
filteredIDs, err := graph.FilterKnownChanIDs(preChanIDs)
|
||||
require.NoError(t, err, "unable to filter chan IDs")
|
||||
if !reflect.DeepEqual(preChanIDs, filteredIDs) {
|
||||
t.Fatalf("chan IDs shouldn't have been filtered!")
|
||||
preChanIDs := []ChannelUpdateInfo{
|
||||
{ShortChannelID: scid1},
|
||||
{ShortChannelID: scid2},
|
||||
{ShortChannelID: scid3},
|
||||
}
|
||||
filteredIDs, err := graph.FilterKnownChanIDs(preChanIDs, isZombieUpdate)
|
||||
require.NoError(t, err, "unable to filter chan IDs")
|
||||
require.EqualValues(t, []uint64{
|
||||
scid1.ToUint64(),
|
||||
scid2.ToUint64(),
|
||||
scid3.ToUint64(),
|
||||
}, filteredIDs)
|
||||
|
||||
// We'll start by creating two nodes which will seed our test graph.
|
||||
node1, err := createTestVertex(graph.db)
|
||||
@@ -1952,7 +1970,7 @@ func TestFilterKnownChanIDs(t *testing.T) {
|
||||
// Next, we'll add 5 channel ID's to the graph, each of them having a
|
||||
// block height 10 blocks after the previous.
|
||||
const numChans = 5
|
||||
chanIDs := make([]uint64, 0, numChans)
|
||||
chanIDs := make([]ChannelUpdateInfo, 0, numChans)
|
||||
for i := 0; i < numChans; i++ {
|
||||
channel, chanID := createEdge(
|
||||
uint32(i*10), 0, 0, 0, node1, node2,
|
||||
@@ -1962,11 +1980,13 @@ func TestFilterKnownChanIDs(t *testing.T) {
|
||||
t.Fatalf("unable to create channel edge: %v", err)
|
||||
}
|
||||
|
||||
chanIDs = append(chanIDs, chanID.ToUint64())
|
||||
chanIDs = append(chanIDs, ChannelUpdateInfo{
|
||||
ShortChannelID: chanID,
|
||||
})
|
||||
}
|
||||
|
||||
const numZombies = 5
|
||||
zombieIDs := make([]uint64, 0, numZombies)
|
||||
zombieIDs := make([]ChannelUpdateInfo, 0, numZombies)
|
||||
for i := 0; i < numZombies; i++ {
|
||||
channel, chanID := createEdge(
|
||||
uint32(i*10+1), 0, 0, 0, node1, node2,
|
||||
@@ -1979,13 +1999,15 @@ func TestFilterKnownChanIDs(t *testing.T) {
|
||||
t.Fatalf("unable to mark edge zombie: %v", err)
|
||||
}
|
||||
|
||||
zombieIDs = append(zombieIDs, chanID.ToUint64())
|
||||
zombieIDs = append(
|
||||
zombieIDs, ChannelUpdateInfo{ShortChannelID: chanID},
|
||||
)
|
||||
}
|
||||
|
||||
queryCases := []struct {
|
||||
queryIDs []uint64
|
||||
queryIDs []ChannelUpdateInfo
|
||||
|
||||
resp []uint64
|
||||
resp []ChannelUpdateInfo
|
||||
}{
|
||||
// If we attempt to filter out all chanIDs we know of, the
|
||||
// response should be the empty set.
|
||||
@@ -2001,28 +2023,70 @@ func TestFilterKnownChanIDs(t *testing.T) {
|
||||
// If we query for a set of ID's that we didn't insert, we
|
||||
// should get the same set back.
|
||||
{
|
||||
queryIDs: []uint64{99, 100},
|
||||
resp: []uint64{99, 100},
|
||||
queryIDs: []ChannelUpdateInfo{
|
||||
{ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 99,
|
||||
}},
|
||||
{ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 100,
|
||||
}},
|
||||
},
|
||||
resp: []ChannelUpdateInfo{
|
||||
{ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 99,
|
||||
}},
|
||||
{ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 100,
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
// If we query for a super-set of our the chan ID's inserted,
|
||||
// we should only get those new chanIDs back.
|
||||
{
|
||||
queryIDs: append(chanIDs, []uint64{99, 101}...),
|
||||
resp: []uint64{99, 101},
|
||||
queryIDs: append(chanIDs, []ChannelUpdateInfo{
|
||||
{
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 99,
|
||||
},
|
||||
},
|
||||
{
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 101,
|
||||
},
|
||||
},
|
||||
}...),
|
||||
resp: []ChannelUpdateInfo{
|
||||
{
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 99,
|
||||
},
|
||||
},
|
||||
{
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 101,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, queryCase := range queryCases {
|
||||
resp, err := graph.FilterKnownChanIDs(queryCase.queryIDs)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to filter chan IDs: %v", err)
|
||||
resp, err := graph.FilterKnownChanIDs(
|
||||
queryCase.queryIDs, isZombieUpdate,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSCIDs := make([]uint64, len(queryCase.resp))
|
||||
for i, info := range queryCase.resp {
|
||||
expectedSCIDs[i] = info.ShortChannelID.ToUint64()
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(resp, queryCase.resp) {
|
||||
t.Fatalf("expected %v, got %v", spew.Sdump(queryCase.resp),
|
||||
spew.Sdump(resp))
|
||||
if len(expectedSCIDs) == 0 {
|
||||
expectedSCIDs = nil
|
||||
}
|
||||
|
||||
require.EqualValues(t, expectedSCIDs, resp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user