Exemple #1
0
        public async Task PruneRepository_PruneAndCompact_FromGenesis_OnStartUpAsync()
        {
            var posBlocks        = CreatePosBlocks(50);
            var chainedHeaderTip = BuildProvenHeaderChainFromBlocks(posBlocks);

            var dataFolderPath = CreateTestDir(this);
            var dataFolder     = new DataFolder(dataFolderPath);

            var dBreezeSerializer = new DBreezeSerializer(this.Network);

            var blockRepository = new BlockRepository(this.Network, dataFolder, this.LoggerFactory.Object, dBreezeSerializer);
            await blockRepository.PutAsync(new HashHeightPair(posBlocks.Last().GetHash(), 50), posBlocks);

            var storeSettings = new StoreSettings(NodeSettings.Default(this.Network))
            {
                AmountOfBlocksToKeep = 10
            };

            var prunedBlockRepository = new PrunedBlockRepository(blockRepository, dBreezeSerializer, this.LoggerFactory.Object, storeSettings);
            await prunedBlockRepository.InitializeAsync();

            await prunedBlockRepository.PruneAndCompactDatabase(chainedHeaderTip.GetAncestor(50), this.Network, true);

            // The first prune will delete blocks from 40 to 0.
            Assert.Equal(chainedHeaderTip.GetAncestor(40).HashBlock, prunedBlockRepository.PrunedTip.Hash);
            Assert.Equal(chainedHeaderTip.GetAncestor(40).Height, prunedBlockRepository.PrunedTip.Height);
            // Ensure that the block has been deleted from disk.
            Assert.Null(await blockRepository.GetBlockAsync(chainedHeaderTip.GetAncestor(39).HashBlock));
        }
Exemple #2
0
        public void DownloadBlocks_CanBreakExecutionOnStallCountReached()
        {
            // Create 3 blocks
            List <Block> blocks = CreateBlocks(3);

            // The repository has 3 blocks stored
            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\DownloadBlocks_EnsureNextChainedBlockIsAskedForOnStartUp")))
            {
                blockRepository.PutAsync(blocks.Last().GetHash(), blocks.Take(3).ToList()).GetAwaiter().GetResult();

                // The chain has 3 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(2));

                // Create block store loop
                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\DownloadBlocks_EnsureNextChainedBlockIsAskedForOnStartUp");

                //Start finding blocks from Block[1]
                var nextChainedBlock = blockStoreLoop.Chain.GetBlock(blocks[1].GetHash());

                // Create Task Context
                var context = new BlockStoreInnerStepContext(new CancellationToken(), blockStoreLoop).Initialize(nextChainedBlock);
                context.StallCount = 10001;

                var task   = new BlockStoreInnerStepDownloadBlocks();
                var result = task.ExecuteAsync(context).GetAwaiter().GetResult();

                Assert.True(result.ShouldBreak);
            }
        }
Exemple #3
0
        public async Task PruneRepository_PruneAndCompact_OnShutDownAsync()
        {
            var posBlocks        = CreatePosBlocks(50);
            var chainedHeaderTip = BuildProvenHeaderChainFromBlocks(posBlocks);

            var dataFolderPath = CreateTestDir(this);
            var dataFolder     = new DataFolder(dataFolderPath);

            var dBreezeSerializer = new DBreezeSerializer(this.Network);

            var blockRepository = new BlockRepository(this.Network, dataFolder, this.LoggerFactory.Object, dBreezeSerializer);
            await blockRepository.PutAsync(new HashHeightPair(posBlocks.Last().GetHash(), 50), posBlocks);

            var storeSettings = new StoreSettings(NodeSettings.Default(this.Network))
            {
                AmountOfBlocksToKeep = 10
            };

            var prunedBlockRepository = new PrunedBlockRepository(blockRepository, dBreezeSerializer, this.LoggerFactory.Object, storeSettings);
            await prunedBlockRepository.InitializeAsync();

            // Delete blocks 30 to 0 from the repo, this would have been done by the service before shutdown was initiated.
            await blockRepository.DeleteBlocksAsync(posBlocks.Take(30).Select(b => b.GetHash()).ToList());

            prunedBlockRepository.UpdatePrunedTip(chainedHeaderTip.GetAncestor(30));
            // Ensure that the block has been deleted from disk.
            Assert.Null(await blockRepository.GetBlockAsync(chainedHeaderTip.GetAncestor(29).HashBlock));

            // On shutdown the database will only be compacted.
            await prunedBlockRepository.PruneAndCompactDatabase(chainedHeaderTip.GetAncestor(50), this.Network, false);

            Assert.Equal(chainedHeaderTip.GetAncestor(30).HashBlock, prunedBlockRepository.PrunedTip.Hash);
            Assert.Equal(chainedHeaderTip.GetAncestor(30).Height, prunedBlockRepository.PrunedTip.Height);
            Assert.Null(await blockRepository.GetBlockAsync(chainedHeaderTip.GetAncestor(29).HashBlock));
        }
        public void CanExecute_TryPending()
        {
            // Create 15 blocks
            var blocks = CreateBlocks(15);

            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\CanExecute_TryPending")))
            {
                // Push 5 blocks to the repository
                blockRepository.PutAsync(blocks.Take(5).Last().GetHash(), blocks.Take(5).ToList()).GetAwaiter().GetResult();

                // The chain has 10 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(9));

                // Create block store loop
                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\CanExecute_TryPending");

                // Add chained blocks 5 - 9 to PendingStorage
                AddToPendingStorage(blockStoreLoop, blocks[5]);
                AddToPendingStorage(blockStoreLoop, blocks[6]);
                AddToPendingStorage(blockStoreLoop, blocks[7]);
                AddToPendingStorage(blockStoreLoop, blocks[8]);
                AddToPendingStorage(blockStoreLoop, blocks[9]);

                //Start processing pending blocks from block 5
                var nextChainedBlock = blockStoreLoop.Chain.GetBlock(blocks[5].GetHash());

                var processPendingStorageStep = new ProcessPendingStorageStep(blockStoreLoop);
                processPendingStorageStep.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult();

                Assert.Equal(blocks[9].GetHash(), blockStoreLoop.BlockRepository.BlockHash);
                Assert.Equal(blocks[9].GetHash(), blockStoreLoop.StoreTip.HashBlock);
            }
        }
        public void CanExecute_CheckNextChainedBlockExistStep()
        {
            var blocks = CreateBlocks(5);

            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\CanExecute_CheckNextChainedBlockExistStep")))
            {
                // Push 5 blocks to the repository
                blockRepository.PutAsync(blocks.Last().GetHash(), blocks).GetAwaiter().GetResult();

                // The chain has 4 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(3));

                // Create the last chained block without appending to the chain
                var block03 = chain.GetBlock(blocks[3].GetHash());
                var block04 = new ChainedBlock(blocks[4].Header, blocks[4].Header.GetHash(), block03);

                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\CanExecute_CheckNextChainedBlockExistStep");
                Assert.Null(blockStoreLoop.StoreTip);

                var nextChainedBlock = block04;
                var checkExistsStep  = new CheckNextChainedBlockExistStep(blockStoreLoop);
                checkExistsStep.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult();

                Assert.Equal(blockStoreLoop.StoreTip.Header.GetHash(), block04.Header.GetHash());
                Assert.Equal(blockStoreLoop.BlockRepository.BlockHash, block04.Header.GetHash());
            }
        }
        private void BlockRepositoryBench()
        {
            using (var dir = TestDirectory.Create())
            {
                using (var blockRepo = new BlockRepository(Network.Main, dir.FolderName, DateTimeProvider.Default, this.loggerFactory))
                {
                    var lst = new List <Block>();
                    for (int i = 0; i < 30; i++)
                    {
                        // roughly 1mb blocks
                        var block = new Block();
                        for (int j = 0; j < 3000; j++)
                        {
                            var trx = new Transaction();
                            block.AddTransaction(new Transaction());
                            trx.AddInput(new TxIn(Script.Empty));
                            trx.AddOutput(Money.COIN + j + i, new Script(Guid.NewGuid().ToByteArray()
                                                                         .Concat(Guid.NewGuid().ToByteArray())
                                                                         .Concat(Guid.NewGuid().ToByteArray())
                                                                         .Concat(Guid.NewGuid().ToByteArray())
                                                                         .Concat(Guid.NewGuid().ToByteArray())
                                                                         .Concat(Guid.NewGuid().ToByteArray())));
                            trx.AddInput(new TxIn(Script.Empty));
                            trx.AddOutput(Money.COIN + j + i + 1, new Script(Guid.NewGuid().ToByteArray()
                                                                             .Concat(Guid.NewGuid().ToByteArray())
                                                                             .Concat(Guid.NewGuid().ToByteArray())
                                                                             .Concat(Guid.NewGuid().ToByteArray())
                                                                             .Concat(Guid.NewGuid().ToByteArray())
                                                                             .Concat(Guid.NewGuid().ToByteArray())));
                            block.AddTransaction(trx);
                        }
                        block.UpdateMerkleRoot();
                        block.Header.HashPrevBlock = lst.Any() ? lst.Last().GetHash() : Network.Main.GenesisHash;
                        lst.Add(block);
                    }

                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();
                    blockRepo.PutAsync(lst.Last().GetHash(), lst).GetAwaiter().GetResult();
                    var first = stopwatch.ElapsedMilliseconds;
                    blockRepo.PutAsync(lst.Last().GetHash(), lst).GetAwaiter().GetResult();
                    var second = stopwatch.ElapsedMilliseconds;
                }
            }
        }
Exemple #7
0
        public void FindBlocks_CanFind()
        {
            // Create 10 blocks
            List <Block> blocks = CreateBlocks(10);

            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\FindBlocks_CanFind")))
            {
                // Push 5 blocks to the repository
                blockRepository.PutAsync(blocks.Take(5).Last().GetHash(), blocks.Take(5).ToList()).GetAwaiter().GetResult();

                // The chain has 10 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(9));

                // Create block store loop
                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\FindBlocks_CanFind");

                // Push blocks 5 - 9 to the downloaded blocks collection
                blockStoreLoop.BlockPuller.InjectBlock(blocks[5].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[5].GetSerializedSize(), Block = blocks[5]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[6].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[6].GetSerializedSize(), Block = blocks[6]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[7].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[7].GetSerializedSize(), Block = blocks[7]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[8].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[8].GetSerializedSize(), Block = blocks[8]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[9].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[9].GetSerializedSize(), Block = blocks[9]
                }, new CancellationToken());

                //Start processing blocks to download from block 5
                var nextChainedBlock = blockStoreLoop.Chain.GetBlock(blocks[5].GetHash());

                // Create Task Context
                var context = new BlockStoreInnerStepContext(new CancellationToken(), blockStoreLoop).Initialize(nextChainedBlock);

                var task = new BlockStoreInnerStepFindBlocks();
                task.ExecuteAsync(context).GetAwaiter().GetResult();

                //Block[5] and Block[6] in the DownloadStack
                Assert.Equal(2, context.DownloadStack.Count());
                Assert.True(context.DownloadStack.Any(cb => cb.HashBlock == blocks[5].GetHash()));
                Assert.True(context.DownloadStack.Any(cb => cb.HashBlock == blocks[6].GetHash()));
            }
        }
Exemple #8
0
        public void DownloadBlocks_Integration()
        {
            // Create 10 blocks
            var blocks = CreateBlocks(10);

            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\DownloadBlocks_Integration")))
            {
                // Push 5 blocks to the repository
                blockRepository.PutAsync(blocks.Take(5).Last().GetHash(), blocks.Take(5).ToList()).GetAwaiter().GetResult();

                // The chain has 10 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(9));

                // Create block store loop
                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\DownloadBlocks_Integration");

                // Push blocks 5 - 9 to the downloaded blocks collection
                blockStoreLoop.BlockPuller.InjectBlock(blocks[5].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[5].GetSerializedSize(), Block = blocks[5]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[6].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[6].GetSerializedSize(), Block = blocks[6]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[7].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[7].GetSerializedSize(), Block = blocks[7]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[8].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[8].GetSerializedSize(), Block = blocks[8]
                }, new CancellationToken());
                blockStoreLoop.BlockPuller.InjectBlock(blocks[9].GetHash(), new DownloadedBlock()
                {
                    Length = blocks[9].GetSerializedSize(), Block = blocks[9]
                }, new CancellationToken());

                // Start processing blocks to download from block 5
                var nextChainedBlock = blockStoreLoop.Chain.GetBlock(blocks[5].GetHash());

                var step = new DownloadBlockStep(blockStoreLoop);
                step.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult();

                Assert.Equal(blocks[9].GetHash(), blockStoreLoop.BlockRepository.BlockHash);
                Assert.Equal(blocks[9].GetHash(), blockStoreLoop.StoreTip.HashBlock);
            }
        }
        public void BlockRepositoryPutBatch()
        {
            using (var dir = TestDirectory.Create())
            {
                using (var blockRepo = new BlockRepository(Network.Main, dir.FolderName, DateTimeProvider.Default, this.loggerFactory))
                {
                    blockRepo.SetTxIndexAsync(true).Wait();

                    var lst = new List <Block>();
                    for (int i = 0; i < 5; i++)
                    {
                        // put
                        var block = new Block();
                        block.AddTransaction(new Transaction());
                        block.AddTransaction(new Transaction());
                        block.Transactions[0].AddInput(new TxIn(Script.Empty));
                        block.Transactions[0].AddOutput(Money.COIN + i * 2, Script.Empty);
                        block.Transactions[1].AddInput(new TxIn(Script.Empty));
                        block.Transactions[1].AddOutput(Money.COIN + i * 2 + 1, Script.Empty);
                        block.UpdateMerkleRoot();
                        block.Header.HashPrevBlock = lst.Any() ? lst.Last().GetHash() : Network.Main.GenesisHash;
                        lst.Add(block);
                    }

                    blockRepo.PutAsync(lst.Last().GetHash(), lst).GetAwaiter().GetResult();

                    // check each block
                    foreach (var block in lst)
                    {
                        var received = blockRepo.GetAsync(block.GetHash()).GetAwaiter().GetResult();
                        Assert.True(block.ToBytes().SequenceEqual(received.ToBytes()));

                        foreach (var transaction in block.Transactions)
                        {
                            var trx = blockRepo.GetTrxAsync(transaction.GetHash()).GetAwaiter().GetResult();
                            Assert.True(trx.ToBytes().SequenceEqual(transaction.ToBytes()));
                        }
                    }

                    // delete
                    blockRepo.DeleteAsync(lst.ElementAt(2).GetHash(), new[] { lst.ElementAt(2).GetHash() }.ToList()).GetAwaiter().GetResult();
                    var deleted = blockRepo.GetAsync(lst.ElementAt(2).GetHash()).GetAwaiter().GetResult();
                    Assert.Null(deleted);
                }
            }
        }
Exemple #10
0
        public void BlockRepositoryPutBatch()
        {
            using (var blockRepository = new BlockRepository(this.network, TestBase.CreateDataFolder(this), DateTimeProvider.Default, this.loggerFactory))
            {
                blockRepository.SetTxIndexAsync(true).Wait();

                var blocks = new List <Block>();
                for (int i = 0; i < 5; i++)
                {
                    Block block = this.network.CreateBlock();
                    block.AddTransaction(this.network.CreateTransaction());
                    block.AddTransaction(this.network.CreateTransaction());
                    block.Transactions[0].AddInput(new TxIn(Script.Empty));
                    block.Transactions[0].AddOutput(Money.COIN + i * 2, Script.Empty);
                    block.Transactions[1].AddInput(new TxIn(Script.Empty));
                    block.Transactions[1].AddOutput(Money.COIN + i * 2 + 1, Script.Empty);
                    block.UpdateMerkleRoot();
                    block.Header.HashPrevBlock = blocks.Any() ? blocks.Last().GetHash() : this.network.GenesisHash;
                    blocks.Add(block);
                }

                // put
                blockRepository.PutAsync(blocks.Last().GetHash(), blocks).GetAwaiter().GetResult();

                // check the presence of each block in the repository
                foreach (Block block in blocks)
                {
                    Block received = blockRepository.GetAsync(block.GetHash()).GetAwaiter().GetResult();
                    Assert.True(block.ToBytes().SequenceEqual(received.ToBytes()));

                    foreach (Transaction transaction in block.Transactions)
                    {
                        Transaction trx = blockRepository.GetTrxAsync(transaction.GetHash()).GetAwaiter().GetResult();
                        Assert.True(trx.ToBytes().SequenceEqual(transaction.ToBytes()));
                    }
                }

                // delete
                blockRepository.DeleteAsync(blocks.ElementAt(2).GetHash(), new[] { blocks.ElementAt(2).GetHash() }.ToList()).GetAwaiter().GetResult();
                Block deleted = blockRepository.GetAsync(blocks.ElementAt(2).GetHash()).GetAwaiter().GetResult();
                Assert.Null(deleted);
            }
        }
Exemple #11
0
        public void FindBlocks_CanRemoveTaskFromRoutine_BlockExistsInPendingStorage()
        {
            // Create 3 blocks
            List <Block> blocks = CreateBlocks(3);

            // The repository has 3 blocks stored
            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\FindBlocks_CanRemoveTaskFromRoutine_BlockExistsInPendingStorage")))
            {
                blockRepository.PutAsync(blocks.Last().GetHash(), blocks).GetAwaiter().GetResult();

                // The chain has 3 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(2));

                // Create block store loop
                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\FindBlocks_CanRemoveTaskFromRoutine_BlockExistsInPendingStorage");

                //Start finding blocks from Block[1]
                var nextChainedBlock = blockStoreLoop.Chain.GetBlock(blocks[1].GetHash());

                //Add nextChainedBlock to Pending Storage
                blockStoreLoop.PendingStorage.TryAdd(blocks[2].GetHash(), new BlockPair(blocks[2], nextChainedBlock));

                // Create Task Context
                var context = new BlockStoreInnerStepContext(new CancellationToken(), blockStoreLoop).Initialize(nextChainedBlock);

                var task = new BlockStoreInnerStepFindBlocks();
                task.ExecuteAsync(context).GetAwaiter().GetResult();

                //DownloadStack should only contain nextChainedBlock
                Assert.Equal(1, context.DownloadStack.Count());
                Assert.True(context.DownloadStack.Any(cb => cb.HashBlock == nextChainedBlock.HashBlock));

                //The FindBlocks() task should be removed from the routine
                //as the next chained block exists in PendingStorage
                Assert.Equal(1, context.Routine.Count());
                Assert.False(context.Routine.OfType <BlockStoreInnerStepFindBlocks>().Any());
            }
        }
Exemple #12
0
        public void FindBlocks_CanRemoveTaskFromRoutine_BatchDownloadSizeReached()
        {
            // Create 3 blocks
            List <Block> blocks = CreateBlocks(3);

            // The repository has 3 blocks stored
            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\FindBlocks_CanRemoveTaskFromRoutine_BatchDownloadSizeReached")))
            {
                blockRepository.PutAsync(blocks.Last().GetHash(), blocks.Take(2).ToList()).GetAwaiter().GetResult();

                // The chain has 2 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(2).ToList());

                // Create block store loop
                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\FindBlocks_CanRemoveTaskFromRoutine_BatchDownloadSizeReached");
                blockStoreLoop.BatchDownloadSize = 2;

                //Start finding blocks from Block[1]
                var nextChainedBlock = blockStoreLoop.Chain.GetBlock(blocks[1].GetHash());

                // Create Task Context
                var context = new BlockStoreInnerStepContext(new CancellationToken(), blockStoreLoop).Initialize(nextChainedBlock);

                var task = new BlockStoreInnerStepFindBlocks();
                task.ExecuteAsync(context).GetAwaiter().GetResult();

                //Block[1] and Block[2] in the DownloadStack
                Assert.Equal(2, context.DownloadStack.Count());
                Assert.True(context.DownloadStack.Any(cb => cb.HashBlock == blocks[1].GetHash()));
                Assert.True(context.DownloadStack.Any(cb => cb.HashBlock == blocks[2].GetHash()));

                //The FindBlocks() task should be removed from the routine
                //as the batch download size is reached
                Assert.Equal(1, context.Routine.Count());
                Assert.False(context.Routine.OfType <BlockStoreInnerStepFindBlocks>().Any());
            }
        }
        public void CanExecute_Reorganise()
        {
            List <Block> blocks = CreateBlocks(15);

            using (var blockRepository = new BlockRepository(Network.Main, TestBase.AssureEmptyDirAsDataFolder(@"BlockStore\CanExecute_Reorganise")))
            {
                // Push 15 blocks to the repository
                blockRepository.PutAsync(blocks.Last().GetHash(), blocks).GetAwaiter().GetResult();

                // The chain has 10 blocks appended
                var chain = new ConcurrentChain(blocks[0].Header);
                AppendBlocks(chain, blocks.Skip(1).Take(9));

                // Create the last 5 chained blocks without appending to the chain
                var block9  = chain.GetBlock(blocks[9].Header.GetHash());
                var block10 = new ChainedBlock(blocks[10].Header, blocks[10].Header.GetHash(), block9);
                var block11 = new ChainedBlock(blocks[11].Header, blocks[11].Header.GetHash(), block10);
                var block12 = new ChainedBlock(blocks[12].Header, blocks[12].Header.GetHash(), block11);
                var block13 = new ChainedBlock(blocks[13].Header, blocks[13].Header.GetHash(), block12);
                var block14 = new ChainedBlock(blocks[14].Header, blocks[14].Header.GetHash(), block13);

                var blockStoreLoop = CreateBlockStoreLoop(chain, blockRepository, @"BlockStore\CanExecute_Reorganise");
                blockStoreLoop.SetStoreTip(block14);

                Assert.Equal(blockStoreLoop.StoreTip.Header.GetHash(), block14.Header.GetHash());
                Assert.Equal(blockStoreLoop.BlockRepository.BlockHash, block14.Header.GetHash());

                //Reorganise (delete) blocks from the block repository that is not found
                var nextChainedBlock = block10;
                var reorganiseStep   = new ReorganiseBlockRepositoryStep(blockStoreLoop);
                reorganiseStep.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult();

                Assert.Equal(blockStoreLoop.StoreTip.Header.GetHash(), block10.Previous.Header.GetHash());
                Assert.Equal(blockStoreLoop.BlockRepository.BlockHash, block10.Previous.Header.GetHash());
            }
        }