Skip to content

Commit

Permalink
use head - 64
Browse files Browse the repository at this point in the history
  • Loading branch information
marcindsobczak committed Oct 11, 2024
1 parent 23a2a6f commit db45de3
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using Nethermind.Logging;
using Nethermind.Merge.Plugin.Handlers;
using Nethermind.Merge.Plugin.Synchronization;
using Nethermind.Optimism;
using Nethermind.Serialization.Rlp;
using Nethermind.Specs;
using Nethermind.Specs.Forks;
Expand Down Expand Up @@ -93,34 +92,34 @@ public void TrySetFreshPivot_saves_FinalizedHash_in_db()
expectedPivotBlockNumber.Should().Be(storedPivotBlockNumber);
}

[Test]
public void TrySetFreshPivot_for_optimism_saves_HeadBlockHash_in_db()
{
OptimismPivotUpdator optimismPivotUpdator = new(
_blockTree!,
_syncModeSelector!,
_syncPeerPool!,
_syncConfig!,
_blockCacheService!,
_beaconSyncStrategy!,
_metadataDb!,
LimboLogs.Instance
);

SyncModeChangedEventArgs args = new(SyncMode.FastSync, SyncMode.UpdatingPivot);
Hash256 expectedHeadBlockHash = _externalPeerBlockTree!.HeadHash;
long expectedPivotBlockNumber = _externalPeerBlockTree!.Head!.Number;
_beaconSyncStrategy!.GetHeadBlockHash().Returns(expectedHeadBlockHash);

_syncModeSelector!.Changed += Raise.EventWith(args);

byte[] storedData = _metadataDb!.Get(MetadataDbKeys.UpdatedPivotData)!;
RlpStream pivotStream = new(storedData!);
long storedPivotBlockNumber = pivotStream.DecodeLong();
Hash256 storedHeadBlockHash = pivotStream.DecodeKeccak()!;

storedHeadBlockHash.Should().Be(expectedHeadBlockHash);
expectedPivotBlockNumber.Should().Be(storedPivotBlockNumber);
}
// [Test]
// public void TrySetFreshPivot_for_optimism_saves_HeadBlockHash_in_db()
// {
// UnsafePivotUpdator unsafePivotUpdator = new(
// _blockTree!,
// _syncModeSelector!,
// _syncPeerPool!,
// _syncConfig!,
// _blockCacheService!,
// _beaconSyncStrategy!,
// _metadataDb!,
// LimboLogs.Instance
// );
//
// SyncModeChangedEventArgs args = new(SyncMode.FastSync, SyncMode.UpdatingPivot);
// Hash256 expectedHeadBlockHash = _externalPeerBlockTree!.HeadHash;
// long expectedPivotBlockNumber = _externalPeerBlockTree!.Head!.Number;
// _beaconSyncStrategy!.GetHeadBlockHash().Returns(expectedHeadBlockHash);
//
// _syncModeSelector!.Changed += Raise.EventWith(args);
//
// byte[] storedData = _metadataDb!.Get(MetadataDbKeys.UpdatedPivotData)!;
// RlpStream pivotStream = new(storedData!);
// long storedPivotBlockNumber = pivotStream.DecodeLong();
// Hash256 storedHeadBlockHash = pivotStream.DecodeKeccak()!;
//
// storedHeadBlockHash.Should().Be(expectedHeadBlockHash);
// expectedPivotBlockNumber.Should().Be(storedPivotBlockNumber);
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public class PivotUpdator
{
private readonly IBlockTree _blockTree;
private readonly ISyncModeSelector _syncModeSelector;
private readonly ISyncPeerPool _syncPeerPool;
protected readonly ISyncPeerPool _syncPeerPool;
private readonly ISyncConfig _syncConfig;
private readonly IBlockCacheService _blockCacheService;
protected readonly IBeaconSyncStrategy _beaconSyncStrategy;
private readonly IDb _metadataDb;
private readonly ILogger _logger;
protected readonly ILogger _logger;

private readonly CancellationTokenSource _cancellation = new();

Expand Down Expand Up @@ -125,7 +125,7 @@ private async void OnSyncModeChanged(object? sender, SyncModeChangedEventArgs sy

private async Task<bool> TrySetFreshPivot(CancellationToken cancellationToken)
{
Hash256? potentialPivotBlockHash = TryGetPotentialPivotBlockHashFromCl();
Hash256? potentialPivotBlockHash = await TryGetPotentialPivotBlockHash(cancellationToken);

if (potentialPivotBlockHash is null || potentialPivotBlockHash == Keccak.Zero)
{
Expand All @@ -139,30 +139,19 @@ private async Task<bool> TrySetFreshPivot(CancellationToken cancellationToken)
return potentialPivotBlockNumber is not null && TryOverwritePivot(potentialPivotBlockHash, (long)potentialPivotBlockNumber);
}

private Hash256? TryGetPotentialPivotBlockHashFromCl()
protected virtual Task<Hash256?> TryGetPotentialPivotBlockHash(CancellationToken cancellationToken)
{
Hash256? potentialPivotBlockHash = GetPotentialPivotBlockHash();

if (potentialPivotBlockHash is null || potentialPivotBlockHash == Keccak.Zero)
{
if (_logger.IsInfo && (_maxAttempts - _attemptsLeft) % 10 == 0) _logger.Info($"Waiting for Forkchoice message from Consensus Layer to set fresh pivot block [{_maxAttempts - _attemptsLeft}s]");

return null;
}
// getting finalized block hash as it is safe, because can't be reorganized
Hash256? finalizedBlockHash = _beaconSyncStrategy.GetFinalizedHash();

if (_alreadyAnnouncedNewPivotHash != potentialPivotBlockHash)
if (finalizedBlockHash is null || finalizedBlockHash == Keccak.Zero)
{
if (_logger.IsInfo) _logger.Info($"Potential new pivot block hash: {potentialPivotBlockHash}");
_alreadyAnnouncedNewPivotHash = potentialPivotBlockHash;
PrintWaitingForMessageFromCl();
return Task.FromResult<Hash256?>(null);
}

return potentialPivotBlockHash;
}

protected virtual Hash256? GetPotentialPivotBlockHash()
{
// getting finalized block hash as it is safe, because can't be reorganized
return _beaconSyncStrategy.GetFinalizedHash();
UpdateAndPrintPotentialNewPivot(finalizedBlockHash);
return Task.FromResult<Hash256?>(finalizedBlockHash);
}

private long? TryGetPotentialPivotBlockNumberFromBlockCache(Hash256 potentialPivotBlockHash)
Expand Down Expand Up @@ -227,7 +216,7 @@ private async Task<bool> TrySetFreshPivot(CancellationToken cancellationToken)
}
}

if (_logger.IsInfo && (_maxAttempts - _attemptsLeft) % 10 == 0) _logger.Info($"Potential new pivot block hash: {potentialPivotBlockHash}. Waiting for pivot block header [{_maxAttempts - _attemptsLeft}s]");
PrintPotentialNewPivotAndWaiting(potentialPivotBlockHash.ToString());
return null;
}

Expand Down Expand Up @@ -262,4 +251,22 @@ private void UpdateConfigValues(Hash256 finalizedBlockHash, long finalizedBlockN
_syncConfig.MaxAttemptsToUpdatePivot = 0;
}

protected void PrintWaitingForMessageFromCl()
{
if (_logger.IsInfo && (_maxAttempts - _attemptsLeft) % 10 == 0) _logger.Info($"Waiting for Forkchoice message from Consensus Layer to set fresh pivot block [{_maxAttempts - _attemptsLeft}s]");
}

protected void PrintPotentialNewPivotAndWaiting(string potentialPivotBlockHash)
{
if (_logger.IsInfo && (_maxAttempts - _attemptsLeft) % 10 == 0) _logger.Info($"Potential new pivot block: {potentialPivotBlockHash}. Waiting for pivot block header [{_maxAttempts - _attemptsLeft}s]");
}

protected void UpdateAndPrintPotentialNewPivot(Hash256 finalizedBlockHash)
{
if (_alreadyAnnouncedNewPivotHash != finalizedBlockHash)
{
if (_logger.IsInfo) _logger.Info($"Potential new pivot block hash: {finalizedBlockHash}");
_alreadyAnnouncedNewPivotHash = finalizedBlockHash;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Threading;
using System.Threading.Tasks;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Synchronization;
using Nethermind.Consensus.Validators;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Db;
using Nethermind.Logging;
using Nethermind.Merge.Plugin.Handlers;
using Nethermind.Synchronization;
using Nethermind.Synchronization.ParallelSync;
using Nethermind.Synchronization.Peers;

namespace Nethermind.Merge.Plugin.Synchronization;

public class UnsafePivotUpdator(
IBlockTree blockTree,
ISyncModeSelector syncModeSelector,
ISyncPeerPool syncPeerPool,
ISyncConfig syncConfig,
IBlockCacheService blockCacheService,
IBeaconSyncStrategy beaconSyncStrategy,
IDb metadataDb,
ILogManager logManager)
: PivotUpdator(blockTree, syncModeSelector, syncPeerPool, syncConfig,
blockCacheService, beaconSyncStrategy, metadataDb, logManager)
{

private const int NumberOfBlocksBehindHeadForSettingPivot = 64;

protected override async Task<Hash256?> TryGetPotentialPivotBlockHash(CancellationToken cancellationToken)
{
// getting potentially unsafe head block hash, because some chains (e.g. optimism) aren't providing finalized block hash until fully synced
Hash256? headBlockHash = _beaconSyncStrategy.GetHeadBlockHash();

if (headBlockHash is not null
&& headBlockHash != Keccak.Zero)
{
long headBlockNumber = await TryGetHeadBlockNumberFromPeers(headBlockHash, cancellationToken);
if (headBlockNumber > NumberOfBlocksBehindHeadForSettingPivot)
{
long potentialPivotBlockNumber = headBlockNumber - NumberOfBlocksBehindHeadForSettingPivot;

Hash256? potentialPivotBlockHash = await TryGetPotentialPivotBlockHashFromPeers(potentialPivotBlockNumber, cancellationToken);

if (potentialPivotBlockHash is not null
&& potentialPivotBlockHash != Keccak.Zero)
{
UpdateAndPrintPotentialNewPivot(potentialPivotBlockHash);
return potentialPivotBlockHash;
}
}
}

PrintWaitingForMessageFromCl();
return null;
}

private async Task<long> TryGetHeadBlockNumberFromPeers(Hash256 headBlockHash, CancellationToken cancellationToken)
{
foreach (PeerInfo peer in _syncPeerPool.InitializedPeers)
{
if (cancellationToken.IsCancellationRequested)
{
return 0;
}
try
{
if (_logger.IsInfo) _logger.Info($"Asking peer {peer.SyncPeer.Node.ClientId} for header of head block {headBlockHash}");
BlockHeader? headBlockHeader = await peer.SyncPeer.GetHeadBlockHeader(headBlockHash, cancellationToken);
if (headBlockHeader is not null)
{
if (HeaderValidator.ValidateHash(headBlockHeader))
{
if (_logger.IsInfo) _logger.Info($"Received header of head block from peer {peer.SyncPeer.Node.ClientId}");
return headBlockHeader.Number;
}
if (_logger.IsInfo) _logger.Info($"Hash of header received from peer {peer.SyncPeer.Node.ClientId} is {headBlockHeader.Hash} when expecting {headBlockHash}");
}
}
catch (Exception exception) when (exception is TimeoutException or OperationCanceledException)
{
if (_logger.IsInfo) _logger.Info($"Peer {peer.SyncPeer.Node.ClientId} didn't respond to request for header of head block {headBlockHash}");
if (_logger.IsDebug) _logger.Debug($"Exception in GetHeadBlockHeader request to peer {peer.SyncPeer.Node.ClientId}. {exception}");
}
}

return 0;
}

private async Task<Hash256?> TryGetPotentialPivotBlockHashFromPeers(long potentialPivotBlockNumber, CancellationToken cancellationToken)
{
foreach (PeerInfo peer in _syncPeerPool.InitializedPeers)
{
if (cancellationToken.IsCancellationRequested)
{
return null;
}
try
{
if (_logger.IsInfo) _logger.Info($"Asking peer {peer.SyncPeer.Node.ClientId} for header of pivot block {potentialPivotBlockNumber}");
BlockHeader? potentialPivotBlockHeader = (await peer.SyncPeer.GetBlockHeaders(potentialPivotBlockNumber, 1, 0, cancellationToken))?[0];
if (potentialPivotBlockHeader is not null)
{
if (HeaderValidator.ValidateHash(potentialPivotBlockHeader))
{
if (_logger.IsInfo) _logger.Info($"Received header of pivot block from peer {peer.SyncPeer.Node.ClientId}");
return potentialPivotBlockHeader.Hash;
}
if (_logger.IsInfo) _logger.Info($"Header received from peer {peer.SyncPeer.Node.ClientId} wasn't valid");
}
}
catch (Exception exception) when (exception is TimeoutException or OperationCanceledException)
{
if (_logger.IsInfo) _logger.Info($"Peer {peer.SyncPeer.Node.ClientId} didn't respond to request for header of pivot block {potentialPivotBlockNumber}");
if (_logger.IsDebug) _logger.Debug($"Exception in GetHeadBlockHeader request to peer {peer.SyncPeer.Node.ClientId}. {exception}");
}
}

PrintPotentialNewPivotAndWaiting(potentialPivotBlockNumber.ToString());
return null;
}
}
34 changes: 0 additions & 34 deletions src/Nethermind/Nethermind.Optimism/OptimismPivotUpdator.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public Task InitSynchronization()
_api.LogManager
);

_ = new OptimismPivotUpdator(
_ = new UnsafePivotUpdator(
_api.BlockTree,
_api.Synchronizer.SyncModeSelector,
_api.SyncPeerPool,
Expand Down

0 comments on commit db45de3

Please sign in to comment.