コード例 #1
0
        public void When_head_block_is_followed_by_a_block_bodies_gap_it_should_delete_all_levels_after_the_gap_start()
        {
            MemDb     blocksDb     = new MemDb();
            MemDb     blockInfosDb = new MemDb();
            MemDb     headersDb    = new MemDb();
            BlockTree tree         = new BlockTree(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance);
            Block     block0       = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject;
            Block     block1       = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject;
            Block     block2       = Build.A.Block.WithNumber(2).WithDifficulty(3).WithParent(block1).TestObject;
            Block     block3       = Build.A.Block.WithNumber(3).WithDifficulty(4).WithParent(block2).TestObject;
            Block     block4       = Build.A.Block.WithNumber(4).WithDifficulty(5).WithParent(block3).TestObject;
            Block     block5       = Build.A.Block.WithNumber(5).WithDifficulty(6).WithParent(block4).TestObject;

            tree.SuggestBlock(block0);
            tree.SuggestBlock(block1);
            tree.SuggestBlock(block2);
            tree.SuggestHeader(block3.Header);
            tree.SuggestHeader(block4.Header);
            tree.SuggestBlock(block5);

            tree.UpdateMainChain(block2);

            StartupBlockTreeFixer fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, LimboNoErrorLogger.Instance);

            tree.Accept(fixer, CancellationToken.None);

            Assert.Null(blockInfosDb.Get(3), "level 3");
            Assert.Null(blockInfosDb.Get(4), "level 4");
            Assert.Null(blockInfosDb.Get(5), "level 5");

            Assert.AreEqual(2L, tree.BestKnownNumber, "best known");
            Assert.AreEqual(block2.Header, tree.Head?.Header, "head");
            Assert.AreEqual(block2.Hash, tree.BestSuggestedHeader.Hash, "suggested");
        }
コード例 #2
0
        public async Task Suggesting_blocks_works_correctly_after_processor_restart(int suggestedBlocksAmount)
        {
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build();

            await testRpc.BlockchainProcessor.StopAsync();

            IBlockTree tree = testRpc.BlockTree;
            long       startingBlockNumber = tree.Head !.Number;

            SuggestNumberOfBlocks(tree, suggestedBlocksAmount);

            // simulating restarts - we stopped the old blockchain processor and create the new one
            BlockchainProcessor newBlockchainProcessor = new BlockchainProcessor(tree, testRpc.BlockProcessor,
                                                                                 testRpc.BlockPreprocessorStep, LimboLogs.Instance, BlockchainProcessor.Options.Default);

            newBlockchainProcessor.Start();
            testRpc.BlockchainProcessor = newBlockchainProcessor;

            // fixing after restart
            StartupBlockTreeFixer fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, testRpc.DbProvider.StateDb, LimboNoErrorLogger.Instance, 5);
            await tree.Accept(fixer, CancellationToken.None);

            // waiting for N new heads
            for (int i = 0; i < suggestedBlocksAmount; ++i)
            {
                await testRpc.WaitForNewHead();
            }

            // add a new block at the end
            await testRpc.AddBlock();

            Assert.AreEqual(startingBlockNumber + suggestedBlocksAmount + 1, tree.Head !.Number);
        }
コード例 #3
0
        private async Task RunBlockTreeInitTasks()
        {
            ISyncConfig syncConfig = _context.Config <ISyncConfig>();

            if (!syncConfig.SynchronizationEnabled)
            {
                return;
            }

            if (_context.BlockTree == null)
            {
                throw new StepDependencyException(nameof(_context.BlockTree));
            }


            if (!syncConfig.FastSync && !syncConfig.BeamSync)
            {
                DbBlocksLoader loader = new DbBlocksLoader(_context.BlockTree, _logger);
                await _context.BlockTree.Accept(loader, _context.RunnerCancellation?.Token ?? CancellationToken.None).ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        if (_logger.IsError)
                        {
                            _logger.Error("Loading blocks from the DB failed.", t.Exception);
                        }
                    }
                    else if (t.IsCanceled)
                    {
                        if (_logger.IsWarn)
                        {
                            _logger.Warn("Loading blocks from the DB canceled.");
                        }
                    }
                });
            }
            else
            {
                StartupBlockTreeFixer fixer = new StartupBlockTreeFixer(_context.Config <ISyncConfig>(), _context.BlockTree, _logger);
                await _context.BlockTree.Accept(fixer, _context.RunnerCancellation?.Token ?? CancellationToken.None).ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        if (_logger.IsError)
                        {
                            _logger.Error("Fixing gaps in DB failed.", t.Exception);
                        }
                    }
                    else if (t.IsCanceled)
                    {
                        if (_logger.IsWarn)
                        {
                            _logger.Warn("Fixing gaps in DB canceled.");
                        }
                    }
                });
            }
        }
コード例 #4
0
        public void Deletes_everything_after_the_missing_level()
        {
            MemDb     blocksDb     = new MemDb();
            MemDb     blockInfosDb = new MemDb();
            MemDb     headersDb    = new MemDb();
            BlockTree tree         = new BlockTree(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance);
            Block     block0       = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject;
            Block     block1       = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject;
            Block     block2       = Build.A.Block.WithNumber(2).WithDifficulty(3).WithParent(block1).TestObject;
            Block     block3       = Build.A.Block.WithNumber(3).WithDifficulty(4).WithParent(block2).TestObject;
            Block     block4       = Build.A.Block.WithNumber(4).WithDifficulty(5).WithParent(block3).TestObject;
            Block     block5       = Build.A.Block.WithNumber(5).WithDifficulty(6).WithParent(block4).TestObject;

            tree.SuggestBlock(block0);
            tree.SuggestBlock(block1);
            tree.SuggestBlock(block2);
            tree.SuggestBlock(block3);
            tree.SuggestBlock(block4);
            tree.SuggestHeader(block5.Header);

            tree.UpdateMainChain(block0);
            tree.UpdateMainChain(block1);
            tree.UpdateMainChain(block2);

            blockInfosDb.Delete(3);

            tree = new BlockTree(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance);

            StartupBlockTreeFixer fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, LimboNoErrorLogger.Instance);

            tree.Accept(fixer, CancellationToken.None);

            Assert.Null(blockInfosDb.Get(3), "level 3");
            Assert.Null(blockInfosDb.Get(4), "level 4");
            Assert.Null(blockInfosDb.Get(5), "level 5");

            tree.Head.Header.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent));
            tree.BestSuggestedHeader.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent));
            tree.BestSuggestedBody.Should().BeEquivalentTo(block2.Body);
            tree.BestKnownNumber.Should().Be(2);
        }
コード例 #5
0
        public async Task Fixer_should_not_suggest_block_with_null_block()
        {
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build();

            await testRpc.BlockchainProcessor.StopAsync();

            IBlockTree tree = testRpc.BlockTree;

            SuggestNumberOfBlocks(tree, 1);

            // simulating restarts - we stopped the old blockchain processor and create the new one
            BlockchainProcessor newBlockchainProcessor = new(tree, testRpc.BlockProcessor,
                                                             testRpc.BlockPreprocessorStep, testRpc.StateReader, LimboLogs.Instance, BlockchainProcessor.Options.Default);

            newBlockchainProcessor.Start();
            testRpc.BlockchainProcessor = newBlockchainProcessor;

            IBlockTreeVisitor fixer  = new StartupBlockTreeFixer(new SyncConfig(), tree, testRpc.DbProvider.StateDb, LimboNoErrorLogger.Instance, 5);
            BlockVisitOutcome result = await fixer.VisitBlock(null, CancellationToken.None);

            Assert.AreEqual(BlockVisitOutcome.None, result);
        }
コード例 #6
0
        public async Task Fixer_should_not_suggest_block_without_state(int suggestedBlocksAmount)
        {
            TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build();

            await testRpc.BlockchainProcessor.StopAsync();

            IBlockTree tree = testRpc.BlockTree;

            SuggestNumberOfBlocks(tree, suggestedBlocksAmount);

            // simulating restarts - we stopped the old blockchain processor and create the new one
            BlockchainProcessor newBlockchainProcessor = new(tree, testRpc.BlockProcessor,
                                                             testRpc.BlockPreprocessorStep, LimboLogs.Instance, BlockchainProcessor.Options.Default);

            newBlockchainProcessor.Start();
            testRpc.BlockchainProcessor = newBlockchainProcessor;

            // we create a new empty db for stateDb so we shouldn't suggest new blocks
            MemDb             stateDb = new();
            IBlockTreeVisitor fixer   = new StartupBlockTreeFixer(new SyncConfig(), tree, stateDb, LimboNoErrorLogger.Instance, 5);
            BlockVisitOutcome result  = await fixer.VisitBlock(tree.Head !, CancellationToken.None);

            Assert.AreEqual(BlockVisitOutcome.None, result);
        }