diff --git a/pkg/syncmgr/blockpool.go b/pkg/syncmgr/blockpool.go new file mode 100644 index 000000000..b038b29f3 --- /dev/null +++ b/pkg/syncmgr/blockpool.go @@ -0,0 +1,57 @@ +package syncmgr + +import ( + "sort" + + "github.com/CityOfZion/neo-go/pkg/wire/payload" +) + +func (s *Syncmgr) addToBlockPool(newBlock payload.Block) { + s.poolLock.Lock() + defer s.poolLock.Unlock() + + for _, block := range s.blockPool { + if block.Index == newBlock.Index { + return + } + } + + s.blockPool = append(s.blockPool, newBlock) + + // sort slice using block index + sort.Slice(s.blockPool, func(i, j int) bool { + return s.blockPool[i].Index < s.blockPool[j].Index + }) + +} + +func (s *Syncmgr) checkPool() error { + // Assuming that the blocks are sorted in order + + var indexesToRemove = -1 + + s.poolLock.Lock() + defer func() { + // removes all elements before this index, including the element at this index + s.blockPool = s.blockPool[indexesToRemove+1:] + s.poolLock.Unlock() + }() + + // loop iterates through the cache, processing any + // blocks that can be added to the chain + for i, block := range s.blockPool { + if s.nextBlockIndex != block.Index { + break + } + + // Save this block and save the indice so we can remove it + err := s.processBlock(block) + if err != nil { + return err + } + + indexesToRemove = i + } + + return nil +} diff --git a/pkg/syncmgr/blockpool_test.go b/pkg/syncmgr/blockpool_test.go new file mode 100644 index 000000000..c236afc2c --- /dev/null +++ b/pkg/syncmgr/blockpool_test.go @@ -0,0 +1,42 @@ +package syncmgr + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddBlockPoolFlush(t *testing.T) { + syncmgr, _ := setupSyncMgr(blockMode, 10) + + blockMessage := randomBlockMessage(t, 11) + + peer := &mockPeer{ + height: 100, + } + + // Since the block has Index 11 and the sync manager needs the block with index 10 + // This block will be added to the blockPool + err := syncmgr.OnBlock(peer, blockMessage) + assert.Nil(t, err) + assert.Equal(t, 1, len(syncmgr.blockPool)) + + // The sync manager is still looking for the block at height 10 + // Since this block is at height 12, it will be added to the block pool + blockMessage = randomBlockMessage(t, 12) + err = syncmgr.OnBlock(peer, blockMessage) + assert.Nil(t, err) + assert.Equal(t, 2, len(syncmgr.blockPool)) + + // This is the block that the sync manager was waiting for + // It should process this block, the check the pool for the next set of blocks + blockMessage = randomBlockMessage(t, 10) + err = syncmgr.OnBlock(peer, blockMessage) + assert.Nil(t, err) + assert.Equal(t, 0, len(syncmgr.blockPool)) + + // Since we processed 3 blocks and the sync manager started + //looking for block with index 10. The syncmananger should be looking for + // the block with index 13 + assert.Equal(t, uint32(13), syncmgr.nextBlockIndex) +}