public void Can_accept_blocks_that_are_fine() { Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; ctx.SyncServer = new SyncServer( new MemDb(), new MemDb(), localBlockTree, NullReceiptStorage.Instance, Always.Valid, Always.Valid, ctx.PeerPool, StaticSelector.Full, new SyncConfig(), NullWitnessCollector.Instance, Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader, block.Header); }
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 ? Always.Valid : Always.Invalid; IBlockValidator blockValidator = validationOk ? Always.Valid : Always.Invalid; _syncServer = new SyncServer(new StateDb(), new StateDb(), localBlockTree, NullReceiptStorage.Instance, blockValidator, sealValidator, _peerPool, StaticSelector.Full, new SyncConfig(), LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (!accepted) { Assert.Throws <EthSyncException>(() => _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock)); } else { _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock); } if (accepted) { Assert.AreEqual(localBlockTree.BestSuggestedHeader, block.Header); } else { Assert.AreNotEqual(localBlockTree.BestSuggestedHeader, block.Header); } }
public void Rejects_new_old_blocks() { Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(600).TestObject; ISealValidator sealValidator = Substitute.For <ISealValidator>(); ctx.SyncServer = new SyncServer( new MemDb(), new MemDb(), localBlockTree, NullReceiptStorage.Instance, Always.Valid, sealValidator, ctx.PeerPool, StaticSelector.Full, new SyncConfig(), NullWitnessCollector.Instance, Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); sealValidator.DidNotReceive().ValidateSeal(Arg.Any <BlockHeader>(), Arg.Any <bool>()); }
public void Fake_total_difficulty_from_peer_does_not_trick_the_node(long ttd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; Context ctx = CreateMergeContext(localBlockTree, (UInt256)ttd); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); block.Header.TotalDifficulty *= 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader !.Hash, block.Header.Hash); Block parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); Assert.AreEqual(parentBlock.TotalDifficulty + block.Difficulty, localBlockTree.BestSuggestedHeader.TotalDifficulty); }
public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_null() { Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; HeaderValidator headerValidator = new( localBlockTree, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance); BlockValidator blockValidator = new( Always.Valid, headerValidator, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance); ctx.SyncServer = new SyncServer( new MemDb(), new MemDb(), localBlockTree, NullReceiptStorage.Instance, blockValidator, Always.Valid, ctx.PeerPool, StaticSelector.Full, new SyncConfig(), NullWitnessCollector.Instance, Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); block.Header.TotalDifficulty *= 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader !.Hash, block.Header.Hash); Block parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); Assert.AreEqual(parentBlock.TotalDifficulty + block.Difficulty, localBlockTree.BestSuggestedHeader.TotalDifficulty); }
public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_null() { 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, new BlockValidator(Always.Valid, new HeaderValidator(localBlockTree, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance), Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance), Always.Valid, _peerPool, StaticSelector.Full, new SyncConfig(), LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); block.Header.TotalDifficulty *= 2; _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader.Hash, block.Header.Hash); Block parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); Assert.AreEqual(parentBlock.TotalDifficulty + block.Difficulty, localBlockTree.BestSuggestedHeader.TotalDifficulty); }
public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_should_be_added_to_block_tree() { Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; TestSpecProvider testSpecProvider = new(London.Instance); testSpecProvider.TerminalTotalDifficulty = 10_000_000; Block newBestLocalBlock = Build.A.Block.WithNumber(localBlockTree.Head !.Number + 1).WithParent(localBlockTree.Head !).WithDifficulty(10_000_002L).TestObject; localBlockTree.SuggestBlock(newBestLocalBlock); PoSSwitcher poSSwitcher = new(new MergeConfig() { Enabled = true }, new SyncConfig(), new MemDb(), localBlockTree, testSpecProvider, LimboLogs.Instance); HeaderValidator headerValidator = new( localBlockTree, Always.Valid, testSpecProvider, LimboLogs.Instance); MergeHeaderValidator mergeHeaderValidator = new(poSSwitcher, headerValidator, localBlockTree, testSpecProvider, Always.Valid, LimboLogs.Instance); BlockValidator blockValidator = new( Always.Valid, mergeHeaderValidator, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance); ctx.SyncServer = new SyncServer( new MemDb(), new MemDb(), localBlockTree, NullReceiptStorage.Instance, blockValidator, Always.Valid, ctx.PeerPool, StaticSelector.Full, new SyncConfig(), NullWitnessCollector.Instance, Policy.FullGossip, testSpecProvider, LimboLogs.Instance); Block remoteBestBlock = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); ctx.SyncServer.AddNewBlock(remoteBestBlock, ctx.NodeWhoSentTheBlock); Assert.AreEqual(newBestLocalBlock.Header.Hash, localBlockTree.BestSuggestedHeader !.Hash); Assert.AreEqual(remoteBestBlock.Hash, localBlockTree.FindBlock(remoteBestBlock.Hash, BlockTreeLookupOptions.None) !.Hash); }
public void Can_accept_blocks_that_are_fine() { 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, Always.Valid, Always.Valid, _peerPool, StaticSelector.Full, new SyncConfig(), LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader, block.Header); }
public void Rejects_new_old_blocks() { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(600).TestObject; ISealValidator sealValidator = Substitute.For <ISealValidator>(); _syncServer = new SyncServer(new StateDb(), new StateDb(), localBlockTree, NullReceiptStorage.Instance, Always.Valid, sealValidator, _peerPool, StaticSelector.Full, new SyncConfig(), LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); _syncServer.AddNewBlock(block, _nodeWhoSentTheBlock); sealValidator.DidNotReceive().ValidateSeal(Arg.Any <BlockHeader>(), Arg.Any <bool>()); }
public void Can_reject_block_POW_block_after_TTD(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; Context ctx = CreateMergeContext(localBlockTree, (UInt256)ttd); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { block.Header.TotalDifficulty *= 2; } Assert.Throws <EthSyncException>(() => ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock)); Assert.AreEqual(localBlockTree.BestSuggestedHeader !.Number, 8); }
public void Can_accept_new_valid_blocks(bool sealOk, bool validationOk, bool accepted) { Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; ISealValidator sealValidator = sealOk ? Always.Valid : Always.Invalid; IBlockValidator blockValidator = validationOk ? Always.Valid : Always.Invalid; ctx.SyncServer = new SyncServer( new MemDb(), new MemDb(), localBlockTree, NullReceiptStorage.Instance, blockValidator, sealValidator, ctx.PeerPool, StaticSelector.Full, new SyncConfig(), NullWitnessCollector.Instance, Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (!accepted) { Assert.Throws <EthSyncException>(() => ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock)); } else { ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); } if (accepted) { Assert.AreEqual(localBlockTree.BestSuggestedHeader, block.Header); } else { Assert.AreNotEqual(localBlockTree.BestSuggestedHeader, block.Header); } }
public void Post_merge_blocks_wont_be_accepted_by_gossip(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; Block postMergeBlock = Build.A.Block.WithDifficulty(0).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty).WithNonce(0u).TestObject; remoteBlockTree.SuggestBlock(postMergeBlock); BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; Context ctx = CreateMergeContext(localBlockTree, (UInt256)ttd); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { block.Header.TotalDifficulty *= 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader !.Number, 8); localBlockTree.FindBlock(postMergeBlock.Hash !, BlockTreeLookupOptions.None).Should().BeNull(); }
public void Can_inject_terminal_block_with_higher_td_than_head(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; Block terminalBlockWithHigherTotalDifficulty = Build.A.Block.WithDifficulty(1000010).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + 1000010).TestObject; remoteBlockTree.SuggestBlock(terminalBlockWithHigherTotalDifficulty); BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; Context ctx = CreateMergeContext(localBlockTree, (UInt256)ttd); Assert.True(terminalBlockWithHigherTotalDifficulty.IsTerminalBlock(ctx.SpecProvider)); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { block.Header.TotalDifficulty *= 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader !.Number, 9); localBlockTree.FindBlock(terminalBlockWithHigherTotalDifficulty.Hash !, BlockTreeLookupOptions.None).Should().NotBeNull(); localBlockTree.BestSuggestedHeader !.Hash.Should().Be(terminalBlockWithHigherTotalDifficulty.Hash !); }