Filter duplicate getblocks requests.
This commit adds detection and filtering for back-to-back duplicate getblocks requests. This is needed because the trigger for requesting more blocks is receiving an orphan. When the peer is further behind than the number of blocks advertised via a single inventory message, the same orphan block will be sent multiple times. When the peer receives the final inventory message, it too contains the orphan that was previously sent. This leads to a duplicate getblocks request that must be filtered to prevent requesting the final series of blocks again.
This commit is contained in:
parent
0195306ff7
commit
346ff6f9e2
1 changed files with 56 additions and 26 deletions
82
peer.go
82
peer.go
|
@ -91,31 +91,34 @@ func newNetAddress(addr net.Addr, services btcwire.ServiceFlag) (*btcwire.NetAdd
|
||||||
|
|
||||||
// peer provides a bitcoin peer for handling bitcoin communications.
|
// peer provides a bitcoin peer for handling bitcoin communications.
|
||||||
type peer struct {
|
type peer struct {
|
||||||
server *server
|
server *server
|
||||||
protocolVersion uint32
|
protocolVersion uint32
|
||||||
btcnet btcwire.BitcoinNet
|
btcnet btcwire.BitcoinNet
|
||||||
services btcwire.ServiceFlag
|
services btcwire.ServiceFlag
|
||||||
started bool
|
started bool
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
addr string
|
addr string
|
||||||
na *btcwire.NetAddress
|
na *btcwire.NetAddress
|
||||||
timeConnected time.Time
|
timeConnected time.Time
|
||||||
inbound bool
|
inbound bool
|
||||||
disconnect bool
|
disconnect bool
|
||||||
persistent bool
|
persistent bool
|
||||||
versionKnown bool
|
versionKnown bool
|
||||||
knownAddresses map[string]bool
|
knownAddresses map[string]bool
|
||||||
knownInventory *MruInventoryMap
|
knownInventory *MruInventoryMap
|
||||||
knownInvMutex sync.Mutex
|
knownInvMutex sync.Mutex
|
||||||
lastBlock int32
|
lastBlock int32
|
||||||
requestQueue *list.List
|
prevGetBlocksBegin *btcwire.ShaHash
|
||||||
invSendQueue *list.List
|
prevGetBlocksStop *btcwire.ShaHash
|
||||||
continueHash *btcwire.ShaHash
|
prevGetBlockMutex sync.Mutex
|
||||||
wg sync.WaitGroup
|
requestQueue *list.List
|
||||||
outputQueue chan btcwire.Message
|
invSendQueue *list.List
|
||||||
outputInvChan chan *btcwire.InvVect
|
continueHash *btcwire.ShaHash
|
||||||
blockProcessed chan bool
|
wg sync.WaitGroup
|
||||||
quit chan bool
|
outputQueue chan btcwire.Message
|
||||||
|
outputInvChan chan *btcwire.InvVect
|
||||||
|
blockProcessed chan bool
|
||||||
|
quit chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// isKnownInventory returns whether or not the peer is known to have the passed
|
// isKnownInventory returns whether or not the peer is known to have the passed
|
||||||
|
@ -340,8 +343,30 @@ func (p *peer) pushBlockMsg(sha btcwire.ShaHash) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pushGetBlocksMsg sends a getblocks message for the provided block locator
|
// pushGetBlocksMsg sends a getblocks message for the provided block locator
|
||||||
// and stop hash.
|
// and stop hash. It will ignore back-to-back duplicate requests.
|
||||||
func (p *peer) pushGetBlocksMsg(locator btcchain.BlockLocator, stopHash *btcwire.ShaHash) error {
|
func (p *peer) pushGetBlocksMsg(locator btcchain.BlockLocator, stopHash *btcwire.ShaHash) error {
|
||||||
|
p.prevGetBlockMutex.Lock()
|
||||||
|
defer p.prevGetBlockMutex.Unlock()
|
||||||
|
|
||||||
|
// Extract the begin hash from the block locator, if one was specified,
|
||||||
|
// to use for filtering duplicate getblocks requests.
|
||||||
|
// request.
|
||||||
|
var beginHash *btcwire.ShaHash
|
||||||
|
if len(locator) > 0 {
|
||||||
|
beginHash = locator[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter duplicate getblocks requests.
|
||||||
|
if p.prevGetBlocksStop != nil && p.prevGetBlocksBegin != nil &&
|
||||||
|
beginHash != nil && stopHash.IsEqual(p.prevGetBlocksStop) &&
|
||||||
|
beginHash.IsEqual(p.prevGetBlocksBegin) {
|
||||||
|
|
||||||
|
log.Tracef("[PEER] Filtering duplicate [getblocks] with begin "+
|
||||||
|
"hash %v, stop hash %v", beginHash, stopHash)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the getblocks request and queue it to be sent.
|
||||||
msg := btcwire.NewMsgGetBlocks(stopHash)
|
msg := btcwire.NewMsgGetBlocks(stopHash)
|
||||||
for _, hash := range locator {
|
for _, hash := range locator {
|
||||||
err := msg.AddBlockLocatorHash(hash)
|
err := msg.AddBlockLocatorHash(hash)
|
||||||
|
@ -350,6 +375,11 @@ func (p *peer) pushGetBlocksMsg(locator btcchain.BlockLocator, stopHash *btcwire
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.QueueMessage(msg)
|
p.QueueMessage(msg)
|
||||||
|
|
||||||
|
// Update the previous getblocks request information for filtering
|
||||||
|
// duplicates.
|
||||||
|
p.prevGetBlocksBegin = beginHash
|
||||||
|
p.prevGetBlocksStop = stopHash
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue