Beispiel #1
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 #2
0
    private async void BuildAndProcessHeaderSyncBatches(
        Context ctx,
        BlockTree blockTree,
        BlockTree syncedBlockTree,
        IBeaconPivot pivot,
        long bestPointer,
        long endLowestBeaconHeader)
    {
        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue();
        blockTree.BestKnownNumber.Should().Be(bestPointer);
        BlockHeader?startBestHeader = syncedBlockTree.FindHeader(bestPointer, BlockTreeLookupOptions.None);

        blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader);
        blockTree.LowestInsertedBeaconHeader.Should().BeEquivalentTo(syncedBlockTree.FindHeader(pivot.PivotNumber, BlockTreeLookupOptions.None));

        BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, endLowestBeaconHeader);

        HeadersSyncBatch result = await ctx.Feed.PrepareRequest();

        result.Should().BeNull();
        // check headers are inserted into block tree during sync
        blockTree.FindHeader(pivot.PivotNumber - 1, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().NotBeNull();
        blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(syncedBlockTree.FindHeader(endLowestBeaconHeader, BlockTreeLookupOptions.None)?.Hash);
        blockTree.BestKnownNumber.Should().Be(bestPointer);
        blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader);
        ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant);
        ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse();
    }
Beispiel #3
0
        public void Test_real_block(string blockRlp)
        {
            Block block       = Rlp.Decode <Block>(new Rlp(Bytes.FromHexString(blockRlp)));
            bool  validHeader = _sealValidator.ValidateParams(_blockTree.FindHeader(block.ParentHash, BlockTreeLookupOptions.None), block.Header);
            bool  validSeal   = _sealValidator.ValidateSeal(block.Header, true);

            Assert.True(validHeader);
            Assert.True(validSeal);
        }
        public void Can_lookup_up_to_256_before_with_headers_only()
        {
            const int chainLength = 512;

            Block     genesis = Build.A.Block.Genesis.TestObject;
            BlockTree tree    = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new BlockhashProvider(tree, LimboLogs.Instance);
            BlockHeader       head     = tree.FindHeader(chainLength - 1);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, chainLength - 256);

            Assert.AreEqual(tree.FindHeader(256).Hash, result);
        }
Beispiel #5
0
    private async void BuildHeadersSyncBatches(
        Context ctx,
        BlockTree blockTree,
        BlockTree syncedBlockTree,
        IBeaconPivot pivot,
        long endLowestBeaconHeader)
    {
        ctx.Feed.InitializeFeed();
        long lowestHeaderNumber = pivot.PivotNumber;

        while (lowestHeaderNumber > endLowestBeaconHeader)
        {
            HeadersSyncBatch batch = await ctx.Feed.PrepareRequest();

            batch.Should().NotBeNull();
            BuildHeadersSyncBatchResponse(batch, syncedBlockTree);
            ctx.Feed.HandleResponse(batch);
            lowestHeaderNumber = lowestHeaderNumber - batch.RequestSize < endLowestBeaconHeader
                ? endLowestBeaconHeader
                : lowestHeaderNumber - batch.RequestSize;

            BlockHeader?lowestHeader = syncedBlockTree.FindHeader(lowestHeaderNumber, BlockTreeLookupOptions.None);
            blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(lowestHeader?.Hash);
        }
    }
Beispiel #6
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();
    }
        public void IsTerminalBlock_returning_expected_results(long terminalTotalDifficulty)
        {
            Block            genesisBlock = Build.A.Block.WithNumber(0).TestObject;
            TestSpecProvider specProvider = new(London.Instance);

            specProvider.TerminalTotalDifficulty = (UInt256)terminalTotalDifficulty;
            BlockTree   blockTree   = Build.A.BlockTree(genesisBlock, specProvider).OfChainLength(6).TestObject;
            PoSSwitcher poSSwitcher = CreatePosSwitcher(blockTree, new MemDb(), specProvider);

            BlockHeader?block3 = blockTree.FindHeader(3, BlockTreeLookupOptions.All);
            BlockHeader?block4 = blockTree.FindHeader(4, BlockTreeLookupOptions.All);
            BlockHeader?block5 = blockTree.FindHeader(5, BlockTreeLookupOptions.All);
            Block       blockWithPostMergeFlag = Build.A.Block.WithNumber(4).WithDifficulty(0).WithPostMergeFlag(true)
                                                 .WithParent(block3 !).TestObject;

            Assert.AreEqual(false, block3 !.IsTerminalBlock(specProvider));               // PoWBlock
            Assert.AreEqual(true, block4 !.IsTerminalBlock(specProvider));                // terminal block
            Assert.AreEqual(false, block5 !.IsTerminalBlock(specProvider));               // incorrect PoW not terminal block
            Assert.AreEqual(false, blockWithPostMergeFlag.IsTerminalBlock(specProvider)); // block with post merge flag
        }
        public void GetBlockSwitchInfo_returning_expected_results(long terminalTotalDifficulty)
        {
            TestSpecProvider specProvider = new(London.Instance);

            specProvider.TerminalTotalDifficulty = (UInt256)terminalTotalDifficulty;
            Block       genesisBlock = Build.A.Block.WithNumber(0).TestObject;
            BlockTree   blockTree    = Build.A.BlockTree(genesisBlock, specProvider).OfChainLength(6).TestObject;
            PoSSwitcher poSSwitcher  = CreatePosSwitcher(blockTree, new MemDb(), specProvider);

            BlockHeader?block3 = blockTree.FindHeader(3, BlockTreeLookupOptions.All);
            BlockHeader?block4 = blockTree.FindHeader(4, BlockTreeLookupOptions.All);
            BlockHeader?block5 = blockTree.FindHeader(5, BlockTreeLookupOptions.All);
            Block       blockWithPostMergeFlag = Build.A.Block.WithNumber(4).WithDifficulty(0).WithPostMergeFlag(true)
                                                 .WithParent(block3 !).TestObject;

            Assert.AreEqual((false, false), poSSwitcher.GetBlockConsensusInfo(block3 !));                     // PoWBlock
            Assert.AreEqual((true, false), poSSwitcher.GetBlockConsensusInfo(block4 !));                      // terminal block
            Assert.AreEqual((false, true), poSSwitcher.GetBlockConsensusInfo(block5 !));                      // incorrect PoW, TTD > TD and it is not terminal, so we should process it in the same way like post merge blocks
            Assert.AreEqual((false, true), poSSwitcher.GetBlockConsensusInfo(blockWithPostMergeFlag.Header)); // block with post merge flag
        }
        public async Task Can_sign_block()
        {
            Block block6 = CreateBlock(2, 6, _lastBlock);
            Block signed = await _clique.SealBlock(block6, CancellationToken.None);

            bool validHeader = _sealValidator.ValidateParams(_blockTree.FindHeader(signed.ParentHash, BlockTreeLookupOptions.None), signed.Header);
            bool validSeal   = _sealValidator.ValidateSeal(signed.Header);

            Assert.True(validHeader);
            Assert.True(validSeal);
        }
 public void AddBlocks(long count)
 {
     for (int i = 0; i < count; i++)
     {
         long number = _head + 1;
         BlockTree.BestPersistedState.Returns(_head);
         Block head = Build.A.Block.WithStateRoot(_stateRoot).WithNumber(number).TestObject;
         BlockTree.Head.Returns(head);
         BlockTree.FindHeader(number).Returns(head.Header);
         BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(head));
     }
 }
        public void GetBlockSwitchInfo_returning_expected_results_when_td_null_or_zero(long terminalTotalDifficulty, bool nullTdValue)
        {
            TestSpecProvider specProvider = new(London.Instance);

            specProvider.TerminalTotalDifficulty = (UInt256)terminalTotalDifficulty;
            Block       genesisBlock = Build.A.Block.WithNumber(0).TestObject;
            BlockTree   blockTree    = Build.A.BlockTree(genesisBlock, specProvider).OfChainLength(6).TestObject;
            PoSSwitcher poSSwitcher  = CreatePosSwitcher(blockTree, new MemDb(), specProvider);

            BlockHeader?block3 = blockTree.FindHeader(3, BlockTreeLookupOptions.All);
            BlockHeader?block4 = blockTree.FindHeader(4, BlockTreeLookupOptions.All);
            BlockHeader?block5 = blockTree.FindHeader(5, BlockTreeLookupOptions.All);
            Block       blockWithPostMergeFlag = Build.A.Block.WithNumber(4).WithDifficulty(0).WithPostMergeFlag(true)
                                                 .WithParent(block3 !).TestObject;

            block3 !.TotalDifficulty = nullTdValue ? null : UInt256.Zero;
            block4 !.TotalDifficulty = nullTdValue ? null : UInt256.Zero;
            block5 !.TotalDifficulty = nullTdValue ? null : UInt256.Zero;
            Assert.AreEqual((false, false), poSSwitcher.GetBlockConsensusInfo(block3 !));                     // PoWBlock
            Assert.AreEqual((false, false), poSSwitcher.GetBlockConsensusInfo(block4 !));                     // terminal block
            Assert.AreEqual((false, false), poSSwitcher.GetBlockConsensusInfo(block5 !));
            Assert.AreEqual((false, true), poSSwitcher.GetBlockConsensusInfo(blockWithPostMergeFlag.Header)); // block with post merge flag
        }
        public void No_lookup_more_than_256_before()
        {
            const int chainLength = 512;

            Block     genesis = Build.A.Block.Genesis.TestObject;
            BlockTree tree    = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new BlockhashProvider(tree);
            BlockHeader       head     = tree.FindHeader(chainLength - 1);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, chainLength - 257);

            Assert.Null(result);
        }
        public void Cannot_ask_about_future()
        {
            const int chainLength = 512;

            Block     genesis = Build.A.Block.Genesis.TestObject;
            BlockTree tree    = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new BlockhashProvider(tree);
            BlockHeader       head     = tree.FindHeader(chainLength - 1);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, chainLength + 1);

            Assert.Null(result);
        }
Beispiel #14
0
        public void Cannot_ask_for_self()
        {
            const int chainLength = 512;

            Block     genesis = Build.A.Block.Genesis.TestObject;
            BlockTree tree    = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new(tree, LimboLogs.Instance);
            BlockHeader       head     = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, chainLength);

            Assert.Null(result);
        }
        public void UInt_256_overflow()
        {
            const int chainLength = 128;

            Block     genesis = Build.A.Block.Genesis.TestObject;
            BlockTree tree    = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new BlockhashProvider(tree, LimboLogs.Instance);
            BlockHeader       head     = tree.FindHeader(chainLength - 1);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, 127);

            Assert.AreEqual(head.Hash, result);
        }
Beispiel #16
0
        public void Can_get_parent_only_headers()
        {
            const int chainLength = 512;

            Block genesis = Build.A.Block.Genesis.TestObject;

            BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new(tree, LimboLogs.Instance);
            BlockHeader       head     = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, chainLength - 1);

            Assert.AreEqual(head.Hash, result);
        }
        public void Can_get_parent_hash()
        {
            const int chainLength = 512;

            Block genesis = Build.A.Block.Genesis.TestObject;

            BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject;

            BlockhashProvider provider = new BlockhashProvider(tree);
            BlockHeader       head     = tree.FindHeader(chainLength - 1);
            Block             current  = Build.A.Block.WithParent(head).TestObject;
            Keccak            result   = provider.GetBlockhash(current.Header, chainLength - 1);

            Assert.AreEqual(head.Hash, result);
        }
        private void AssertTreeSynced(IBlockTree tree, bool bodiesSync = false, bool receiptSync = false)
        {
            Keccak nextHash = tree.Head.Hash;

            for (int i = 0; i < tree.Head.Number; i++)
            {
                BlockHeader header = _localBlockTree.FindHeader(nextHash, BlockTreeLookupOptions.None);
                Assert.NotNull(header, $"header {tree.Head.Number - i}");
                if (bodiesSync)
                {
                    Block expectedBlock = _localBlockTree.FindBlock(nextHash, BlockTreeLookupOptions.None);
                    Assert.AreEqual(nextHash, expectedBlock?.Hash, $"hash difference {tree.Head.Number - i}");
                    if (expectedBlock != null)
                    {
                        Block actualBlock = tree.FindBlock(expectedBlock.Hash, BlockTreeLookupOptions.None);
                        Rlp   saved       = Rlp.Encode(actualBlock);
                        Rlp   expected    = Rlp.Encode(expectedBlock);
                        Assert.AreEqual(expected, saved, $"body {tree.Head.Number - i}");

                        if (receiptSync)
                        {
                            int txIndex = 0;
                            foreach (Transaction transaction in expectedBlock.Transactions)
                            {
                                Assert.NotNull(_localReceiptStorage.Find(transaction.Hash), $"receipt {expectedBlock.Number}.{txIndex}");
                                txIndex++;
                            }
                        }
                    }
                }

                nextHash = header.ParentHash;
            }

            Assert.True(_feed.IsFinished);
        }