From b413da23503e06bb1928057e021244fa04ec37fb Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 27 Sep 2018 18:07:09 -0500 Subject: [PATCH] blockmanager: Avoid duplicate header announcements. Clients are able to choose between two modes of notification about new blocks via the wire protocol. The first, and current default, is via inv messages and the second is via direct header announcements. There is code in the peer package which deals with filtering duplicate inventory announcements via the QueueInventory message. This works as expected for inv-based announcements, however, direct header announcements are not inv messages and hence do not use that code path. Consequently, the recent addition of the fast relay path which relied on that filtering to avoid sending duplicate announcements resulted in duplicate announcements being sent to peers who requested the header announcements mode. This resolves the issue by adding some logic directly to the notifications themselves to deal with filtering duplicates, both for inv and header-based announcements. --- blockmanager.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index b9238347..0b6cd1f7 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -330,6 +330,10 @@ type blockManager struct { cachedCurrentTemplate *BlockTemplate cachedParentTemplate *BlockTemplate AggressiveMining bool + + // The following fields are used to filter duplicate block announcements. + announcedBlockMtx sync.Mutex + announcedBlock *chainhash.Hash } // resetHeaderState sets the headers-first mode state to values appropriate for @@ -1659,6 +1663,9 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) { // Generate the inventory vector and relay it immediately. iv := wire.NewInvVect(wire.InvTypeBlock, block.Hash()) b.server.RelayInventory(iv, block.MsgBlock().Header, true) + b.announcedBlockMtx.Lock() + b.announcedBlock = block.Hash() + b.announcedBlockMtx.Unlock() // A block has been accepted into the block chain. Relay it to other peers // (will be ignored if already relayed via NTNewTipBlockChecked) and @@ -1736,9 +1743,16 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) { } } - // Generate the inventory vector and relay it immediately. - iv := wire.NewInvVect(wire.InvTypeBlock, blockHash) - b.server.RelayInventory(iv, block.MsgBlock().Header, true) + // Generate the inventory vector and relay it immediately if not already + // known to have been sent in NTNewTipBlockChecked. + b.announcedBlockMtx.Lock() + sent := b.announcedBlock != nil && *b.announcedBlock == *blockHash + b.announcedBlock = nil + b.announcedBlockMtx.Unlock() + if !sent { + iv := wire.NewInvVect(wire.InvTypeBlock, blockHash) + b.server.RelayInventory(iv, block.MsgBlock().Header, true) + } // A block has been connected to the main block chain. case blockchain.NTBlockConnected: