diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index f6c7a951f22..f3b9cb9e8ce 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -1308,6 +1308,34 @@ public void Cannot_insert_genesis() Assert.Throws(() => tree.Insert(new[] { genesis })); } + [Test, Timeout(Timeout.MaxTestTime)] + public void Should_set_zero_total_difficulty() + { + MemDb blocksDb = new(); + MemDb blockInfosDb = new(); + MemDb headersDb = new(); + MemDb metadataDb = new(); + + long pivotNumber = 0L; + + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = pivotNumber.ToString(); + + CustomSpecProvider specProvider = new(((ForkActivation)0, London.Instance)); + specProvider.UpdateMergeTransitionInfo(null, 0); + + BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, + new ChainLevelInfoRepository(blockInfosDb), specProvider, + NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); + Block genesis = Build.A.Block.WithDifficulty(0).TestObject; + tree.SuggestBlock(genesis).Should().Be(AddBlockResult.Added); + tree.FindBlock(genesis.Hash, BlockTreeLookupOptions.None)!.TotalDifficulty.Should().Be(UInt256.Zero); + + Block A = Build.A.Block.WithParent(genesis).WithDifficulty(0).TestObject; + tree.SuggestBlock(A).Should().Be(AddBlockResult.Added); + tree.FindBlock(A.Hash, BlockTreeLookupOptions.None)!.TotalDifficulty.Should().Be(UInt256.Zero); + } + [Test, Timeout(Timeout.MaxTestTime)] public void Can_batch_insert_blocks() { diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index de61be4ff50..9ed7fefc14b 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -886,8 +886,7 @@ public AddBlockResult SuggestBlock(Block block, BlockTreeSuggestOptions options } else { - if (blockInfo.TotalDifficulty != UInt256.Zero || header.IsGenesis) - header.TotalDifficulty = blockInfo.TotalDifficulty; + SetTotalDifficultyFromBlockInfo(header, blockInfo); } if (requiresCanonical) @@ -1834,8 +1833,7 @@ private bool ShouldCache(long number) } else { - if (blockInfo.TotalDifficulty != UInt256.Zero || block.IsGenesis) - block.Header.TotalDifficulty = blockInfo.TotalDifficulty; + SetTotalDifficultyFromBlockInfo(block.Header, blockInfo); } if (requiresCanonical) @@ -1854,6 +1852,33 @@ private bool ShouldCache(long number) return block; } + private bool IsTotalDifficultyAlwaysZero() + { + // In some Ethereum tests and possible testnets difficulty of all blocks might be zero + // We also checking TTD is zero to ensure that block after genesis have zero difficulty + return Genesis?.Difficulty == 0 && _specProvider.TerminalTotalDifficulty == 0; + } + + private void SetTotalDifficultyFromBlockInfo(BlockHeader header, BlockInfo blockInfo) + { + if (header.IsGenesis) + { + header.TotalDifficulty = header.Difficulty; + return; + } + + if (blockInfo.TotalDifficulty != UInt256.Zero) + { + header.TotalDifficulty = blockInfo.TotalDifficulty; + return; + } + + if (IsTotalDifficultyAlwaysZero()) + { + header.TotalDifficulty = 0; + } + } + private void SetTotalDifficulty(BlockHeader header) { if (header.IsGenesis) @@ -1863,9 +1888,7 @@ private void SetTotalDifficulty(BlockHeader header) return; } - // In some Ethereum tests and possible testnets difficulty of all blocks might be zero - // We also checking TTD is zero to ensure that block after genesis have zero difficulty - if (Genesis!.Difficulty == 0 && _specProvider.TerminalTotalDifficulty == 0) + if (IsTotalDifficultyAlwaysZero()) { header.TotalDifficulty = 0; if (_logger.IsTrace) _logger.Trace($"Block {header} has zero total difficulty");