Merge pull request #1384 from nspcc-dev/network/blockcache

network: restrict block queue size
This commit is contained in:
Roman Khimov 2020-09-02 20:00:47 +03:00 committed by GitHub
commit d91836c9dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 1 deletions

View file

@ -15,6 +15,12 @@ type blockQueue struct {
relayF func(*block.Block) relayF func(*block.Block)
} }
const (
// blockCacheSize is the amount of blocks above current height
// which are stored in queue.
blockCacheSize = 2000
)
func newBlockQueue(capacity int, bc blockchainer.Blockchainer, log *zap.Logger, relayer func(*block.Block)) *blockQueue { func newBlockQueue(capacity int, bc blockchainer.Blockchainer, log *zap.Logger, relayer func(*block.Block)) *blockQueue {
if log == nil { if log == nil {
return nil return nil
@ -66,7 +72,8 @@ func (bq *blockQueue) run() {
} }
func (bq *blockQueue) putBlock(block *block.Block) error { func (bq *blockQueue) putBlock(block *block.Block) error {
if bq.chain.BlockHeight() >= block.Index { h := bq.chain.BlockHeight()
if block.Index <= h || h+blockCacheSize < block.Index {
// can easily happen when fetching the same blocks from // can easily happen when fetching the same blocks from
// different peers, thus not considered as error // different peers, thus not considered as error
return nil return nil

View file

@ -31,6 +31,9 @@ func TestBlockQueue(t *testing.T) {
// but they're still not put into the blockchain, because bq isn't running // but they're still not put into the blockchain, because bq isn't running
assert.Equal(t, uint32(0), chain.BlockHeight()) assert.Equal(t, uint32(0), chain.BlockHeight())
assert.Equal(t, 4, bq.length()) assert.Equal(t, 4, bq.length())
// block with too big index is dropped
assert.NoError(t, bq.putBlock(&block.Block{Base: block.Base{Index: bq.chain.BlockHeight() + blockCacheSize + 1}}))
assert.Equal(t, 4, bq.length())
go bq.run() go bq.run()
// run() is asynchronous, so we need some kind of timeout anyway and this is the simplest one // run() is asynchronous, so we need some kind of timeout anyway and this is the simplest one
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {