From 751d2711d478b9b8328c27e92d68b2e86269cbc1 Mon Sep 17 00:00:00 2001 From: BlockChainDev Date: Sat, 30 Mar 2019 21:36:50 +0000 Subject: [PATCH] [syncmgr] - refactored OnBlockBlockMode to use blockPool - syncmgr now checks for future blocks, instead of looking for a FutureBlockErr from the Chain. This makes it so that syncmgr does not depend on the Chain package. - removed GetBestBlockHash function from config(unused) - refactored all tests in the syncmgr package --- pkg/syncmgr/blockmode.go | 30 ++++++++++++++++----------- pkg/syncmgr/config.go | 3 --- pkg/syncmgr/mockhelpers_test.go | 4 ++-- pkg/syncmgr/normalmode.go | 2 +- pkg/syncmgr/syncmgr_onblock_test.go | 12 +++++------ pkg/syncmgr/syncmgr_onheaders_test.go | 14 ++++++------- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/pkg/syncmgr/blockmode.go b/pkg/syncmgr/blockmode.go index 83d3acd50..406204bf5 100644 --- a/pkg/syncmgr/blockmode.go +++ b/pkg/syncmgr/blockmode.go @@ -9,22 +9,29 @@ import ( // and receives a block. func (s *Syncmgr) blockModeOnBlock(peer SyncPeer, block payload.Block) error { - // Process Block - err := s.cfg.ProcessBlock(block) - - if err == chain.ErrFutureBlock { - // XXX(Optimisation): We can cache future blocks in blockmode, if we have the corresponding header - // We can have the server cache them and sort out the semantics for when to send them to the chain - // Server can listen on chain for when a new block is saved - // or we could embed a struct in this syncmgr called blockCache, syncmgr can just tell it when it has processed - //a block and we can call ProcessBlock - return err + // Check if it is a future block + // XXX: since we are storing blocks in memory, we do not want to store blocks + // from the tip + if block.Index > s.nextBlockIndex+2000 { + return nil + } + if block.Index != s.nextBlockIndex { + s.addToBlockPool(block) + return nil } + // Process Block + err := s.processBlock(block) if err != nil && err != chain.ErrBlockAlreadyExists { return s.cfg.FetchBlockAgain(block.Hash) } + // Check the block pool + err = s.checkPool() + if err != nil { + return err + } + // Check if blockhashReceived == the header hash from last get headers this node performed // if not then increment and request next block if s.headerHash != block.Hash { @@ -32,8 +39,7 @@ func (s *Syncmgr) blockModeOnBlock(peer SyncPeer, block payload.Block) error { if err != nil { return err } - err = s.cfg.RequestBlock(nextHash, block.Index) - return err + return s.cfg.RequestBlock(nextHash, block.Index) } // If we are caught up then go into normal mode diff --git a/pkg/syncmgr/config.go b/pkg/syncmgr/config.go index 713059802..43387d414 100644 --- a/pkg/syncmgr/config.go +++ b/pkg/syncmgr/config.go @@ -24,9 +24,6 @@ type Config struct { // at the tip of this nodes chain. This assumes that the node is not in sync GetNextBlockHash func() (util.Uint256, error) - // GetBestBlockHash gets the block hash of the last saved block. - GetBestBlockHash func() (util.Uint256, error) - // AskForNewBlocks will send out a message to the network // asking for new blocks AskForNewBlocks func() diff --git a/pkg/syncmgr/mockhelpers_test.go b/pkg/syncmgr/mockhelpers_test.go index 157fdd513..d95e95e6a 100644 --- a/pkg/syncmgr/mockhelpers_test.go +++ b/pkg/syncmgr/mockhelpers_test.go @@ -89,7 +89,7 @@ func randomUint256(t *testing.T) util.Uint256 { return u } -func setupSyncMgr(mode mode) (*Syncmgr, *syncTestHelper) { +func setupSyncMgr(mode mode, nextBlockIndex uint32) (*Syncmgr, *syncTestHelper) { helper := &syncTestHelper{} cfg := &Config{ @@ -106,7 +106,7 @@ func setupSyncMgr(mode mode) (*Syncmgr, *syncTestHelper) { RequestHeaders: helper.RequestHeaders, } - syncmgr := New(cfg) + syncmgr := New(cfg, nextBlockIndex) syncmgr.syncmode = mode return syncmgr, helper diff --git a/pkg/syncmgr/normalmode.go b/pkg/syncmgr/normalmode.go index 10bbac365..ad22e52f2 100644 --- a/pkg/syncmgr/normalmode.go +++ b/pkg/syncmgr/normalmode.go @@ -43,7 +43,7 @@ func (s *Syncmgr) normalModeOnBlock(peer SyncPeer, block payload.Block) error { s.timer.Stop() // process block - err := s.cfg.ProcessBlock(block) + err := s.processBlock(block) if err != nil { s.timer.Reset(blockTimer) return s.cfg.FetchBlockAgain(block.Hash) diff --git a/pkg/syncmgr/syncmgr_onblock_test.go b/pkg/syncmgr/syncmgr_onblock_test.go index d5b79f0b3..d08aa8a74 100644 --- a/pkg/syncmgr/syncmgr_onblock_test.go +++ b/pkg/syncmgr/syncmgr_onblock_test.go @@ -11,7 +11,7 @@ import ( func TestHeadersModeOnBlock(t *testing.T) { - syncmgr, helper := setupSyncMgr(headersMode) + syncmgr, helper := setupSyncMgr(headersMode, 0) syncmgr.OnBlock(&mockPeer{}, randomBlockMessage(t, 0)) @@ -21,7 +21,7 @@ func TestHeadersModeOnBlock(t *testing.T) { func TestBlockModeOnBlock(t *testing.T) { - syncmgr, helper := setupSyncMgr(blockMode) + syncmgr, helper := setupSyncMgr(blockMode, 0) syncmgr.OnBlock(&mockPeer{}, randomBlockMessage(t, 0)) @@ -30,7 +30,7 @@ func TestBlockModeOnBlock(t *testing.T) { } func TestNormalModeOnBlock(t *testing.T) { - syncmgr, helper := setupSyncMgr(normalMode) + syncmgr, helper := setupSyncMgr(normalMode, 0) syncmgr.OnBlock(&mockPeer{}, randomBlockMessage(t, 0)) @@ -40,7 +40,7 @@ func TestNormalModeOnBlock(t *testing.T) { func TestBlockModeToNormalMode(t *testing.T) { - syncmgr, _ := setupSyncMgr(blockMode) + syncmgr, _ := setupSyncMgr(blockMode, 100) peer := &mockPeer{ height: 100, @@ -57,7 +57,7 @@ func TestBlockModeToNormalMode(t *testing.T) { } func TestBlockModeStayInBlockMode(t *testing.T) { - syncmgr, _ := setupSyncMgr(blockMode) + syncmgr, _ := setupSyncMgr(blockMode, 0) // We need our latest know hash to not be equal to the hash // of the block we received, to stay in blockmode @@ -77,7 +77,7 @@ func TestBlockModeStayInBlockMode(t *testing.T) { } func TestBlockModeAlreadyExistsErr(t *testing.T) { - syncmgr, helper := setupSyncMgr(blockMode) + syncmgr, helper := setupSyncMgr(blockMode, 100) helper.err = chain.ErrBlockAlreadyExists syncmgr.OnBlock(&mockPeer{}, randomBlockMessage(t, 100)) diff --git a/pkg/syncmgr/syncmgr_onheaders_test.go b/pkg/syncmgr/syncmgr_onheaders_test.go index 2f60a4b72..f2bcef3f3 100644 --- a/pkg/syncmgr/syncmgr_onheaders_test.go +++ b/pkg/syncmgr/syncmgr_onheaders_test.go @@ -12,7 +12,7 @@ import ( func TestHeadersModeOnHeaders(t *testing.T) { - syncmgr, helper := setupSyncMgr(headersMode) + syncmgr, helper := setupSyncMgr(headersMode, 0) syncmgr.OnHeader(&mockPeer{}, randomHeadersMessage(t, 0)) @@ -29,14 +29,14 @@ func TestHeadersModeOnHeaders(t *testing.T) { } func TestBlockModeOnHeaders(t *testing.T) { - syncmgr, helper := setupSyncMgr(blockMode) + syncmgr, helper := setupSyncMgr(blockMode, 0) // If we receive a header in blockmode, no headers will be processed syncmgr.OnHeader(&mockPeer{}, randomHeadersMessage(t, 100)) assert.Equal(t, 0, helper.headersProcessed) } func TestNormalModeOnHeadersMaxHeaders(t *testing.T) { - syncmgr, helper := setupSyncMgr(normalMode) + syncmgr, helper := setupSyncMgr(normalMode, 0) // If we receive a header in normalmode, headers will be processed syncmgr.OnHeader(&mockPeer{}, randomHeadersMessage(t, 2000)) @@ -49,7 +49,7 @@ func TestNormalModeOnHeadersMaxHeaders(t *testing.T) { // This differs from the previous function in that //we did not receive the max amount of headers func TestNormalModeOnHeaders(t *testing.T) { - syncmgr, helper := setupSyncMgr(normalMode) + syncmgr, helper := setupSyncMgr(normalMode, 0) // If we receive a header in normalmode, headers will be processed syncmgr.OnHeader(&mockPeer{}, randomHeadersMessage(t, 200)) @@ -60,7 +60,7 @@ func TestNormalModeOnHeaders(t *testing.T) { } func TestLastHeaderUpdates(t *testing.T) { - syncmgr, _ := setupSyncMgr(headersMode) + syncmgr, _ := setupSyncMgr(headersMode, 0) hdrsMessage := randomHeadersMessage(t, 200) hdrs := hdrsMessage.Headers @@ -95,7 +95,7 @@ func TestLastHeaderUpdates(t *testing.T) { func TestHeadersModeOnHeadersErr(t *testing.T) { - syncmgr, helper := setupSyncMgr(headersMode) + syncmgr, helper := setupSyncMgr(headersMode, 0) helper.err = &chain.ValidationError{} syncmgr.OnHeader(&mockPeer{}, randomHeadersMessage(t, 200)) @@ -106,7 +106,7 @@ func TestHeadersModeOnHeadersErr(t *testing.T) { } func TestNormalModeOnHeadersErr(t *testing.T) { - syncmgr, helper := setupSyncMgr(normalMode) + syncmgr, helper := setupSyncMgr(normalMode, 0) helper.err = &chain.ValidationError{} syncmgr.OnHeader(&mockPeer{}, randomHeadersMessage(t, 200))