diff --git a/cmd/node/main.go b/cmd/node/main.go index ae3f721cf07..33ada4c089e 100644 --- a/cmd/node/main.go +++ b/cmd/node/main.go @@ -165,6 +165,12 @@ VERSION: Usage: "The file containing the secret keys which ...", Value: "./config/initialNodesSk.pem", } + // boostrapRoundIndex defines a flag that specifies the round index from which node should bootstrap from storage + boostrapRoundIndex = cli.UintFlag{ + Name: "boostrap-round-index", + Usage: "Boostrap round index specifies the round index from which node should bootstrap from storage", + Value: math.MaxUint32, + } //TODO remove uniqueID uniqueID = "" @@ -216,6 +222,7 @@ func main() { gopsEn, serversConfigurationFile, restApiPort, + boostrapRoundIndex, } app.Authors = []cli.Author{ { @@ -440,6 +447,7 @@ func startNode(ctx *cli.Context, log *logger.Logger) error { cryptoComponents, processComponents, networkComponents, + uint32(ctx.GlobalUint(boostrapRoundIndex.Name)), ) if err != nil { return err @@ -618,6 +626,7 @@ func createNode( crypto *factory.Crypto, process *factory.Process, network *factory.Network, + boostrapRoundIndex uint32, ) (*node.Node, error) { nd, err := node.NewNode( node.WithMessenger(network.NetMessenger), @@ -650,6 +659,7 @@ func createNode( node.WithConsensusType(config.Consensus.Type), node.WithTxSingleSigner(crypto.TxSingleSigner), node.WithTxStorageSize(config.TxStorage.Cache.Size), + node.WithBoostrapRoundIndex(boostrapRoundIndex), ) if err != nil { return nil, errors.New("error creating node: " + err.Error()) diff --git a/dataRetriever/requestHandlers/requestHandler.go b/dataRetriever/requestHandlers/requestHandler.go index e9e6bd7b5f0..93c058cce88 100644 --- a/dataRetriever/requestHandlers/requestHandler.go +++ b/dataRetriever/requestHandlers/requestHandler.go @@ -7,6 +7,7 @@ import ( "github.com/ElrondNetwork/elrond-go/core/logger" "github.com/ElrondNetwork/elrond-go/core/partitioning" "github.com/ElrondNetwork/elrond-go/dataRetriever" + "github.com/ElrondNetwork/elrond-go/sharding" ) type ResolverRequestHandler struct { @@ -136,7 +137,16 @@ func (rrh *ResolverRequestHandler) RequestHeader(shardId uint32, hash []byte) { func (rrh *ResolverRequestHandler) requestByHash(destShardID uint32, hash []byte, baseTopic string) { log.Debug(fmt.Sprintf("Requesting %s from shard %d with hash %s from network\n", baseTopic, destShardID, core.ToB64(hash))) - resolver, err := rrh.resolversFinder.CrossShardResolver(baseTopic, destShardID) + + var resolver dataRetriever.Resolver + var err error + + if destShardID == sharding.MetachainShardId { + resolver, err = rrh.resolversFinder.MetaChainResolver(baseTopic) + } else { + resolver, err = rrh.resolversFinder.CrossShardResolver(baseTopic, destShardID) + } + if err != nil { log.Error(fmt.Sprintf("missing resolver to %s topic to shard %d", baseTopic, destShardID)) return diff --git a/node/defineOptions.go b/node/defineOptions.go index e85a5f85eaa..e7c598731e4 100644 --- a/node/defineOptions.go +++ b/node/defineOptions.go @@ -377,3 +377,11 @@ func WithTxStorageSize(txStorageSize uint32) Option { return nil } } + +// WithBoostrapRoundIndex sets up a boostrapRoundIndex option for the Node +func WithBoostrapRoundIndex(boostrapRoundIndex uint32) Option { + return func(n *Node) error { + n.boostrapRoundIndex = boostrapRoundIndex + return nil + } +} diff --git a/node/node.go b/node/node.go index e0ccba2badc..16522fa0e2a 100644 --- a/node/node.go +++ b/node/node.go @@ -98,6 +98,7 @@ type Node struct { isMetachainActive bool txStorageSize uint32 currentSendingGoRoutines int32 + boostrapRoundIndex uint32 } // ApplyOptions can set up different configurable options of a Node instance @@ -425,6 +426,7 @@ func (n *Node) createShardBootstrapper(rounder consensus.Rounder) (process.Boots n.resolversFinder, n.shardCoordinator, n.accounts, + n.boostrapRoundIndex, ) if err != nil { return nil, err @@ -447,6 +449,7 @@ func (n *Node) createMetaChainBootstrapper(rounder consensus.Rounder) (process.B n.resolversFinder, n.shardCoordinator, n.accounts, + n.boostrapRoundIndex, ) if err != nil { diff --git a/process/block/metablock.go b/process/block/metablock.go index 2548fc32a8c..5c9de6e25da 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -396,6 +396,7 @@ func (mp *metaProcessor) CommitBlock( return err } + //TODO: Should be analyzed if put in pool is really necessary or not (right now there is no action of removing them) _ = headerNoncePool.Put(headerHandler.GetNonce(), headerHash) for i := 0; i < len(header.ShardInfo); i++ { @@ -813,14 +814,14 @@ func (mp *metaProcessor) computeMissingHeaders(metaBlock *block.MetaBlock) map[u for i := 0; i < len(metaBlock.ShardInfo); i++ { shardData := metaBlock.ShardInfo[i] - header, _ := process.GetShardHeaderFromPool(shardData.HeaderHash, mp.dataPool.ShardHeaders()) - if header == nil { + hdr, err := process.GetShardHeaderFromPool(shardData.HeaderHash, mp.dataPool.ShardHeaders()) + if err != nil { missingHeaders[shardData.ShardId] = append(missingHeaders[shardData.ShardId], shardData.HeaderHash) continue } - if header.Nonce > mp.currHighestShardHdrsNonces[shardData.ShardId] { - mp.currHighestShardHdrsNonces[shardData.ShardId] = header.Nonce + if hdr.Nonce > mp.currHighestShardHdrsNonces[shardData.ShardId] { + mp.currHighestShardHdrsNonces[shardData.ShardId] = hdr.Nonce } } diff --git a/process/block/shardblock.go b/process/block/shardblock.go index d0e8f6325ad..22a5508dd64 100644 --- a/process/block/shardblock.go +++ b/process/block/shardblock.go @@ -465,6 +465,7 @@ func (sp *shardProcessor) CommitBlock( return err } + //TODO: Should be analyzed if put in pool is really necessary or not (right now there is no action of removing them) _ = headerNoncePool.Put(headerHandler.GetNonce(), headerHash) err = sp.txPreProcess.SaveTxBlockToStorage(body) @@ -821,25 +822,15 @@ func (sp *shardProcessor) computeMissingHeaders(header *block.Header) [][]byte { missingHeaders := make([][]byte, 0) sp.currHighestMetaHdrNonce = uint64(0) - metaBlockCache := sp.dataPool.MetaBlocks() - if metaBlockCache == nil { - return missingHeaders - } - for i := 0; i < len(header.MetaBlockHashes); i++ { - obj, ok := metaBlockCache.Peek(header.MetaBlockHashes[i]) - if !ok { + hdr, err := process.GetMetaHeaderFromPool(header.MetaBlockHashes[i], sp.dataPool.MetaBlocks()) + if err != nil { missingHeaders = append(missingHeaders, header.MetaBlockHashes[i]) continue } - metaBlock, ok := obj.(data.HeaderHandler) - if !ok { - continue - } - - if metaBlock.GetNonce() > sp.currHighestMetaHdrNonce { - sp.currHighestMetaHdrNonce = metaBlock.GetNonce() + if hdr.Nonce > sp.currHighestMetaHdrNonce { + sp.currHighestMetaHdrNonce = hdr.Nonce } } @@ -1244,7 +1235,7 @@ func (sp *shardProcessor) createMiniBlocks( return miniBlocks, nil } - addedTxs := 0 + addedTxs := int(txs) for i := 0; i < int(noShards); i++ { miniBlock, err := sp.txPreProcess.CreateAndProcessMiniBlock(sp.shardCoordinator.SelfId(), uint32(i), maxTxInBlock-addedTxs, haveTime, round) if err != nil { diff --git a/process/errors.go b/process/errors.go index 56d3bc01f77..68114a42480 100644 --- a/process/errors.go +++ b/process/errors.go @@ -214,9 +214,6 @@ var ErrNilHeadersNonceHashStorage = errors.New("nil headers nonce hash storage") // ErrNilMetachainHeadersStorage signals that a nil metachain header storage has been provided var ErrNilMetachainHeadersStorage = errors.New("nil metachain headers storage") -// ErrNilResolverSender signals that a nil resolver sender object has been provided -var ErrNilResolverSender = errors.New("nil resolver sender") - // ErrNilBlockBodyStorage signals that a nil block body storage has been provided var ErrNilBlockBodyStorage = errors.New("nil block body storage") @@ -358,8 +355,8 @@ var ErrNilBalanceFromSC = errors.New("output balance from VM is nil") // ErrNilTemporaryAccountsHandler signals that temporary accounts handler is nil var ErrNilTemporaryAccountsHandler = errors.New("temporary accounts handler is nil") -// ErrBoostrapFromStorage signals that boostrap from storage has been failed -var ErrBoostrapFromStorage = errors.New("boostrap from storage has been failed") +// ErrNotEnoughValidBlocksInStorage signals that boostrap from storage failed due to not enough valid blocks stored +var ErrNotEnoughValidBlocksInStorage = errors.New("not enough valid blocks in storage") // ErrNilSmartContractResult signals that the smart contract result is nil var ErrNilSmartContractResult = errors.New("smart contract result is nil") diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index b7717b58741..d0a949267f6 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -64,6 +64,7 @@ type baseBootstrap struct { syncStateListeners []func(bool) mutSyncStateListeners sync.RWMutex uint64Converter typeConverters.Uint64ByteSliceConverter + boostrapRoundIndex uint32 } func (boot *baseBootstrap) loadBlocks( @@ -72,48 +73,31 @@ func (boot *baseBootstrap) loadBlocks( hdrNonceHashDataUnit dataRetriever.UnitType, getHeader func(uint64) (data.HeaderHandler, []byte, error), getBlockBody func(data.HeaderHandler) (data.BodyHandler, error), + removeBlockBody func(uint64, dataRetriever.UnitType, dataRetriever.UnitType) error, ) error { - highestNonceInStorer := uint64(0) + var err error + var currentNonce uint64 - for { - highestNonceInStorer++ - nonceToByteSlice := boot.uint64Converter.ToByteSlice(highestNonceInStorer) - err := boot.store.Has(hdrNonceHashDataUnit, nonceToByteSlice) - if err != nil { - highestNonceInStorer-- - break - } - } + highestNonceInStorer := boot.computeHighestNonce(hdrNonceHashDataUnit) log.Info(fmt.Sprintf("the highest header nonce committed in storer is %d\n", highestNonceInStorer)) - var err error - lastBlocksToSkip := uint64(0) - - for { - if highestNonceInStorer <= blockFinality+lastBlocksToSkip { - return process.ErrBoostrapFromStorage - } - - for i := highestNonceInStorer - blockFinality - lastBlocksToSkip; i <= highestNonceInStorer; i++ { - if i > highestNonceInStorer-lastBlocksToSkip { - errNotCritical := boot.removeBlock(i, blockUnit, hdrNonceHashDataUnit) - if errNotCritical != nil { - log.Info(errNotCritical.Error()) - } - } else { - err = boot.applyBlock(i, getHeader, getBlockBody) - if err != nil { - lastBlocksToSkip++ - break - } + for currentNonce = highestNonceInStorer; currentNonce > blockFinality; currentNonce-- { + for i := currentNonce - blockFinality; i <= currentNonce; i++ { + err = boot.applyBlock(i, getHeader, getBlockBody) + if err != nil { + log.Info(fmt.Sprintf("apply block with nonce %d: %s\n", i, err.Error())) + break } } if err == nil { err = boot.accounts.RecreateTrie(boot.blkc.GetCurrentBlockHeader().GetRootHash()) if err != nil { - lastBlocksToSkip++ + log.Info(fmt.Sprintf("recreate trie for block with nonce %d in shard %d: %s\n", + boot.blkc.GetCurrentBlockHeader().GetNonce(), + boot.blkc.GetCurrentBlockHeader().GetShardID(), + err.Error())) continue } @@ -121,26 +105,72 @@ func (boot *baseBootstrap) loadBlocks( } } + if currentNonce <= blockFinality { + return process.ErrNotEnoughValidBlocksInStorage + } + + boostrapRoundIndex, errNotCritical := boot.getBlockRoundFromNonce(currentNonce, getHeader) + if errNotCritical != nil { + log.Info(fmt.Sprintf(errNotCritical.Error())) + } else { + boot.boostrapRoundIndex = boostrapRoundIndex + } + + for i := currentNonce + 1; i <= highestNonceInStorer; i++ { + boot.cleanupStorage(removeBlockBody, i, blockUnit, hdrNonceHashDataUnit) + } + return nil } +func (boot *baseBootstrap) computeHighestNonce(hdrNonceHashDataUnit dataRetriever.UnitType) uint64 { + highestNonceInStorer := uint64(0) + + for { + highestNonceInStorer++ + nonceToByteSlice := boot.uint64Converter.ToByteSlice(highestNonceInStorer) + err := boot.store.Has(hdrNonceHashDataUnit, nonceToByteSlice) + if err != nil { + highestNonceInStorer-- + break + } + } + + return highestNonceInStorer +} + +func (boot *baseBootstrap) cleanupStorage( + removeBlockBody func(uint64, dataRetriever.UnitType, dataRetriever.UnitType) error, + nonce uint64, + blockUnit dataRetriever.UnitType, + hdrNonceHashDataUnit dataRetriever.UnitType) { + + errNotCritical := removeBlockBody(nonce, blockUnit, hdrNonceHashDataUnit) + if errNotCritical != nil { + log.Info(fmt.Sprintf("remove block body with nonce %d: %s\n", nonce, errNotCritical.Error())) + } + + errNotCritical = boot.removeBlockHeader(nonce, blockUnit, hdrNonceHashDataUnit) + if errNotCritical != nil { + log.Info(fmt.Sprintf("remove block header with nonce %d: %s\n", nonce, errNotCritical.Error())) + } +} + func (boot *baseBootstrap) applyBlock( nonce uint64, getHeader func(uint64) (data.HeaderHandler, []byte, error), getBlockBody func(data.HeaderHandler) (data.BodyHandler, error), ) error { - header, headerHash, err := getHeader(nonce) if err != nil { return err } - headerNoncePool := boot.headersNonces - if headerNoncePool == nil { - return process.ErrNilDataPoolHolder - } + log.Info(fmt.Sprintf("apply block with nonce %d and round %d\n", header.GetNonce(), header.GetRound())) - _ = headerNoncePool.Put(header.GetNonce(), headerHash) + if header.GetRound() > boot.boostrapRoundIndex { + return ErrHigherBootstrapRound + } errNotCritical := boot.forkDetector.AddHeader(header, headerHash, process.BHProcessed) if errNotCritical != nil { @@ -167,7 +197,7 @@ func (boot *baseBootstrap) applyBlock( return nil } -func (boot *baseBootstrap) removeBlock( +func (boot *baseBootstrap) removeBlockHeader( nonce uint64, blockUnit dataRetriever.UnitType, hdrNonceHashDataUnit dataRetriever.UnitType, @@ -201,36 +231,25 @@ func (boot *baseBootstrap) removeBlock( return nil } -func (boot *baseBootstrap) loadNotarizedBlocks(blockFinality uint64, +func (boot *baseBootstrap) loadNotarizedBlocks( + blockFinality uint64, hdrNonceHashDataUnit dataRetriever.UnitType, applyNotarisedBlock func(uint64, dataRetriever.UnitType) error, ) error { - highestNonceInStorer := uint64(0) - - for { - highestNonceInStorer++ - nonceToByteSlice := boot.uint64Converter.ToByteSlice(highestNonceInStorer) - err := boot.store.Has(hdrNonceHashDataUnit, nonceToByteSlice) - if err != nil { - highestNonceInStorer-- - break - } - } - - log.Info(fmt.Sprintf("the highest notarized header nonce committed in unit storer %d is %d\n", hdrNonceHashDataUnit, highestNonceInStorer)) - var err error - lastBlocksToSkip := uint64(0) + var currentNonce uint64 - for { - if highestNonceInStorer <= blockFinality+lastBlocksToSkip { - return process.ErrBoostrapFromStorage - } + highestNonceInStorer := boot.computeHighestNonce(hdrNonceHashDataUnit) - for i := highestNonceInStorer - blockFinality - lastBlocksToSkip; i <= highestNonceInStorer-lastBlocksToSkip; i++ { + log.Info(fmt.Sprintf("the highest notarized header nonce committed in unit storer %d is %d\n", + hdrNonceHashDataUnit, + highestNonceInStorer)) + + for currentNonce = highestNonceInStorer; currentNonce > blockFinality; currentNonce-- { + for i := currentNonce - blockFinality; i <= currentNonce; i++ { err = applyNotarisedBlock(i, hdrNonceHashDataUnit) if err != nil { - lastBlocksToSkip++ + log.Info(fmt.Sprintf("apply notarized block with nonce %d: %s\n", i, err.Error())) break } } @@ -240,9 +259,55 @@ func (boot *baseBootstrap) loadNotarizedBlocks(blockFinality uint64, } } + if currentNonce <= blockFinality { + return process.ErrNotEnoughValidBlocksInStorage + } + + for i := currentNonce + 1; i <= highestNonceInStorer; i++ { + boot.cleanupNotarizedStorage(i, hdrNonceHashDataUnit) + } + + return nil +} + +func (boot *baseBootstrap) cleanupNotarizedStorage(nonce uint64, hdrNonceHashDataUnit dataRetriever.UnitType) { + errNotCritical := boot.removeNotarizedBlockHeader(nonce, hdrNonceHashDataUnit) + if errNotCritical != nil { + log.Info(fmt.Sprintf("remove notarized block header with nonce %d: %s\n", nonce, errNotCritical.Error())) + } +} + +func (boot *baseBootstrap) removeNotarizedBlockHeader( + nonce uint64, + notarizedHdrNonceHashDataUnit dataRetriever.UnitType, +) error { + headerNonceHashStore := boot.store.GetStorer(notarizedHdrNonceHashDataUnit) + if headerNonceHashStore == nil { + return process.ErrNilHeadersNonceHashStorage + } + + nonceToByteSlice := boot.uint64Converter.ToByteSlice(nonce) + err := headerNonceHashStore.Remove(nonceToByteSlice) + if err != nil { + return err + } + return nil } +func (boot *baseBootstrap) getBlockRoundFromNonce( + nonce uint64, + getHeader func(uint64) (data.HeaderHandler, []byte, error), +) (uint32, error) { + + header, _, err := getHeader(nonce) + if err != nil { + return 0, err + } + + return header.GetRound(), nil +} + // setRequestedHeaderNonce method sets the header nonce requested by the sync mechanism func (boot *baseBootstrap) setRequestedHeaderNonce(nonce *uint64) { boot.mutHeader.Lock() diff --git a/process/sync/errors.go b/process/sync/errors.go index e2d0f4980d3..fd4d2d8f8d4 100644 --- a/process/sync/errors.go +++ b/process/sync/errors.go @@ -23,6 +23,9 @@ var ErrLowerRoundInBlock = errors.New("lower round in block") // ErrHigherRoundInBlock signals that the round index in block is higher than the current round of chronology var ErrHigherRoundInBlock = errors.New("higher round in block") +// ErrHigherBootstrapRound signals that the round index in block is higher than the given round to bootstrap +var ErrHigherBootstrapRound = errors.New("higher bootstrap round in block") + // ErrBlockIsNotSigned signals that the block is not signed var ErrBlockIsNotSigned = errors.New("block is not signed") diff --git a/process/sync/export_test.go b/process/sync/export_test.go index ca5337ed8aa..bb5189a5e3f 100644 --- a/process/sync/export_test.go +++ b/process/sync/export_test.go @@ -133,8 +133,9 @@ func (boot *baseBootstrap) LoadBlocks( hdrNonceHashDataUnit dataRetriever.UnitType, getHeader func(uint64) (data.HeaderHandler, []byte, error), getBlockBody func(data.HeaderHandler) (data.BodyHandler, error), + removeBlockBody func(uint64, dataRetriever.UnitType, dataRetriever.UnitType) error, ) error { - return boot.loadBlocks(blockFinality, blockUnit, hdrNonceHashDataUnit, getHeader, getBlockBody) + return boot.loadBlocks(blockFinality, blockUnit, hdrNonceHashDataUnit, getHeader, getBlockBody, removeBlockBody) } func (boot *baseBootstrap) ApplyBlock( @@ -145,12 +146,28 @@ func (boot *baseBootstrap) ApplyBlock( return boot.applyBlock(nonce, getHeader, getBlockBody) } -func (boot *baseBootstrap) RemoveBlock( +func (boot *baseBootstrap) RemoveBlockHeader( nonce uint64, blockUnit dataRetriever.UnitType, hdrNonceHashDataUnit dataRetriever.UnitType, ) error { - return boot.removeBlock(nonce, blockUnit, hdrNonceHashDataUnit) + return boot.removeBlockHeader(nonce, blockUnit, hdrNonceHashDataUnit) +} + +func (boot *ShardBootstrap) RemoveBlockBody( + nonce uint64, + blockUnit dataRetriever.UnitType, + hdrNonceHashDataUnit dataRetriever.UnitType, +) error { + return boot.removeBlockBody(nonce, blockUnit, hdrNonceHashDataUnit) +} + +func (boot *MetaBootstrap) RemoveBlockBody( + nonce uint64, + blockUnit dataRetriever.UnitType, + hdrNonceHashDataUnit dataRetriever.UnitType, +) error { + return boot.removeBlockBody(nonce, blockUnit, hdrNonceHashDataUnit) } func (boot *baseBootstrap) LoadNotarizedBlocks(blockFinality uint64, @@ -168,6 +185,13 @@ func (boot *MetaBootstrap) ApplyNotarizedBlock(nonce uint64, notarizedHdrNonceHa return boot.applyNotarizedBlock(nonce, notarizedHdrNonceHashDataUnit) } +func (boot *baseBootstrap) RemoveNotarizedBlockHeader( + nonce uint64, + hdrNonceHashDataUnit dataRetriever.UnitType, +) error { + return boot.removeNotarizedBlockHeader(nonce, hdrNonceHashDataUnit) +} + func (boot *ShardBootstrap) SyncFromStorer( blockFinality uint64, blockUnit dataRetriever.UnitType, diff --git a/process/sync/metablock.go b/process/sync/metablock.go index 8a6de26a4ed..2c1d457a08d 100644 --- a/process/sync/metablock.go +++ b/process/sync/metablock.go @@ -41,6 +41,7 @@ func NewMetaBootstrap( resolversFinder dataRetriever.ResolversFinder, shardCoordinator sharding.Coordinator, accounts state.AccountsAdapter, + boostrapRoundIndex uint32, ) (*MetaBootstrap, error) { if poolsHolder == nil { @@ -70,18 +71,19 @@ func NewMetaBootstrap( } base := &baseBootstrap{ - blkc: blkc, - blkExecutor: blkExecutor, - store: store, - headers: poolsHolder.MetaChainBlocks(), - headersNonces: poolsHolder.MetaBlockNonces(), - rounder: rounder, - waitTime: waitTime, - hasher: hasher, - marshalizer: marshalizer, - forkDetector: forkDetector, - shardCoordinator: shardCoordinator, - accounts: accounts, + blkc: blkc, + blkExecutor: blkExecutor, + store: store, + headers: poolsHolder.MetaChainBlocks(), + headersNonces: poolsHolder.MetaBlockNonces(), + rounder: rounder, + waitTime: waitTime, + hasher: hasher, + marshalizer: marshalizer, + forkDetector: forkDetector, + shardCoordinator: shardCoordinator, + accounts: accounts, + boostrapRoundIndex: boostrapRoundIndex, } boot := MetaBootstrap{ @@ -129,7 +131,8 @@ func (boot *MetaBootstrap) syncFromStorer( blockUnit, hdrNonceHashDataUnit, boot.getHeaderFromStorage, - boot.getBlockBody) + boot.getBlockBody, + boot.removeBlockBody) if err != nil { return err } @@ -146,7 +149,18 @@ func (boot *MetaBootstrap) syncFromStorer( return nil } -func (boot *MetaBootstrap) applyNotarizedBlock(nonce uint64, notarizedHdrNonceHashDataUnit dataRetriever.UnitType) error { +func (boot *MetaBootstrap) removeBlockBody( + nonce uint64, + blockUnit dataRetriever.UnitType, + hdrNonceHashDataUnit dataRetriever.UnitType, +) error { + return nil +} + +func (boot *MetaBootstrap) applyNotarizedBlock( + nonce uint64, + notarizedHdrNonceHashDataUnit dataRetriever.UnitType, +) error { nonceToByteSlice := boot.uint64Converter.ToByteSlice(nonce) headerHash, err := boot.store.Get(notarizedHdrNonceHashDataUnit, nonceToByteSlice) if err != nil { @@ -158,6 +172,12 @@ func (boot *MetaBootstrap) applyNotarizedBlock(nonce uint64, notarizedHdrNonceHa return err } + log.Info(fmt.Sprintf("apply notarized block with nonce %d and round %d\n", header.Nonce, header.Round)) + + if header.GetRound() > boot.boostrapRoundIndex { + return ErrHigherBootstrapRound + } + boot.blkExecutor.SetLastNotarizedHdr(header.ShardId, header) return nil @@ -350,7 +370,7 @@ func (boot *MetaBootstrap) requestHeader(nonce uint64) { // getHeaderWithNonce method gets the header with given nonce from pool, if it exist there, // and if not it will be requested from network func (boot *MetaBootstrap) getHeaderRequestingIfMissing(nonce uint64) (*block.MetaBlock, error) { - hdr, err := boot.getHeaderWithNonce(nonce) + hdr, err := boot.getHeaderFromPoolWithNonce(nonce) if err != nil { process.EmptyChannel(boot.chRcvHdr) boot.requestHeader(nonce) @@ -359,7 +379,7 @@ func (boot *MetaBootstrap) getHeaderRequestingIfMissing(nonce uint64) (*block.Me return nil, err } - hdr, err = boot.getHeaderWithNonce(nonce) + hdr, err = boot.getHeaderFromPoolWithNonce(nonce) if err != nil { return nil, err } diff --git a/process/sync/metablock_test.go b/process/sync/metablock_test.go index 89396e1583b..27dc5a8936d 100644 --- a/process/sync/metablock_test.go +++ b/process/sync/metablock_test.go @@ -129,6 +129,7 @@ func TestNewMetaBootstrap_NilPoolsHolderShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -165,6 +166,7 @@ func TestNewMetaBootstrap_PoolsHolderRetNilOnHeadersShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -200,6 +202,7 @@ func TestNewMetaBootstrap_PoolsHolderRetNilOnHeadersNoncesShouldErr(t *testing.T &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -231,6 +234,7 @@ func TestNewMetaBootstrap_NilStoreShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -262,6 +266,7 @@ func TestNewMetaBootstrap_NilBlockchainShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -293,6 +298,7 @@ func TestNewMetaBootstrap_NilRounderShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -324,6 +330,7 @@ func TestNewMetaBootstrap_NilBlockProcessorShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -355,6 +362,7 @@ func TestNewMetaBootstrap_NilHasherShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -386,6 +394,7 @@ func TestNewMetaBootstrap_NilMarshalizerShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -417,6 +426,7 @@ func TestNewMetaBootstrap_NilForkDetectorShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -449,6 +459,7 @@ func TestNewMetaBootstrap_NilResolversContainerShouldErr(t *testing.T) { nil, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -480,6 +491,7 @@ func TestNewMetaBootstrap_NilShardCoordinatorShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, nil, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -511,6 +523,7 @@ func TestNewMetaBootstrap_NilAccountsAdapterShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, nil, + math.MaxUint32, ) assert.Nil(t, bs) @@ -553,6 +566,7 @@ func TestNewMetaBootstrap_NilHeaderResolverShouldErr(t *testing.T) { resFinder, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -595,6 +609,7 @@ func TestNewMetaBootstrap_NilTxBlockBodyResolverShouldErr(t *testing.T) { resFinder, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -651,6 +666,7 @@ func TestNewMetaBootstrap_OkValsShouldWork(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) assert.NotNil(t, bs) @@ -710,6 +726,7 @@ func TestMetaBootstrap_SyncBlockShouldCallForkChoice(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) r := bs.SyncBlock() @@ -761,6 +778,7 @@ func TestMetaBootstrap_ShouldReturnTimeIsOutWhenMissingHeader(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) r := bs.SyncBlock() @@ -812,6 +830,7 @@ func TestMetaBootstrap_ShouldNotNeedToSync(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) bs.StartSync() @@ -908,6 +927,7 @@ func TestMetaBootstrap_SyncShouldSyncOneBlock(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) bs.StartSync() @@ -1000,6 +1020,7 @@ func TestMetaBootstrap_ShouldReturnNilErr(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) r := bs.SyncBlock() @@ -1094,6 +1115,7 @@ func TestMetaBootstrap_SyncBlockShouldReturnErrorWhenProcessBlockFailed(t *testi createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncBlock() @@ -1133,6 +1155,7 @@ func TestMetaBootstrap_ShouldSyncShouldReturnFalseWhenCurrentBlockIsNilAndRoundI createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, err) @@ -1172,6 +1195,7 @@ func TestMetaBootstrap_ShouldReturnTrueWhenCurrentBlockIsNilAndRoundIndexIsGreat createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) assert.True(t, bs.ShouldSync()) @@ -1215,6 +1239,7 @@ func TestMetaBootstrap_ShouldReturnFalseWhenNodeIsSynced(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) assert.False(t, bs.ShouldSync()) @@ -1258,6 +1283,7 @@ func TestMetaBootstrap_ShouldReturnTrueWhenNodeIsNotSynced(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) assert.True(t, bs.ShouldSync()) @@ -1292,6 +1318,7 @@ func TestMetaBootstrap_GetHeaderFromPoolShouldReturnNil(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) hdr, _ := bs.GetHeaderFromPoolWithNonce(0) @@ -1355,6 +1382,7 @@ func TestMetaBootstrap_GetHeaderFromPoolShouldReturnHeader(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) hdr2, _ := bs.GetHeaderFromPoolWithNonce(0) @@ -1423,6 +1451,7 @@ func TestMetaBootstrap_ReceivedHeadersFoundInPoolShouldAddToForkDetector(t *test createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) bs.ReceivedHeaders(addedHash) @@ -1495,6 +1524,7 @@ func TestMetaBootstrap_ReceivedHeadersNotFoundInPoolButFoundInStorageShouldAddTo createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) bs.ReceivedHeaders(addedHash) @@ -1530,6 +1560,7 @@ func TestMetaBootstrap_ForkChoiceNilBlockchainHeaderShouldErr(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ForkChoice() @@ -1562,6 +1593,7 @@ func TestMetaBootstrap_ForkChoiceNilParamHeaderShouldErr(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) blkc.GetCurrentBlockHeaderCalled = func() data.HeaderHandler { @@ -1609,6 +1641,7 @@ func TestMetaBootstrap_ForkChoiceIsNotEmptyShouldErr(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) blkc.GetCurrentBlockHeaderCalled = func() data.HeaderHandler { @@ -1730,6 +1763,7 @@ func TestMetaBootstrap_ForkChoiceIsEmptyCallRollBackOkValsShouldWork(t *testing. createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) bs.SetForkNonce(currentHdrNonce) @@ -1885,6 +1919,7 @@ func TestMetaBootstrap_ForkChoiceIsEmptyCallRollBackToGenesisShouldWork(t *testi createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) bs.SetForkNonce(currentHdrNonce) @@ -1946,6 +1981,7 @@ func TestMetaBootstrap_AddSyncStateListenerShouldAppendAnotherListener(t *testin createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) f1 := func(bool) {} @@ -1986,6 +2022,7 @@ func TestMetaBootstrap_NotifySyncStateListenersShouldNotify(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) mutex.RLock() @@ -2058,6 +2095,7 @@ func TestMetaBootstrap_SyncFromStorerShouldErrWhenLoadBlocksFails(t *testing.T) createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncFromStorer(process.MetaBlockFinality, @@ -2066,7 +2104,7 @@ func TestMetaBootstrap_SyncFromStorerShouldErrWhenLoadBlocksFails(t *testing.T) process.ShardBlockFinality, dataRetriever.ShardHdrNonceHashDataUnit) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestMetaBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *testing.T) { @@ -2133,6 +2171,7 @@ func TestMetaBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *te createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncFromStorer(process.MetaBlockFinality, @@ -2141,7 +2180,7 @@ func TestMetaBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *te process.ShardBlockFinality, dataRetriever.ShardHdrNonceHashDataUnit) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestMetaBootstrap_SyncFromStorerShouldWork(t *testing.T) { @@ -2220,6 +2259,7 @@ func TestMetaBootstrap_SyncFromStorerShouldWork(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncFromStorer(process.MetaBlockFinality, @@ -2267,6 +2307,7 @@ func TestMetaBootstrap_ApplyNotarizedBlockShouldErrWhenHeaderIsNotFound(t *testi createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyNotarizedBlock(1, @@ -2314,6 +2355,7 @@ func TestMetaBootstrap_ApplyNotarizedBlockShouldErrWhenGetMetaHeaderFromStorageF createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyNotarizedBlock(1, @@ -2322,6 +2364,58 @@ func TestMetaBootstrap_ApplyNotarizedBlockShouldErrWhenGetMetaHeaderFromStorageF assert.Equal(t, process.ErrMissingHeader, err) } +func TestMetaBootstrap_ApplyNotarizedBlockShouldErrHigherBootstrapRound(t *testing.T) { + t.Parallel() + + pools := createMockMetaPools() + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{ + SetLastNotarizedHdrCalled: func(shardId uint32, processedHdr data.HeaderHandler) { + }, + } + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + store.GetStorerCalled = func(unitType dataRetriever.UnitType) storage.Storer { + if unitType == dataRetriever.BlockHeaderUnit { + return &mock.StorerStub{ + GetCalled: func(key []byte) ([]byte, error) { + buff, _ := marshalizer.Marshal(&block.Header{Round: 2}) + return buff, nil + }, + } + } + + return nil + } + + bs, _ := sync.NewMetaBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinderMeta(), + shardCoordinator, + account, + 1, + ) + + err := bs.ApplyNotarizedBlock(1, + dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) + + assert.Equal(t, sync.ErrHigherBootstrapRound, err) +} + func TestMetaBootstrap_ApplyNotarizedBlockShouldWork(t *testing.T) { t.Parallel() @@ -2365,6 +2459,7 @@ func TestMetaBootstrap_ApplyNotarizedBlockShouldWork(t *testing.T) { createMockResolversFinderMeta(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyNotarizedBlock(1, diff --git a/process/sync/shardblock.go b/process/sync/shardblock.go index e2bae6bcf06..ce48245fda4 100644 --- a/process/sync/shardblock.go +++ b/process/sync/shardblock.go @@ -46,6 +46,7 @@ func NewShardBootstrap( resolversFinder dataRetriever.ResolversFinder, shardCoordinator sharding.Coordinator, accounts state.AccountsAdapter, + boostrapRoundIndex uint32, ) (*ShardBootstrap, error) { if poolsHolder == nil { @@ -78,18 +79,19 @@ func NewShardBootstrap( } base := &baseBootstrap{ - blkc: blkc, - blkExecutor: blkExecutor, - store: store, - headers: poolsHolder.Headers(), - headersNonces: poolsHolder.HeadersNonces(), - rounder: rounder, - waitTime: waitTime, - hasher: hasher, - marshalizer: marshalizer, - forkDetector: forkDetector, - shardCoordinator: shardCoordinator, - accounts: accounts, + blkc: blkc, + blkExecutor: blkExecutor, + store: store, + headers: poolsHolder.Headers(), + headersNonces: poolsHolder.HeadersNonces(), + rounder: rounder, + waitTime: waitTime, + hasher: hasher, + marshalizer: marshalizer, + forkDetector: forkDetector, + shardCoordinator: shardCoordinator, + accounts: accounts, + boostrapRoundIndex: boostrapRoundIndex, } boot := ShardBootstrap{ @@ -145,7 +147,8 @@ func (boot *ShardBootstrap) syncFromStorer( blockUnit, hdrNonceHashDataUnit, boot.getHeaderFromStorage, - boot.getBlockBody) + boot.getBlockBody, + boot.removeBlockBody) if err != nil { return err } @@ -160,7 +163,76 @@ func (boot *ShardBootstrap) syncFromStorer( return nil } -func (boot *ShardBootstrap) applyNotarizedBlock(nonce uint64, notarizedHdrNonceHashDataUnit dataRetriever.UnitType) error { +func (boot *ShardBootstrap) removeBlockBody( + nonce uint64, + blockUnit dataRetriever.UnitType, + hdrNonceHashDataUnit dataRetriever.UnitType, +) error { + + blockBodyStore := boot.store.GetStorer(dataRetriever.MiniBlockUnit) + if blockBodyStore == nil { + return process.ErrNilBlockBodyStorage + } + + txStore := boot.store.GetStorer(dataRetriever.TransactionUnit) + if txStore == nil { + return process.ErrNilTxStorage + } + + nonceToByteSlice := boot.uint64Converter.ToByteSlice(nonce) + headerHash, err := boot.store.Get(hdrNonceHashDataUnit, nonceToByteSlice) + if err != nil { + return err + } + + hdrBuff, err := boot.store.Get(blockUnit, headerHash) + if err != nil { + return err + } + + hdr := block.Header{} + err = boot.marshalizer.Unmarshal(&hdr, hdrBuff) + if err != nil { + return err + } + + miniBlockHashes := make([][]byte, 0) + for i := 0; i < len(hdr.MiniBlockHeaders); i++ { + miniBlockHashes = append(miniBlockHashes, hdr.MiniBlockHeaders[i].Hash) + } + + miniBlocks, err := boot.store.GetAll(dataRetriever.MiniBlockUnit, miniBlockHashes) + if err != nil { + return err + } + + for miniBlockHash, miniBlockBuff := range miniBlocks { + miniBlock := block.MiniBlock{} + err = boot.marshalizer.Unmarshal(&miniBlock, miniBlockBuff) + if err != nil { + return err + } + + for _, txHash := range miniBlock.TxHashes { + err = txStore.Remove(txHash) + if err != nil { + return err + } + } + + err = blockBodyStore.Remove([]byte(miniBlockHash)) + if err != nil { + return err + } + } + + return nil +} + +func (boot *ShardBootstrap) applyNotarizedBlock( + nonce uint64, + notarizedHdrNonceHashDataUnit dataRetriever.UnitType, +) error { nonceToByteSlice := boot.uint64Converter.ToByteSlice(nonce) headerHash, err := boot.store.Get(notarizedHdrNonceHashDataUnit, nonceToByteSlice) if err != nil { @@ -172,6 +244,12 @@ func (boot *ShardBootstrap) applyNotarizedBlock(nonce uint64, notarizedHdrNonceH return err } + log.Info(fmt.Sprintf("apply notarized block with nonce %d and round %d\n", header.Nonce, header.Round)) + + if header.GetRound() > boot.boostrapRoundIndex { + return ErrHigherBootstrapRound + } + boot.blkExecutor.SetLastNotarizedHdr(sharding.MetachainShardId, header) return nil } @@ -419,7 +497,7 @@ func (boot *ShardBootstrap) requestHeader(nonce uint64) { // getHeaderWithNonce method gets the header with given nonce from pool, if it exist there, // and if not it will be requested from network func (boot *ShardBootstrap) getHeaderRequestingIfMissing(nonce uint64) (*block.Header, error) { - hdr, err := boot.getHeaderWithNonce(nonce) + hdr, err := boot.getHeaderFromPoolWithNonce(nonce) if err != nil { process.EmptyChannel(boot.chRcvHdr) boot.requestHeader(nonce) @@ -428,7 +506,7 @@ func (boot *ShardBootstrap) getHeaderRequestingIfMissing(nonce uint64) (*block.H return nil, err } - hdr, err = boot.getHeaderWithNonce(nonce) + hdr, err = boot.getHeaderFromPoolWithNonce(nonce) if err != nil { return nil, err } diff --git a/process/sync/shardblock_test.go b/process/sync/shardblock_test.go index eba04c5776a..939487717b5 100644 --- a/process/sync/shardblock_test.go +++ b/process/sync/shardblock_test.go @@ -295,6 +295,7 @@ func TestNewShardBootstrap_NilPoolsHolderShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -331,6 +332,7 @@ func TestNewShardBootstrap_PoolsHolderRetNilOnHeadersShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -366,6 +368,7 @@ func TestNewShardBootstrap_PoolsHolderRetNilOnHeadersNoncesShouldErr(t *testing. &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -401,6 +404,7 @@ func TestNewShardBootstrap_PoolsHolderRetNilOnTxBlockBodyShouldErr(t *testing.T) &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -432,6 +436,7 @@ func TestNewShardBootstrap_NilStoreShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -463,6 +468,7 @@ func TestNewShardBootstrap_NilBlockchainShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -494,6 +500,7 @@ func TestNewShardBootstrap_NilRounderShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -525,6 +532,7 @@ func TestNewShardBootstrap_NilBlockProcessorShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -556,6 +564,7 @@ func TestNewShardBootstrap_NilHasherShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -587,6 +596,7 @@ func TestNewShardBootstrap_NilMarshalizerShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -618,6 +628,7 @@ func TestNewShardBootstrap_NilForkDetectorShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -650,6 +661,7 @@ func TestNewShardBootstrap_NilResolversContainerShouldErr(t *testing.T) { nil, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -681,6 +693,7 @@ func TestNewShardBootstrap_NilShardCoordinatorShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, nil, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -712,6 +725,7 @@ func TestNewShardBootstrap_NilAccountsAdapterShouldErr(t *testing.T) { &mock.ResolversFinderStub{}, shardCoordinator, nil, + math.MaxUint32, ) assert.Nil(t, bs) @@ -759,6 +773,7 @@ func TestNewShardBootstrap_NilHeaderResolverShouldErr(t *testing.T) { resFinder, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -806,6 +821,7 @@ func TestNewShardBootstrap_NilTxBlockBodyResolverShouldErr(t *testing.T) { resFinder, shardCoordinator, account, + math.MaxUint32, ) assert.Nil(t, bs) @@ -870,6 +886,7 @@ func TestNewShardBootstrap_OkValsShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) assert.NotNil(t, bs) @@ -935,6 +952,7 @@ func TestBootstrap_SyncBlockShouldCallForkChoice(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) r := bs.SyncBlock() @@ -986,6 +1004,7 @@ func TestBootstrap_ShouldReturnTimeIsOutWhenMissingHeader(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) r := bs.SyncBlock() @@ -1064,6 +1083,7 @@ func TestBootstrap_ShouldReturnTimeIsOutWhenMissingBody(t *testing.T) { createMockResolversFinderNilMiniBlocks(), shardCoordinator, account, + math.MaxUint32, ) bs.RequestHeader(2) @@ -1115,6 +1135,7 @@ func TestBootstrap_ShouldNotNeedToSync(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) bs.StartSync() @@ -1226,6 +1247,7 @@ func TestBootstrap_SyncShouldSyncOneBlock(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) bs.StartSync() @@ -1333,6 +1355,7 @@ func TestBootstrap_ShouldReturnNilErr(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) r := bs.SyncBlock() @@ -1442,6 +1465,7 @@ func TestBootstrap_SyncBlockShouldReturnErrorWhenProcessBlockFailed(t *testing.T createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncBlock() @@ -1481,6 +1505,7 @@ func TestBootstrap_ShouldSyncShouldReturnFalseWhenCurrentBlockIsNilAndRoundIndex createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) assert.False(t, bs.ShouldSync()) @@ -1519,6 +1544,7 @@ func TestBootstrap_ShouldReturnTrueWhenCurrentBlockIsNilAndRoundIndexIsGreaterTh createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) assert.True(t, bs.ShouldSync()) @@ -1562,6 +1588,7 @@ func TestBootstrap_ShouldReturnFalseWhenNodeIsSynced(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) assert.False(t, bs.ShouldSync()) @@ -1605,6 +1632,7 @@ func TestBootstrap_ShouldReturnTrueWhenNodeIsNotSynced(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) assert.True(t, bs.ShouldSync()) @@ -1639,6 +1667,7 @@ func TestBootstrap_GetHeaderFromPoolShouldReturnNil(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) hdr, _ := bs.GetHeaderFromPoolWithNonce(0) @@ -1702,6 +1731,7 @@ func TestBootstrap_GetHeaderFromPoolShouldReturnHeader(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) hdr2, _ := bs.GetHeaderFromPoolWithNonce(0) @@ -1748,6 +1778,7 @@ func TestShardGetBlockFromPoolShouldReturnBlock(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) mbHashes := make([][]byte, 0) @@ -1820,6 +1851,7 @@ func TestBootstrap_ReceivedHeadersFoundInPoolShouldAddToForkDetector(t *testing. createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) bs.ReceivedHeaders(addedHash) @@ -1892,6 +1924,7 @@ func TestBootstrap_ReceivedHeadersNotFoundInPoolButFoundInStorageShouldAddToFork createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) bs.ReceivedHeaders(addedHash) @@ -1927,6 +1960,7 @@ func TestBootstrap_ForkChoiceNilBlockchainHeaderShouldErr(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ForkChoice() @@ -1959,6 +1993,7 @@ func TestBootstrap_ForkChoiceNilParamHeaderShouldErr(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) blkc.GetCurrentBlockHeaderCalled = func() data.HeaderHandler { @@ -2006,6 +2041,7 @@ func TestBootstrap_ForkChoiceIsNotEmptyShouldErr(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) blkc.GetCurrentBlockHeaderCalled = func() data.HeaderHandler { @@ -2127,6 +2163,7 @@ func TestBootstrap_ForkChoiceIsEmptyCallRollBackOkValsShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) bs.SetForkNonce(currentHdrNonce) @@ -2282,6 +2319,7 @@ func TestBootstrap_ForkChoiceIsEmptyCallRollBackToGenesisShouldWork(t *testing.T createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) bs.SetForkNonce(currentHdrNonce) @@ -2374,6 +2412,7 @@ func TestBootstrap_GetTxBodyHavingHashReturnsFromCacherShouldWork(t *testing.T) createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) txBlockRecovered := bs.GetMiniBlocks(requestedHash) @@ -2423,6 +2462,7 @@ func TestBootstrap_GetTxBodyHavingHashNotFoundInCacherOrStorageShouldRetNil(t *t createMockResolversFinderNilMiniBlocks(), shardCoordinator, account, + math.MaxUint32, ) txBlockRecovered := bs.GetMiniBlocks(requestedHash) @@ -2479,6 +2519,7 @@ func TestBootstrap_GetTxBodyHavingHashFoundInStorageShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) txBlockRecovered := bs.GetMiniBlocks(requestedHash) @@ -2511,6 +2552,7 @@ func TestBootstrap_AddSyncStateListenerShouldAppendAnotherListener(t *testing.T) createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) f1 := func(bool) {} @@ -2551,6 +2593,7 @@ func TestBootstrap_NotifySyncStateListenersShouldNotify(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) mutex.RLock() @@ -2645,6 +2688,7 @@ func TestBootstrap_LoadBlocksShouldErrBoostrapFromStorage(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadBlocks(process.ShardBlockFinality, @@ -2652,9 +2696,10 @@ func TestBootstrap_LoadBlocksShouldErrBoostrapFromStorage(t *testing.T) { dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId()), getHeaderFromStorage, getBlockBody, + removeBlockBody, ) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_LoadBlocksShouldErrBoostrapFromStorageWhenBlocksAreNotValid(t *testing.T) { @@ -2717,6 +2762,7 @@ func TestBootstrap_LoadBlocksShouldErrBoostrapFromStorageWhenBlocksAreNotValid(t createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadBlocks(process.ShardBlockFinality, @@ -2726,9 +2772,10 @@ func TestBootstrap_LoadBlocksShouldErrBoostrapFromStorageWhenBlocksAreNotValid(t return nil, nil, errors.New("header not found") }, getBlockBody, + removeBlockBody, ) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_LoadBlocksShouldErrWhenRecreateTrieFail(t *testing.T) { @@ -2749,9 +2796,6 @@ func TestBootstrap_LoadBlocksShouldErrWhenRecreateTrieFail(t *testing.T) { hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -2807,6 +2851,7 @@ func TestBootstrap_LoadBlocksShouldErrWhenRecreateTrieFail(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadBlocks(process.ShardBlockFinality, @@ -2814,10 +2859,11 @@ func TestBootstrap_LoadBlocksShouldErrWhenRecreateTrieFail(t *testing.T) { dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId()), getHeaderFromStorage, getBlockBody, + removeBlockBody, ) assert.True(t, wasCalled) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_LoadBlocksShouldWorkAfterRemoveInvalidBlocks(t *testing.T) { @@ -2837,8 +2883,7 @@ func TestBootstrap_LoadBlocksShouldWorkAfterRemoveInvalidBlocks(t *testing.T) { hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true + hnc.RemoveCalled = func(u uint64) { } return hnc @@ -2896,6 +2941,7 @@ func TestBootstrap_LoadBlocksShouldWorkAfterRemoveInvalidBlocks(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadBlocks(process.ShardBlockFinality, @@ -2908,6 +2954,7 @@ func TestBootstrap_LoadBlocksShouldWorkAfterRemoveInvalidBlocks(t *testing.T) { return &block.Header{Nonce: 1}, []byte("hash"), nil }, getBlockBody, + removeBlockBody, ) assert.Nil(t, err) @@ -2963,6 +3010,7 @@ func TestBootstrap_ApplyBlockShouldErrWhenHeaderIsNotFound(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) errExpected := errors.New("header not found") @@ -2975,7 +3023,7 @@ func TestBootstrap_ApplyBlockShouldErrWhenHeaderIsNotFound(t *testing.T) { assert.Equal(t, errExpected, err) } -func TestBootstrap_ApplyBlockShouldErrWhenBodyIsNotFound(t *testing.T) { +func TestBootstrap_ApplyBlockShouldErrHigherBootstrapRound(t *testing.T) { t.Parallel() pools := &mock.PoolsHolderStub{} @@ -2990,8 +3038,69 @@ func TestBootstrap_ApplyBlockShouldErrWhenBodyIsNotFound(t *testing.T) { hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) {} + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{} + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{ + AddHeaderCalled: func(header data.HeaderHandler, hash []byte, state process.BlockHeaderState) error { + return nil + }, + } + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + 1, + ) + + err := bs.ApplyBlock(1, + getHeaderFromStorage, + getBlockBody, + ) + + assert.Equal(t, sync.ErrHigherBootstrapRound, err) +} + +func TestBootstrap_ApplyBlockShouldErrWhenBodyIsNotFound(t *testing.T) { + t.Parallel() + + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } return hnc @@ -3032,6 +3141,7 @@ func TestBootstrap_ApplyBlockShouldErrWhenBodyIsNotFound(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) errExpected := errors.New("body not found") @@ -3060,9 +3170,6 @@ func TestBootstrap_ApplyBlockShouldErrWhenSetCurrentBlockBodyFails(t *testing.T) hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -3105,6 +3212,7 @@ func TestBootstrap_ApplyBlockShouldErrWhenSetCurrentBlockBodyFails(t *testing.T) createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyBlock(1, @@ -3130,9 +3238,6 @@ func TestBootstrap_ApplyBlockShouldErrWhenSetCurrentBlockHeaderFails(t *testing. hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -3176,6 +3281,7 @@ func TestBootstrap_ApplyBlockShouldErrWhenSetCurrentBlockHeaderFails(t *testing. createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyBlock(1, @@ -3200,9 +3306,6 @@ func TestBootstrap_ApplyBlockShouldWork(t *testing.T) { hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -3242,6 +3345,7 @@ func TestBootstrap_ApplyBlockShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyBlock(1, @@ -3251,7 +3355,147 @@ func TestBootstrap_ApplyBlockShouldWork(t *testing.T) { assert.Nil(t, err) } -func TestBootstrap_RemoveBlockShouldErrWhenHeaderIsNotFound(t *testing.T) { +func TestBootstrap_RemoveBlockHeaderShouldErrNilHeadersStorage(t *testing.T) { + t.Parallel() + + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { + } + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) { + } + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{} + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + store.GetStorerCalled = func(unitType dataRetriever.UnitType) storage.Storer { + if unitType == dataRetriever.BlockHeaderUnit { + return nil + } + if unitType == dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId()) { + return &mock.StorerStub{} + } + + return nil + } + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + math.MaxUint32, + ) + + err := bs.RemoveBlockHeader(1, + dataRetriever.BlockHeaderUnit, + dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) + + assert.Equal(t, process.ErrNilHeadersStorage, err) +} + +func TestBootstrap_RemoveBlockHeaderShouldErrNilHeadersNonceHashStorage(t *testing.T) { + t.Parallel() + + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { + } + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) { + } + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{} + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + store.GetStorerCalled = func(unitType dataRetriever.UnitType) storage.Storer { + if unitType == dataRetriever.BlockHeaderUnit { + return &mock.StorerStub{} + } + if unitType == dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId()) { + return nil + } + + return nil + } + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + math.MaxUint32, + ) + + err := bs.RemoveBlockHeader(1, + dataRetriever.BlockHeaderUnit, + dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) + + assert.Equal(t, process.ErrNilHeadersNonceHashStorage, err) +} + +func TestBootstrap_RemoveBlockHeaderShouldErrWhenHeaderIsNotFound(t *testing.T) { t.Parallel() errExpected := errors.New("key not found") @@ -3305,16 +3549,17 @@ func TestBootstrap_RemoveBlockShouldErrWhenHeaderIsNotFound(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) - err := bs.RemoveBlock(1, + err := bs.RemoveBlockHeader(1, dataRetriever.BlockHeaderUnit, dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) assert.Equal(t, errExpected, err) } -func TestBootstrap_RemoveBlockShouldErrWhenRemoveHeaderHashFails(t *testing.T) { +func TestBootstrap_RemoveBlockHeaderShouldErrWhenRemoveHeaderHashFails(t *testing.T) { t.Parallel() errExpected := errors.New("remove header hash failed") @@ -3383,16 +3628,17 @@ func TestBootstrap_RemoveBlockShouldErrWhenRemoveHeaderHashFails(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) - err := bs.RemoveBlock(1, + err := bs.RemoveBlockHeader(1, dataRetriever.BlockHeaderUnit, dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) assert.Equal(t, errExpected, err) } -func TestBootstrap_RemoveBlockShouldErrWhenRemoveHeaderNonceFails(t *testing.T) { +func TestBootstrap_RemoveBlockHeaderShouldErrWhenRemoveHeaderNonceFails(t *testing.T) { t.Parallel() errExpected := errors.New("remove header nonce failed") @@ -3461,16 +3707,17 @@ func TestBootstrap_RemoveBlockShouldErrWhenRemoveHeaderNonceFails(t *testing.T) createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) - err := bs.RemoveBlock(1, + err := bs.RemoveBlockHeader(1, dataRetriever.BlockHeaderUnit, dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) assert.Equal(t, errExpected, err) } -func TestBootstrap_RemoveBlockShouldWork(t *testing.T) { +func TestBootstrap_RemoveBlockHeaderShouldWork(t *testing.T) { t.Parallel() pools := &mock.PoolsHolderStub{} @@ -3485,6 +3732,8 @@ func TestBootstrap_RemoveBlockShouldWork(t *testing.T) { hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } + hnc.RemoveCalled = func(u uint64) { + } return hnc } @@ -3520,9 +3769,10 @@ func TestBootstrap_RemoveBlockShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) - err := bs.RemoveBlock(1, + err := bs.RemoveBlockHeader(1, dataRetriever.BlockHeaderUnit, dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) @@ -3582,6 +3832,7 @@ func TestBootstrap_LoadNotarizedBlocksShouldErrBoostrapFromStorage(t *testing.T) createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadNotarizedBlocks(process.ShardBlockFinality, @@ -3589,7 +3840,7 @@ func TestBootstrap_LoadNotarizedBlocksShouldErrBoostrapFromStorage(t *testing.T) applyNotarisedBlock, ) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_LoadNotarizedBlocksShouldErrBoostrapFromStorageWhenBlocksAreNotValid(t *testing.T) { @@ -3652,6 +3903,7 @@ func TestBootstrap_LoadNotarizedBlocksShouldErrBoostrapFromStorageWhenBlocksAreN createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadNotarizedBlocks(process.ShardBlockFinality, @@ -3661,7 +3913,7 @@ func TestBootstrap_LoadNotarizedBlocksShouldErrBoostrapFromStorageWhenBlocksAreN }, ) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_LoadNotarizedBlocksShouldWorkAfterRemoveInvalidBlocks(t *testing.T) { @@ -3681,9 +3933,6 @@ func TestBootstrap_LoadNotarizedBlocksShouldWorkAfterRemoveInvalidBlocks(t *test hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -3736,6 +3985,7 @@ func TestBootstrap_LoadNotarizedBlocksShouldWorkAfterRemoveInvalidBlocks(t *test createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.LoadNotarizedBlocks(process.ShardBlockFinality, @@ -3805,6 +4055,7 @@ func TestBootstrap_SyncFromStorerShouldErrWhenLoadBlocksFails(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncFromStorer(process.ShardBlockFinality, @@ -3813,7 +4064,7 @@ func TestBootstrap_SyncFromStorerShouldErrWhenLoadBlocksFails(t *testing.T) { process.MetaBlockFinality, dataRetriever.MetaHdrNonceHashDataUnit) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *testing.T) { @@ -3833,9 +4084,6 @@ func TestBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *testin hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -3905,6 +4153,7 @@ func TestBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *testin createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncFromStorer(process.ShardBlockFinality, @@ -3913,7 +4162,7 @@ func TestBootstrap_SyncFromStorerShouldErrWhenLoadNotarizedBlocksFails(t *testin process.MetaBlockFinality, dataRetriever.MetaHdrNonceHashDataUnit) - assert.Equal(t, process.ErrBoostrapFromStorage, err) + assert.Equal(t, process.ErrNotEnoughValidBlocksInStorage, err) } func TestBootstrap_SyncFromStorerShouldWork(t *testing.T) { @@ -3933,9 +4182,6 @@ func TestBootstrap_SyncFromStorerShouldWork(t *testing.T) { hnc := &mock.Uint64CacherStub{} hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { } - hnc.PutCalled = func(u uint64, i interface{}) bool { - return true - } return hnc } @@ -4017,6 +4263,7 @@ func TestBootstrap_SyncFromStorerShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.SyncFromStorer(process.ShardBlockFinality, @@ -4086,6 +4333,7 @@ func TestBootstrap_ApplyNotarizedBlockShouldErrWhenHeaderIsNotFound(t *testing.T createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyNotarizedBlock(1, @@ -4155,6 +4403,7 @@ func TestBootstrap_ApplyNotarizedBlockShouldErrWhenGetMetaHeaderFromStorageFails createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyNotarizedBlock(1, @@ -4163,6 +4412,80 @@ func TestBootstrap_ApplyNotarizedBlockShouldErrWhenGetMetaHeaderFromStorageFails assert.Equal(t, process.ErrMissingHeader, err) } +func TestBootstrap_ApplyNotarizedBlockShouldErrHigherBootstrapRound(t *testing.T) { + t.Parallel() + + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { + } + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) { + } + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{ + SetLastNotarizedHdrCalled: func(shardId uint32, processedHdr data.HeaderHandler) { + }, + } + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + store.GetStorerCalled = func(unitType dataRetriever.UnitType) storage.Storer { + if unitType == dataRetriever.MetaBlockUnit { + return &mock.StorerStub{ + GetCalled: func(key []byte) ([]byte, error) { + buff, _ := marshalizer.Marshal(&block.Header{Round: 2}) + return buff, nil + }, + } + } + + return nil + } + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + 1, + ) + + err := bs.ApplyNotarizedBlock(1, + dataRetriever.MetaHdrNonceHashDataUnit) + + assert.Equal(t, sync.ErrHigherBootstrapRound, err) +} + func TestBootstrap_ApplyNotarizedBlockShouldWork(t *testing.T) { t.Parallel() @@ -4228,6 +4551,7 @@ func TestBootstrap_ApplyNotarizedBlockShouldWork(t *testing.T) { createMockResolversFinder(), shardCoordinator, account, + math.MaxUint32, ) err := bs.ApplyNotarizedBlock(1, @@ -4236,8 +4560,202 @@ func TestBootstrap_ApplyNotarizedBlockShouldWork(t *testing.T) { assert.Nil(t, err) } +func TestBootstrap_RemoveNotarizedBlockShouldErrNilHeadersNonceHashStorage(t *testing.T) { + t.Parallel() + + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { + } + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) { + } + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{} + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + store.GetStorerCalled = func(unitType dataRetriever.UnitType) storage.Storer { + return nil + } + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + math.MaxUint32, + ) + + err := bs.RemoveNotarizedBlockHeader(1, + dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) + + assert.Equal(t, process.ErrNilHeadersNonceHashStorage, err) +} + +func TestBootstrap_RemoveNotarizedBlockShouldErrWhenRemoveHeaderNonceFails(t *testing.T) { + t.Parallel() + + errExpected := errors.New("remove header nonce failed") + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { + } + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) { + } + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{} + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + store.GetStorerCalled = func(unitType dataRetriever.UnitType) storage.Storer { + if unitType == dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId()) { + return &mock.StorerStub{ + RemoveCalled: func(key []byte) error { + return errExpected + }, + } + } + + return nil + } + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + math.MaxUint32, + ) + + err := bs.RemoveNotarizedBlockHeader(1, + dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) + + assert.Equal(t, errExpected, err) +} + +func TestBootstrap_RemoveNotarizedBlockShouldWork(t *testing.T) { + t.Parallel() + + pools := &mock.PoolsHolderStub{} + pools.HeadersCalled = func() storage.Cacher { + sds := &mock.CacherStub{} + sds.RegisterHandlerCalled = func(func(key []byte)) { + } + + return sds + } + pools.HeadersNoncesCalled = func() dataRetriever.Uint64Cacher { + hnc := &mock.Uint64CacherStub{} + hnc.RegisterHandlerCalled = func(handler func(nonce uint64)) { + } + hnc.RemoveCalled = func(u uint64) { + } + + return hnc + } + pools.MiniBlocksCalled = func() storage.Cacher { + cs := &mock.CacherStub{} + cs.RegisterHandlerCalled = func(i func(key []byte)) { + } + + return cs + } + + blkc := initBlockchain() + rnd := &mock.RounderMock{} + blkExec := &mock.BlockProcessorMock{} + hasher := &mock.HasherMock{} + marshalizer := &mock.MarshalizerMock{} + forkDetector := &mock.ForkDetectorMock{} + shardCoordinator := mock.NewOneShardCoordinatorMock() + account := &mock.AccountsStub{} + + store := createStore() + + bs, _ := sync.NewShardBootstrap( + pools, + store, + blkc, + rnd, + blkExec, + waitTime, + hasher, + marshalizer, + forkDetector, + createMockResolversFinder(), + shardCoordinator, + account, + math.MaxUint32, + ) + + err := bs.RemoveNotarizedBlockHeader(1, + dataRetriever.ShardHdrNonceHashDataUnit+dataRetriever.UnitType(shardCoordinator.SelfId())) + + assert.Nil(t, err) +} + func getHeaderFromStorage(nonce uint64) (data.HeaderHandler, []byte, error) { - return &block.Header{Nonce: nonce}, []byte("hash"), nil + return &block.Header{Nonce: nonce, Round: 2}, []byte("hash"), nil } func getBlockBody(header data.HeaderHandler) (data.BodyHandler, error) { @@ -4252,3 +4770,15 @@ func applyNotarisedBlock(nonce uint64, unitType dataRetriever.UnitType) error { fmt.Printf("apply block with nonce %d in unit type %d", nonce, unitType) return nil } + +func removeBlockBody( + nonce uint64, + hdrNonceHashDataUnit dataRetriever.UnitType, + blockUnit dataRetriever.UnitType, +) error { + fmt.Printf("remove block body with nonce %d with hdr nonce hash data unit type %d and block unit type %d", + nonce, + hdrNonceHashDataUnit, + blockUnit) + return nil +}