Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

+6 hive tests. Merge/two blocks #4106

Merged
merged 12 commits into from
Jun 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Blockchain/BlockTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,7 @@ private ChainLevelInfo UpdateOrCreateLevel(long number, Keccak hash, BlockInfo b
return level;
}
}
public (BlockInfo Info, ChainLevelInfo Level) GetInfo(long number, Keccak blockHash) => LoadInfo(number, blockHash, true);

private (BlockInfo Info, ChainLevelInfo Level) LoadInfo(long number, Keccak blockHash, bool forceLoad)
{
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Blockchain/IBlockTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ public interface IBlockTree : IBlockFinder

UInt256? BackFillTotalDifficulty(long startNumber, long endNumber, long batchSize, UInt256? startingTotalDifficulty = null);

(BlockInfo Info, ChainLevelInfo Level) GetInfo(long number, Keccak blockHash);

ChainLevelInfo? FindLevel(long number);

BlockInfo FindCanonicalBlockInfo(long blockNumber);
Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public BlockHeader? LowestInsertedBeaconHeader
public Block Head => _wrapped.Head;
public void MarkChainAsProcessed(Block[] blocks) => throw new InvalidOperationException($"{nameof(ReadOnlyBlockTree)} does not expect {nameof(MarkChainAsProcessed)} calls");
public UInt256? BackFillTotalDifficulty(long startNumber, long endNumber, long batchSize, UInt256? startingTotalDifficulty = null) => throw new InvalidOperationException();
public (BlockInfo Info, ChainLevelInfo Level) GetInfo(long number, Keccak blockHash) => _wrapped.GetInfo(number, blockHash);
public UInt256? UpdateTotalDifficulty(Block block, UInt256 totalDifficulty) => throw new InvalidOperationException();
public bool CanAcceptNewBlocks { get; } = false;

Expand Down
5 changes: 5 additions & 0 deletions src/Nethermind/Nethermind.Core/BlockInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public bool IsFinalized
}
}
}

public bool IsBeaconInfo
{
get => (Metadata & (BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader)) != 0;
}

public BlockMetadata Metadata { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ protected override BlockProcessor CreateBlockProcessor()
private IBlockValidator CreateBlockValidator()
{
IBlockCacheService blockCacheService = new BlockCacheService();
PoSSwitcher = new PoSSwitcher(MergeConfig, SyncConfig.Default, new MemDb(), BlockTree, SpecProvider, blockCacheService, LogManager);
PoSSwitcher = new PoSSwitcher(MergeConfig, SyncConfig.Default, new MemDb(), BlockTree, SpecProvider, LogManager);
SealValidator = new MergeSealValidator(PoSSwitcher, Always.Valid);
HeaderValidator = new MergeHeaderValidator(PoSSwitcher, BlockTree, SpecProvider, SealValidator, LogManager);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private static PoSSwitcher CreatePosSwitcher()
specProvider.TerminalTotalDifficulty = 2;
MergeConfig? mergeConfig = new() {Enabled = true };
IBlockCacheService blockCacheService = new BlockCacheService();
return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider, blockCacheService, LimboLogs.Instance);
return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider, LimboLogs.Instance);
}

}
Expand Down
10 changes: 5 additions & 5 deletions src/Nethermind/Nethermind.Merge.Plugin.Test/PoSSwitcherTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void Initial_TTD_should_be_null()
{
UInt256? expectedTtd = null;
IBlockTree blockTree = Substitute.For<IBlockTree>();
PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, MainnetSpecProvider.Instance, _blockCacheService, LimboLogs.Instance);
PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, MainnetSpecProvider.Instance, LimboLogs.Instance);

Assert.AreEqual(expectedTtd, poSSwitcher.TerminalTotalDifficulty);
}
Expand All @@ -62,7 +62,7 @@ public void Read_TTD_from_chainspec_if_not_specified_in_merge_config()
ChainSpec chainSpec = loader.Load(File.ReadAllText(path));

ChainSpecBasedSpecProvider specProvider = new(chainSpec);
PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, specProvider, _blockCacheService, LimboLogs.Instance);
PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, specProvider, LimboLogs.Instance);

Assert.AreEqual(expectedTtd, poSSwitcher.TerminalTotalDifficulty);
Assert.AreEqual(101, specProvider.MergeBlockNumber);
Expand Down Expand Up @@ -110,7 +110,7 @@ public void Override_TTD_and_number_from_merge_config()
IBlockTree blockTree = Substitute.For<IBlockTree>();
TestSpecProvider specProvider = new(London.Instance);
specProvider.UpdateMergeTransitionInfo(100, 20);
PoSSwitcher poSSwitcher = new(new MergeConfig() {TerminalTotalDifficulty = "340", TerminalBlockNumber = 2000}, new SyncConfig(), new MemDb(), blockTree, specProvider, _blockCacheService, LimboLogs.Instance);
PoSSwitcher poSSwitcher = new(new MergeConfig() {TerminalTotalDifficulty = "340", TerminalBlockNumber = 2000}, new SyncConfig(), new MemDb(), blockTree, specProvider, LimboLogs.Instance);

Assert.AreEqual(expectedTtd, poSSwitcher.TerminalTotalDifficulty);
Assert.AreEqual(2001, specProvider.MergeBlockNumber);
Expand All @@ -123,7 +123,7 @@ public void Can_update_merge_transition_info()
IBlockTree blockTree = Substitute.For<IBlockTree>();
TestSpecProvider specProvider = new(London.Instance);
specProvider.UpdateMergeTransitionInfo(2001, expectedTtd);
PoSSwitcher poSSwitcher = new(new MergeConfig() {}, new SyncConfig(), new MemDb(), blockTree, specProvider, _blockCacheService, LimboLogs.Instance);
PoSSwitcher poSSwitcher = new(new MergeConfig() {}, new SyncConfig(), new MemDb(), blockTree, specProvider, LimboLogs.Instance);

Assert.AreEqual(expectedTtd, poSSwitcher.TerminalTotalDifficulty);
Assert.AreEqual(2001, specProvider.MergeBlockNumber);
Expand Down Expand Up @@ -198,7 +198,7 @@ private static PoSSwitcher CreatePosSwitcher(IBlockTree blockTree, IDb? db = nul
{
db ??= new MemDb();
MergeConfig? mergeConfig = new() {Enabled = true};
return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider ?? MainnetSpecProvider.Instance, _blockCacheService, LimboLogs.Instance);
return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider ?? MainnetSpecProvider.Instance, LimboLogs.Instance);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public Context(
_mergeConfig = mergeConfig ?? new MergeConfig();
_metadataDb = metadataDb ?? new MemDb();
PoSSwitcher poSSwitcher = new(_mergeConfig, _syncConfig, _metadataDb, blockTree!,
MainnetSpecProvider.Instance, new BlockCacheService(), LimboLogs.Instance);
MainnetSpecProvider.Instance, LimboLogs.Instance);

ProgressTracker progressTracker = new(BlockTree, stateDb, LimboLogs.Instance);

Expand Down Expand Up @@ -122,7 +122,7 @@ public async Task Can_keep_returning_nulls_after_all_batches_were_prepared()
PivotTotalDifficulty = "1000"
};
PoSSwitcher poSSwitcher = new(new MergeConfig(), syncConfig, memDbProvider.MetadataDb, blockTree!,
MainnetSpecProvider.Instance, new BlockCacheService(), LimboLogs.Instance);
MainnetSpecProvider.Instance, LimboLogs.Instance);
IBeaconPivot pivot = PreparePivot(2000, syncConfig, blockTree);
BeaconHeadersSyncFeed feed = new(poSSwitcher, Substitute.For<ISyncModeSelector>(), blockTree,
Substitute.For<ISyncPeerPool>(), syncConfig, Substitute.For<ISyncReport>(),
Expand Down Expand Up @@ -155,7 +155,7 @@ public async Task Finishes_when_all_downloaded()
PivotTotalDifficulty = "1000"
};
PoSSwitcher poSSwitcher = new(new MergeConfig(), syncConfig, new MemDb(), blockTree!,
MainnetSpecProvider.Instance, new BlockCacheService(), LimboLogs.Instance);
MainnetSpecProvider.Instance, LimboLogs.Instance);
IBeaconPivot pivot = PreparePivot(2000, syncConfig, blockTree);
BeaconHeadersSyncFeed feed = new (poSSwitcher, Substitute.For<ISyncModeSelector>(), blockTree, Substitute.For<ISyncPeerPool>(), syncConfig, report, pivot, new MergeConfig() {Enabled = true}, LimboLogs.Instance);
feed.InitializeFeed();
Expand Down
15 changes: 12 additions & 3 deletions src/Nethermind/Nethermind.Merge.Plugin/MergeGossipPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,25 @@
using System;
using Nethermind.Consensus;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Merge.Plugin.Handlers;

namespace Nethermind.Merge.Plugin
{
public class MergeGossipPolicy : IGossipPolicy
{
private readonly IGossipPolicy _preMergeGossipPolicy;
private readonly IPoSSwitcher _poSSwitcher;
private readonly IBlockCacheService _blockCacheService;

public MergeGossipPolicy(
IGossipPolicy? apiGossipPolicy,
IPoSSwitcher? poSSwitcher)
IPoSSwitcher? poSSwitcher,
IBlockCacheService blockCacheService)
{
_preMergeGossipPolicy = apiGossipPolicy ?? throw new ArgumentNullException(nameof(apiGossipPolicy));
_poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher));
_blockCacheService = blockCacheService ?? throw new ArgumentNullException(nameof(blockCacheService));
}

// According to spec (https://github.com/ethereum/EIPs/blob/d896145678bd65d3eafd8749690c1b5228875c39/EIPS/eip-3675.md#network)
Expand All @@ -41,10 +46,14 @@ public MergeGossipPolicy(

// ...and gossipping policy will be decided according to the header difficulty.
public bool ShouldGossipBlock(BlockHeader header) => !_poSSwitcher.GetBlockConsensusInfo(header).IsPostMerge;

// According to spec (https://github.com/ethereum/EIPs/blob/d896145678bd65d3eafd8749690c1b5228875c39/EIPS/eip-3675.md#network)
// We MUST discard NewBlock/NewBlockHash messages after receiving FIRST_FINALIZED_BLOCK.
public bool ShouldDiscardBlocks => _poSSwitcher.TransitionFinished;
public bool ShouldDiscardBlocks => _poSSwitcher.TransitionFinished ||
_blockCacheService.FinalizedHash != Keccak.Zero; /* _blockCacheService.FinalizedHash != Keccak.Zero - this condition was added for edge case situation.
We started beacon sync, and we hadn't reached transition yet. If CL sent us non zero finalization hash, it would mean that network reached transition.
However, in edge case situation (verified by merge hive tests), our node needs to be reorged to PoW again, so we can't add this condition _blockCacheService.FinalizedHash != Keccak.Zero
to PoSSwitcher.TransitionFinished. On the other hand, we don't want to receive any blocks from the network, so we want to discard blocks. */

// According to spec (https://github.com/ethereum/EIPs/blob/d896145678bd65d3eafd8749690c1b5228875c39/EIPS/eip-3675.md#network)
// We SHOULD start disconnecting gossiping peers after receiving next finalized block to FIRST_FINALIZED_BLOCK, so one block after we started discarding NewBlock/NewBlockHash messages.
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ public Task Init(INethermindApi nethermindApi)

_blockCacheService = new BlockCacheService();
_poSSwitcher = new PoSSwitcher(_mergeConfig, _syncConfig,
_api.DbProvider.GetDb<IDb>(DbNames.Metadata), _api.BlockTree, _api.SpecProvider, _blockCacheService, _api.LogManager);
_api.DbProvider.GetDb<IDb>(DbNames.Metadata), _api.BlockTree, _api.SpecProvider, _api.LogManager);
_blockFinalizationManager = new ManualBlockFinalizationManager();

_api.RewardCalculatorSource = new MergeRewardCalculatorSource(
_api.RewardCalculatorSource ?? NoBlockRewards.Instance, _poSSwitcher);
_api.SealValidator = new MergeSealValidator(_poSSwitcher, _api.SealValidator);

_api.GossipPolicy = new MergeGossipPolicy(_api.GossipPolicy, _poSSwitcher);
_api.GossipPolicy = new MergeGossipPolicy(_api.GossipPolicy, _poSSwitcher, _blockCacheService);

_api.BlockPreprocessor.AddFirst(new MergeProcessingRecoveryStep(_poSSwitcher));
}
Expand Down
5 changes: 1 addition & 4 deletions src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ public class PoSSwitcher : IPoSSwitcher
private readonly IDb _metadataDb;
private readonly IBlockTree _blockTree;
private readonly ISpecProvider _specProvider;
private readonly IBlockCacheService _blockCacheService;
private readonly ILogger _logger;
private Keccak? _terminalBlockHash;

Expand All @@ -72,15 +71,13 @@ public PoSSwitcher(
IDb metadataDb,
IBlockTree blockTree,
ISpecProvider specProvider,
IBlockCacheService blockCacheService,
ILogManager logManager)
{
_mergeConfig = mergeConfig;
_syncConfig = syncConfig;
_metadataDb = metadataDb;
_blockTree = blockTree;
_specProvider = specProvider;
_blockCacheService = blockCacheService;
_logger = logManager.GetClassLogger();

Initialize();
Expand Down Expand Up @@ -184,7 +181,7 @@ public void ForkchoiceUpdated(BlockHeader newHeadHash, Keccak finalizedHash)
}
}

public bool TransitionFinished => FinalTotalDifficulty != null || _finalizedBlockHash != Keccak.Zero || _blockCacheService.FinalizedHash != Keccak.Zero;
public bool TransitionFinished => FinalTotalDifficulty != null || _finalizedBlockHash != Keccak.Zero;

public (bool IsTerminal, bool IsPostMerge) GetBlockConsensusInfo(BlockHeader header)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
using Nethermind.Blockchain;
using Nethermind.Blockchain.Synchronization;
using Nethermind.Core;
using Nethermind.Crypto;
using Nethermind.Core.Crypto;
using Nethermind.Logging;

namespace Nethermind.Merge.Plugin.Synchronization;

public interface IChainLevelHelper
{
BlockHeader[] GetNextHeaders(int maxCount);
BlockHeader[]? GetNextHeaders(int maxCount);

Block[] GetNextBlocks(int maxCount);
Block[]? GetNextBlocks(int maxCount);
}

public class ChainLevelHelper : IChainLevelHelper
Expand All @@ -47,7 +47,7 @@ public ChainLevelHelper(
_logger = logManager.GetClassLogger();
}

public BlockHeader[] GetNextHeaders(int maxCount)
public BlockHeader[]? GetNextHeaders(int maxCount)
{
long? startingPoint = GetStartingPoint();
if (startingPoint == null)
Expand Down Expand Up @@ -84,7 +84,7 @@ public BlockHeader[] GetNextHeaders(int maxCount)
}
}

if ((beaconMainChainBlock.Metadata & (BlockMetadata.BeaconHeader | BlockMetadata.BeaconBody)) != 0)
if (beaconMainChainBlock.IsBeaconInfo)
newHeader.TotalDifficulty = beaconMainChainBlock.TotalDifficulty == 0 ? null : beaconMainChainBlock.TotalDifficulty;
if (_logger.IsTrace)
_logger.Trace(
Expand All @@ -100,7 +100,7 @@ public BlockHeader[] GetNextHeaders(int maxCount)
return headers.ToArray();
}

public Block[] GetNextBlocks(int maxCount)
public Block[]? GetNextBlocks(int maxCount)
{
long? startingPoint = GetStartingPoint();
if (startingPoint == null)
Expand Down Expand Up @@ -144,29 +144,39 @@ public Block[] GetNextBlocks(int maxCount)
private long? GetStartingPoint()
{
long startingPoint = _blockTree.BestKnownNumber + 1;
bool parentBlockExists;
bool foundBeaconBlock;
ChainLevelInfo? startingLevel = _blockTree.FindLevel(startingPoint);
BlockInfo? beaconMainChainBlock = startingLevel?.BeaconMainChainBlock;
if (beaconMainChainBlock == null)
{
if (_logger.IsTrace) _logger.Trace($"Beacon main chain block for number {startingPoint} was not found");
return null;
}

Keccak currentHash = startingLevel?.BeaconMainChainBlock!.BlockHash!;
// in normal situation we will have one iteration of this loop, in some cases a few. Thanks to that we don't need to add extra pointer to manage forward syncing
do
{
BlockHeader? header = _blockTree.FindHeader(startingPoint, BlockTreeLookupOptions.None);
BlockHeader? header = _blockTree.FindHeader(currentHash!, BlockTreeLookupOptions.None);
if (header == null)
{
if (_logger.IsTrace) _logger.Trace($"Header for number {startingPoint} was not found");
return null;
}

Block? block = _blockTree.FindBlock(header.ParentHash ?? header.CalculateHash());
parentBlockExists = block != null;
BlockInfo blockInfo = (_blockTree.GetInfo( header.Number - 1, header.ParentHash!)).Info;
foundBeaconBlock = blockInfo.IsBeaconInfo;
if (_logger.IsTrace)
_logger.Trace(
$"Searching for starting point on level {startingPoint}. Header: {header.ToString(BlockHeader.Format.FullHashAndNumber)}, Block: {block?.ToString(Block.Format.FullHashAndNumber)}");
$"Searching for starting point on level {startingPoint}. Header: {header.ToString(BlockHeader.Format.FullHashAndNumber)}, BlockInfo: {blockInfo?.ToString()}");
--startingPoint;
currentHash = header.ParentHash!;
if (_syncConfig.FastSync && startingPoint <= _syncConfig.PivotNumberParsed)
{
if (_logger.IsTrace) _logger.Trace($"Reached syncConfig pivot. Starting point: {startingPoint}");
break;
}
} while (!parentBlockExists);
} while (foundBeaconBlock);

return startingPoint;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,8 @@ bool HasMoreToSync()
{
if (_logger.IsDebug)
_logger.Debug($"Continue full sync with {bestPeer} (our best {_blockTree.BestKnownNumber})");

long upperDownloadBoundary = _blockTree.BestKnownBeaconNumber;
long blocksLeft = upperDownloadBoundary - currentNumber;
int headersToRequest = (int)Math.Min(blocksLeft + 1, _syncBatchSize.Current);
if (headersToRequest <= 1)
{
break;
}

headersToRequest = Math.Min(headersToRequest, bestPeer.MaxHeadersPerRequest());


int headersToRequest = Math.Min(_syncBatchSize.Current, bestPeer.MaxHeadersPerRequest());
if (_logger.IsTrace)
_logger.Trace(
$"Full sync request {currentNumber}+{headersToRequest} to peer {bestPeer} with {bestPeer.HeadNumber} blocks. Got {currentNumber} and asking for {headersToRequest} more.");
Expand All @@ -132,7 +123,7 @@ bool HasMoreToSync()
_logger.Trace(
$"Downloading blocks from peer. CurrentNumber: {currentNumber}, BeaconPivot: {_beaconPivot.PivotNumber}, BestPeer: {bestPeer}, HeaderToRequest: {headersToRequest}");

BlockHeader[] headers = _chainLevelHelper.GetNextHeaders(headersToRequest);
BlockHeader[]? headers = _chainLevelHelper.GetNextHeaders(headersToRequest);
if (headers == null || headers.Length == 0)
break;
BlockDownloadContext context = new(_specProvider, bestPeer, headers, downloadReceipts,
Expand Down
Loading