public static void AddBranch(this BlockTree blockTree, int branchLength, int splitBlockNumber)
        {
            var          splitVariant = 0;
            BlockTree    alternative  = Build.A.BlockTree(blockTree.FindBlock(0, BlockTreeLookupOptions.RequireCanonical)).OfChainLength(branchLength, splitVariant).TestObject;
            List <Block> blocks       = new List <Block>();
            Keccak       parentHash   = null;

            for (int i = splitBlockNumber + 1; i < branchLength; i++)
            {
                Block block = alternative.FindBlock(i, BlockTreeLookupOptions.RequireCanonical);
                if (i == splitBlockNumber + 1)
                {
                    var mainBlock = blockTree.FindBlock(i - 1, BlockTreeLookupOptions.RequireCanonical);
                    if (mainBlock != null)
                    {
                        parentHash = mainBlock.Hash;
                    }
                }

                block.Header.ParentHash = parentHash;
                block.Header.Hash       = block.Header.CalculateHash();
                parentHash = block.Hash;
                blockTree.SuggestBlock(block, i == branchLength - 1, false);
                blocks.Add(block);
            }
        }
Beispiel #2
0
    public async Task Feed_able_to_sync_when_new_pivot_is_set()
    {
        BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(1000).TestObject;
        Block     genesisBlock    = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !;
        BlockTree blockTree       = Build.A.BlockTree().TestObject;

        blockTree.SuggestBlock(genesisBlock);
        ISyncConfig syncConfig = new SyncConfig
        {
            FastSync             = true,
            FastBlocks           = true,
            PivotNumber          = "500",
            PivotHash            = Keccak.Zero.ToString(),
            PivotTotalDifficulty = "1000000" // default difficulty in block tree builder
        };
        BlockHeader? pivotHeader = syncedBlockTree.FindHeader(700, BlockTreeLookupOptions.None);
        IBeaconPivot pivot       = PreparePivot(700, syncConfig, blockTree, pivotHeader);
        Context      ctx         = new (blockTree, syncConfig, pivot);

        BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 0, 501);

        // move best pointers forward as proxy for chain merge
        Block highestBlock = syncedBlockTree.FindBlock(700, BlockTreeLookupOptions.None) !;

        blockTree.Insert(highestBlock, BlockTreeInsertBlockOptions.SaveHeader);

        pivot.EnsurePivot(syncedBlockTree.FindHeader(900, BlockTreeLookupOptions.None));
        BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 700, 701);

        highestBlock = syncedBlockTree.FindBlock(900, BlockTreeLookupOptions.None) !;
        blockTree.Insert(highestBlock, BlockTreeInsertBlockOptions.SaveHeader);
        pivot.EnsurePivot(syncedBlockTree.FindHeader(999, BlockTreeLookupOptions.None));
        BuildAndProcessHeaderSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 900, 901);
    }
Beispiel #3
0
    public async Task Feed_able_to_connect_to_existing_chain_through_block_hash()
    {
        BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(600).TestObject;
        Block     genesisBlock    = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !;
        BlockTree blockTree       = Build.A.BlockTree().TestObject;

        blockTree.SuggestBlock(genesisBlock);
        Block?firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None);

        blockTree.SuggestBlock(firstBlock);
        BlockHeader? pivotHeader = syncedBlockTree.FindHeader(500, BlockTreeLookupOptions.None);
        IBeaconPivot pivot       = PreparePivot(500, new SyncConfig(), blockTree, pivotHeader);
        Context      ctx         = new (blockTree, new SyncConfig(), pivot);
        // fork in chain
        Block parent = firstBlock;

        for (int i = 0; i < 5; i++)
        {
            Block block = Build.A.Block.WithParent(parent).WithNonce(1).TestObject;
            blockTree.SuggestBlock(block);
            parent = block;
        }

        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue();
        blockTree.BestKnownNumber.Should().Be(6);
        BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 2);
        HeadersSyncBatch result = await ctx.Feed.PrepareRequest();

        result.Should().BeNull();
        blockTree.BestKnownNumber.Should().Be(6);
        ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant);
        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse();
    }
Beispiel #4
0
        public static void AddBranch(this BlockTree blockTree, int branchLength, int splitBlockNumber)
        {
            int       splitVariant = 0;
            BlockTree alternative  = Build.A.BlockTree(blockTree.FindBlock(0, BlockTreeLookupOptions.RequireCanonical) !).OfChainLength(branchLength, splitVariant).TestObject;
            Block?    parent       = null;

            for (int i = splitBlockNumber + 1; i < branchLength; i++)
            {
                Block block = alternative.FindBlock(i, BlockTreeLookupOptions.RequireCanonical) !;
                if (i == splitBlockNumber + 1)
                {
                    Block?mainBlock = blockTree.FindBlock(i - 1, BlockTreeLookupOptions.RequireCanonical);
                    if (mainBlock != null)
                    {
                        parent = mainBlock;
                    }
                }

                block.Header.ParentHash = parent?.Hash;
                block.Header.StateRoot  = parent?.StateRoot;
                block.Header.Hash       = block.Header.CalculateHash();
                parent = block;
                blockTree.SuggestBlock(block, i == branchLength - 1, false);
            }
        }
Beispiel #5
0
        public async Task Can_load_blocks_from_db_odd()
        {
            for (int chainLength = 2; chainLength <= 32; chainLength++)
            {
                Block genesisBlock = Build.A.Block.Genesis.TestObject;

                MemDb blocksDb     = new MemDb();
                MemDb blockInfosDb = new MemDb();

                BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject;
                for (int i = 0; i < testTree.Head.Number + 1; i++)
                {
                    Block ithBlock = testTree.FindBlock((ulong)i);
                    blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes);

                    ChainLevelInfo ithLevel = new ChainLevelInfo(true, new BlockInfo[1] {
                        new BlockInfo(ithBlock.Hash, ithBlock.TotalDifficulty.Value, (ulong)ithBlock.Transactions.Length)
                    });
                    blockInfosDb.Set(i, Rlp.Encode(ithLevel).Bytes);
                }

                blocksDb.Set(Keccak.Zero, Rlp.Encode(testTree.FindBlock(1)).Bytes);

                BlockTree blockTree = new BlockTree(blocksDb, blockInfosDb, OlympicSpecProvider.Instance, Substitute.For <ITransactionPool>(), LimboLogs.Instance);
                await blockTree.LoadBlocksFromDb(CancellationToken.None);

                Assert.AreEqual(blockTree.BestSuggested.Hash, testTree.Head.Hash, $"head {chainLength}");
            }
        }
Beispiel #6
0
        public async Task Can_load_blocks_from_db()
        {
            for (int chainLength = 2; chainLength <= 32; chainLength++)
            {
                Block genesisBlock = Build.A.Block.Genesis.TestObject;

                MemDb blocksDb     = new();
                MemDb blockInfosDb = new();
                MemDb headersDb    = new();

                BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject;
                for (int i = 0; i < testTree.Head.Number + 1; i++)
                {
                    Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None);
                    blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes);

                    headersDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock.Header).Bytes);

                    ChainLevelInfo ithLevel = new(
                        true,
                        new BlockInfo[1]
                    {
                        new(
                            ithBlock.Hash,
                            ithBlock.TotalDifficulty.Value) { WasProcessed = true }
                    });
        protected override UInt256 CalculateDifficulty(BlockHeader parent, UInt256 timestamp)
        {
            Block parentBlock = BlockTree.FindBlock(parent.Hash, BlockTreeLookupOptions.None);

            return(_difficultyCalculator.Calculate(
                       parent.Difficulty, parent.Timestamp, timestamp, parent.Number + 1, parentBlock.Ommers.Length > 0));
        }
Beispiel #8
0
        public async Task Can_load_blocks_from_db_odd()
        {
            for (int chainLength = 2; chainLength <= 32; chainLength++)
            {
                Block genesisBlock = Build.A.Block.Genesis.TestObject;

                MemDb blocksDb     = new MemDb();
                MemDb blockInfosDb = new MemDb();
                MemDb headersDb    = new MemDb();

                BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject;
                for (int i = 0; i < testTree.Head.Number + 1; i++)
                {
                    Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None);
                    blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes);

                    headersDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock.Header).Bytes);

                    ChainLevelInfo ithLevel = new ChainLevelInfo(true, new BlockInfo[1] {
                        new BlockInfo(ithBlock.Hash, ithBlock.TotalDifficulty.Value)
                    });
                    blockInfosDb.Set(i, Rlp.Encode(ithLevel).Bytes);
                }

                blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash.Bytes);
                headersDb.Set(genesisBlock.Header.Hash, Rlp.Encode(genesisBlock.Header).Bytes);

                BlockTree      blockTree = new BlockTree(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), OlympicSpecProvider.Instance, Substitute.For <ITxPool>(), NullBloomStorage.Instance, LimboLogs.Instance);
                DbBlocksLoader loader    = new DbBlocksLoader(blockTree, LimboNoErrorLogger.Instance);
                await blockTree.Accept(loader, CancellationToken.None);

                Assert.AreEqual(testTree.Head.Hash, blockTree.BestSuggestedHeader.Hash, $"head {chainLength}");
            }
        }
Beispiel #9
0
        public void Can_accept_new_valid_blocks(bool sealOk, bool validationOk, bool accepted)
        {
            BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject;
            BlockTree localBlockTree  = Build.A.BlockTree().OfChainLength(9).TestObject;

            ISealValidator  sealValidator  = sealOk ? TestSealValidator.AlwaysValid : TestSealValidator.NeverValid;
            IBlockValidator blockValidator = validationOk ? TestBlockValidator.AlwaysValid : TestBlockValidator.NeverValid;

            _syncServer = new SyncServer(new StateDb(), new StateDb(), localBlockTree, NullReceiptStorage.Instance, blockValidator, sealValidator, _peerPool, _synchronizer, new SyncConfig(), LimboLogs.Instance);

            Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None);

            _synchronizer.SyncMode.Returns(SyncMode.Full);

            if (!accepted)
            {
                Assert.Throws <EthSynchronizationException>(() => _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock));
            }
            else
            {
                _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock);
            }

            if (accepted)
            {
                Assert.AreEqual(localBlockTree.BestSuggestedHeader, block.Header);
            }
            else
            {
                Assert.AreNotEqual(localBlockTree.BestSuggestedHeader, block.Header);
            }
        }
 private void SetupLocalTree(int length = 1)
 {
     _localBlockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), MainNetSpecProvider.Instance, NullTxPool.Instance, _syncConfig, LimboLogs.Instance);
     for (int i = 0; i < length; i++)
     {
         _localBlockTree.SuggestBlock(_validTree2048.FindBlock(i));
     }
 }
Beispiel #11
0
        public void Test_real_block(string blockRlp)
        {
            Block block       = Rlp.Decode <Block>(new Rlp(Bytes.FromHexString(blockRlp)));
            bool  validHeader = _clique.ValidateParams(_blockTree.FindBlock(block.ParentHash, false), block.Header);
            bool  validSeal   = _clique.ValidateSeal(block.Header);

            Assert.True(validHeader);
            Assert.True(validSeal);
        }
Beispiel #12
0
        public void Add_on_branch_and_not_find_on_main()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block     = Build.A.Block.TestObject;

            blockTree.SuggestBlock(block);
            Block found = blockTree.FindBlock(block.Hash, true);

            Assert.IsNull(found);
        }
Beispiel #13
0
        public void Add_on_branch_move_find()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block     = Build.A.Block.TestObject;

            AddToMain(blockTree, block);
            Block found = blockTree.FindBlock(block.Hash, true);

            Assert.AreEqual(block.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #14
0
        public void Add_and_find_branch()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block     = Build.A.Block.TestObject;

            blockTree.SuggestBlock(block);
            Block found = blockTree.FindBlock(block.Hash, false);

            Assert.AreEqual(block.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #15
0
        public void Add_and_find_branch()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block     = Build.A.Block.TestObject;

            blockTree.SuggestBlock(block);
            Block found = blockTree.FindBlock(block.Hash, false);

            Assert.AreEqual(block.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #16
0
        public void Add_on_branch_move_find()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block     = Build.A.Block.TestObject;

            AddToMain(blockTree, block);
            Block found = blockTree.FindBlock(block.Hash, true);

            Assert.AreEqual(block.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #17
0
        public void Add_on_branch_and_not_find_on_main()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block     = Build.A.Block.TestObject;

            blockTree.SuggestBlock(block);
            Block found = blockTree.FindBlock(block.Hash, true);

            Assert.IsNull(found);
        }
        private void SetupLocalTree(int length = 1)
        {
            var blockInfoDb = new MemDb();

            _localBlockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), MainNetSpecProvider.Instance, NullTxPool.Instance, _syncConfig, LimboLogs.Instance);
            for (int i = 0; i < length; i++)
            {
                _localBlockTree.SuggestBlock(_validTree2048.FindBlock(i, BlockTreeLookupOptions.None));
            }
        }
Beispiel #19
0
        public async Task Can_sign_block()
        {
            Block block6 = CreateBlock(2, 6, _lastBlock);
            Block signed = await _clique.SealBlock(block6, CancellationToken.None);

            bool validHeader = _clique.ValidateParams(_blockTree.FindBlock(signed.ParentHash, false), signed.Header);
            bool validSeal   = _clique.ValidateSeal(signed.Header);

            Assert.True(validHeader);
            Assert.True(validSeal);
        }
Beispiel #20
0
        public void Find_by_number_negative()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);

            Assert.Throws <ArgumentException>(() => blockTree.FindBlock(-1));
        }
Beispiel #21
0
        public void Find_by_number_returns_null_when_block_is_missing()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);

            Block found = blockTree.FindBlock(5);

            Assert.IsNull(found);
        }
Beispiel #22
0
        public void Find_by_number_missing()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);

            Block found = blockTree.FindBlock(5);

            Assert.IsNull(found);
        }
Beispiel #23
0
        public void Rejects_new_blocks_with_failing_seal()
        {
            BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject;
            BlockTree localBlockTree  = Build.A.BlockTree().OfChainLength(9).TestObject;

            _syncServer = new SyncServer(new StateDb(), new StateDb(), localBlockTree, NullReceiptStorage.Instance, TestBlockValidator.AlwaysValid, TestSealValidator.AlwaysValid, _peerPool, _synchronizer, new SyncConfig(), LimboLogs.Instance);

            Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None);

            _synchronizer.SyncMode.Returns(SyncMode.Full);
            _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock);

            Assert.AreEqual(localBlockTree.BestSuggestedHeader, block.Header);
        }
Beispiel #24
0
        public void Find_by_number_basic()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;
            Block     block2    = Build.A.Block.WithNumber(2).WithParent(block1).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);
            AddToMain(blockTree, block2);

            Block found = blockTree.FindBlock(2);

            Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #25
0
        public static void AddBranch(this BlockTree blockTree, int branchLength, int splitBlockNumber, int splitVariant)
        {
            BlockTree alternative = Build.A.BlockTree(blockTree.RetrieveGenesisBlock()).OfChainLength(branchLength, splitBlockNumber, splitVariant).TestObject;

            for (int i = splitBlockNumber + 1; i < branchLength; i++)
            {
                Block block = alternative.FindBlock((ulong)i);
                blockTree.SuggestBlock(block);
                blockTree.MarkAsProcessed(block.Hash);
                if (branchLength > blockTree.Head.Number)
                {
                    blockTree.MoveToMain(block.Hash);
                }
            }
        }
Beispiel #26
0
        public void Find_by_number_beyond_what_is_known_returns_null()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;
            Block     block2    = Build.A.Block.WithNumber(2).WithParent(block1).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);
            AddToMain(blockTree, block2);

            Block found = blockTree.FindBlock(1920000);

            Assert.Null(found);
        }
Beispiel #27
0
        public void Stores_multiple_blocks_per_level()
        {
            BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance);
            Block     block0    = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject;
            Block     block1B   = Build.A.Block.WithNumber(1).WithDifficulty(3).WithParent(block0).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);
            blockTree.SuggestBlock(block1B);

            Block found = blockTree.FindBlock(block1B.Hash, false);

            Assert.AreEqual(block1B.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #28
0
        public void Stores_multiple_blocks_per_level()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block0    = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject;
            Block     block1B   = Build.A.Block.WithNumber(1).WithDifficulty(3).WithParent(block0).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);
            blockTree.SuggestBlock(block1B);

            Block found = blockTree.FindBlock(block1B.Hash, false);

            Assert.AreEqual(block1B.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #29
0
        public void Find_by_number_basic()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;
            Block     block2    = Build.A.Block.WithNumber(2).WithParent(block1).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);
            AddToMain(blockTree, block2);

            Block found = blockTree.FindBlock(2);

            Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(found.Header));
        }
Beispiel #30
0
        public void Find_by_number_beyond_what_is_known_returns_null()
        {
            BlockTree blockTree = BuildBlockTree();
            Block     block0    = Build.A.Block.WithNumber(0).TestObject;
            Block     block1    = Build.A.Block.WithNumber(1).WithParent(block0).TestObject;
            Block     block2    = Build.A.Block.WithNumber(2).WithParent(block1).TestObject;

            AddToMain(blockTree, block0);
            AddToMain(blockTree, block1);
            AddToMain(blockTree, block2);

            Block found = blockTree.FindBlock(1920000);

            Assert.Null(found);
        }