Merge pull request #4804 from wpaulino/proper-gossip-query-reply-chunk-splitting
discovery: adhere to proper channel chunk splitting for ReplyChannelRange
This commit is contained in:
9 files changed
+396
-245
No files matched your search
+47
-14
@@ -10,6 +10,7 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -1704,12 +1705,25 @@ func (c *ChannelGraph) FilterKnownChanIDs(chanIDs []uint64) ([]uint64, error) {
|
||||
return newChanIDs, nil
|
||||
}
|
||||
|
||||
// BlockChannelRange represents a range of channels for a given block height.
|
||||
type BlockChannelRange struct {
|
||||
// Height is the height of the block all of the channels below were
|
||||
// included in.
|
||||
Height uint32
|
||||
|
||||
// Channels is the list of channels identified by their short ID
|
||||
// representation known to us that were included in the block height
|
||||
// above.
|
||||
Channels []lnwire.ShortChannelID
|
||||
}
|
||||
|
||||
// FilterChannelRange returns the channel ID's of all known channels which were
|
||||
// mined in a block height within the passed range. This method can be used to
|
||||
// quickly share with a peer the set of channels we know of within a particular
|
||||
// range to catch them up after a period of time offline.
|
||||
func (c *ChannelGraph) FilterChannelRange(startHeight, endHeight uint32) ([]uint64, error) {
|
||||
var chanIDs []uint64
|
||||
// mined in a block height within the passed range. The channel IDs are grouped
|
||||
// by their common block height. This method can be used to quickly share with a
|
||||
// peer the set of channels we know of within a particular range to catch them
|
||||
// up after a period of time offline.
|
||||
func (c *ChannelGraph) FilterChannelRange(startHeight,
|
||||
endHeight uint32) ([]BlockChannelRange, error) {
|
||||
|
||||
startChanID := &lnwire.ShortChannelID{
|
||||
BlockHeight: startHeight,
|
||||
@@ -1728,6 +1742,7 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, endHeight uint32) ([]uint
|
||||
byteOrder.PutUint64(chanIDStart[:], startChanID.ToUint64())
|
||||
byteOrder.PutUint64(chanIDEnd[:], endChanID.ToUint64())
|
||||
|
||||
var channelsPerBlock map[uint32][]lnwire.ShortChannelID
|
||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||
edges := tx.ReadBucket(edgeBucket)
|
||||
if edges == nil {
|
||||
@@ -1742,33 +1757,51 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, endHeight uint32) ([]uint
|
||||
|
||||
// We'll now iterate through the database, and find each
|
||||
// channel ID that resides within the specified range.
|
||||
var cid uint64
|
||||
for k, _ := cursor.Seek(chanIDStart[:]); k != nil &&
|
||||
bytes.Compare(k, chanIDEnd[:]) <= 0; k, _ = cursor.Next() {
|
||||
|
||||
// This channel ID rests within the target range, so
|
||||
// we'll convert it into an integer and add it to our
|
||||
// returned set.
|
||||
cid = byteOrder.Uint64(k)
|
||||
chanIDs = append(chanIDs, cid)
|
||||
// we'll add it to our returned set.
|
||||
rawCid := byteOrder.Uint64(k)
|
||||
cid := lnwire.NewShortChanIDFromInt(rawCid)
|
||||
channelsPerBlock[cid.BlockHeight] = append(
|
||||
channelsPerBlock[cid.BlockHeight], cid,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func() {
|
||||
chanIDs = nil
|
||||
channelsPerBlock = make(map[uint32][]lnwire.ShortChannelID)
|
||||
})
|
||||
|
||||
switch {
|
||||
// If we don't know of any channels yet, then there's nothing to
|
||||
// filter, so we'll return an empty slice.
|
||||
case err == ErrGraphNoEdgesFound:
|
||||
return chanIDs, nil
|
||||
case err == ErrGraphNoEdgesFound || len(channelsPerBlock) == 0:
|
||||
return nil, nil
|
||||
|
||||
case err != nil:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return chanIDs, nil
|
||||
// Return the channel ranges in ascending block height order.
|
||||
blocks := make([]uint32, 0, len(channelsPerBlock))
|
||||
for block := range channelsPerBlock {
|
||||
blocks = append(blocks, block)
|
||||
}
|
||||
sort.Slice(blocks, func(i, j int) bool {
|
||||
return blocks[i] < blocks[j]
|
||||
})
|
||||
|
||||
channelRanges := make([]BlockChannelRange, 0, len(channelsPerBlock))
|
||||
for _, block := range blocks {
|
||||
channelRanges = append(channelRanges, BlockChannelRange{
|
||||
Height: block,
|
||||
Channels: channelsPerBlock[block],
|
||||
})
|
||||
}
|
||||
|
||||
return channelRanges, nil
|
||||
}
|
||||
|
||||
// FetchChanInfos returns the set of channel edges that correspond to the passed
|
||||
|
||||
+27
-12
@@ -1848,24 +1848,32 @@ func TestFilterChannelRange(t *testing.T) {
|
||||
t.Fatalf("expected zero chans, instead got %v", len(resp))
|
||||
}
|
||||
|
||||
// To start, we'll create a set of channels, each mined in a block 10
|
||||
// To start, we'll create a set of channels, two mined in a block 10
|
||||
// blocks after the prior one.
|
||||
startHeight := uint32(100)
|
||||
endHeight := startHeight
|
||||
const numChans = 10
|
||||
chanIDs := make([]uint64, 0, numChans)
|
||||
for i := 0; i < numChans; i++ {
|
||||
channelRanges := make([]BlockChannelRange, 0, numChans/2)
|
||||
for i := 0; i < numChans/2; i++ {
|
||||
chanHeight := endHeight
|
||||
channel, chanID := createEdge(
|
||||
uint32(chanHeight), uint32(i+1), 0, 0, node1, node2,
|
||||
channel1, chanID1 := createEdge(
|
||||
chanHeight, uint32(i+1), 0, 0, node1, node2,
|
||||
)
|
||||
|
||||
if err := graph.AddChannelEdge(&channel); err != nil {
|
||||
if err := graph.AddChannelEdge(&channel1); err != nil {
|
||||
t.Fatalf("unable to create channel edge: %v", err)
|
||||
}
|
||||
|
||||
chanIDs = append(chanIDs, chanID.ToUint64())
|
||||
channel2, chanID2 := createEdge(
|
||||
chanHeight, uint32(i+2), 0, 0, node1, node2,
|
||||
)
|
||||
if err := graph.AddChannelEdge(&channel2); err != nil {
|
||||
t.Fatalf("unable to create channel edge: %v", err)
|
||||
}
|
||||
|
||||
channelRanges = append(channelRanges, BlockChannelRange{
|
||||
Height: chanHeight,
|
||||
Channels: []lnwire.ShortChannelID{chanID1, chanID2},
|
||||
})
|
||||
endHeight += 10
|
||||
}
|
||||
|
||||
@@ -1876,7 +1884,7 @@ func TestFilterChannelRange(t *testing.T) {
|
||||
startHeight uint32
|
||||
endHeight uint32
|
||||
|
||||
resp []uint64
|
||||
resp []BlockChannelRange
|
||||
}{
|
||||
// If we query for the entire range, then we should get the same
|
||||
// set of short channel IDs back.
|
||||
@@ -1884,7 +1892,7 @@ func TestFilterChannelRange(t *testing.T) {
|
||||
startHeight: startHeight,
|
||||
endHeight: endHeight,
|
||||
|
||||
resp: chanIDs,
|
||||
resp: channelRanges,
|
||||
},
|
||||
|
||||
// If we query for a range of channels right before our range, we
|
||||
@@ -1900,7 +1908,7 @@ func TestFilterChannelRange(t *testing.T) {
|
||||
startHeight: endHeight - 10,
|
||||
endHeight: endHeight - 10,
|
||||
|
||||
resp: chanIDs[9:],
|
||||
resp: channelRanges[4:],
|
||||
},
|
||||
|
||||
// If we query for just the first height, we should only get a
|
||||
@@ -1909,7 +1917,14 @@ func TestFilterChannelRange(t *testing.T) {
|
||||
startHeight: startHeight,
|
||||
endHeight: startHeight,
|
||||
|
||||
resp: chanIDs[:1],
|
||||
resp: channelRanges[:1],
|
||||
},
|
||||
|
||||
{
|
||||
startHeight: startHeight + 10,
|
||||
endHeight: endHeight - 10,
|
||||
|
||||
resp: channelRanges[1:5],
|
||||
},
|
||||
}
|
||||
for i, queryCase := range queryCases {
|
||||
|
||||
Reference in new issue
Block a user