public void ProcessPendingStorage_PushToRepo_IBD_InMemory() { var blocks = this.CreateBlocks(15); using (var fluent = new FluentBlockStoreLoop().AsIBD()) { // Push 5 blocks to the repository fluent.BlockRepository.PutAsync(blocks.Take(5).Last().GetHash(), blocks.Take(5).ToList()).GetAwaiter().GetResult(); // The chain has 15 blocks appended var chain = new ConcurrentChain(blocks[0].Header); this.AppendBlocksToChain(chain, blocks.Skip(1).Take(14)); // Create block store loop fluent.Create(chain); //Set the store's tip fluent.Loop.SetStoreTip(fluent.Loop.Chain.GetBlock(blocks.Take(5).Last().GetHash())); // Add chained blocks 5 - 14 to PendingStorage for (int i = 5; i <= 14; i++) { this.AddBlockToPendingStorage(fluent.Loop, blocks[i]); } //Start processing pending blocks from block 5 var nextChainedBlock = fluent.Loop.Chain.GetBlock(blocks[5].GetHash()); var processPendingStorageStep = new ProcessPendingStorageStep(fluent.Loop, this.loggerFactory); processPendingStorageStep.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult(); Assert.Equal(blocks[14].GetHash(), fluent.Loop.BlockRepository.BlockHash); Assert.Equal(blocks[14].GetHash(), fluent.Loop.StoreTip.HashBlock); } }
public void CheckNextChainedBlockExists_WithNextChainedBlock_Exists_SetStoreTipAndBlockHash_InMemory() { var blocks = this.CreateBlocks(5); using (var fluent = new FluentBlockStoreLoop()) { // Push 5 blocks to the repository fluent.BlockRepository.PutAsync(blocks.Last().GetHash(), blocks).GetAwaiter().GetResult(); // The chain has 4 blocks appended var chain = new ConcurrentChain(blocks[0].Header); this.AppendBlocksToChain(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); fluent.Create(chain); Assert.Null(fluent.Loop.StoreTip); var nextChainedBlock = block04; var checkExistsStep = new CheckNextChainedBlockExistStep(fluent.Loop, this.loggerFactory); checkExistsStep.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult(); var options = NetworkOptions.TemporaryOptions; Assert.Equal(fluent.Loop.StoreTip.Header.GetHash(options), block04.Header.GetHash(options)); Assert.Equal(fluent.Loop.BlockRepository.BlockHash, block04.Header.GetHash(options)); } }
public void BlockStoreInnerStepFindBlocks_CanRemoveTaskFromRoutine_NextChainedBlockIsNull() { var blocks = this.CreateBlocks(3); using (var fluent = new FluentBlockStoreLoop()) { // Push 2 blocks to the repository fluent.BlockRepository.PutAsync(blocks.Take(2).Last().GetHash(), blocks.Take(2).ToList()).GetAwaiter().GetResult(); // The chain has 3 blocks appended var chain = new ConcurrentChain(blocks[0].Header); this.AppendBlocksToChain(chain, blocks.Skip(1).Take(2)); // Create block store loop fluent.Create(chain); // Start finding blocks from Block[2] var nextChainedBlock = fluent.Loop.Chain.GetBlock(blocks[2].GetHash()); // Create Task Context var context = new BlockStoreInnerStepContext(new CancellationToken(), fluent.Loop, nextChainedBlock, this.loggerFactory, DateTimeProvider.Default); var task = new BlockStoreInnerStepFindBlocks(this.loggerFactory); task.ExecuteAsync(context).GetAwaiter().GetResult(); // DownloadStack should only contain nextChainedBlock Assert.Single(context.DownloadStack); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == nextChainedBlock.HashBlock); // The FindBlocks() task should be removed from the routine // as the next chained block is null Assert.Single(context.InnerSteps); Assert.False(context.InnerSteps.OfType <BlockStoreInnerStepFindBlocks>().Any()); } }
public void BlockStoreInnerStepFindBlocks_CanRemoveTaskFromRoutine_DownloadStackSizeReached() { var blocks = this.CreateBlocks(55); using (var fluent = new FluentBlockStoreLoop()) { // Push 45 blocks to the repository fluent.BlockRepository.PutAsync(blocks.Take(45).Last().GetHash(), blocks.Take(45).ToList()).GetAwaiter().GetResult(); // The chain has 55 blocks appended var chain = new ConcurrentChain(blocks[0].Header); this.AppendBlocksToChain(chain, blocks.Skip(1).Take(54).ToList()); // Create block store loop fluent.Create(chain); // Start finding blocks from Block[45] var nextChainedBlock = fluent.Loop.Chain.GetBlock(blocks[45].GetHash()); // Create Task Context var context = new BlockStoreInnerStepContext(new CancellationToken(), fluent.Loop, nextChainedBlock, this.loggerFactory, DateTimeProvider.Default); var task = new BlockStoreInnerStepFindBlocks(this.loggerFactory); task.ExecuteAsync(context).GetAwaiter().GetResult(); // Block[45] through Block[50] should be in the DownloadStack Assert.Equal(10, context.DownloadStack.Count()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[45].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[46].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[47].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[48].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[49].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[50].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[51].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[52].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[53].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[54].GetHash()); // The FindBlocks() task should be removed from the routine // as the batch download size is reached Assert.Single(context.InnerSteps); Assert.False(context.InnerSteps.OfType <BlockStoreInnerStepFindBlocks>().Any()); } }
public void BlockStoreInnerStepFindBlocks_WithBlocksFound_AddToDownloadStack() { var blocks = this.CreateBlocks(10); using (var fluent = new FluentBlockStoreLoop()) { // Push 5 blocks to the repository fluent.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); this.AppendBlocksToChain(chain, blocks.Skip(1).Take(9)); // Create block store loop fluent.Create(chain); // Push blocks[5] - [9] to the downloaded blocks collection for (int i = 5; i <= 9; i++) { fluent.Loop.BlockPuller.InjectBlock(blocks[i].GetHash(), new DownloadedBlock { Length = blocks[i].GetSerializedSize(), Block = blocks[i] }, new CancellationToken()); } // Start finding blocks from block[5] var nextChainedBlock = fluent.Loop.Chain.GetBlock(blocks[5].GetHash()); // Create Task Context var context = new BlockStoreInnerStepContext(new CancellationToken(), fluent.Loop, nextChainedBlock, this.loggerFactory, DateTimeProvider.Default); var task = new BlockStoreInnerStepFindBlocks(this.loggerFactory); task.ExecuteAsync(context).GetAwaiter().GetResult(); // Block[5] through Block[9] should be in the DownloadStack Assert.Equal(5, context.DownloadStack.Count()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[5].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[6].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[7].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[8].GetHash()); Assert.Contains(context.DownloadStack, cb => cb.HashBlock == blocks[9].GetHash()); } }
public void ReorganiseBlockRepository_WithBlockRepositoryAndChainOutofSync_ReorganiseBlocks() { var blocks = this.CreateBlocks(15); using (var fluent = new FluentBlockStoreLoop()) { fluent.WithConcreteRepository(Path.Combine(AppContext.BaseDirectory, "BlockStore", "ReorganiseBlockRepository_Integration")); // Push 15 blocks to the repository fluent.BlockRepository.PutAsync(blocks.Last().GetHash(), blocks).GetAwaiter().GetResult(); // The chain has 10 blocks appended var chain = new ConcurrentChain(blocks[0].Header); this.AppendBlocksToChain(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); fluent.Create(chain); fluent.Loop.SetStoreTip(block14); Assert.Equal(fluent.Loop.StoreTip.Header.GetHash(), block14.Header.GetHash()); Assert.Equal(fluent.Loop.BlockRepository.BlockHash, block14.Header.GetHash()); var nextChainedBlock = block10; var reorganiseStep = new ReorganiseBlockRepositoryStep(fluent.Loop, this.loggerFactory); reorganiseStep.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult(); Assert.Equal(fluent.Loop.StoreTip.Header.GetHash(), block10.Previous.Header.GetHash()); Assert.Equal(fluent.Loop.BlockRepository.BlockHash, block10.Previous.Header.GetHash()); } }
public void DownloadBlockStep_WithNewBlocksToDownload_DownloadBlocksAndPushToRepo() { var blocks = this.CreateBlocks(10); using (var fluent = new FluentBlockStoreLoop()) { fluent.WithConcreteRepository(Path.Combine(AppContext.BaseDirectory, "BlockStore", "DownloadBlocks_Integration")); // Push 5 blocks to the repository fluent.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); this.AppendBlocksToChain(chain, blocks.Skip(1).Take(9)); // Create block store loop fluent.Create(chain); // Push blocks 5 - 9 to the downloaded blocks collection for (int i = 5; i <= 9; i++) { fluent.Loop.BlockPuller.InjectBlock(blocks[i].GetHash(), new DownloadedBlock { Length = blocks[i].GetSerializedSize(), Block = blocks[i] }, new CancellationToken()); } // Start processing blocks to download from block 5 var nextChainedBlock = fluent.Loop.Chain.GetBlock(blocks[5].GetHash()); var step = new DownloadBlockStep(fluent.Loop, this.loggerFactory, DateTimeProvider.Default); step.ExecuteAsync(nextChainedBlock, new CancellationToken(), false).GetAwaiter().GetResult(); Assert.Equal(blocks[9].GetHash(), fluent.Loop.BlockRepository.BlockHash); Assert.Equal(blocks[9].GetHash(), fluent.Loop.StoreTip.HashBlock); } }