mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-30 07:35:07 +02:00
discovery: properly set FirstBlockHeight and NumBlocks in responses
In this commit we fix in a bug in `lnd` that could cause other implementations which implement a strict version of the spec to disconnect when trying to sync their channel graph using the gossip query feature. Before this commit, we would embed the request to a `QueryChannelRange` in the response, causing some clients to reject the response as the `FirstBlockHeight` and `NumBlocks` field would be identical for each chunk of the response. In order to remedy this, we now properly set these two fields with each returned chunk. Note that even after this commit, we keep our existing behavior surrounding the `Complete` field as is. Otherwise, current `lnd` clients which rely on this field (rather than the two aforementioned fields) wouldn't be able to properly detect when a set of responses to their query was "complete". Partially fixes #3728.
This commit is contained in:
@@ -824,6 +824,14 @@ func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
||||
// TODO(roasbeef): means can't send max uint above?
|
||||
// * 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))
|
||||
numChansSent := int32(0)
|
||||
for {
|
||||
@@ -854,13 +862,31 @@ func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
||||
"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
|
||||
// the current chunk.
|
||||
replyChunk := lnwire.ReplyChannelRange{
|
||||
QueryChannelRange: *query,
|
||||
Complete: 0,
|
||||
EncodingType: g.cfg.encodingType,
|
||||
ShortChanIDs: channelChunk,
|
||||
QueryChannelRange: lnwire.QueryChannelRange{
|
||||
ChainHash: query.ChainHash,
|
||||
NumBlocks: numBlocksInResp,
|
||||
FirstBlockHeight: firstBlockHeight,
|
||||
},
|
||||
Complete: 0,
|
||||
EncodingType: g.cfg.encodingType,
|
||||
ShortChanIDs: channelChunk,
|
||||
}
|
||||
if isFinalChunk {
|
||||
replyChunk.Complete = 1
|
||||
|
Reference in New Issue
Block a user