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

FCU should move GlobalWorldState Root #8154

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ protected IEngineRpcModule CreateEngineModule(MergeTestBlockchain chain, ISyncCo
peerRefresher,
chain.SpecProvider,
chain.SyncPeerPool,
chain.WorldStateManager.GlobalWorldState,
chain.LogManager,
new BlocksConfig().SecondsPerSlot),
new GetPayloadBodiesByHashV1Handler(chain.BlockTree, chain.LogManager),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using Nethermind.Merge.Plugin.Data;
using Nethermind.Merge.Plugin.InvalidChainTracker;
using Nethermind.Merge.Plugin.Synchronization;
using Nethermind.State;
using Nethermind.Synchronization.Peers;

namespace Nethermind.Merge.Plugin.Handlers;
Expand All @@ -34,57 +35,29 @@ namespace Nethermind.Merge.Plugin.Handlers;
/// <remarks>
/// May initiate a new payload creation.
/// </remarks>
public class ForkchoiceUpdatedHandler : IForkchoiceUpdatedHandler
public class ForkchoiceUpdatedHandler(
IBlockTree blockTree,
IManualBlockFinalizationManager manualBlockFinalizationManager,
IPoSSwitcher poSSwitcher,
IPayloadPreparationService payloadPreparationService,
IBlockProcessingQueue processingQueue,
IBlockCacheService blockCacheService,
IInvalidChainTracker invalidChainTracker,
IMergeSyncController mergeSyncController,
IBeaconPivot beaconPivot,
IPeerRefresher peerRefresher,
ISpecProvider specProvider,
ISyncPeerPool syncPeerPool,
IWorldState globalWorldState,
ILogManager logManager,
ulong secondsPerSlot,
bool simulateBlockProduction = false)
: IForkchoiceUpdatedHandler
{
protected readonly IBlockTree _blockTree;
private readonly IManualBlockFinalizationManager _manualBlockFinalizationManager;
private readonly IPoSSwitcher _poSSwitcher;
private readonly IPayloadPreparationService _payloadPreparationService;
private readonly IBlockProcessingQueue _processingQueue;
private readonly IBlockCacheService _blockCacheService;
private readonly IInvalidChainTracker _invalidChainTracker;
private readonly IMergeSyncController _mergeSyncController;
private readonly IBeaconPivot _beaconPivot;
private readonly ILogger _logger;
private readonly IPeerRefresher _peerRefresher;
private readonly ISpecProvider _specProvider;
private readonly bool _simulateBlockProduction;
private readonly ulong _secondsPerSlot;
private readonly ISyncPeerPool _syncPeerPool;

public ForkchoiceUpdatedHandler(
IBlockTree blockTree,
IManualBlockFinalizationManager manualBlockFinalizationManager,
IPoSSwitcher poSSwitcher,
IPayloadPreparationService payloadPreparationService,
IBlockProcessingQueue processingQueue,
IBlockCacheService blockCacheService,
IInvalidChainTracker invalidChainTracker,
IMergeSyncController mergeSyncController,
IBeaconPivot beaconPivot,
IPeerRefresher peerRefresher,
ISpecProvider specProvider,
ISyncPeerPool syncPeerPool,
ILogManager logManager,
ulong secondsPerSlot,
bool simulateBlockProduction = false)
{
_blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
_manualBlockFinalizationManager = manualBlockFinalizationManager ?? throw new ArgumentNullException(nameof(manualBlockFinalizationManager));
_poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher));
_payloadPreparationService = payloadPreparationService;
_processingQueue = processingQueue;
_blockCacheService = blockCacheService;
_invalidChainTracker = invalidChainTracker;
_mergeSyncController = mergeSyncController;
_beaconPivot = beaconPivot;
_peerRefresher = peerRefresher;
_specProvider = specProvider;
_syncPeerPool = syncPeerPool;
_simulateBlockProduction = simulateBlockProduction;
_secondsPerSlot = secondsPerSlot;
_logger = logManager.GetClassLogger();
}
protected readonly IBlockTree _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
private readonly IManualBlockFinalizationManager _manualBlockFinalizationManager = manualBlockFinalizationManager ?? throw new ArgumentNullException(nameof(manualBlockFinalizationManager));
private readonly IPoSSwitcher _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher));
private readonly ILogger _logger = logManager.GetClassLogger();

public async Task<ResultWrapper<ForkchoiceUpdatedV1Result>> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int version)
{
Expand Down Expand Up @@ -116,7 +89,7 @@ protected virtual bool IsOnMainChainBehindHead(Block newHeadBlock, ForkchoiceSta
default : // Don't boost priority if we are definitely syncing
Thread.CurrentThread.BoostPriority();

if (_invalidChainTracker.IsOnKnownInvalidChain(forkchoiceState.HeadBlockHash, out Hash256? lastValidHash))
if (invalidChainTracker.IsOnKnownInvalidChain(forkchoiceState.HeadBlockHash, out Hash256? lastValidHash))
{
if (_logger.IsWarn) _logger.Warn($"Received Invalid {forkchoiceState} {payloadAttributes} - {forkchoiceState.HeadBlockHash} is known to be a part of an invalid chain.");
return ForkchoiceUpdatedV1Result.Invalid(lastValidHash);
Expand All @@ -129,15 +102,15 @@ protected virtual bool IsOnMainChainBehindHead(Block newHeadBlock, ForkchoiceSta

BlockHeader? headBlockHeader = null;

if (_blockCacheService.BlockCache.TryGetValue(forkchoiceState.HeadBlockHash, out Block? block))
if (blockCacheService.BlockCache.TryGetValue(forkchoiceState.HeadBlockHash, out Block? block))
{
headBlockHeader = block.Header;
}

if (headBlockHeader is null)
{
if (_logger.IsDebug) _logger.Debug($"Attempting to fetch header from peer: {simpleRequestStr}.");
headBlockHeader = await _syncPeerPool.FetchHeaderFromPeer(forkchoiceState.HeadBlockHash);
headBlockHeader = await syncPeerPool.FetchHeaderFromPeer(forkchoiceState.HeadBlockHash);
}

if (headBlockHeader is not null)
Expand Down Expand Up @@ -185,7 +158,7 @@ protected virtual bool IsOnMainChainBehindHead(Block newHeadBlock, ForkchoiceSta
return ForkchoiceUpdatedV1Result.Syncing;
}

if (_beaconPivot.ShouldForceStartNewSync)
if (beaconPivot.ShouldForceStartNewSync)
{
if (_logger.IsInfo) _logger.Info("Force starting new sync.");

Expand All @@ -199,23 +172,23 @@ protected virtual bool IsOnMainChainBehindHead(Block newHeadBlock, ForkchoiceSta
ReorgBeaconChainDuringSync(newHeadBlock!, blockInfo);
}

int processingQueueCount = _processingQueue.Count;
int processingQueueCount = processingQueue.Count;
if (processingQueueCount == 0)
{
_peerRefresher.RefreshPeers(newHeadBlock!.Hash!, newHeadBlock.ParentHash!, finalizedBlockHash);
_blockCacheService.FinalizedHash = finalizedBlockHash;
_blockCacheService.HeadBlockHash = forkchoiceState.HeadBlockHash;
_mergeSyncController.StopBeaconModeControl();
peerRefresher.RefreshPeers(newHeadBlock!.Hash!, newHeadBlock.ParentHash!, finalizedBlockHash);
blockCacheService.FinalizedHash = finalizedBlockHash;
blockCacheService.HeadBlockHash = forkchoiceState.HeadBlockHash;
mergeSyncController.StopBeaconModeControl();

// Debug as already output in Received ForkChoice
if (_logger.IsDebug) _logger.Debug($"Syncing beacon headers, Request: {requestStr}");
}
else
{
if (_logger.IsInfo) _logger.Info($"Processing {_processingQueue.Count} blocks, Request: {requestStr}");
if (_logger.IsInfo) _logger.Info($"Processing {processingQueue.Count} blocks, Request: {requestStr}");
}

_beaconPivot.ProcessDestination ??= newHeadBlock!.Header;
beaconPivot.ProcessDestination ??= newHeadBlock!.Header;
return ForkchoiceUpdatedV1Result.Syncing;
}

Expand Down Expand Up @@ -259,6 +232,7 @@ protected virtual bool IsOnMainChainBehindHead(Block newHeadBlock, ForkchoiceSta
if (shouldUpdateHead)
{
_blockTree.UpdateMainChain(blocks!, true, true);
globalWorldState.StateRoot = newHeadBlock.StateRoot!;
LukaszRozmej marked this conversation as resolved.
Show resolved Hide resolved
}

if (IsInconsistent(finalizedBlockHash))
Expand Down Expand Up @@ -308,11 +282,11 @@ private ResultWrapper<ForkchoiceUpdatedV1Result> StartBuildingPayload(Block newH
{
string? payloadId = null;

if (_simulateBlockProduction)
if (simulateBlockProduction)
{
payloadAttributes ??= new PayloadAttributes()
{
Timestamp = newHeadBlock.Timestamp + _secondsPerSlot,
Timestamp = newHeadBlock.Timestamp + secondsPerSlot,
ParentBeaconBlockRoot = newHeadBlock.ParentHash, // it doesn't matter
PrevRandao = newHeadBlock.ParentHash ?? Keccak.Zero, // it doesn't matter
Withdrawals = [],
Expand All @@ -328,7 +302,7 @@ private ResultWrapper<ForkchoiceUpdatedV1Result> StartBuildingPayload(Block newH
return errorResult;
}

payloadId = _payloadPreparationService.StartPreparingPayload(newHeadBlock.Header, payloadAttributes);
payloadId = payloadPreparationService.StartPreparingPayload(newHeadBlock.Header, payloadAttributes);
}

_blockTree.ForkChoiceUpdated(forkchoiceState.FinalizedBlockHash, forkchoiceState.SafeBlockHash);
Expand All @@ -338,7 +312,7 @@ private ResultWrapper<ForkchoiceUpdatedV1Result> StartBuildingPayload(Block newH
private ResultWrapper<ForkchoiceUpdatedV1Result>? ValidateAttributes(PayloadAttributes? payloadAttributes, int version)
{
string? error = null;
return payloadAttributes?.Validate(_specProvider, version, out error) switch
return payloadAttributes?.Validate(specProvider, version, out error) switch
{
PayloadAttributesValidationResult.InvalidParams =>
ResultWrapper<ForkchoiceUpdatedV1Result>.Fail(error!, ErrorCodes.InvalidParams),
Expand All @@ -352,11 +326,11 @@ private ResultWrapper<ForkchoiceUpdatedV1Result> StartBuildingPayload(Block newH

private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, BlockHeader blockHeader, string requestStr)
{
bool isSyncInitialized = _mergeSyncController.TryInitBeaconHeaderSync(blockHeader);
_beaconPivot.ProcessDestination = blockHeader;
_peerRefresher.RefreshPeers(blockHeader.Hash!, blockHeader.ParentHash!, forkchoiceState.FinalizedBlockHash);
_blockCacheService.FinalizedHash = forkchoiceState.FinalizedBlockHash;
_blockCacheService.HeadBlockHash = forkchoiceState.HeadBlockHash;
bool isSyncInitialized = mergeSyncController.TryInitBeaconHeaderSync(blockHeader);
beaconPivot.ProcessDestination = blockHeader;
peerRefresher.RefreshPeers(blockHeader.Hash!, blockHeader.ParentHash!, forkchoiceState.FinalizedBlockHash);
blockCacheService.FinalizedHash = forkchoiceState.FinalizedBlockHash;
blockCacheService.HeadBlockHash = forkchoiceState.HeadBlockHash;

if (isSyncInitialized && _logger.IsInfo) _logger.Info($"Start a new sync process, Request: {requestStr}.");
}
Expand Down Expand Up @@ -434,8 +408,8 @@ private void ReorgBeaconChainDuringSync(Block newHeadBlock, BlockInfo newHeadBlo
{
if (_logger.IsInfo) _logger.Info("BeaconChain reorged during the sync or cache rebuilt");
BlockInfo[] beaconMainChainBranch = GetBeaconChainBranch(newHeadBlock, newHeadBlockInfo);
_blockTree.UpdateBeaconMainChain(beaconMainChainBranch, Math.Max(_beaconPivot.ProcessDestination?.Number ?? 0, newHeadBlock.Number));
_beaconPivot.ProcessDestination = newHeadBlock.Header;
_blockTree.UpdateBeaconMainChain(beaconMainChainBranch, Math.Max(beaconPivot.ProcessDestination?.Number ?? 0, newHeadBlock.Number));
beaconPivot.ProcessDestination = newHeadBlock.Header;
}

private BlockInfo[] GetBeaconChainBranch(Block newHeadBlock, BlockInfo newHeadBlockInfo)
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ public Task InitRpcModules()
if (_api.TxPool is null) throw new ArgumentNullException(nameof(_api.TxPool));
if (_api.SpecProvider is null) throw new ArgumentNullException(nameof(_api.SpecProvider));
if (_api.StateReader is null) throw new ArgumentNullException(nameof(_api.StateReader));
if (_api.WorldStateManager is null) throw new ArgumentNullException(nameof(_api.WorldStateManager));
if (_beaconPivot is null) throw new ArgumentNullException(nameof(_beaconPivot));
if (_beaconSync is null) throw new ArgumentNullException(nameof(_beaconSync));
if (_peerRefresher is null) throw new ArgumentNullException(nameof(_peerRefresher));
Expand Down Expand Up @@ -357,6 +358,7 @@ IBlockImprovementContextFactory CreateBlockImprovementContextFactory()
_peerRefresher,
_api.SpecProvider,
_api.SyncPeerPool!,
_api.WorldStateManager.GlobalWorldState,
_api.LogManager,
_api.Config<IBlocksConfig>().SecondsPerSlot,
_api.Config<IMergeConfig>().SimulateBlockProduction),
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ public async Task InitRpcModules()
ArgumentNullException.ThrowIfNull(_api.RpcModuleProvider);
ArgumentNullException.ThrowIfNull(_api.BlockProducer);
ArgumentNullException.ThrowIfNull(_api.TxPool);
ArgumentNullException.ThrowIfNull(_api.WorldStateManager);

ArgumentNullException.ThrowIfNull(_beaconSync);
ArgumentNullException.ThrowIfNull(_beaconPivot);
Expand Down Expand Up @@ -265,6 +266,7 @@ public async Task InitRpcModules()
_peerRefresher,
_api.SpecProvider,
_api.SyncPeerPool!,
_api.WorldStateManager.GlobalWorldState,
_api.LogManager,
_api.Config<IBlocksConfig>().SecondsPerSlot,
_api.Config<IMergeConfig>().SimulateBlockProduction),
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Taiko.Test/TaikoEngineApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Nethermind.Core.Test.Builders;
using Nethermind.Merge.Plugin.Data;
using Nethermind.JsonRpc;
using Nethermind.State;
using Nethermind.Taiko.Rpc;

namespace Nethermind.Taiko.Test;
Expand Down Expand Up @@ -47,6 +48,7 @@ public async Task Test_ForkchoiceUpdatedHandler_Allows_UnknownFinalizedSafeBlock
Substitute.For<IPeerRefresher>(),
Substitute.For<ISpecProvider>(),
Substitute.For<ISyncPeerPool>(),
Substitute.For<IWorldState>(),
Substitute.For<ILogManager>(),
12UL, // secondsPerSlot
false // simulateBlockProduction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Nethermind.Merge.Plugin.Synchronization;
using Nethermind.Synchronization.Peers;
using System.Diagnostics.CodeAnalysis;
using Nethermind.State;

namespace Nethermind.Taiko.Rpc;

Expand All @@ -33,6 +34,7 @@ internal class TaikoForkchoiceUpdatedHandler(IBlockTree blockTree,
IPeerRefresher peerRefresher,
ISpecProvider specProvider,
ISyncPeerPool syncPeerPool,
IWorldState globalWorldState,
ILogManager logManager,
ulong secondsPerSlot,
bool simulateBlockProduction = false) : ForkchoiceUpdatedHandler(blockTree,
Expand All @@ -47,6 +49,7 @@ internal class TaikoForkchoiceUpdatedHandler(IBlockTree blockTree,
peerRefresher,
specProvider,
syncPeerPool,
globalWorldState,
logManager,
secondsPerSlot,
simulateBlockProduction)
Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Taiko/TaikoPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ public async Task InitRpcModules()
_peerRefresher,
_api.SpecProvider,
_api.SyncPeerPool,
_api.WorldStateManager.GlobalWorldState,
_api.LogManager,
_api.Config<IBlocksConfig>().SecondsPerSlot,
_api.Config<IMergeConfig>().SimulateBlockProduction),
Expand Down
Loading