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); }
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(); }
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); }
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); } }
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); }
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); }
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); }