Merge pull request #3785 from Roasbeef/gossip-queries-fix
discovery: properly set FirstBlockHeight and NumBlocks in responses
This commit is contained in:
commit
a7c2b12f5c
@ -824,6 +824,14 @@ func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
|||||||
// TODO(roasbeef): means can't send max uint above?
|
// TODO(roasbeef): means can't send max uint above?
|
||||||
// * or make internal 64
|
// * or make internal 64
|
||||||
|
|
||||||
|
// In the base case (no actual response) the first block and the last
|
||||||
|
// block in the query will be the same. In the loop below, we'll update
|
||||||
|
// these two variables incrementally with each chunk to properly
|
||||||
|
// compute the starting block for each response and the number of
|
||||||
|
// blocks in a response.
|
||||||
|
firstBlockHeight := query.FirstBlockHeight
|
||||||
|
lastBlockHeight := query.FirstBlockHeight
|
||||||
|
|
||||||
numChannels := int32(len(channelRange))
|
numChannels := int32(len(channelRange))
|
||||||
numChansSent := int32(0)
|
numChansSent := int32(0)
|
||||||
for {
|
for {
|
||||||
@ -854,13 +862,31 @@ func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
|||||||
"size=%v", g.cfg.peerPub[:], len(channelChunk))
|
"size=%v", g.cfg.peerPub[:], len(channelChunk))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have any channels at all to return, then we need to
|
||||||
|
// update our pointers to the first and last blocks for each
|
||||||
|
// response.
|
||||||
|
if len(channelChunk) > 0 {
|
||||||
|
firstBlockHeight = channelChunk[0].BlockHeight
|
||||||
|
lastBlockHeight = channelChunk[len(channelChunk)-1].BlockHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
// The number of blocks contained in this response (the total
|
||||||
|
// span) is the difference between the last channel ID and the
|
||||||
|
// first in the range. We add one as even if all channels
|
||||||
|
// returned are in the same block, we need to count that.
|
||||||
|
numBlocksInResp := lastBlockHeight - firstBlockHeight + 1
|
||||||
|
|
||||||
// With our chunk assembled, we'll now send to the remote peer
|
// With our chunk assembled, we'll now send to the remote peer
|
||||||
// the current chunk.
|
// the current chunk.
|
||||||
replyChunk := lnwire.ReplyChannelRange{
|
replyChunk := lnwire.ReplyChannelRange{
|
||||||
QueryChannelRange: *query,
|
QueryChannelRange: lnwire.QueryChannelRange{
|
||||||
Complete: 0,
|
ChainHash: query.ChainHash,
|
||||||
EncodingType: g.cfg.encodingType,
|
NumBlocks: numBlocksInResp,
|
||||||
ShortChanIDs: channelChunk,
|
FirstBlockHeight: firstBlockHeight,
|
||||||
|
},
|
||||||
|
Complete: 0,
|
||||||
|
EncodingType: g.cfg.encodingType,
|
||||||
|
ShortChanIDs: channelChunk,
|
||||||
}
|
}
|
||||||
if isFinalChunk {
|
if isFinalChunk {
|
||||||
replyChunk.Complete = 1
|
replyChunk.Complete = 1
|
||||||
|
@ -709,20 +709,31 @@ func TestGossipSyncerReplyChanRangeQuery(t *testing.T) {
|
|||||||
|
|
||||||
// Next, we'll craft a query to ask for all the new chan ID's after
|
// Next, we'll craft a query to ask for all the new chan ID's after
|
||||||
// block 100.
|
// block 100.
|
||||||
|
const startingBlockHeight int = 100
|
||||||
query := &lnwire.QueryChannelRange{
|
query := &lnwire.QueryChannelRange{
|
||||||
FirstBlockHeight: 100,
|
FirstBlockHeight: uint32(startingBlockHeight),
|
||||||
NumBlocks: 50,
|
NumBlocks: 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll then launch a goroutine to reply to the query with a set of 5
|
// We'll then launch a goroutine to reply to the query with a set of 5
|
||||||
// responses. This will ensure we get two full chunks, and one partial
|
// responses. This will ensure we get two full chunks, and one partial
|
||||||
// chunk.
|
// chunk.
|
||||||
resp := []lnwire.ShortChannelID{
|
queryResp := []lnwire.ShortChannelID{
|
||||||
lnwire.NewShortChanIDFromInt(1),
|
{
|
||||||
lnwire.NewShortChanIDFromInt(2),
|
BlockHeight: uint32(startingBlockHeight),
|
||||||
lnwire.NewShortChanIDFromInt(3),
|
},
|
||||||
lnwire.NewShortChanIDFromInt(4),
|
{
|
||||||
lnwire.NewShortChanIDFromInt(5),
|
BlockHeight: 102,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlockHeight: 104,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlockHeight: 106,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BlockHeight: 108,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
@ -740,7 +751,7 @@ func TestGossipSyncerReplyChanRangeQuery(t *testing.T) {
|
|||||||
|
|
||||||
// If the proper request was sent, then we'll respond
|
// If the proper request was sent, then we'll respond
|
||||||
// with our set of short channel ID's.
|
// with our set of short channel ID's.
|
||||||
chanSeries.filterRangeResp <- resp
|
chanSeries.filterRangeResp <- queryResp
|
||||||
errCh <- nil
|
errCh <- nil
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -767,16 +778,52 @@ func TestGossipSyncerReplyChanRangeQuery(t *testing.T) {
|
|||||||
t.Fatalf("expected ReplyChannelRange instead got %T", msg)
|
t.Fatalf("expected ReplyChannelRange instead got %T", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only for the first iteration do we set the offset to
|
||||||
|
// zero as no chunks have been processed yet. For every
|
||||||
|
// other iteration, we want to move forward by the
|
||||||
|
// chunkSize (from the staring block height).
|
||||||
|
offset := 0
|
||||||
|
if i != 0 {
|
||||||
|
offset = 1
|
||||||
|
}
|
||||||
|
expectedFirstBlockHeight := (i+offset)*2 + startingBlockHeight
|
||||||
|
|
||||||
|
switch {
|
||||||
// If this is not the last chunk, then Complete should
|
// If this is not the last chunk, then Complete should
|
||||||
// be set to zero. Otherwise, it should be one.
|
// be set to zero. Otherwise, it should be one.
|
||||||
switch {
|
|
||||||
case i < 2 && rangeResp.Complete != 0:
|
case i < 2 && rangeResp.Complete != 0:
|
||||||
t.Fatalf("non-final chunk should have "+
|
t.Fatalf("non-final chunk should have "+
|
||||||
"Complete=0: %v", spew.Sdump(rangeResp))
|
"Complete=0: %v", spew.Sdump(rangeResp))
|
||||||
|
|
||||||
|
case i < 2 && rangeResp.NumBlocks != chunkSize+1:
|
||||||
|
t.Fatalf("NumBlocks fields in resp "+
|
||||||
|
"incorrect: expected %v got %v",
|
||||||
|
chunkSize+1, rangeResp.NumBlocks)
|
||||||
|
|
||||||
|
case i < 2 && rangeResp.FirstBlockHeight !=
|
||||||
|
uint32(expectedFirstBlockHeight):
|
||||||
|
|
||||||
|
t.Fatalf("FirstBlockHeight incorrect: "+
|
||||||
|
"expected %v got %v",
|
||||||
|
rangeResp.FirstBlockHeight,
|
||||||
|
expectedFirstBlockHeight)
|
||||||
case i == 2 && rangeResp.Complete != 1:
|
case i == 2 && rangeResp.Complete != 1:
|
||||||
t.Fatalf("final chunk should have "+
|
t.Fatalf("final chunk should have "+
|
||||||
"Complete=1: %v", spew.Sdump(rangeResp))
|
"Complete=1: %v", spew.Sdump(rangeResp))
|
||||||
|
|
||||||
|
case i == 2 && rangeResp.NumBlocks != 1:
|
||||||
|
t.Fatalf("NumBlocks fields in resp "+
|
||||||
|
"incorrect: expected %v got %v", 1,
|
||||||
|
rangeResp.NumBlocks)
|
||||||
|
|
||||||
|
case i == 2 && rangeResp.FirstBlockHeight !=
|
||||||
|
queryResp[len(queryResp)-1].BlockHeight:
|
||||||
|
|
||||||
|
t.Fatalf("FirstBlockHeight incorrect: "+
|
||||||
|
"expected %v got %v",
|
||||||
|
rangeResp.FirstBlockHeight,
|
||||||
|
queryResp[len(queryResp)-1].BlockHeight)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
respMsgs = append(respMsgs, rangeResp.ShortChanIDs...)
|
respMsgs = append(respMsgs, rangeResp.ShortChanIDs...)
|
||||||
@ -785,13 +832,13 @@ func TestGossipSyncerReplyChanRangeQuery(t *testing.T) {
|
|||||||
|
|
||||||
// We should get back exactly 5 short chan ID's, and they should match
|
// We should get back exactly 5 short chan ID's, and they should match
|
||||||
// exactly the ID's we sent as a reply.
|
// exactly the ID's we sent as a reply.
|
||||||
if len(respMsgs) != len(resp) {
|
if len(respMsgs) != len(queryResp) {
|
||||||
t.Fatalf("expected %v chan ID's, instead got %v",
|
t.Fatalf("expected %v chan ID's, instead got %v",
|
||||||
len(resp), spew.Sdump(respMsgs))
|
len(queryResp), spew.Sdump(respMsgs))
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(resp, respMsgs) {
|
if !reflect.DeepEqual(queryResp, respMsgs) {
|
||||||
t.Fatalf("mismatched response: expected %v, got %v",
|
t.Fatalf("mismatched response: expected %v, got %v",
|
||||||
spew.Sdump(resp), spew.Sdump(respMsgs))
|
spew.Sdump(queryResp), spew.Sdump(respMsgs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for error from goroutine.
|
// Wait for error from goroutine.
|
||||||
|
Loading…
Reference in New Issue
Block a user