diff --git a/src/Nethermind/Nethermind.Api/IApiWithNetwork.cs b/src/Nethermind/Nethermind.Api/IApiWithNetwork.cs index 20b0bd847d9..5abb6d545e6 100644 --- a/src/Nethermind/Nethermind.Api/IApiWithNetwork.cs +++ b/src/Nethermind/Nethermind.Api/IApiWithNetwork.cs @@ -47,6 +47,7 @@ public interface IApiWithNetwork : IApiWithBlockchain ISynchronizer? Synchronizer { get; } ISyncModeSelector SyncModeSelector { get; } ISyncProgressResolver? SyncProgressResolver { get; } + ISyncPointers? SyncPointers { get; } IPivot? Pivot { get; set; } ISyncPeerPool? SyncPeerPool { get; } IPeerDifficultyRefreshPool? PeerDifficultyRefreshPool { get; } diff --git a/src/Nethermind/Nethermind.Api/IBasicApi.cs b/src/Nethermind/Nethermind.Api/IBasicApi.cs index 47bd60ab5bf..4ae6be45f4c 100644 --- a/src/Nethermind/Nethermind.Api/IBasicApi.cs +++ b/src/Nethermind/Nethermind.Api/IBasicApi.cs @@ -7,6 +7,7 @@ using Autofac; using Nethermind.Abi; using Nethermind.Api.Extensions; +using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; using Nethermind.Core; @@ -63,6 +64,7 @@ public ContainerBuilder ConfigureContainerBuilderFromBasicApi(ContainerBuilder b builder .AddPropertiesFrom(this) .AddSingleton(ConfigProvider.GetConfig()) + .AddSingleton(ConfigProvider.GetConfig()) .AddModule(new DbModule()); return builder; diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index fa3299fc4b1..5e9e0618b91 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -190,6 +190,7 @@ public ISealEngine SealEngine public ISyncModeSelector SyncModeSelector => ApiWithNetworkServiceContainer?.Resolve()!; public ISyncProgressResolver? SyncProgressResolver => ApiWithNetworkServiceContainer?.Resolve(); + public ISyncPointers? SyncPointers => ApiWithNetworkServiceContainer?.Resolve(); public IBetterPeerStrategy? BetterPeerStrategy { get; set; } public IPivot? Pivot { get; set; } public ISyncPeerPool? SyncPeerPool => ApiWithNetworkServiceContainer?.Resolve(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index fd64cb15cf7..22a50743061 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -1170,47 +1170,38 @@ public void Loads_lowest_inserted_header_correctly(long beginIndex, long inserte Assert.That(loadedTree.LowestInsertedHeader?.Number, Is.EqualTo(expectedResult), "loaded tree"); } - [Test, MaxTime(Timeout.MaxTestTime), TestCaseSource(nameof(SourceOfBSearchTestCases))] - public void Loads_lowest_inserted_body_correctly(long beginIndex, long insertedBlocks) + [TestCase(5, 10)] + [TestCase(10, 10)] + [TestCase(12, 0)] + public void Does_not_load_bestKnownNumber_before_syncPivot(long syncPivot, long expectedBestKnownNumber) { - // left old code to prove that it does not matter for the result nowadays - // we store and no longer binary search lowest body number - - MemDb blocksDb = new(); - blocksDb.Set(BlockTree.LowestInsertedBodyNumberDbEntryAddress, Rlp.Encode(1L).Bytes); - SyncConfig syncConfig = new() { - PivotNumber = beginIndex.ToString(), + FastSync = true, + PivotNumber = $"{syncPivot}" }; - BlockTreeBuilder builder = Build.A.BlockTree() - .WithBlocksDb(blocksDb) - .WithSyncConfig(syncConfig) - .WithoutSettingHead; - - BlockTree tree = builder.TestObject; - - tree.SuggestBlock(Build.A.Block.Genesis.TestObject); + MemDb blockInfosDb = new MemDb(); + MemDb headersDb = new MemDb(); + MemDb blockDb = new MemDb(); - for (long i = beginIndex; i > beginIndex - insertedBlocks; i--) - { - Block block = Build.A.Block.WithNumber(i).WithTotalDifficulty(i).TestObject; - tree.Insert(block.Header); - tree.Insert(block); - } + _ = Build.A.BlockTree() + .WithHeadersDb(headersDb) + .WithBlockInfoDb(blockInfosDb) + .WithBlocksDb(blockDb) + .OfChainLength(11) + .TestObject; - BlockTree loadedTree = Build.A.BlockTree() - .WithoutSettingHead - .WithDatabaseFrom(builder) + BlockTree tree = Build.A.BlockTree() .WithSyncConfig(syncConfig) + .WithHeadersDb(headersDb) + .WithBlockInfoDb(blockInfosDb) + .WithBlocksDb(blockDb) .TestObject; - Assert.That(tree.LowestInsertedBodyNumber, Is.EqualTo(null), "tree"); - Assert.That(loadedTree.LowestInsertedBodyNumber, Is.EqualTo(1), "loaded tree"); + Assert.That(tree.BestKnownNumber, Is.EqualTo(expectedBestKnownNumber)); } - private static readonly object[] SourceOfBSearchTestCases = { new object[] {1L, 0L}, @@ -1362,7 +1353,6 @@ public void Loads_best_known_correctly_on_inserts_followed_by_suggests(long pivo Assert.That(tree.BestKnownNumber, Is.EqualTo(pivotNumber + 1), "tree"); Assert.That(tree.LowestInsertedHeader?.Number, Is.EqualTo(1), "loaded tree - lowest header"); - Assert.That(tree.LowestInsertedBodyNumber, Is.EqualTo(null), "loaded tree - lowest body"); Assert.That(loadedTree.BestKnownNumber, Is.EqualTo(pivotNumber + 1), "loaded tree"); } diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs index e335bbf59cc..ef52ac0b413 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs @@ -16,7 +16,6 @@ public partial class BlockTree public void RecalculateTreeLevels() { - LoadLowestInsertedBodyNumber(); LoadLowestInsertedHeader(); LoadLowestInsertedBeaconHeader(); LoadBestKnown(); @@ -115,13 +114,6 @@ private void LoadForkChoiceInfo() SafeHash ??= _metadataDb.Get(MetadataDbKeys.SafeBlockHash)?.AsRlpStream().DecodeKeccak(); } - private void LoadLowestInsertedBodyNumber() - { - LowestInsertedBodyNumber = - _blockStore.GetMetadata(LowestInsertedBodyNumberDbEntryAddress)? - .AsRlpValueContext().DecodeLong(); - } - private void LoadLowestInsertedBeaconHeader() { if (_metadataDb.KeyExists(MetadataDbKeys.LowestInsertedBeaconHeaderHash)) @@ -148,30 +140,15 @@ private void LoadBestKnown() long right = Math.Max(0, left) + BestKnownSearchLimit; - long bestKnownNumberFound = - BinarySearchBlockNumber(1, left, LevelExists) ?? 0; - long bestKnownNumberAlternative = - BinarySearchBlockNumber(left, right, LevelExists) ?? 0; - - long bestSuggestedHeaderNumber = - BinarySearchBlockNumber(1, left, HeaderExists) ?? 0; - long bestSuggestedHeaderNumberAlternative - = BinarySearchBlockNumber(left, right, HeaderExists) ?? 0; - - long bestSuggestedBodyNumber - = BinarySearchBlockNumber(1, left, BodyExists) ?? 0; - long bestSuggestedBodyNumberAlternative - = BinarySearchBlockNumber(left, right, BodyExists) ?? 0; + long bestKnownNumberFound = BinarySearchBlockNumber(left, right, LevelExists) ?? 0; + long bestSuggestedHeaderNumber = BinarySearchBlockNumber(left, right, HeaderExists) ?? 0; + long bestSuggestedBodyNumber = BinarySearchBlockNumber(left, right, BodyExists) ?? 0; if (_logger.IsInfo) _logger.Info("Numbers resolved, " + - $"level = Max({bestKnownNumberFound}, {bestKnownNumberAlternative}), " + - $"header = Max({bestSuggestedHeaderNumber}, {bestSuggestedHeaderNumberAlternative}), " + - $"body = Max({bestSuggestedBodyNumber}, {bestSuggestedBodyNumberAlternative})"); - - bestKnownNumberFound = Math.Max(bestKnownNumberFound, bestKnownNumberAlternative); - bestSuggestedHeaderNumber = Math.Max(bestSuggestedHeaderNumber, bestSuggestedHeaderNumberAlternative); - bestSuggestedBodyNumber = Math.Max(bestSuggestedBodyNumber, bestSuggestedBodyNumberAlternative); + $"level = {bestKnownNumberFound}, " + + $"header = {bestSuggestedHeaderNumber}, " + + $"body = {bestSuggestedBodyNumber}"); if (bestKnownNumberFound < 0 || bestSuggestedHeaderNumber < 0 || @@ -195,7 +172,7 @@ long bestSuggestedBodyNumberAlternative } } - BestKnownNumber = Math.Max(bestKnownNumberFound, bestKnownNumberAlternative); + BestKnownNumber = bestKnownNumberFound; BestSuggestedHeader = FindHeader(bestSuggestedHeaderNumber, BlockTreeLookupOptions.None); BlockHeader? bestSuggestedBodyHeader = FindHeader(bestSuggestedBodyNumber, BlockTreeLookupOptions.None); BestSuggestedBody = bestSuggestedBodyHeader is null diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 3b278d2c8a2..e9d685a5df3 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -34,7 +34,6 @@ namespace Nethermind.Blockchain public partial class BlockTree : IBlockTree { // there is not much logic in the addressing here - public static readonly byte[] LowestInsertedBodyNumberDbEntryAddress = ((long)0).ToBigEndianByteArrayWithoutLeadingZeros(); private static readonly byte[] StateHeadHashDbEntryAddress = new byte[16]; internal static Hash256 DeletePointerAddressInDb = new(new BitArray(32 * 8, true).ToBytes()); internal static Hash256 HeadAddressInDb = Keccak.Zero; @@ -79,22 +78,8 @@ public BlockHeader? LowestInsertedBeaconHeader private BlockHeader? _lowestInsertedBeaconHeader; - private long? _lowestInsertedReceiptBlock; private long? _highestPersistedState; - public long? LowestInsertedBodyNumber - { - get => _lowestInsertedReceiptBlock; - set - { - _lowestInsertedReceiptBlock = value; - if (value.HasValue) - { - _blockStore.SetMetadata(LowestInsertedBodyNumberDbEntryAddress, Rlp.Encode(value.Value).Bytes); - } - } - } - public long BestKnownNumber { get; private set; } public long BestKnownBeaconNumber { get; private set; } @@ -169,7 +154,6 @@ public BlockTree( $"best queued is {BestSuggestedHeader?.Number.ToString() ?? "0"}, " + $"best known is {BestKnownNumber}, " + $"lowest inserted header {LowestInsertedHeader?.Number}, " + - $"body {LowestInsertedBodyNumber}, " + $"lowest sync inserted block number {LowestInsertedBeaconHeader?.Number}"); ProductInfo.Network = $"{(ChainId == NetworkId ? BlockchainIds.GetBlockchainName(NetworkId) : ChainId)}"; ThisNodeInfo.AddInfo("Chain ID :", ProductInfo.Network); diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTreeExtensions.cs b/src/Nethermind/Nethermind.Blockchain/BlockTreeExtensions.cs index 99412dc594b..a0f7a216525 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTreeExtensions.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTreeExtensions.cs @@ -10,5 +10,14 @@ public static class BlockTreeExtensions public static ReadOnlyBlockTree AsReadOnly(this IBlockTree blockTree) => new(blockTree); public static BlockHeader? GetProducedBlockParent(this IBlockTree blockTree, BlockHeader? parentHeader) => parentHeader ?? blockTree.Head?.Header; + + public static (bool isSyncing, long headNumber, long bestSuggested) IsSyncing(this IBlockTree blockTree, int maxDistanceForSynced = 0) + { + long bestSuggestedNumber = blockTree.FindBestSuggestedHeader()?.Number ?? 0; + long headNumberOrZero = blockTree.Head?.Number ?? 0; + bool isSyncing = bestSuggestedNumber == 0 || bestSuggestedNumber > headNumberOrZero + maxDistanceForSynced; + + return (isSyncing, headNumberOrZero, bestSuggestedNumber); + } } } diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTreeOverlay.cs b/src/Nethermind/Nethermind.Blockchain/BlockTreeOverlay.cs index 214a0ada99e..7f73af6a73d 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTreeOverlay.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTreeOverlay.cs @@ -32,12 +32,6 @@ public BlockTreeOverlay(IReadOnlyBlockTree baseTree, IBlockTree overlayTree) public BlockHeader? BestSuggestedBeaconHeader => _overlayTree.BestSuggestedBeaconHeader ?? _baseTree.BestSuggestedBeaconHeader; public BlockHeader? LowestInsertedHeader => _overlayTree.LowestInsertedHeader ?? _baseTree.LowestInsertedHeader; - public long? LowestInsertedBodyNumber - { - get => _overlayTree.LowestInsertedBodyNumber ?? _baseTree.LowestInsertedBodyNumber; - set => _overlayTree.LowestInsertedBodyNumber = value; - } - public BlockHeader? LowestInsertedBeaconHeader { get => _overlayTree.LowestInsertedBeaconHeader ?? _baseTree.LowestInsertedBeaconHeader; diff --git a/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs b/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs index d72ce5f9224..eca635bc9d2 100644 --- a/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs +++ b/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs @@ -19,9 +19,5 @@ public interface IBlockStore byte[]? GetRlp(long blockNumber, Hash256 blockHash); ReceiptRecoveryBlock? GetReceiptRecoveryBlock(long blockNumber, Hash256 blockHash); void Cache(Block block); - - // These two are used by blocktree. Try not to use them... - void SetMetadata(byte[] key, byte[] value); - byte[]? GetMetadata(byte[] key); bool HasBlock(long blockNumber, Hash256 blockHash); } diff --git a/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs b/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs index 3c90e3dc736..77cccd0e7d5 100644 --- a/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs +++ b/src/Nethermind/Nethermind.Blockchain/ChainHeadInfoProvider.cs @@ -17,6 +17,10 @@ namespace Nethermind.Blockchain { public class ChainHeadInfoProvider : IChainHeadInfoProvider { + private readonly IBlockTree _blockTree; + // For testing + public bool HasSynced { private get; init; } + public ChainHeadInfoProvider(ISpecProvider specProvider, IBlockTree blockTree, IStateReader stateReader, ICodeInfoRepository codeInfoRepository) : this(new ChainHeadSpecProvider(specProvider, blockTree), blockTree, new ChainHeadReadOnlyStateProvider(blockTree, stateReader), codeInfoRepository) { @@ -35,6 +39,7 @@ public ChainHeadInfoProvider(IChainHeadSpecProvider specProvider, IBlockTree blo CodeInfoRepository = codeInfoRepository; blockTree.BlockAddedToMain += OnHeadChanged; + _blockTree = blockTree; } public IChainHeadSpecProvider SpecProvider { get; } @@ -51,6 +56,20 @@ public ChainHeadInfoProvider(IChainHeadSpecProvider specProvider, IBlockTree blo public UInt256 CurrentFeePerBlobGas { get; internal set; } + public bool IsSyncing + { + get + { + if (HasSynced) + { + return false; + } + + (bool isSyncing, _, _) = _blockTree.IsSyncing(maxDistanceForSynced: 2); + return isSyncing; + } + } + public event EventHandler? HeadChanged; private void OnHeadChanged(object? sender, BlockReplacementEventArgs e) diff --git a/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs index 006f2de938b..b5948a00f07 100644 --- a/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs @@ -47,11 +47,6 @@ public interface IBlockTree : IBlockFinder /// BlockHeader? LowestInsertedHeader { get; } - /// - /// Lowest body added in reverse fast sync insert - /// - long? LowestInsertedBodyNumber { get; set; } - /// /// Lowest header number added in reverse beacon sync insert. Used to determine if BeaconHeaderSync is completed. /// diff --git a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs index 45aa4969678..04864e33179 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs @@ -32,12 +32,6 @@ public ReadOnlyBlockTree(IBlockTree wrapped) public BlockHeader BestSuggestedBeaconHeader => _wrapped.BestSuggestedBeaconHeader; public BlockHeader LowestInsertedHeader => _wrapped.LowestInsertedHeader; - public long? LowestInsertedBodyNumber - { - get => _wrapped.LowestInsertedBodyNumber; - set => _wrapped.LowestInsertedBodyNumber = value; - } - public long? BestPersistedState { get => _wrapped.BestPersistedState; diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs index dc59a7ddc25..bcfaab6a6ec 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs @@ -11,7 +11,6 @@ public interface IReceiptStorage : IReceiptFinder { void Insert(Block block, params TxReceipt[]? txReceipts) => Insert(block, txReceipts, true); void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical, WriteFlags writeFlags = WriteFlags.None); - long? LowestInsertedReceiptBlockNumber { get; set; } long MigratedBlockNumber { get; set; } bool HasBlock(long blockNumber, Hash256 hash); void EnsureCanonical(Block block); diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs index a7610ab4fde..21e2e55948b 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs @@ -87,8 +87,6 @@ public void EnsureCanonical(Block block) } } - public long? LowestInsertedReceiptBlockNumber { get; set; } - public long MigratedBlockNumber { get; set; } public int Count => _transactions.Count; diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs index 1b6ce91a6f2..81dc6ea4043 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs @@ -33,12 +33,6 @@ public bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out Rece return false; } - public long? LowestInsertedReceiptBlockNumber - { - get => 0; - set { } - } - public long MigratedBlockNumber { get; set; } = 0; public bool HasBlock(long blockNumber, Hash256 hash) diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index dd389bf0d17..87e9d16a997 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -25,7 +25,6 @@ public class PersistentReceiptStorage : IReceiptStorage private readonly IColumnsDb _database; private readonly ISpecProvider _specProvider; private readonly IReceiptsRecovery _receiptsRecovery; - private long? _lowestInsertedReceiptBlock; private readonly IDb _blocksDb; private readonly IDb _defaultColumn; private readonly IDb _transactionDb; @@ -65,8 +64,6 @@ public PersistentReceiptStorage( _storageDecoder = storageDecoder ?? ReceiptArrayStorageDecoder.Instance; _receiptConfig = receiptConfig ?? throw new ArgumentNullException(nameof(receiptConfig)); - byte[] lowestBytes = _defaultColumn.Get(Keccak.Zero); - _lowestInsertedReceiptBlock = lowestBytes is null ? (long?)null : new RlpStream(lowestBytes).DecodeLong(); _migratedBlockNumber = Get(MigrationBlockNumberKey, long.MaxValue); KeyValuePair? firstValue = _blocksDb.GetAll().FirstOrDefault(); @@ -302,19 +299,6 @@ public void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical = } } - public long? LowestInsertedReceiptBlockNumber - { - get => _lowestInsertedReceiptBlock; - set - { - _lowestInsertedReceiptBlock = value; - if (value.HasValue) - { - _defaultColumn.Set(Keccak.Zero, Rlp.Encode(value.Value).Bytes); - } - } - } - public long MigratedBlockNumber { get => _migratedBlockNumber; diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index f2dc73eb650..4694d5ead47 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -161,4 +161,7 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "_Technical._ Min distance of state sync from best suggested header.", DefaultValue = "32", HiddenFromDocs = true)] int StateMinDistanceFromHead { get; set; } + + [ConfigItem(Description = "_Technical._ Run explicit GC after state sync finished.", DefaultValue = "true", HiddenFromDocs = true)] + bool GCOnFeedFinished { get; set; } } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index 8e3cc5c125b..6ce0c295c5e 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -72,6 +72,7 @@ public string? PivotHash public bool TrieHealing { get; set; } = true; public int StateMaxDistanceFromHead { get; set; } = 128; public int StateMinDistanceFromHead { get; set; } = 32; + public bool GCOnFeedFinished { get; set; } = true; public override string ToString() { diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs index 53b97a680b4..9643fb56daa 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; using System.Timers; using Nethermind.Blockchain; @@ -67,8 +68,7 @@ public CliqueBlockProducerRunner( _timer.Start(); } - private readonly BlockingCollection _signalsQueue = - new(new ConcurrentQueue()); + private readonly Channel _signalsQueue = Channel.CreateUnbounded(); private Block? _scheduledBlock; @@ -91,7 +91,7 @@ public void UncastVote(Address signer) public void ProduceOnTopOf(Hash256 hash) { - _signalsQueue.Add(_blockTree.FindBlock(hash, BlockTreeLookupOptions.None)); + _signalsQueue.Writer.TryWrite(_blockTree.FindBlock(hash, BlockTreeLookupOptions.None)); } public IReadOnlyDictionary GetProposals() => _blockProducer.Proposals.ToDictionary(); @@ -111,7 +111,7 @@ private void TimerOnElapsed(object sender, ElapsedEventArgs e) { if (_blockTree.Head.Timestamp + _config.BlockPeriod < _timestamper.UnixTime.Seconds) { - _signalsQueue.Add(_blockTree.FindBlock(_blockTree.Head.Hash, BlockTreeLookupOptions.None)); + _signalsQueue.Writer.TryWrite(_blockTree.FindBlock(_blockTree.Head.Hash, BlockTreeLookupOptions.None)); } _timer.Enabled = true; @@ -216,17 +216,17 @@ private Task RunConsumeSignal() private void BlockTreeOnNewHeadBlock(object? sender, BlockEventArgs e) { - _signalsQueue.Add(e.Block); + _signalsQueue.Writer.TryWrite(e.Block); } private async Task ConsumeSignal() { _lastProducedBlock = DateTime.UtcNow; - foreach (Block signal in _signalsQueue.GetConsumingEnumerable(_cancellationTokenSource.Token)) + await foreach (Block signal in _signalsQueue.Reader.ReadAllAsync(_cancellationTokenSource.Token)) { // TODO: Maybe use IBlockProducer specific to clique? Block parentBlock = signal; - while (_signalsQueue.TryTake(out Block? nextSignal)) + while (_signalsQueue.Reader.TryRead(out Block? nextSignal)) { if (parentBlock.Number <= nextSignal.Number) { @@ -259,6 +259,7 @@ public async Task StopAsync() _blockTree.NewHeadBlock -= BlockTreeOnNewHeadBlock; _cancellationTokenSource?.Cancel(); await (_producerTask ?? Task.CompletedTask); + _signalsQueue.Writer.TryComplete(); } bool IBlockProducerRunner.IsProducingBlocks(ulong? maxProducingInterval) @@ -273,11 +274,12 @@ bool IBlockProducerRunner.IsProducingBlocks(ulong? maxProducingInterval) public event EventHandler? BlockProduced; - public void Dispose() { _cancellationTokenSource?.Dispose(); _timer?.Dispose(); + _signalsQueue.Writer.TryComplete(); + BlockProduced = null; } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs b/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs index 018da79aa26..ace943c6a4c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/CensorshipDetector/CensorshipDetector.cs @@ -69,13 +69,8 @@ public CensorshipDetector( private bool IsSyncing() { - long bestSuggestedNumber = _blockTree.FindBestSuggestedHeader()?.Number ?? 0; - if (bestSuggestedNumber == 0) - { - return true; - } - long headNumberOrZero = _blockTree.Head?.Number ?? 0; - return bestSuggestedNumber > headNumberOrZero; + (bool isSyncing, _, _) = _blockTree.IsSyncing(); + return isSyncing; } private void OnBlockProcessing(object? sender, BlockEventArgs e) diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index d8411dcd46d..cb721272e2a 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -320,7 +320,7 @@ protected virtual TxPool.TxPool CreateTxPool(CodeInfoRepository codeInfoReposito new( EthereumEcdsa, new BlobTxStorage(), - new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(SpecProvider), BlockTree, ReadOnlyState, codeInfoRepository), + new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(SpecProvider), BlockTree, ReadOnlyState, codeInfoRepository) { HasSynced = true }, new TxPoolConfig { BlobsSupport = BlobsSupportMode.InMemory }, new TxValidator(SpecProvider.ChainId), LogManager, diff --git a/src/Nethermind/Nethermind.Core.Test/CachedBlockTreeBuilder.cs b/src/Nethermind/Nethermind.Core.Test/CachedBlockTreeBuilder.cs new file mode 100644 index 00000000000..143f360b202 --- /dev/null +++ b/src/Nethermind/Nethermind.Core.Test/CachedBlockTreeBuilder.cs @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Blockchain; +using Nethermind.Core.Test.Builders; +using Nethermind.Db; +using NonBlocking; + +namespace Nethermind.Core.Test; + +public class CachedBlockTreeBuilder +{ + private static ConcurrentDictionary _cachedDbs = new(); + private record CachedDb( + MemDb blocksDb, + MemDb metadataDb, + MemDb headersDb, + MemDb blockNumbersDb, + MemDb blockInfo + ); + + public static IBlockTree BuildCached(string key, Func blockTreeBuilderFactory) + { + if (_cachedDbs.TryGetValue(key, out CachedDb? db)) + { + return Build.A.BlockTree() + .WithBlocksDb(MemDb.CopyFrom(db.blocksDb)) + .WithMetadataDb(MemDb.CopyFrom(db.metadataDb)) + .WithHeadersDb(MemDb.CopyFrom(db.headersDb)) + .WithBlocksNumberDb(MemDb.CopyFrom(db.blockNumbersDb)) + .WithBlockInfoDb(MemDb.CopyFrom(db.blockInfo)) + .TestObject; + } + else + { + BlockTreeBuilder builder = blockTreeBuilderFactory(); + CachedDb cachedValue = new CachedDb( + MemDb.CopyFrom(builder.BlocksDb), + MemDb.CopyFrom(builder.MetadataDb), + MemDb.CopyFrom(builder.HeadersDb), + MemDb.CopyFrom(builder.BlockNumbersDb), + MemDb.CopyFrom(builder.BlockInfoDb) + ); + _cachedDbs.GetOrAdd(key, cachedValue); + + return builder.TestObject; + } + } + + public static IBlockTree OfLength(int length) + { + return BuildCached($"{nameof(CachedBlockTreeBuilder)}-{length}", () => Build.A.BlockTree().OfChainLength(length)); + } +} diff --git a/src/Nethermind/Nethermind.Core/Caching/ClockCache.cs b/src/Nethermind/Nethermind.Core/Caching/ClockCache.cs index 8d30ef44fce..774b36c8cfa 100644 --- a/src/Nethermind/Nethermind.Core/Caching/ClockCache.cs +++ b/src/Nethermind/Nethermind.Core/Caching/ClockCache.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; - +using System.Runtime.InteropServices; using Nethermind.Core.Collections; using Nethermind.Core.Threading; @@ -24,7 +24,7 @@ public TValue Get(TKey key) { if (MaxCapacity == 0) return default!; - if (_cacheMap.TryGetValue(key, out LruCacheItem? ov)) + if (_cacheMap.TryGetValue(key, out LruCacheItem ov)) { MarkAccessed(ov.Offset); return ov.Value; @@ -37,7 +37,7 @@ public bool TryGet(TKey key, out TValue value) value = default!; if (MaxCapacity == 0) return false; - if (_cacheMap.TryGetValue(key, out LruCacheItem? ov)) + if (_cacheMap.TryGetValue(key, out LruCacheItem ov)) { MarkAccessed(ov.Offset); value = ov.Value; @@ -56,9 +56,9 @@ public bool Set(TKey key, TValue val) return Delete(key); } - if (_cacheMap.TryGetValue(key, out LruCacheItem? ov)) + if (_cacheMap.TryGetValue(key, out LruCacheItem ov)) { - ov.Value = val; + _cacheMap[key] = new(val, ov.Offset); MarkAccessed(ov.Offset); return false; } @@ -71,9 +71,9 @@ private bool SetSlow(TKey key, TValue val) using var lockRelease = _lock.Acquire(); // Recheck under lock - if (_cacheMap.TryGetValue(key, out LruCacheItem? ov)) + if (_cacheMap.TryGetValue(key, out LruCacheItem ov)) { - ov.Value = val; + _cacheMap[key] = new(val, ov.Offset); MarkAccessed(ov.Offset); return false; } @@ -89,7 +89,7 @@ private bool SetSlow(TKey key, TValue val) offset = Replace(key); } - _cacheMap[key] = new LruCacheItem(offset, val); + _cacheMap[key] = new(val, offset); KeyToOffset[offset] = key; _count++; Debug.Assert(_cacheMap.Count == _count); @@ -138,7 +138,7 @@ public bool Delete(TKey key) using var lockRelease = _lock.Acquire(); - if (_cacheMap.Remove(key, out LruCacheItem? ov)) + if (_cacheMap.Remove(key, out LruCacheItem ov)) { _count--; KeyToOffset[ov.Offset] = default; @@ -166,9 +166,10 @@ public bool Contains(TKey key) return _cacheMap.ContainsKey(key); } - private class LruCacheItem(int offset, TValue v) + [StructLayout(LayoutKind.Auto)] + private readonly struct LruCacheItem(TValue v, int offset) { + public readonly TValue Value = v; public readonly int Offset = offset; - public TValue Value = v; } } diff --git a/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs b/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs index a49c7aea622..574e574992b 100644 --- a/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs +++ b/src/Nethermind/Nethermind.Core/Collections/ArrayPoolList.cs @@ -93,7 +93,11 @@ public void AddRange(ReadOnlySpan items) Count += items.Length; } - public void Clear() => Count = 0; + public void Clear() + { + ClearToCount(_array); + Count = 0; + } public bool Contains(T item) { @@ -140,6 +144,7 @@ public void ReduceCount(int count) _array.AsSpan(0, count).CopyTo(newArray); T[] oldArray = Interlocked.Exchange(ref _array, newArray); _capacity = newArray.Length; + ClearToCount(oldArray); _arrayPool.Return(oldArray); } else if (RuntimeHelpers.IsReferenceOrContainsReferences()) @@ -154,6 +159,16 @@ void ThrowOnlyReduce(int count) } } + private void ClearToCount(T[] array) + { + int count = Count; + // Release any references to the objects in the array so can be GC'd. + if (count > 0 && RuntimeHelpers.IsReferenceOrContainsReferences()) + { + Array.Clear(array, 0, count); + } + } + public void Sort(Comparison comparison) { ArgumentNullException.ThrowIfNull(comparison); @@ -223,6 +238,7 @@ private void GuardResize(int itemsToAdd = 1) _array.CopyTo(newArray, 0); T[] oldArray = Interlocked.Exchange(ref _array, newArray); _capacity = newArray.Length; + ClearToCount(oldArray); _arrayPool.Return(oldArray); } } @@ -249,6 +265,10 @@ private bool RemoveAtInternal(int index, bool shouldThrow) } Count--; + if (RuntimeHelpers.IsReferenceOrContainsReferences()) + { + _array[Count] = default!; + } } return isValid; @@ -335,13 +355,14 @@ public void Dispose() if (!_disposed) { _disposed = true; - Count = 0; T[]? array = _array; + _array = null!; if (array is not null) { - _arrayPool.Return(_array); - _array = null!; + ClearToCount(array); + _arrayPool.Return(array); } + Count = 0; } #if DEBUG diff --git a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs index a61de81f89a..fa4af408c93 100644 --- a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs @@ -153,6 +153,15 @@ public static ContainerBuilder Map(this ContainerBuilder builder, Fu return builder; } + + public static ContainerBuilder Bind(this ContainerBuilder builder) where TFrom : TTo where TTo : notnull + { + builder.Register((it) => it.Resolve()) + .As() + .ExternallyOwned(); + + return builder; + } } /// diff --git a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs index 21ed6e8e66a..39d8429cec8 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs @@ -27,8 +27,12 @@ public static unsafe partial class Bytes public static readonly IEqualityComparer EqualityComparer = new BytesEqualityComparer(); public static readonly IEqualityComparer NullableEqualityComparer = new NullableBytesEqualityComparer(); public static readonly BytesComparer Comparer = new(); - public static readonly ReadOnlyMemory ZeroByte = new byte[] { 0 }; - public static readonly ReadOnlyMemory OneByte = new byte[] { 1 }; + // The ReadOnlyMemory needs to be initialized = or it will be created each time. + public static ReadOnlyMemory ZeroByte = new byte[] { 0 }; + public static ReadOnlyMemory OneByte = new byte[] { 1 }; + // The Jit converts a ReadOnlySpan => new byte[] to a data section load, no allocation. + public static ReadOnlySpan ZeroByteSpan => new byte[] { 0 }; + public static ReadOnlySpan OneByteSpan => new byte[] { 1 }; public const string ZeroHexValue = "0x0"; public const string ZeroValue = "0"; @@ -210,7 +214,7 @@ public static ReadOnlySpan WithoutLeadingZeros(this Span bytes) public static ReadOnlySpan WithoutLeadingZeros(this ReadOnlySpan bytes) { - if (bytes.Length == 0) return ZeroByte.Span; + if (bytes.Length == 0) return ZeroByteSpan; int nonZeroIndex = bytes.IndexOfAnyExcept((byte)0); // Keep one or it will be interpreted as null diff --git a/src/Nethermind/Nethermind.Db/MemDb.cs b/src/Nethermind/Nethermind.Db/MemDb.cs index aaad49b326e..43f759b8320 100644 --- a/src/Nethermind/Nethermind.Db/MemDb.cs +++ b/src/Nethermind/Nethermind.Db/MemDb.cs @@ -27,6 +27,17 @@ public MemDb(string name) Name = name; } + public static MemDb CopyFrom(IDb anotherDb) + { + MemDb newDb = new MemDb(); + foreach (KeyValuePair kv in anotherDb.GetAll()) + { + newDb[kv.Key] = kv.Value; + } + + return newDb; + } + public MemDb() : this(0, 0) { } diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs index 1c3c0599562..4ea3983493b 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs @@ -30,7 +30,7 @@ public void GlobalSetup() [ArgumentsSource(nameof(ValueSource))] public UInt256 Uint256(UInt256 v) { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(0, NullTxTracer.Instance, _stack.AsSpan()); stack.PushUInt256(in v); stack.PopUInt256(out UInt256 value); @@ -50,7 +50,7 @@ public UInt256 Uint256(UInt256 v) [Benchmark(OperationsPerInvoke = 4)] public byte Byte() { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(0, NullTxTracer.Instance, _stack.AsSpan()); byte b = 1; @@ -72,7 +72,7 @@ public byte Byte() [Benchmark(OperationsPerInvoke = 4)] public void PushZero() { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(0, NullTxTracer.Instance, _stack.AsSpan()); stack.PushZero(); stack.PushZero(); @@ -83,7 +83,7 @@ public void PushZero() [Benchmark(OperationsPerInvoke = 4)] public void PushOne() { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(0, NullTxTracer.Instance, _stack.AsSpan()); stack.PushOne(); stack.PushOne(); @@ -94,7 +94,7 @@ public void PushOne() [Benchmark(OperationsPerInvoke = 4)] public void Swap() { - EvmStack stack = new(_stack.AsSpan(), 2, NullTxTracer.Instance); + EvmStack stack = new(0, NullTxTracer.Instance, _stack.AsSpan()); stack.Swap(2); stack.Swap(2); @@ -105,7 +105,7 @@ public void Swap() [Benchmark(OperationsPerInvoke = 4)] public void Dup() { - EvmStack stack = new(_stack.AsSpan(), 1, NullTxTracer.Instance); + EvmStack stack = new(1, NullTxTracer.Instance, _stack.AsSpan()); stack.Dup(1); stack.Dup(1); diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs index b2fd2017894..6f4f5831642 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs @@ -276,7 +276,7 @@ public void Debugger_Can_Alter_Data_Stack(string bytecodeHex) if (tracer.CanReadState) { // we pop the condition and overwrite it with a false to force breaking out of the loop - EvmStack stack = new(tracer.CurrentState.DataStack, tracer.CurrentState.DataStackHead, tracer); + EvmStack stack = new(tracer.CurrentState.DataStackHead, tracer, tracer.CurrentState.DataStack); stack.PopLimbo(); stack.PushByte(0x00); diff --git a/src/Nethermind/Nethermind.Evm/EvmStack.cs b/src/Nethermind/Nethermind.Evm/EvmStack.cs index ef6dc068bde..ebe1eabd04f 100644 --- a/src/Nethermind/Nethermind.Evm/EvmStack.cs +++ b/src/Nethermind/Nethermind.Evm/EvmStack.cs @@ -19,6 +19,7 @@ namespace Nethermind.Evm; using static VirtualMachine; using Word = Vector256; +[StructLayout(LayoutKind.Auto)] public ref struct EvmStack where TTracing : struct, IIsTracing { @@ -26,36 +27,44 @@ public ref struct EvmStack public const int WordSize = EvmStack.WordSize; public const int AddressSize = EvmStack.AddressSize; - public EvmStack(scoped in Span bytes, scoped in int head, ITxTracer txTracer) + public EvmStack(scoped in int head, ITxTracer txTracer, scoped in Span bytes) { - _bytes = bytes; Head = head; _tracer = txTracer; + _bytes = bytes; } + private readonly ITxTracer _tracer; + private readonly Span _bytes; public int Head; - private readonly Span _bytes; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref byte PushBytesRef() + { + // Workhorse method + int head = Head; + if ((Head = head + 1) >= MaxStackSize) + { + EvmStack.ThrowEvmStackOverflowException(); + } - private readonly ITxTracer _tracer; + return ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), head * WordSize); + } public void PushBytes(scoped ReadOnlySpan value) { if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); + ref byte bytes = ref PushBytesRef(); if (value.Length != WordSize) { - ClearWordAtHead(); - value.CopyTo(_bytes.Slice(Head * WordSize + WordSize - value.Length, value.Length)); + // Not full entry, clear first + Unsafe.As(ref bytes) = default; + value.CopyTo(MemoryMarshal.CreateSpan(ref Unsafe.Add(ref bytes, WordSize - value.Length), value.Length)); } else { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Unsafe.As(ref MemoryMarshal.GetReference(value))); - } - - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); + Unsafe.As(ref bytes) = Unsafe.As(ref MemoryMarshal.GetReference(value)); } } @@ -63,94 +72,75 @@ public void PushBytes(scoped in ZeroPaddedSpan value) { if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); + ref byte bytes = ref PushBytesRef(); ReadOnlySpan valueSpan = value.Span; if (valueSpan.Length != WordSize) { - ClearWordAtHead(); - Span stack = _bytes.Slice(Head * WordSize, valueSpan.Length); - valueSpan.CopyTo(stack); + // Not full entry, clear first + Unsafe.As(ref bytes) = default; + valueSpan.CopyTo(MemoryMarshal.CreateSpan(ref bytes, value.Length)); } else { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Unsafe.As(ref MemoryMarshal.GetReference(valueSpan))); - } - - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); + Unsafe.As(ref bytes) = Unsafe.As(ref MemoryMarshal.GetReference(valueSpan)); } } - public ref byte PushBytesRef() + public void PushLeftPaddedBytes(ReadOnlySpan value, int paddingLength) { - ref byte bytes = ref _bytes[Head * WordSize]; + if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); - if (++Head >= MaxStackSize) + ref byte bytes = ref PushBytesRef(); + if (value.Length != WordSize) { - EvmStack.ThrowEvmStackOverflowException(); + // Not full entry, clear first + Unsafe.As(ref bytes) = default; + value.CopyTo(MemoryMarshal.CreateSpan(ref Unsafe.Add(ref bytes, WordSize - paddingLength), value.Length)); + } + else + { + Unsafe.As(ref bytes) = Unsafe.As(ref MemoryMarshal.GetReference(value)); } - - return ref bytes; } public void PushByte(byte value) { if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); - ClearWordAtHead(); - _bytes[Head * WordSize + WordSize - sizeof(byte)] = value; - - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); - } + ref byte bytes = ref PushBytesRef(); + // Not full entry, clear first + Unsafe.As(ref bytes) = default; + Unsafe.Add(ref bytes, WordSize - sizeof(byte)) = value; } - private static ReadOnlySpan OneStackItem() => Bytes.OneByte.Span; - public void PushOne() { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(OneStackItem()); - - ClearWordAtHead(); - _bytes[Head * WordSize + WordSize - sizeof(byte)] = 1; + if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(Bytes.OneByteSpan); - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); - } + ref byte bytes = ref PushBytesRef(); + // Not full entry, clear first + Unsafe.As(ref bytes) = default; + Unsafe.Add(ref bytes, WordSize - sizeof(byte)) = 1; } - private static ReadOnlySpan ZeroStackItem() => Bytes.ZeroByte.Span; - public void PushZero() { - if (typeof(TTracing) == typeof(IsTracing)) - { - _tracer.ReportStackPush(ZeroStackItem()); - } + if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(Bytes.ZeroByteSpan); - ClearWordAtHead(); - - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); - } + ref byte bytes = ref PushBytesRef(); + Unsafe.As(ref bytes) = default; } public void PushUInt32(in int value) { - ClearWordAtHead(); + ref byte bytes = ref PushBytesRef(); + // Not full entry, clear first + Unsafe.As(ref bytes) = default; - Span intPlace = _bytes.Slice(Head * WordSize + WordSize - sizeof(uint), sizeof(uint)); + Span intPlace = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref bytes, WordSize - sizeof(uint)), sizeof(uint)); BinaryPrimitives.WriteInt32BigEndian(intPlace, value); if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(intPlace); - - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); - } } /// @@ -161,17 +151,14 @@ public void PushUInt32(in int value) /// public void PushUInt256(in UInt256 value) { - Span word = _bytes.Slice(Head * WordSize, WordSize); - ref byte bytes = ref MemoryMarshal.GetReference(word); - + ref byte bytes = ref PushBytesRef(); if (Avx2.IsSupported) { Word shuffle = Vector256.Create( - (byte) - 31, 30, 29, 28, 27, 26, 25, 24, - 23, 22, 21, 20, 19, 18, 17, 16, - 15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0); + 0x18191a1b1c1d1e1ful, + 0x1011121314151617ul, + 0x08090a0b0c0d0e0ful, + 0x0001020304050607ul).AsByte(); if (Avx512Vbmi.VL.IsSupported) { Word data = Unsafe.As(ref Unsafe.AsRef(in value)); @@ -205,18 +192,13 @@ public void PushUInt256(in UInt256 value) Unsafe.WriteUnaligned(ref bytes, Vector256.Create(u3, u2, u1, u0)); } - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(word); - - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); - } + if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(MemoryMarshal.CreateReadOnlySpan(ref bytes, WordSize)); } public void PushSignedInt256(in Int256.Int256 value) { // tail call into UInt256 - PushUInt256(Unsafe.As(ref Unsafe.AsRef(in value))); + PushUInt256(in Unsafe.As(ref Unsafe.AsRef(in value))); } public void PopLimbo() @@ -245,11 +227,10 @@ public bool PopUInt256(out UInt256 result) { Word data = Unsafe.ReadUnaligned(ref bytes); Word shuffle = Vector256.Create( - (byte) - 31, 30, 29, 28, 27, 26, 25, 24, - 23, 22, 21, 20, 19, 18, 17, 16, - 15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0); + 0x18191a1b1c1d1e1ful, + 0x1011121314151617ul, + 0x08090a0b0c0d0e0ful, + 0x0001020304050607ul).AsByte(); if (Avx512Vbmi.VL.IsSupported) { Word convert = Avx512Vbmi.VL.PermuteVar32x8(data, shuffle); @@ -312,54 +293,33 @@ public readonly Span PeekWord256() public Address? PopAddress() => Head-- == 0 ? null : new Address(_bytes.Slice(Head * WordSize + WordSize - AddressSize, AddressSize).ToArray()); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref byte PopBytesByRef() { - if (Head-- == 0) + int head = Head; + if (head == 0) { return ref Unsafe.NullRef(); } - - return ref _bytes[Head * WordSize]; + head--; + Head = head; + return ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), head * WordSize); } public Span PopWord256() { - if (Head-- == 0) - { - EvmStack.ThrowEvmStackUnderflowException(); - } + ref byte bytes = ref PopBytesByRef(); + if (Unsafe.IsNullRef(ref bytes)) EvmStack.ThrowEvmStackUnderflowException(); - return _bytes.Slice(Head * WordSize, WordSize); + return MemoryMarshal.CreateSpan(ref bytes, WordSize); } public byte PopByte() { - if (Head-- == 0) - { - EvmStack.ThrowEvmStackUnderflowException(); - } - - return _bytes[Head * WordSize + WordSize - sizeof(byte)]; - } - - public void PushLeftPaddedBytes(ReadOnlySpan value, int paddingLength) - { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); - - if (value.Length != WordSize) - { - ClearWordAtHead(); - value.CopyTo(_bytes.Slice(Head * WordSize + WordSize - paddingLength, value.Length)); - } - else - { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Unsafe.As(ref MemoryMarshal.GetReference(value))); - } + ref byte bytes = ref PopBytesByRef(); + if (Unsafe.IsNullRef(ref bytes)) EvmStack.ThrowEvmStackUnderflowException(); - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); - } + return Unsafe.Add(ref bytes, WordSize - sizeof(byte)); } public bool Dup(in int depth) @@ -387,14 +347,7 @@ public bool Dup(in int depth) } public readonly bool EnsureDepth(int depth) - { - if (Head < depth) - { - return false; - } - - return true; - } + => Head >= depth; public readonly bool Swap(int depth) { @@ -424,12 +377,6 @@ private readonly void Trace(int depth) _tracer.ReportStackPush(_bytes.Slice(Head * WordSize - i * WordSize, WordSize)); } } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private readonly void ClearWordAtHead() - { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Word.Zero); - } } public static class EvmStack @@ -440,7 +387,6 @@ public static class EvmStack public const int WordSize = 32; public const int AddressSize = 20; - [StackTraceHidden] [DoesNotReturn] internal static void ThrowEvmStackUnderflowException() diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 3512f53574c..2d12fccfef9 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -648,7 +648,7 @@ private CallResult ExecuteCall(EvmState vmState, ReadOnlyM } vmState.InitStacks(); - EvmStack stack = new(vmState.DataStack.AsSpan(), vmState.DataStackHead, _txTracer); + EvmStack stack = new(vmState.DataStackHead, _txTracer, vmState.DataStack.AsSpan()); long gasAvailable = vmState.GasAvailable; if (previousCallResult is not null) diff --git a/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs b/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs index cdeb7f58bf4..b95dd0f8d3a 100644 --- a/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/Eth/EthSyncingInfoTests.cs @@ -4,11 +4,13 @@ using System.Threading; using FluentAssertions; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Test.Builders; using Nethermind.Facade.Eth; using Nethermind.Logging; +using Nethermind.Synchronization; using Nethermind.Synchronization.ParallelSync; using NSubstitute; using NUnit.Framework; @@ -24,13 +26,13 @@ public void GetFullInfo_WhenNotSyncing() { ISyncConfig syncConfig = new SyncConfig(); IBlockTree blockTree = Substitute.For(); - IReceiptStorage receiptStorage = Substitute.For(); + ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(false); syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(false); blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(6178001L).TestObject); blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(6178000L).TestObject).TestObject); - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, syncConfig, + EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, syncConfig, new StaticSelector(SyncMode.All), syncProgressResolver, LimboLogs.Instance); SyncingResult syncingResult = ethSyncingInfo.GetFullInfo(); Assert.That(syncingResult.IsSyncing, Is.EqualTo(false)); @@ -45,13 +47,13 @@ public void GetFullInfo_WhenSyncing() { ISyncConfig syncConfig = new SyncConfig(); IBlockTree blockTree = Substitute.For(); - IReceiptStorage receiptStorage = Substitute.For(); + ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(false); syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(false); blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(6178010L).TestObject); blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(6178000L).TestObject).TestObject); - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, syncConfig, + EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, syncConfig, new StaticSelector(SyncMode.All), syncProgressResolver, LimboLogs.Instance); SyncingResult syncingResult = ethSyncingInfo.GetFullInfo(); Assert.That(syncingResult.IsSyncing, Is.EqualTo(true)); @@ -66,13 +68,13 @@ public void GetFullInfo_WhenSyncing() public void IsSyncing_ReturnsExpectedResult(long bestHeader, long currentHead, bool expectedResult) { IBlockTree blockTree = Substitute.For(); - IReceiptStorage receiptStorage = Substitute.For(); + ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(false); syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(false); blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(bestHeader).TestObject); blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(currentHead).TestObject).TestObject); - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, new SyncConfig(), + EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, new SyncConfig(), new StaticSelector(SyncMode.All), syncProgressResolver, LimboLogs.Instance); SyncingResult syncingResult = ethSyncingInfo.GetFullInfo(); Assert.That(syncingResult.IsSyncing, Is.EqualTo(expectedResult)); @@ -97,7 +99,7 @@ public void IsSyncing_AncientBarriers(bool resolverDownloadingBodies, PivotNumber = "1000" }; IBlockTree blockTree = Substitute.For(); - IReceiptStorage receiptStorage = Substitute.For(); + ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(resolverDownloadingBodies); syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(resolverDownloadingreceipts); @@ -105,7 +107,7 @@ public void IsSyncing_AncientBarriers(bool resolverDownloadingBodies, blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(6178001L).TestObject); blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(6178000L).TestObject).TestObject); - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, syncConfig, + EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, syncConfig, new StaticSelector(SyncMode.FastBlocks), syncProgressResolver, LimboLogs.Instance); SyncingResult syncingResult = ethSyncingInfo.GetFullInfo(); Assert.That(syncingResult, Is.EqualTo(CreateSyncingResult(expectedResult, 6178000L, 6178001L, SyncMode.FastBlocks))); @@ -116,7 +118,7 @@ public void Should_calculate_sync_time() { SyncConfig syncConfig = new(); IBlockTree blockTree = Substitute.For(); - IReceiptStorage receiptStorage = Substitute.For(); + ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(false); syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(false); @@ -125,7 +127,7 @@ public void Should_calculate_sync_time() blockTree.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(100).TestObject) .TestObject); - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, syncConfig, + EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, syncConfig, new StaticSelector(SyncMode.All), syncProgressResolver, LimboLogs.Instance); ethSyncingInfo.IsSyncing().Should().Be(false); @@ -159,7 +161,7 @@ public void Should_calculate_sync_time() public void IsSyncing_ReturnsFalseOnFastSyncWithoutPivot(long bestHeader, long currentHead) { IBlockTree blockTree = Substitute.For(); - IReceiptStorage receiptStorage = Substitute.For(); + ISyncPointers syncPointers = Substitute.For(); ISyncProgressResolver syncProgressResolver = Substitute.For(); syncProgressResolver.IsFastBlocksBodiesFinished().Returns(false); syncProgressResolver.IsFastBlocksReceiptsFinished().Returns(false); @@ -171,7 +173,7 @@ public void IsSyncing_ReturnsFalseOnFastSyncWithoutPivot(long bestHeader, long c SnapSync = true, PivotNumber = "0", // Equivalent to not having a pivot }; - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, syncConfig, + EthSyncingInfo ethSyncingInfo = new(blockTree, syncPointers, syncConfig, new StaticSelector(SyncMode.All), syncProgressResolver, LimboLogs.Instance); SyncingResult syncingResult = ethSyncingInfo.GetFullInfo(); diff --git a/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs b/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs index 55420cad4d1..f55d158d411 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs @@ -4,9 +4,11 @@ using System; using System.Diagnostics; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; using Nethermind.Logging; +using Nethermind.Synchronization; using Nethermind.Synchronization.ParallelSync; namespace Nethermind.Facade.Eth @@ -16,20 +18,20 @@ public class EthSyncingInfo : IEthSyncingInfo private readonly IBlockTree _blockTree; private readonly ISyncConfig _syncConfig; private readonly ILogger _logger; - private readonly IReceiptStorage _receiptStorage; + private readonly ISyncPointers _syncPointers; private readonly ISyncModeSelector _syncModeSelector; private readonly ISyncProgressResolver _syncProgressResolver; public EthSyncingInfo( IBlockTree blockTree, - IReceiptStorage receiptStorage, + ISyncPointers syncPointers, ISyncConfig syncConfig, ISyncModeSelector syncModeSelector, ISyncProgressResolver syncProgressResolver, ILogManager logManager) { _blockTree = blockTree; - _receiptStorage = receiptStorage; + _syncPointers = syncPointers; _syncConfig = syncConfig; _syncModeSelector = syncModeSelector; _syncProgressResolver = syncProgressResolver; @@ -38,12 +40,10 @@ public EthSyncingInfo( public SyncingResult GetFullInfo() { - long bestSuggestedNumber = _blockTree.FindBestSuggestedHeader()?.Number ?? 0; - long headNumberOrZero = _blockTree.Head?.Number ?? 0; - bool isSyncing = bestSuggestedNumber > headNumberOrZero + 8; + (bool isSyncing, long headNumberOrZero, long bestSuggestedNumber) = _blockTree.IsSyncing(maxDistanceForSynced: 8); SyncMode syncMode = _syncModeSelector.Current; - if (_logger.IsTrace) _logger.Trace($"Start - EthSyncingInfo - BestSuggestedNumber: {bestSuggestedNumber}, HeadNumberOrZero: {headNumberOrZero}, IsSyncing: {isSyncing} {_syncConfig}. LowestInsertedBodyNumber: {_blockTree.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_receiptStorage.LowestInsertedReceiptBlockNumber}"); + if (_logger.IsTrace) _logger.Trace($"Start - EthSyncingInfo - BestSuggestedNumber: {bestSuggestedNumber}, HeadNumberOrZero: {headNumberOrZero}, IsSyncing: {isSyncing} {_syncConfig}. LowestInsertedBodyNumber: {_syncPointers.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_syncPointers.LowestInsertedReceiptBlockNumber}"); if (isSyncing) { if (_logger.IsTrace) _logger.Trace($"Too far from head - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}"); @@ -58,18 +58,18 @@ public SyncingResult GetFullInfo() { if (_syncConfig.DownloadReceiptsInFastSync && !_syncProgressResolver.IsFastBlocksReceiptsFinished()) { - if (_logger.IsTrace) _logger.Trace($"Receipts not finished - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}, AncientReceiptsBarrier: {_syncConfig.AncientReceiptsBarrierCalc}. LowestInsertedBodyNumber: {_blockTree.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_receiptStorage.LowestInsertedReceiptBlockNumber}"); + if (_logger.IsTrace) _logger.Trace($"Receipts not finished - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}, AncientReceiptsBarrier: {_syncConfig.AncientReceiptsBarrierCalc}. LowestInsertedBodyNumber: {_syncPointers.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_syncPointers.LowestInsertedReceiptBlockNumber}"); return ReturnSyncing(headNumberOrZero, bestSuggestedNumber, syncMode); } if (_syncConfig.DownloadBodiesInFastSync && !_syncProgressResolver.IsFastBlocksBodiesFinished()) { - if (_logger.IsTrace) _logger.Trace($"Bodies not finished - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}, AncientBodiesBarrier: {_syncConfig.AncientBodiesBarrierCalc}. LowestInsertedBodyNumber: {_blockTree.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_receiptStorage.LowestInsertedReceiptBlockNumber}"); + if (_logger.IsTrace) _logger.Trace($"Bodies not finished - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}, AncientBodiesBarrier: {_syncConfig.AncientBodiesBarrierCalc}. LowestInsertedBodyNumber: {_syncPointers.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_syncPointers.LowestInsertedReceiptBlockNumber}"); return ReturnSyncing(headNumberOrZero, bestSuggestedNumber, syncMode); } } - if (_logger.IsTrace) _logger.Trace($"Node is not syncing - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}. LowestInsertedBodyNumber: {_blockTree.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_receiptStorage.LowestInsertedReceiptBlockNumber}"); + if (_logger.IsTrace) _logger.Trace($"Node is not syncing - EthSyncingInfo - HighestBlock: {bestSuggestedNumber}, CurrentBlock: {headNumberOrZero}. LowestInsertedBodyNumber: {_syncPointers.LowestInsertedBodyNumber} LowestInsertedReceiptBlockNumber: {_syncPointers.LowestInsertedReceiptBlockNumber}"); return SyncingResult.NotSyncing; } @@ -86,6 +86,7 @@ private static SyncingResult ReturnSyncing(long headNumberOrZero, long bestSugge } private readonly Stopwatch _syncStopwatch = new(); + public TimeSpan UpdateAndGetSyncTime() { if (!_syncStopwatch.IsRunning) diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs index 05a4fe994e3..c0c26e49869 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateDictionaryBlockStore.cs @@ -71,17 +71,6 @@ public void Cache(Block block) Insert(block); } - public void SetMetadata(byte[] key, byte[] value) - { - _metadataDict[key] = value; - readonlyBaseBlockStore.SetMetadata(key, value); - } - - public byte[]? GetMetadata(byte[] key) - { - return _metadataDict.TryGetValue(key, out var value) ? value : readonlyBaseBlockStore.GetMetadata(key); - } - public bool HasBlock(long blockNumber, Hash256 blockHash) { return _blockNumDict.ContainsKey(blockNumber); diff --git a/src/Nethermind/Nethermind.HealthChecks.Test/NodeHealthServiceTests.cs b/src/Nethermind/Nethermind.HealthChecks.Test/NodeHealthServiceTests.cs index 5ac6b770edf..47072d9b9ae 100644 --- a/src/Nethermind/Nethermind.HealthChecks.Test/NodeHealthServiceTests.cs +++ b/src/Nethermind/Nethermind.HealthChecks.Test/NodeHealthServiceTests.cs @@ -7,6 +7,7 @@ using System.Linq; using Nethermind.Api; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Services; using Nethermind.Blockchain.Synchronization; @@ -23,6 +24,7 @@ using NSubstitute; using NUnit.Framework; using Nethermind.Core.Extensions; +using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; namespace Nethermind.HealthChecks.Test; @@ -63,7 +65,7 @@ public void CheckHealth_returns_expected_results([ValueSource(nameof(CheckHealth blockFinder.FindBestSuggestedHeader().Returns(GetBlockHeader(2).TestObject); } - IEthSyncingInfo ethSyncingInfo = new EthSyncingInfo(blockFinder, receiptStorage, syncConfig, Substitute.For(), Substitute.For(), LimboLogs.Instance); + IEthSyncingInfo ethSyncingInfo = new EthSyncingInfo(blockFinder, Substitute.For(), syncConfig, Substitute.For(), Substitute.For(), LimboLogs.Instance); NodeHealthService nodeHealthService = new(syncServer, blockchainProcessor, blockProducerRunner, new HealthChecksConfig(), healthHintService, ethSyncingInfo, new EngineRpcCapabilitiesProvider(api.SpecProvider), api, new[] { drive }, test.IsMining); @@ -130,7 +132,7 @@ public void post_merge_health_checks([ValueSource(nameof(CheckHealthPostMergeTes CustomRpcCapabilitiesProvider customProvider = new(test.EnabledCapabilities, test.DisabledCapabilities); - IEthSyncingInfo ethSyncingInfo = new EthSyncingInfo(blockFinder, new InMemoryReceiptStorage(), + IEthSyncingInfo ethSyncingInfo = new EthSyncingInfo(blockFinder, Substitute.For(), new SyncConfig(), syncModeSelector, Substitute.For(), new TestLogManager()); NodeHealthService nodeHealthService = new(syncServer, blockchainProcessor, blockProducerRunner, new HealthChecksConfig(), diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index bc5a8ca046e..0e6843148ca 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Autofac; using Nethermind.Api; using Nethermind.Blockchain.FullPruning; using Nethermind.Blockchain.Synchronization; @@ -29,6 +30,7 @@ using Nethermind.Logging; using Nethermind.Network.Config; using Nethermind.JsonRpc.Modules.Rpc; +using Nethermind.Synchronization.FastBlocks; namespace Nethermind.Init.Steps; @@ -67,8 +69,13 @@ public virtual async Task Execute(CancellationToken cancellationToken) StepDependencyException.ThrowIfNull(_api.PeerManager); // Used only by rpc - _api.EthSyncingInfo = new EthSyncingInfo(_api.BlockTree, _api.ReceiptStorage!, _api.Config(), - _api.SyncModeSelector!, _api.SyncProgressResolver!, _api.LogManager); + _api.EthSyncingInfo = new EthSyncingInfo( + _api.BlockTree, + _api.SyncPointers!, + _api.Config(), + _api.SyncModeSelector!, + _api.SyncProgressResolver!, + _api.LogManager); _api.RpcModuleProvider = new RpcModuleProvider(_api.FileSystem, _jsonRpcConfig, _api.LogManager); IRpcModuleProvider rpcModuleProvider = _api.RpcModuleProvider; diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 817b5d0be02..997a4107c2a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -39,7 +39,9 @@ using Nethermind.Config; using Nethermind.Facade.Find; using Nethermind.Facade.Simulate; +using Nethermind.Synchronization; using Nethermind.Synchronization.ParallelSync; +using NSubstitute; namespace Nethermind.JsonRpc.Benchmark { @@ -162,7 +164,7 @@ TransactionProcessor transactionProcessor IReceiptStorage receiptStorage = new InMemoryReceiptStorage(); ISyncConfig syncConfig = new SyncConfig(); - EthSyncingInfo ethSyncingInfo = new(blockTree, receiptStorage, syncConfig, new StaticSelector(SyncMode.All), null, LimboLogs.Instance); + EthSyncingInfo ethSyncingInfo = new(blockTree, Substitute.For(), syncConfig, new StaticSelector(SyncMode.All), null, LimboLogs.Instance); _ethModule = new EthRpcModule( new JsonRpcConfig(), diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs index b2603727410..66ac673179d 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs @@ -76,7 +76,7 @@ public void Initialize() _txPool = new TxPool.TxPool(_ethereumEcdsa, new BlobTxStorage(), - new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(specProvider), _blockTree, stateProvider, new CodeInfoRepository()), + new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(specProvider), _blockTree, stateProvider, new CodeInfoRepository()) { HasSynced = true }, new TxPoolConfig(), new TxValidator(specProvider.ChainId), LimboLogs.Instance, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 9abd1ff32e3..a1c4c14e068 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -11,6 +11,7 @@ using FluentAssertions; using FluentAssertions.Json; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; @@ -28,6 +29,8 @@ using Nethermind.Serialization.Json; using Nethermind.Sockets; using Nethermind.Specs; +using Nethermind.Synchronization; +using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; using Nethermind.TxPool; using Newtonsoft.Json.Linq; @@ -77,7 +80,7 @@ public void Setup() _txPool, _receiptCanonicalityMonitor, _filterStore, - new EthSyncingInfo(_blockTree, _receiptStorage, _syncConfig, + new EthSyncingInfo(_blockTree, Substitute.For(), _syncConfig, new StaticSelector(SyncMode.All), _syncProgressResolver, _logManager), _specProvider, jsonSerializer); @@ -192,7 +195,7 @@ private SyncingSubscription GetSyncingSubscription(int bestSuggested, int head) Block block = Build.A.Block.WithNumber(head).TestObject; _blockTree.Head.Returns(block); - EthSyncingInfo ethSyncingInfo = new(_blockTree, _receiptStorage, _syncConfig, + EthSyncingInfo ethSyncingInfo = new(_blockTree, Substitute.For(), _syncConfig, new StaticSelector(SyncMode.All), _syncProgressResolver, _logManager); SyncingSubscription syncingSubscription = new(_jsonRpcDuplexClient, _blockTree, ethSyncingInfo, _logManager); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index 5d81df7afa7..dce7775ba64 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -5,6 +5,7 @@ using System.IO; using System.Threading.Tasks; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; @@ -31,6 +32,8 @@ using Nethermind.Db; using Nethermind.Facade.Simulate; using Nethermind.State; +using Nethermind.Synchronization; +using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; using NSubstitute; @@ -130,7 +133,7 @@ public async Task Build( LimboLogs.Instance, @this.SpecProvider, @this.GasPriceOracle, - new EthSyncingInfo(@this.BlockTree, @this.ReceiptStorage, new SyncConfig(), + new EthSyncingInfo(@this.BlockTree, Substitute.For(), new SyncConfig(), new StaticSelector(SyncMode.All), Substitute.For(), @this.LogManager), @this.FeeHistoryOracle ?? new FeeHistoryOracle(@this.BlockTree, @this.ReceiptStorage, @this.SpecProvider), diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index d429cac1300..236a200ae12 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -28,6 +28,7 @@ using Nethermind.Specs.Test; using Nethermind.JsonRpc.Data; using Nethermind.Serialization.Rlp; +using Nethermind.State; using Newtonsoft.Json.Linq; namespace Nethermind.JsonRpc.Test.Modules; @@ -45,6 +46,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) await Blockchain.AddFunds(TestItem.AddressB, 1000.Ether()); await Blockchain.AddFunds(TestItem.AddressC, 1000.Ether()); + Hash256 stateRoot = Blockchain.BlockTree.Head!.StateRoot!; for (int i = 1; i < 10; i++) { List transactions = new(); @@ -52,10 +54,12 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) { transactions.Add(Core.Test.Builders.Build.A.Transaction .WithTo(Address.Zero) - .WithNonce(Blockchain.State.GetNonce(TestItem.AddressB) + (UInt256)j) + .WithNonce(Blockchain.StateReader.GetNonce(stateRoot, TestItem.AddressB) + (UInt256)j) .SignedAndResolved(Blockchain.EthereumEcdsa, TestItem.PrivateKeyB).TestObject); } await Blockchain.AddBlock(transactions.ToArray()); + + stateRoot = Blockchain.BlockTree.Head!.StateRoot!; } Factory = new( diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index 3064491f896..a266e41b9ec 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -35,6 +35,8 @@ using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Test.ChainSpecStyle; +using Nethermind.Synchronization; +using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; using NSubstitute; using NUnit.Framework; @@ -173,7 +175,7 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT BlocksConfig blocksConfig = new() { MinGasPrice = 0 }; ISyncConfig syncConfig = new SyncConfig(); TargetAdjustedGasLimitCalculator targetAdjustedGasLimitCalculator = new(SpecProvider, blocksConfig); - EthSyncingInfo = new EthSyncingInfo(BlockTree, ReceiptStorage, syncConfig, + EthSyncingInfo = new EthSyncingInfo(BlockTree, Substitute.For(), syncConfig, new StaticSelector(SyncMode.All), Substitute.For(), LogManager); PostMergeBlockProducerFactory blockProducerFactory = new( SpecProvider, diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index fcdc3f435c4..5c8be744150 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -37,6 +37,8 @@ using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; +using Nethermind.Synchronization; +using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; using NSubstitute; @@ -202,7 +204,7 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT BlocksConfig blocksConfig = new() { MinGasPrice = 0 }; TargetAdjustedGasLimitCalculator targetAdjustedGasLimitCalculator = new(SpecProvider, blocksConfig); ISyncConfig syncConfig = new SyncConfig(); - EthSyncingInfo = new EthSyncingInfo(BlockTree, ReceiptStorage, syncConfig, + EthSyncingInfo = new EthSyncingInfo(BlockTree, Substitute.For(), syncConfig, new StaticSelector(SyncMode.All), Substitute.For(), LogManager); PostMergeBlockProducerFactory? blockProducerFactory = new( SpecProvider, diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs index 4288106a08d..6e17e0a076a 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs @@ -305,7 +305,7 @@ public override void DisconnectProtocol(DisconnectReason disconnectReason, strin if (NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportDisconnect(Session.Node.Address, $"Local {disconnectReason} {details}"); Send(message); - + Dispose(); } private void SendHello() @@ -337,6 +337,7 @@ private void HandlePing() private void Close(EthDisconnectReason ethDisconnectReason) { + Dispose(); if (ethDisconnectReason != EthDisconnectReason.TooManyPeers && ethDisconnectReason != EthDisconnectReason.Other && ethDisconnectReason != EthDisconnectReason.DisconnectRequested) @@ -363,5 +364,8 @@ private void HandlePong(Packet msg) public override void Dispose() { + // Clear Events if set + ProtocolInitialized = null; + SubprotocolRequested = null; } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs index df904df6ea9..fb5c330b1b7 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs @@ -379,6 +379,8 @@ private void HintNewBlock(Hash256 blockHash, long number) protected override void OnDisposed() { + // Clear Events + ProtocolInitialized = null; } } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/NodeData/NodeDataProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/NodeData/NodeDataProtocolHandler.cs index 641be2577c3..9db1209ee49 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/NodeData/NodeDataProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/NodeData/NodeDataProtocolHandler.cs @@ -54,6 +54,8 @@ public override void Init() public override void Dispose() { + // Clear Events if set + ProtocolInitialized = null; } public override void DisconnectProtocol(DisconnectReason disconnectReason, string details) { diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs index 171e83e89c7..9c71578b6cb 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs @@ -88,6 +88,8 @@ public override void Init() public override void Dispose() { + // Clear Events if set + ProtocolInitialized = null; } public override void HandleMessage(ZeroPacket message) diff --git a/src/Nethermind/Nethermind.Optimism.Test/Rpc/OptimismEthRpcModuleTest.cs b/src/Nethermind/Nethermind.Optimism.Test/Rpc/OptimismEthRpcModuleTest.cs index ac1a02e3452..e25b2f77874 100644 --- a/src/Nethermind/Nethermind.Optimism.Test/Rpc/OptimismEthRpcModuleTest.cs +++ b/src/Nethermind/Nethermind.Optimism.Test/Rpc/OptimismEthRpcModuleTest.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading.Tasks; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; using Nethermind.Core; @@ -16,6 +17,8 @@ using Nethermind.Logging; using Nethermind.Optimism.Rpc; using Nethermind.Serialization.Rlp; +using Nethermind.Synchronization; +using Nethermind.Synchronization.FastBlocks; using Nethermind.Synchronization.ParallelSync; using Nethermind.TxPool; using NSubstitute; @@ -78,7 +81,7 @@ public static TestRpcBlockchain.Builder WithOptimismEthRpcMod LimboLogs.Instance, blockchain.SpecProvider, blockchain.GasPriceOracle, - new EthSyncingInfo(blockchain.BlockTree, blockchain.ReceiptStorage, new SyncConfig(), + new EthSyncingInfo(blockchain.BlockTree, Substitute.For(), new SyncConfig(), new StaticSelector(SyncMode.All), Substitute.For(), blockchain.LogManager), blockchain.FeeHistoryOracle ?? new FeeHistoryOracle(blockchain.BlockTree, blockchain.ReceiptStorage, blockchain.SpecProvider), diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs index b0f892774bb..bc7560cb850 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs @@ -119,6 +119,7 @@ public static NethermindApi ContextWithMocks() ApiWithNetworkServiceContainer = new ContainerBuilder() .AddSingleton(Substitute.For()) .AddSingleton(Substitute.For()) + .AddSingleton(Substitute.For()) .AddSingleton(Substitute.For()) .AddSingleton(Substitute.For()) .AddSingleton(Substitute.For()) diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs index d7cb8645bc5..2ed20142439 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs @@ -139,11 +139,6 @@ public TestReceiptStorage(IReceiptStorage inStorage, IReceiptStorage outStorage) public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical, WriteFlags writeFlags) => _outStorage.Insert(block, txReceipts, ensureCanonical, writeFlags); - public long? LowestInsertedReceiptBlockNumber - { - get => _outStorage.LowestInsertedReceiptBlockNumber; - set => _outStorage.LowestInsertedReceiptBlockNumber = value; - } public long MigratedBlockNumber { get => _outStorage.MigratedBlockNumber; diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 048ac615c2c..ab6414bcdc2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 22990000, - "PivotHash": "0xc729e80336902c7ceeb2af714f9add4434e1fbfc7b8e41f28698742160bd8535", + "PivotNumber": 23100000, + "PivotHash": "0xdae463b199e43a393bc75bd11332c9d5bf6c2639c5c27342eb5f2ae23d1a5fa6", "PivotTotalDifficulty": "0" }, "Discovery": { diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index b9ed2276b67..eb8bb1219e9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 18500000, - "PivotHash": "0xf02c06395fca279452eec89b9a16fd6764312f75f5776ff42e5157ce163f08fb", + "PivotNumber": 18610000, + "PivotHash": "0xf5c1be202907568363af3ba9643b089a207a5497a7fe9a97fa1505d2e358a1d8", "PivotTotalDifficulty": "0" }, "Discovery": { diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 669b62121a8..bd15388639a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -16,8 +16,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 13030000, - "PivotHash": "0x95ada4054aab7d4ec861ef1c57111d6ca02d4c763cded077d9584804ce9e5772", + "PivotNumber": 13070000, + "PivotHash": "0x473a8b01df14b82dd2e89576d292f8b62bfcacfa4039145c1b80451a7204f580", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": "10000000000", "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/energyweb.json b/src/Nethermind/Nethermind.Runner/configs/energyweb.json index 8ce975fa12b..a2ba0bcf21f 100644 --- a/src/Nethermind/Nethermind.Runner/configs/energyweb.json +++ b/src/Nethermind/Nethermind.Runner/configs/energyweb.json @@ -11,9 +11,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 33020000, - "PivotHash": "0xb5b267d07638ca300da6a54a8a433f7a97bf63c309f39188acf9879f21e09123", - "PivotTotalDifficulty": "11236123755729388063560629537396986341897685812", + "PivotNumber": 33060000, + "PivotHash": "0xa944eb14a0eb04fd18d00a92502ebdabc5eef1251b9e86ffdd53663c1471dd36", + "PivotTotalDifficulty": "11249735050406225602099164521694257070355841331", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/exosama.json b/src/Nethermind/Nethermind.Runner/configs/exosama.json index ca572a8f782..11a67304371 100644 --- a/src/Nethermind/Nethermind.Runner/configs/exosama.json +++ b/src/Nethermind/Nethermind.Runner/configs/exosama.json @@ -11,9 +11,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 13270000, - "PivotHash": "0x2c9747816ad7aa6489fcae1b4cb9f817d3d4e14df288078bb318b54f994281e4", - "PivotTotalDifficulty": "4515547009040853410158981040619564165661433283", + "PivotNumber": 13310000, + "PivotHash": "0x753a91d0212478ff84a764dc685777feb89b2348e581703e3b2df367d5281823", + "PivotTotalDifficulty": "4529158303717690948697516024916834894119593282", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index 37feffd7b25..467f1707b4a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -13,8 +13,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 37240000, - "PivotHash": "0xe04265e7b5a3c274b4b505c37aac6cce1bfad81fa21afe1550989d9e6ae2d2e1", + "PivotNumber": 37280000, + "PivotHash": "0xffdf05bd6e0b2a1ea66647cec5e7e66ab9562a5aece15768a162d59d8dd097cc", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json index f788af5021e..a4de141222b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -11,9 +11,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 14630000, - "PivotHash": "0xd9185715bede87b96e7c282a0ed7d52a3e8b7ea550fe7e2f290282b89362fa23", - "PivotTotalDifficulty": "28635797" + "PivotNumber": 14670000, + "PivotHash": "0x608525796e84b63d4758442ddbe0f5f78b8cb395c99760f09ab3d1d4f0fb6dca", + "PivotTotalDifficulty": "28692401" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json index a07dd125d35..47b1e2c6219 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -11,9 +11,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 8240000, - "PivotHash": "0xdd3a33d583d2192dafce0e8d469ba5d011e1a187d9104596337dacb5da8a9199", - "PivotTotalDifficulty": "14806762" + "PivotNumber": 8280000, + "PivotHash": "0x38d9958d5a82723ec6c217fbe37c7ea2829c22c3e8dc838765cc996002e5cf94", + "PivotTotalDifficulty": "14865312" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json index 229e37a123a..bc970f53d51 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -16,9 +16,9 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 12630000, - "PivotHash": "0x8839adda5953b7294aac20c71193407c643d2d460b81217fcc554bdb8f6f65a9", - "PivotTotalDifficulty": "25260001" + "PivotNumber": 12730000, + "PivotHash": "0x8113f7ed2f64c246ce1c29259b427bd263e9c17b2d0f71f94773df8b03b74ff4", + "PivotTotalDifficulty": "25460001" }, "JsonRpc": { "Enabled": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 3a25cf0faf4..028d4724de9 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -16,9 +16,9 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 6420000, - "PivotHash": "0xca464ef9ec6636bd194ea059ef932ae3938ae48956b0c5936e9ebcc5b0823ac1", - "PivotTotalDifficulty": "12840001" + "PivotNumber": 6530000, + "PivotHash": "0xa897fe765b7a27e95799aeefe03dfbcb2dbac9dbbc63d6439320b602384cdb30", + "PivotTotalDifficulty": "13060001" }, "JsonRpc": { "Enabled": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index 1a77df6e72f..a9b223d5c24 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -9,8 +9,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 21285000, - "PivotHash": "0x313760f259dda6ca0909b353bbfd8a8e02ccbd132b2a8d48dba17c8bdbe085ab", + "PivotNumber": 21303000, + "PivotHash": "0xb7df0dcbb96842bed2fccc51e28dbbd2fddc6e3eb52ea972ecf473a2005be820", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 5669f2d9020..28386125096 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -16,8 +16,8 @@ "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 128590000, - "PivotHash": "0x4418eac3a427325f43bf6c0f140acb7a8f5d8c8a80a3234db34c0c48b0f0aca5", + "PivotNumber": 128690000, + "PivotHash": "0x6ba4ae18a363b318dad04a6dc638a60cad1d5b42a8d8c05048408ffadcb100c8", "PivotTotalDifficulty": "0" }, "Discovery": { diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 9b15639430b..69571fbc5ea 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 20490000, - "PivotHash": "0xd2d8b3b7b14182c73c0c55a6736888c96491bbb93ef643438b023e013ab4df4e", + "PivotNumber": 20590000, + "PivotHash": "0xfd0deea4ebadfb45c4688f269c436ee91f0ee4a33f1b5fa93dc0553443dd5191", "PivotTotalDifficulty": "0" }, "Discovery": { diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index a8c90daa4cc..3313fbddc28 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -17,8 +17,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 7169000, - "PivotHash": "0xb919fdc4e52fae3b99db49f5f3e251f2cba95f94ac3e4f21c1a3bb100ff193c6", + "PivotNumber": 7185000, + "PivotHash": "0x13fcdf643750023999d19a7ce52c338cebc591f704aaf0e6c14060c1216834f9", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.json b/src/Nethermind/Nethermind.Runner/configs/volta.json index 427e764804e..75de098999a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/volta.json +++ b/src/Nethermind/Nethermind.Runner/configs/volta.json @@ -15,9 +15,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 30120000, - "PivotHash": "0xd80df7e7b2d8e9d216b372f9e56acf9a43fa30e50da6b62e9142830e825e85af", - "PivotTotalDifficulty": "10249304891658666519516843175844858528678183947", + "PivotNumber": 30140000, + "PivotHash": "0x1377f22defd21de16f23b4f88bf1dda892ad290e1ed396c202c42d5d31e3148d", + "PivotTotalDifficulty": "10256110538997085288786110667993493892907252336", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 }, diff --git a/src/Nethermind/Nethermind.State/StateReader.cs b/src/Nethermind/Nethermind.State/StateReader.cs index 9b4e73229e5..269bd1cc12c 100644 --- a/src/Nethermind/Nethermind.State/StateReader.cs +++ b/src/Nethermind/Nethermind.State/StateReader.cs @@ -29,7 +29,7 @@ public ReadOnlySpan GetStorage(Hash256 stateRoot, Address address, in UInt ValueHash256 storageRoot = account.StorageRoot; if (storageRoot == Keccak.EmptyTreeHash) { - return Bytes.ZeroByte.Span; + return Bytes.ZeroByteSpan; } Metrics.StorageReaderReads++; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs index 4638459df26..886cf38112c 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs @@ -276,7 +276,7 @@ public async Task Does_not_deadlock_on_replace_peer() peerAllocationStrategy .Allocate(Arg.Any(), Arg.Any>(), Arg.Any(), Arg.Any()) .Returns(new PeerInfo(syncPeer1)); - SyncPeerAllocation peerAllocation = new(peerAllocationStrategy, AllocationContexts.Blocks); + SyncPeerAllocation peerAllocation = new(peerAllocationStrategy, AllocationContexts.Blocks, null); peerAllocation.AllocateBestPeer(new List(), Substitute.For(), ctx.BlockTree); ctx.PeerPool .Allocate(Arg.Any(), Arg.Any(), Arg.Any()) @@ -332,7 +332,7 @@ public void No_old_bodies_and_receipts() BlockTreeScenario = blockTrees, }; - ctx.Feed = new FastSyncFeed(new SyncConfig + ctx.Feed = new FastSyncFeed(new TestSyncConfig { NonValidatorNode = true, DownloadBodiesInFastSync = false, @@ -349,7 +349,7 @@ public void No_old_bodies_and_receipts() peerAllocationStrategy .Allocate(Arg.Any(), Arg.Any>(), Arg.Any(), Arg.Any()) .Returns(peerInfo); - SyncPeerAllocation peerAllocation = new(peerAllocationStrategy, AllocationContexts.Blocks); + SyncPeerAllocation peerAllocation = new(peerAllocationStrategy, AllocationContexts.Blocks, null); peerAllocation.AllocateBestPeer(new List(), Substitute.For(), ctx.BlockTree); ctx.PeerPool @@ -479,13 +479,13 @@ public MergeConfig MergeConfig public PoSSwitcher PosSwitcher => _posSwitcher ??= new( MergeConfig, - new SyncConfig(), + new TestSyncConfig(), MetadataDb, BlockTree, SpecProvider, new ChainSpec(), LimboLogs.Instance); - public BeaconPivot BeaconPivot => _beaconPivot ??= new(new SyncConfig(), MetadataDb, BlockTree, _posSwitcher!, LimboLogs.Instance); + public BeaconPivot BeaconPivot => _beaconPivot ??= new(new TestSyncConfig(), MetadataDb, BlockTree, _posSwitcher!, LimboLogs.Instance); protected override IBetterPeerStrategy BetterPeerStrategy => _betterPeerStrategy ??= new MergeBetterPeerStrategy(new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), PosSwitcher, BeaconPivot, LimboLogs.Instance); @@ -498,7 +498,7 @@ public IChainLevelHelper ChainLevelHelper _chainLevelHelper ??= new ChainLevelHelper( BlockTree, BeaconPivot, - new SyncConfig(), + new TestSyncConfig(), LimboLogs.Instance); set => _chainLevelHelper = value; } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs index 1f3929efe6c..dcd985cd73b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs @@ -38,6 +38,7 @@ using NUnit.Framework; using BlockTree = Nethermind.Blockchain.BlockTree; using System.Diagnostics.CodeAnalysis; +using Nethermind.Core.Test; namespace Nethermind.Synchronization.Test; @@ -108,7 +109,7 @@ public async Task Ancestor_lookup_simple() { Context ctx = new() { - BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject, + BlockTree = CachedBlockTreeBuilder.OfLength(1024), }; BlockDownloader downloader = ctx.BlockDownloader; @@ -139,7 +140,7 @@ public async Task Ancestor_lookup_headers() { Context ctx = new() { - BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject, + BlockTree = CachedBlockTreeBuilder.OfLength(1024), }; BlockDownloader downloader = ctx.BlockDownloader; @@ -168,7 +169,7 @@ public void Ancestor_failure() { Context ctx = new() { - BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject, + BlockTree = CachedBlockTreeBuilder.OfLength(2048 + 1), }; BlockDownloader downloader = ctx.BlockDownloader; @@ -186,7 +187,7 @@ public void Ancestor_failure_blocks() { Context ctx = new() { - BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject, + BlockTree = CachedBlockTreeBuilder.OfLength(2048 + 1), }; BlockDownloader downloader = ctx.BlockDownloader; @@ -1024,11 +1025,9 @@ public IBlockValidator BlockValidator private SyncDispatcher? _dispatcher; public SyncDispatcher Dispatcher => _dispatcher ??= new SyncDispatcher( - new SyncConfig() + new TestSyncConfig() { MaxProcessingThreads = 0, - SyncDispatcherEmptyRequestDelayMs = 1, - SyncDispatcherAllocateTimeoutMs = 1 }, Feed!, BlockDownloader, @@ -1062,7 +1061,7 @@ private class SyncPeerMock : ISyncPeer private readonly ReceiptsMessageSerializer _receiptsSerializer = new(MainnetSpecProvider.Instance); private readonly Response _flags; - public BlockTree BlockTree { get; private set; } = null!; + public IBlockTree BlockTree { get; private set; } = null!; private IReceiptStorage _receiptStorage = new InMemoryReceiptStorage(); public string Name => "Mock"; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs index 5fbc4f1d977..b87a9950773 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/BodiesSyncFeedTests.cs @@ -28,6 +28,7 @@ public class BodiesSyncFeedTests private IBlockTree _syncingFromBlockTree = null!; private IBlockTree _syncingToBlockTree = null!; private TestMemDb _blocksDb = null!; + private ISyncPointers _syncPointers = null!; private BodiesSyncFeed _feed = null!; private ISyncConfig _syncConfig = null!; private MemDb _metadataDb = null!; @@ -42,6 +43,7 @@ public void Setup() _blocksDb = new TestMemDb(); _metadataDb = new MemDb(); + _syncPointers = new MemorySyncPointers(); _syncingToBlockTree = Build.A.BlockTree() .WithBlocksDb(_blocksDb) .TestObject; @@ -54,7 +56,7 @@ public void Setup() _pivotBlock = _syncingFromBlockTree.FindBlock(99, BlockTreeLookupOptions.None)!; - _syncConfig = new SyncConfig() + _syncConfig = new TestSyncConfig() { FastSync = true, PivotHash = _pivotBlock.Hash!.ToString(), @@ -66,6 +68,7 @@ public void Setup() _feed = new BodiesSyncFeed( MainnetSpecProvider.Instance, _syncingToBlockTree, + _syncPointers, Substitute.For(), _syncConfig, new NullSyncReport(), @@ -198,11 +201,11 @@ public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely _syncConfig.AncientBodiesBarrier = AncientBarrierInConfig; _syncConfig.AncientReceiptsBarrier = AncientBarrierInConfig; _syncConfig.PivotNumber = (AncientBarrierInConfig + 1_000_000).ToString(); - _syncingToBlockTree.LowestInsertedBodyNumber = JustStarted ? null : _pivotBlock.Number; + _syncPointers.LowestInsertedBodyNumber = JustStarted ? null : _pivotBlock.Number; if (previousBarrierInDb is not null) _metadataDb.Set(MetadataDbKeys.BodiesBarrierWhenStarted, previousBarrierInDb.Value.ToBigEndianByteArrayWithoutLeadingZeros()); _feed.InitializeFeed(); - _syncingToBlockTree.LowestInsertedBodyNumber = lowestInsertedBlockNumber; + _syncPointers.LowestInsertedBodyNumber = lowestInsertedBlockNumber; _feed.IsFinished.Should().Be(shouldfinish); } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs index 7f9d9e93c3b..2f7277c0af9 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs @@ -14,6 +14,7 @@ using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Stats.Model; @@ -40,7 +41,7 @@ public Task Will_fail_if_launched_without_fast_blocks_enabled() HeadersSyncFeed _ = new HeadersSyncFeed( blockTree: blockTree, syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig(), + syncConfig: new TestSyncConfig(), syncReport: Substitute.For(), logManager: LimboLogs.Instance); }); @@ -56,7 +57,7 @@ public async Task Can_prepare_3_requests_in_a_row() HeadersSyncFeed feed = new( blockTree: blockTree, syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig + syncConfig: new TestSyncConfig { FastSync = true, PivotNumber = "1000", @@ -89,7 +90,7 @@ public async Task When_next_header_hash_update_is_delayed_do_not_drop_peer() ResettableHeaderSyncFeed feed = new( blockTree: blockTree, syncPeerPool: syncPeerPool, - syncConfig: new SyncConfig + syncConfig: new TestSyncConfig { FastSync = true, PivotNumber = "1000", @@ -149,7 +150,7 @@ public async Task Can_prepare_several_request_and_ignore_request_from_previous_s using ResettableHeaderSyncFeed feed = new( blockTree: blockTree, syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig + syncConfig: new TestSyncConfig { FastSync = true, PivotNumber = "500", @@ -196,7 +197,7 @@ public async Task Will_dispatch_when_only_partially_processed_dependency() using HeadersSyncFeed feed = new( blockTree: blockTree, syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig + syncConfig: new TestSyncConfig { FastSync = true, PivotNumber = pivot.Number.ToString(), @@ -267,7 +268,7 @@ public async Task Can_reset_and_not_hang_when_a_batch_is_processing() ResettableHeaderSyncFeed feed = new( blockTree: blockTree, syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig + syncConfig: new TestSyncConfig { FastSync = true, PivotNumber = "500", @@ -321,7 +322,7 @@ public async Task Can_keep_returning_nulls_after_all_batches_were_prepared() HeadersSyncFeed feed = new( blockTree: blockTree, syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig + syncConfig: new TestSyncConfig { FastSync = true, PivotNumber = "1000", @@ -349,7 +350,7 @@ public async Task Finishes_when_all_downloaded() report.HeadersInQueue.Returns(new MeasuredProgress()); MeasuredProgress measuredProgress = new(); report.FastBlocksHeaders.Returns(measuredProgress); - HeadersSyncFeed feed = new(blockTree, Substitute.For(), new SyncConfig { FastSync = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); + HeadersSyncFeed feed = new(blockTree, Substitute.For(), new TestSyncConfig { FastSync = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); await feed.PrepareRequest(); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).TestObject); using HeadersSyncBatch? result = await feed.PrepareRequest(); @@ -372,7 +373,7 @@ public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() report.HeadersInQueue.Returns(new MeasuredProgress()); report.FastBlocksHeaders.Returns(new MeasuredProgress()); - HeadersSyncFeed feed = new(blockTree, Substitute.For(), new SyncConfig { FastSync = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); + HeadersSyncFeed feed = new(blockTree, Substitute.For(), new TestSyncConfig { FastSync = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); feed.InitializeFeed(); using HeadersSyncBatch? result = await feed.PrepareRequest(); @@ -406,8 +407,8 @@ public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() [TestCase(0, 192, 1, false, true)] public async Task Can_insert_all_good_headers_from_dependent_batch_with_missing_or_null_headers(int nullIndex, int count, int increment, bool shouldReport, bool useNulls) { - var peerChain = Build.A.BlockTree().OfChainLength(1000).TestObject; - var syncConfig = new SyncConfig { FastSync = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }; + var peerChain = CachedBlockTreeBuilder.OfLength(1000); + var syncConfig = new TestSyncConfig { FastSync = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }; IBlockTree localBlockTree = Build.A.BlockTree(peerChain.FindBlock(0, BlockTreeLookupOptions.None)!, null).WithSyncConfig(syncConfig).TestObject; const int lowestInserted = 999; @@ -472,7 +473,7 @@ public async Task Will_never_lose_batch_on_invalid_batch() HeadersSyncFeed feed = new( blockTree, Substitute.For(), - new SyncConfig + new TestSyncConfig { FastSync = true, PivotNumber = "1000", @@ -538,7 +539,7 @@ public async Task Will_never_lose_batch_on_invalid_batch() public void IsFinished_returns_false_when_headers_not_downloaded() { IBlockTree blockTree = Substitute.For(); - SyncConfig syncConfig = new() + TestSyncConfig syncConfig = new() { FastSync = true, DownloadBodiesInFastSync = true, diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs index b8d065984e9..c04084b9236 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/ReceiptsSyncFeedTests.cs @@ -67,6 +67,7 @@ public Scenario(ISpecProvider specProvider, int nonEmptyBlocks, int txPerBlock, private static readonly ISpecProvider _specProvider; private IReceiptStorage _receiptStorage = null!; + private ISyncPointers _syncPointers = null!; private ISyncPeerPool _syncPeerPool = null!; private ReceiptsSyncFeed _feed = null!; private ISyncConfig _syncConfig = null!; @@ -97,10 +98,11 @@ static ReceiptsSyncFeedTests() public void Setup() { _receiptStorage = Substitute.For(); + _syncPointers = new MemorySyncPointers(); _blockTree = Substitute.For(); _metadataDb = new TestMemDb(); - _syncConfig = new SyncConfig { FastSync = true }; + _syncConfig = new TestSyncConfig { FastSync = true }; _syncConfig.PivotNumber = _pivotNumber.ToString(); _syncConfig.PivotHash = Keccak.Zero.ToString(); @@ -130,6 +132,7 @@ private ReceiptsSyncFeed CreateFeed() _specProvider, _blockTree, _receiptStorage, + _syncPointers, _syncPeerPool, _syncConfig, _syncReport, @@ -140,12 +143,13 @@ private ReceiptsSyncFeed CreateFeed() [Test] public void Should_throw_when_fast_block_not_enabled() { - _syncConfig = new SyncConfig { FastSync = false }; + _syncConfig = new TestSyncConfig { FastSync = false }; Assert.Throws( () => _feed = new ReceiptsSyncFeed( _specProvider, _blockTree, _receiptStorage, + _syncPointers, _syncPeerPool, _syncConfig, _syncReport, @@ -156,10 +160,12 @@ public void Should_throw_when_fast_block_not_enabled() [Test] public async Task Should_finish_on_start_when_receipts_not_stored() { + _syncPointers.LowestInsertedReceiptBlockNumber = 0; _feed = new ReceiptsSyncFeed( _specProvider, _blockTree, NullReceiptStorage.Instance, + _syncPointers, _syncPeerPool, _syncConfig, _syncReport, @@ -270,6 +276,7 @@ public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely long? previousBarrierInDb, bool shouldfinish) { + _syncPointers = Substitute.For(); _syncConfig.AncientBodiesBarrier = AncientBarrierInConfig; _syncConfig.AncientReceiptsBarrier = AncientBarrierInConfig; _pivotNumber = AncientBarrierInConfig + 1_000_000; @@ -277,7 +284,7 @@ public void When_finished_sync_with_old_default_barrier_then_finishes_imedietely if (previousBarrierInDb is not null) _metadataDb.Set(MetadataDbKeys.ReceiptsBarrierWhenStarted, previousBarrierInDb.Value.ToBigEndianByteArrayWithoutLeadingZeros()); LoadScenario(_256BodiesWithOneTxEach); - _receiptStorage.LowestInsertedReceiptBlockNumber.Returns(lowestInsertedReceiptBlockNumber); + _syncPointers.LowestInsertedReceiptBlockNumber.Returns(lowestInsertedReceiptBlockNumber); _feed.IsFinished.Should().Be(shouldfinish); } @@ -291,11 +298,13 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) _syncConfig = syncConfig; _syncConfig.PivotNumber = _pivotNumber.ToString(); _syncConfig.PivotHash = scenario.Blocks.Last()?.Hash?.ToString(); + _syncPointers = Substitute.For(); _feed = new ReceiptsSyncFeed( _specProvider, _blockTree, _receiptStorage, + _syncPointers, _syncPeerPool, _syncConfig, _syncReport, @@ -327,8 +336,7 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) scenario.BlocksByHash.TryGetValue(ci.Arg(), out Block? value) ? value.Header : null); - _receiptStorage.LowestInsertedReceiptBlockNumber.Returns((long?)null); - _blockTree.LowestInsertedBodyNumber.Returns(scenario.LowestInsertedBody!.Number); + _syncPointers.LowestInsertedReceiptBlockNumber.Returns((long?)null); } [Test] @@ -398,7 +406,7 @@ public async Task Can_sync_final_batch() FillBatchResponses(batch!); _feed.HandleResponse(batch); - _receiptStorage.LowestInsertedReceiptBlockNumber.Returns(1); + _syncPointers.LowestInsertedReceiptBlockNumber.Returns(1); _feed.PrepareRequest().Result.Should().Be(null); _feed.CurrentState.Should().Be(SyncFeedState.Finished); @@ -408,7 +416,7 @@ public async Task Can_sync_final_batch() public void Is_fast_block_receipts_finished_returns_false_when_receipts_not_downloaded() { _blockTree = Substitute.For(); - _syncConfig = new SyncConfig() + _syncConfig = new TestSyncConfig() { FastSync = true, DownloadBodiesInFastSync = true, @@ -417,10 +425,9 @@ public void Is_fast_block_receipts_finished_returns_false_when_receipts_not_down }; _blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); - _blockTree.LowestInsertedBodyNumber.Returns(1); - _receiptStorage = Substitute.For(); - _receiptStorage.LowestInsertedReceiptBlockNumber.Returns(2); + _syncPointers = Substitute.For(); + _syncPointers.LowestInsertedReceiptBlockNumber.Returns(2); ReceiptsSyncFeed feed = CreateFeed(); Assert.That(feed.IsFinished, Is.False); @@ -430,7 +437,7 @@ public void Is_fast_block_receipts_finished_returns_false_when_receipts_not_down public void Is_fast_block_bodies_finished_returns_true_when_bodies_not_downloaded_and_we_do_not_want_to_download_bodies() { _blockTree = Substitute.For(); - _syncConfig = new SyncConfig() + _syncConfig = new TestSyncConfig() { FastSync = true, DownloadBodiesInFastSync = false, @@ -439,9 +446,8 @@ public void Is_fast_block_bodies_finished_returns_true_when_bodies_not_downloade }; _blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); - _blockTree.LowestInsertedBodyNumber.Returns(2); - _receiptStorage = Substitute.For(); - _receiptStorage.LowestInsertedReceiptBlockNumber.Returns(1); + _syncPointers = Substitute.For(); + _syncPointers.LowestInsertedReceiptBlockNumber.Returns(1); ReceiptsSyncFeed feed = CreateFeed(); feed.InitializeFeed(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs index 80a7a517763..00260452ef6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs @@ -18,6 +18,7 @@ using Nethermind.Core.Crypto; using System.Net; using FluentAssertions; +using Nethermind.Core.Test; using Nethermind.Trie; namespace Nethermind.Synchronization.Test.FastSync.SnapProtocolTests; @@ -43,7 +44,7 @@ public void Setup() { _logManager = LimboLogs.Instance; - BlockTree blockTree = Build.A.BlockTree().OfChainLength((int)BlockTree.BestSuggestedHeader!.Number).TestObject; + IBlockTree blockTree = CachedBlockTreeBuilder.OfLength((int)BlockTree.BestSuggestedHeader!.Number); ITimerFactory timerFactory = Substitute.For(); _pool = new SyncPeerPool(blockTree, new NodeStatsManager(timerFactory, LimboLogs.Instance), new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), LimboLogs.Instance, 25); _pool.Start(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs index 59ae28883b5..43a9b7d42f5 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs @@ -33,8 +33,6 @@ using NSubstitute; using NUnit.Framework; -using BlockTree = Nethermind.Blockchain.BlockTree; - namespace Nethermind.Synchronization.Test.FastSync { public class StateSyncFeedTestsBase @@ -113,9 +111,8 @@ protected IContainer PrepareDownloader(DbContext dbContext, Action protected ContainerBuilder BuildTestContainerBuilder(DbContext dbContext, int syncDispatcherAllocateTimeoutMs = 10) { ContainerBuilder containerBuilder = new ContainerBuilder() - .AddModule(new TestSynchronizerModule(new SyncConfig() + .AddModule(new TestSynchronizerModule(new TestSyncConfig() { - SyncDispatcherEmptyRequestDelayMs = 1, SyncDispatcherAllocateTimeoutMs = syncDispatcherAllocateTimeoutMs, // there is a test for requested nodes which get affected if allocate timeout FastSync = true })) @@ -125,7 +122,9 @@ protected ContainerBuilder BuildTestContainerBuilder(DbContext dbContext, int sy .AddSingleton(dbContext.LocalNodeStorage) // Use factory function to make it lazy in case test need to replace IBlockTree - .AddSingleton((ctx) => Build.A.BlockTree().WithStateRoot(dbContext.RemoteStateTree.RootHash).OfChainLength((int)BlockTree.BestSuggestedHeader!.Number).TestObject) + .AddSingleton((ctx) => CachedBlockTreeBuilder.BuildCached( + $"{nameof(StateSyncFeedTestsBase)}{dbContext.RemoteStateTree.RootHash}{BlockTree.BestSuggestedHeader!.Number}", + () => Build.A.BlockTree().WithStateRoot(dbContext.RemoteStateTree.RootHash).OfChainLength((int)BlockTree.BestSuggestedHeader!.Number))) .Add(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/MemorySyncPointers.cs b/src/Nethermind/Nethermind.Synchronization.Test/MemorySyncPointers.cs new file mode 100644 index 00000000000..6a7ac030f50 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization.Test/MemorySyncPointers.cs @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Synchronization.Test; + +public class MemorySyncPointers : ISyncPointers +{ + public long? LowestInsertedBodyNumber { get; set; } + public long? LowestInsertedReceiptBlockNumber { get; set; } +} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs index 150ae4dde4f..9b4d5721819 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs @@ -55,12 +55,7 @@ public async Task Setup() ITimerFactory timerFactory = Substitute.For(); NodeStatsManager stats = new(timerFactory, LimboLogs.Instance); - SyncConfig syncConfig = new() - { - MultiSyncModeSelectorLoopTimerMs = 1, - SyncDispatcherEmptyRequestDelayMs = 1, - SyncDispatcherAllocateTimeoutMs = 1 - }; + SyncConfig syncConfig = new TestSyncConfig(); NodeStorage nodeStorage = new NodeStorage(_stateDb); TrieStore trieStore = new(nodeStorage, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs index 8e677c9e2db..2ff6d1c21a1 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs @@ -621,7 +621,7 @@ public void Switch_correctly_from_full_sync_to_state_nodes_catch_up() syncPeerPool.InitializedPeers.Returns(peerInfos); syncPeerPool.AllPeers.Returns(peerInfos); - ISyncConfig syncConfig = new SyncConfig() { FastSyncCatchUpHeightDelta = 2 }; + ISyncConfig syncConfig = new TestSyncConfig() { FastSyncCatchUpHeightDelta = 2 }; syncConfig.FastSync = true; TotalDifficultyBetterPeerStrategy bestPeerStrategy = new(LimboLogs.Instance); @@ -671,7 +671,7 @@ public void Changed_event_no_longer_gets_blocked_when_invoking_delegates() syncPeerPool.InitializedPeers.Returns(peerInfos); syncPeerPool.AllPeers.Returns(peerInfos); - ISyncConfig syncConfig = new SyncConfig + ISyncConfig syncConfig = new TestSyncConfig { FastSyncCatchUpHeightDelta = 2, FastSync = true, @@ -685,7 +685,16 @@ public void Changed_event_no_longer_gets_blocked_when_invoking_delegates() selector.Current.Should().Be(SyncMode.Full); CancellationTokenSource waitTokenSource = new(); - ReceiptsSyncFeed receiptsSyncFeed = Substitute.ForPartsOf(MainnetSpecProvider.Instance, Substitute.For(), Substitute.For(), syncPeerPool, syncConfig, Substitute.For(), Substitute.For(), LimboLogs.Instance); + ReceiptsSyncFeed receiptsSyncFeed = Substitute.ForPartsOf( + MainnetSpecProvider.Instance, + Substitute.For(), + Substitute.For(), + Substitute.For(), + syncPeerPool, + syncConfig, + Substitute.For(), + Substitute.For(), + LimboLogs.Instance); receiptsSyncFeed.When(rsf => rsf.InitializeFeed()).DoNotCallBase(); receiptsSyncFeed.When(rsf => rsf.InitializeFeed()).Do(e => { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs index 87ab10fe7bd..8e94ff818b5 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs @@ -150,7 +150,7 @@ public class ScenarioBuilder public ISyncProgressResolver SyncProgressResolver { get; set; } = null!; - public ISyncConfig SyncConfig { get; } = new SyncConfig(); + public ISyncConfig SyncConfig { get; } = new TestSyncConfig(); public IBeaconSyncStrategy BeaconSyncStrategy { get; set; } = No.BeaconSync; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs index 52af5db10bc..a842b0329f6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs @@ -255,12 +255,7 @@ public async Task Simple_test_sync() TestSyncFeed syncFeed = new(); TestDownloader downloader = new TestDownloader(); SyncDispatcher dispatcher = new( - new SyncConfig() - { - MultiSyncModeSelectorLoopTimerMs = 1, - SyncDispatcherEmptyRequestDelayMs = 1, - SyncDispatcherAllocateTimeoutMs = 1 - }, + new TestSyncConfig(), syncFeed, downloader, new TestSyncPeerPool(), @@ -287,10 +282,9 @@ public async Task Test_release_before_processing_complete(bool isMultiSync, int TestDownloader downloader = new TestDownloader(); SyncDispatcher dispatcher = new( - new SyncConfig() + new TestSyncConfig() { MaxProcessingThreads = processingThread, - SyncDispatcherEmptyRequestDelayMs = 1, }, syncFeed, downloader, diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs index eef137e816f..24a7fecedb1 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ReceiptSyncFeedTests.cs @@ -56,7 +56,7 @@ public void Setup() _pivotBlock = _syncingFromBlockTree.FindBlock(99, BlockTreeLookupOptions.None)!; - _syncConfig = new SyncConfig() + _syncConfig = new TestSyncConfig() { FastSync = true, PivotHash = _pivotBlock.Hash!.ToString(), @@ -69,6 +69,7 @@ public void Setup() MainnetSpecProvider.Instance, _syncingToBlockTree, _receiptStorage, + new MemorySyncPointers(), Substitute.For(), _syncConfig, new NullSyncReport(), diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs index 216f970cf18..bbb039b8402 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs @@ -146,7 +146,7 @@ public void Will_mark_progress_and_flush_when_finished() .WithStateRoot(Keccak.EmptyTreeHash) .TestObject).TestObject; TestMemDb memDb = new(); - SyncConfig syncConfig = new SyncConfig() { SnapSyncAccountRangePartitionCount = 1 }; + SyncConfig syncConfig = new TestSyncConfig() { SnapSyncAccountRangePartitionCount = 1 }; using ProgressTracker progressTracker = new(memDb, syncConfig, new StateSyncPivot(blockTree, syncConfig, LimboLogs.Instance), LimboLogs.Instance); progressTracker.IsFinished(out SnapSyncBatch? request); @@ -164,7 +164,7 @@ public void Will_mark_progress_and_flush_when_finished() private ProgressTracker CreateProgressTracker(int accountRangePartition = 1) { BlockTree blockTree = Build.A.BlockTree().WithBlocks(Build.A.Block.WithStateRoot(Keccak.EmptyTreeHash).TestObject).TestObject; - SyncConfig syncConfig = new SyncConfig() { SnapSyncAccountRangePartitionCount = accountRangePartition }; + SyncConfig syncConfig = new TestSyncConfig() { SnapSyncAccountRangePartitionCount = accountRangePartition }; return new(new MemDb(), syncConfig, new StateSyncPivot(blockTree, syncConfig, LimboLogs.Instance), LimboLogs.Instance); } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromAccountRangesTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromAccountRangesTests.cs index 5cadd953f6c..5e74e84aca6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromAccountRangesTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromAccountRangesTests.cs @@ -113,7 +113,7 @@ public void RecreateAccountStateFromOneRangeWithNonExistenceProof() byte[][] firstProof = CreateProofForPath(Keccak.Zero.Bytes); byte[][] lastProof = CreateProofForPath(TestItem.Tree.AccountsWithPaths[5].Path.Bytes); - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -132,7 +132,7 @@ public void RecreateAccountStateFromOneRangeWithExistenceProof() byte[][] firstProof = CreateProofForPath(TestItem.Tree.AccountsWithPaths[0].Path.Bytes); byte[][] lastProof = CreateProofForPath(TestItem.Tree.AccountsWithPaths[5].Path.Bytes); - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -148,7 +148,7 @@ public void RecreateAccountStateFromOneRangeWithoutProof() { Hash256 rootHash = _inputTree.RootHash; // "0x8c81279168edc449089449bc0f2136fc72c9645642845755633cf259cd97988b" - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -165,7 +165,7 @@ public void RecreateAccountStateFromMultipleRange() Hash256 rootHash = _inputTree.RootHash; // "0x8c81279168edc449089449bc0f2136fc72c9645642845755633cf259cd97988b" // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -201,7 +201,7 @@ public void RecreateAccountStateFromMultipleRange_InReverseOrder() Hash256 rootHash = _inputTree.RootHash; // "0x8c81279168edc449089449bc0f2136fc72c9645642845755633cf259cd97988b" // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -234,7 +234,7 @@ public void RecreateAccountStateFromMultipleRange_OutOfOrder() Hash256 rootHash = _inputTree.RootHash; // "0x8c81279168edc449089449bc0f2136fc72c9645642845755633cf259cd97988b" // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -267,7 +267,7 @@ public void RecreateAccountStateFromMultipleOverlappingRange() Hash256 rootHash = _inputTree.RootHash; // "0x8c81279168edc449089449bc0f2136fc72c9645642845755633cf259cd97988b" // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); @@ -390,7 +390,7 @@ public void MissingAccountFromRange() Hash256 rootHash = _inputTree.RootHash; // "0x8c81279168edc449089449bc0f2136fc72c9645642845755633cf259cd97988b" // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); IDb db = container.ResolveKeyed(DbNames.State); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs index e5f6f90e3fe..043951df9d2 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs @@ -51,7 +51,7 @@ public void RecreateStorageStateFromOneRangeWithNonExistenceProof() _inputStateTree!.Accept(accountProofCollector, _inputStateTree.RootHash); var proof = accountProofCollector.BuildResult(); - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); var result = snapProvider.AddStorageRange(1, _pathWithAccount, rootHash, Keccak.Zero, TestItem.Tree.SlotsWithPaths, proof!.StorageProofs![0].Proof!.Concat(proof!.StorageProofs![1].Proof!).ToArray()); @@ -68,7 +68,7 @@ public void RecreateAccountStateFromOneRangeWithExistenceProof() _inputStateTree!.Accept(accountProofCollector, _inputStateTree.RootHash); var proof = accountProofCollector.BuildResult(); - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); var result = snapProvider.AddStorageRange(1, _pathWithAccount, rootHash, Keccak.Zero, TestItem.Tree.SlotsWithPaths, proof!.StorageProofs![0].Proof!.Concat(proof!.StorageProofs![1].Proof!).ToArray()); @@ -81,7 +81,7 @@ public void RecreateStorageStateFromOneRangeWithoutProof() { Hash256 rootHash = _inputStorageTree!.RootHash; // "..." - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); var result = snapProvider.AddStorageRange(1, _pathWithAccount, rootHash, TestItem.Tree.SlotsWithPaths[0].Path, TestItem.Tree.SlotsWithPaths); @@ -95,7 +95,7 @@ public void RecreateAccountStateFromMultipleRange() Hash256 rootHash = _inputStorageTree!.RootHash; // "..." // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); AccountProofCollector accountProofCollector = new(TestItem.Tree.AccountAddress0.Bytes, new ValueHash256[] { Keccak.Zero, TestItem.Tree.SlotsWithPaths[1].Path }); @@ -127,7 +127,7 @@ public void MissingAccountFromRange() Hash256 rootHash = _inputStorageTree!.RootHash; // "..." // output state - using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new SyncConfig())).Build(); + using IContainer container = new ContainerBuilder().AddModule(new TestSynchronizerModule(new TestSyncConfig())).Build(); SnapProvider snapProvider = container.Resolve(); AccountProofCollector accountProofCollector = new(TestItem.Tree.AccountAddress0.Bytes, new ValueHash256[] { Keccak.Zero, TestItem.Tree.SlotsWithPaths[1].Path }); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapProviderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapProviderTests.cs index 883875647ff..38d5fe2e231 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapProviderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapProviderTests.cs @@ -37,7 +37,7 @@ public class SnapProviderTests public void AddAccountRange_AccountListIsEmpty_ThrowArgumentException() { using IContainer container = new ContainerBuilder() - .AddModule(new TestSynchronizerModule(new SyncConfig())) + .AddModule(new TestSynchronizerModule(new TestSyncConfig())) .Build(); SnapProvider snapProvider = container.Resolve(); @@ -55,7 +55,7 @@ public void AddAccountRange_AccountListIsEmpty_ThrowArgumentException() public void AddAccountRange_ResponseHasEmptyListOfAccountsAndOneProof_ReturnsExpiredRootHash() { using IContainer container = new ContainerBuilder() - .AddModule(new TestSynchronizerModule(new SyncConfig())) + .AddModule(new TestSynchronizerModule(new TestSyncConfig())) .Build(); SnapProvider snapProvider = container.Resolve(); @@ -85,7 +85,7 @@ public void AddAccountRange_SetStartRange_ToAfterLastPath() (SnapServer ss, Hash256 root) = BuildSnapServerFromEntries(entries); using IContainer container = new ContainerBuilder() - .AddModule(new TestSynchronizerModule(new SyncConfig() + .AddModule(new TestSynchronizerModule(new TestSyncConfig() { SnapSyncAccountRangePartitionCount = 1 })) @@ -127,7 +127,7 @@ public void AddAccountRange_ShouldNotStoreStorageAfterLimit() (SnapServer ss, Hash256 root) = BuildSnapServerFromEntries(entries); using IContainer container = new ContainerBuilder() - .AddModule(new TestSynchronizerModule(new SyncConfig() + .AddModule(new TestSynchronizerModule(new TestSyncConfig() { SnapSyncAccountRangePartitionCount = 2 })) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapServerTest.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapServerTest.cs index edbdfb04fc0..951fe44fc9d 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapServerTest.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/SnapServerTest.cs @@ -41,7 +41,7 @@ private Context CreateContext(ILastNStateRootTracker? stateRootTracker = null) SnapServer server = new(store.AsReadOnly(), codeDbServer, stateRootTracker ?? CreateConstantStateRootTracker(true), LimboLogs.Instance); MemDb clientStateDb = new(); - using ProgressTracker progressTracker = new(clientStateDb, new SyncConfig(), new StateSyncPivot(null!, new SyncConfig(), LimboLogs.Instance), LimboLogs.Instance); + using ProgressTracker progressTracker = new(clientStateDb, new TestSyncConfig(), new StateSyncPivot(null!, new TestSyncConfig(), LimboLogs.Instance), LimboLogs.Instance); INodeStorage nodeStorage = new NodeStorage(clientStateDb); @@ -263,7 +263,7 @@ public void TestGetStorageRange() dbProviderClient.RegisterDb(DbNames.State, new MemDb()); dbProviderClient.RegisterDb(DbNames.Code, new MemDb()); - using ProgressTracker progressTracker = new(dbProviderClient.StateDb, new SyncConfig(), new StateSyncPivot(null!, new SyncConfig(), LimboLogs.Instance), LimboLogs.Instance); + using ProgressTracker progressTracker = new(dbProviderClient.StateDb, new TestSyncConfig(), new StateSyncPivot(null!, new TestSyncConfig(), LimboLogs.Instance), LimboLogs.Instance); SnapProvider snapProvider = new(progressTracker, dbProviderClient.CodeDb, new NodeStorage(dbProviderClient.StateDb), LimboLogs.Instance); (IOwnedReadOnlyList> storageSlots, IOwnedReadOnlyList proofs) = @@ -299,7 +299,7 @@ public void TestGetStorageRangeMulti() dbProviderClient.RegisterDb(DbNames.State, new MemDb()); dbProviderClient.RegisterDb(DbNames.Code, new MemDb()); - using ProgressTracker progressTracker = new(dbProviderClient.StateDb, new SyncConfig(), new StateSyncPivot(null!, new SyncConfig(), LimboLogs.Instance), LimboLogs.Instance); + using ProgressTracker progressTracker = new(dbProviderClient.StateDb, new TestSyncConfig(), new StateSyncPivot(null!, new TestSyncConfig(), LimboLogs.Instance), LimboLogs.Instance); SnapProvider snapProvider = new(progressTracker, dbProviderClient.CodeDb, new NodeStorage(dbProviderClient.StateDb), LimboLogs.Instance); Hash256 startRange = Keccak.Zero; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs index ce160cb1274..b455a35b1d1 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/StateSyncPivotTest.cs @@ -30,7 +30,7 @@ int newBestHeader .Returns((ci) => Build.A.BlockHeader.WithNumber((long)ci[0]).TestObject); Synchronization.FastSync.StateSyncPivot stateSyncPivot = new Synchronization.FastSync.StateSyncPivot(blockTree, - new SyncConfig() + new TestSyncConfig() { StateMinDistanceFromHead = minDistance, StateMaxDistanceFromHead = maxDistance, diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPointersTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPointersTests.cs new file mode 100644 index 00000000000..f7703debc97 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPointersTests.cs @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Blockchain.Receipts; +using Nethermind.Core.Test; +using Nethermind.Db; +using NUnit.Framework; + +namespace Nethermind.Synchronization.Test; + +public class SyncPointersTests +{ + [Test] + public void WhenReceiptNotStore_SetLowestInsertedReceiptTo0() + { + SyncPointers pointers = new SyncPointers(new TestMemDb(), new TestMemColumnsDb(), new ReceiptConfig() + { + StoreReceipts = false + }); + + pointers.LowestInsertedReceiptBlockNumber.Should().Be(0); + } +} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs index 4ab8f3a901a..640b231d44e 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs @@ -143,7 +143,6 @@ public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_download }; blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); - blockTree.LowestInsertedBodyNumber.Returns(2); SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, false, syncConfig, LimboLogs.Instance); Assert.That(syncProgressResolver.IsFastBlocksBodiesFinished(), Is.False); @@ -163,7 +162,6 @@ public void Is_fast_block_receipts_finished_returns_true_when_receipts_not_downl }; blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); - blockTree.LowestInsertedBodyNumber.Returns(1); SyncProgressResolver syncProgressResolver = CreateProgressResolver(blockTree, stateReader, true, syncConfig, LimboLogs.Instance); Assert.That(syncProgressResolver.IsFastBlocksReceiptsFinished(), Is.True); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs index 8ca63c93f95..c17070946b6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs @@ -99,7 +99,7 @@ public void Can_accept_new_valid_blocks(bool sealOk, bool validationOk, bool acc sealValidator, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -141,7 +141,7 @@ public void Can_accept_blocks_that_are_fine() Always.Valid, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -178,7 +178,7 @@ public void Should_accept_or_not_blocks_depends_on_sync_mode(SyncMode syncMode, Always.Valid, ctx.PeerPool, staticSelector, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -211,7 +211,7 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh { TerminalTotalDifficulty = $"{testSpecProvider.TerminalTotalDifficulty}" }, - new SyncConfig(), + new TestSyncConfig(), new MemDb(), localBlockTree, testSpecProvider, @@ -246,7 +246,7 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh Always.Valid, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, testSpecProvider, LimboLogs.Instance); @@ -420,7 +420,7 @@ private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) { TerminalTotalDifficulty = $"{ttd}" }, - new SyncConfig(), + new TestSyncConfig(), new MemDb(), localBlockTree, testSpecProvider, @@ -469,7 +469,7 @@ private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) sealEngine, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, testSpecProvider, LimboLogs.Instance); @@ -509,7 +509,7 @@ public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_nul Always.Valid, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -541,7 +541,7 @@ public void Rejects_new_old_blocks() sealValidator, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -568,7 +568,7 @@ public async Task Broadcast_NewBlock_on_arrival() Always.Valid, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -604,7 +604,7 @@ public async Task Skip_known_block() Always.Valid, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -645,7 +645,7 @@ public async Task Broadcast_NewBlock_on_arrival_to_sqrt_of_peers([Values(1, 2, 3 Always.Valid, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -683,7 +683,7 @@ public void GetNodeData_returns_cached_trie_nodes() sealValidator, ctx.PeerPool, StaticSelector.Full, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); @@ -723,7 +723,7 @@ public Context() Always.Valid, PeerPool, selector, - new SyncConfig(), + new TestSyncConfig(), Policy.FullGossip, MainnetSpecProvider.Instance, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index b5741810d2f..e6548282966 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -259,7 +259,8 @@ private SyncTestContext CreateSyncManager(int index) InMemoryReceiptStorage receiptStorage = new(); EthereumEcdsa ecdsa = new(specProvider.ChainId); - BlockTree tree = Build.A.BlockTree().WithoutSettingHead.TestObject; + IBlockStore blockStore = new BlockStore(dbProvider.BlocksDb); + BlockTree tree = Build.A.BlockTree().WithBlockStore(blockStore).WithoutSettingHead.TestObject; ITransactionComparerProvider transactionComparerProvider = new TransactionComparerProvider(specProvider, tree); @@ -354,7 +355,9 @@ private SyncTestContext CreateSyncManager(int index) builder .AddModule(new DbModule()) .AddModule(new SynchronizerModule(syncConfig)) + .AddSingleton(new ReceiptConfig()) .AddSingleton(dbProvider) + .AddSingleton(blockStore) .AddSingleton(new NodeStorage(dbProvider.StateDb)) .AddSingleton(MainnetSpecProvider.Instance) .AddSingleton(tree) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs index cb4d9e62d99..10e0481d5fe 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerModuleTests.cs @@ -29,7 +29,7 @@ public IContainer CreateTestContainer() IBlockProcessingQueue blockQueue = Substitute.For(); return new ContainerBuilder() - .AddModule(new SynchronizerModule(new SyncConfig() + .AddModule(new SynchronizerModule(new TestSyncConfig() { FastSync = true, VerifyTrieOnStateSyncFinished = true diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs index 855aa7ec3b7..8e42c3649ab 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Autofac; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; @@ -314,8 +315,10 @@ ISyncConfig GetSyncConfig() => IDbProvider dbProvider = TestMemDbProvider.Init(); IDb stateDb = new MemDb(); IDb codeDb = dbProvider.CodeDb; + IBlockStore blockStore = new BlockStore(dbProvider.BlocksDb); BlockTree = Build.A.BlockTree() .WithSpecProvider(new TestSingleReleaseSpecProvider(Constantinople.Instance)) + .WithBlockStore(blockStore) .WithoutSettingHead .TestObject; @@ -346,7 +349,9 @@ ISyncConfig GetSyncConfig() => ContainerBuilder builder = new ContainerBuilder() .AddModule(new DbModule()) .AddModule(new SynchronizerModule(syncConfig)) + .AddSingleton(new ReceiptConfig()) .AddSingleton(dbProvider) + .AddSingleton(blockStore) .AddSingleton(nodeStorage) .AddSingleton(MainnetSpecProvider.Instance) .AddSingleton(BlockTree) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/TestSyncConfig.cs b/src/Nethermind/Nethermind.Synchronization.Test/TestSyncConfig.cs new file mode 100644 index 00000000000..27141b0d4a1 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization.Test/TestSyncConfig.cs @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain.Synchronization; + +namespace Nethermind.Synchronization.Test; + +public class TestSyncConfig : SyncConfig +{ + public TestSyncConfig() + { + GCOnFeedFinished = false; + MultiSyncModeSelectorLoopTimerMs = 1; + SyncDispatcherEmptyRequestDelayMs = 1; + SyncDispatcherAllocateTimeoutMs = 1; + } +} diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs index f06a176c46a..a7301bb563f 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs @@ -6,12 +6,15 @@ using System.Threading.Tasks; using Autofac.Features.AttributeFilters; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Synchronization; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.Stats.Model; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; @@ -22,11 +25,11 @@ namespace Nethermind.Synchronization.FastBlocks { public class BodiesSyncFeed : BarrierSyncFeed { - protected override long? LowestInsertedNumber => _blockTree.LowestInsertedBodyNumber; + protected override long? LowestInsertedNumber => _syncPointers.LowestInsertedBodyNumber; protected override int BarrierWhenStartedMetadataDbKey => MetadataDbKeys.BodiesBarrierWhenStarted; protected override long SyncConfigBarrierCalc => _syncConfig.AncientBodiesBarrierCalc; protected override Func HasPivot => - () => _blockTree.LowestInsertedBodyNumber is not null && _blockTree.LowestInsertedBodyNumber <= _syncConfig.PivotNumberParsed; + () => _syncPointers.LowestInsertedBodyNumber is not null && _syncPointers.LowestInsertedBodyNumber <= _syncConfig.PivotNumberParsed; private int _requestSize = GethSyncLimits.MaxBodyFetch; private const long DefaultFlushDbInterval = 100000; // About every 10GB on mainnet @@ -36,32 +39,35 @@ public class BodiesSyncFeed : BarrierSyncFeed private readonly ISyncConfig _syncConfig; private readonly ISyncReport _syncReport; private readonly ISyncPeerPool _syncPeerPool; - private readonly IDbMeta _blocksDb; + private readonly ISyncPointers _syncPointers; + private readonly IDb _blocksDb; private SyncStatusList _syncStatusList; private bool ShouldFinish => !_syncConfig.DownloadBodiesInFastSync || AllDownloaded; - private bool AllDownloaded => (_blockTree.LowestInsertedBodyNumber ?? long.MaxValue) <= _barrier + private bool AllDownloaded => (_syncPointers.LowestInsertedBodyNumber ?? long.MaxValue) <= _barrier || WithinOldBarrierDefault; public override bool IsFinished => AllDownloaded; public BodiesSyncFeed( ISpecProvider specProvider, IBlockTree blockTree, + ISyncPointers syncPointers, ISyncPeerPool syncPeerPool, ISyncConfig syncConfig, ISyncReport syncReport, - [KeyFilter(DbNames.Blocks)] IDbMeta blocksDb, + [KeyFilter(DbNames.Blocks)] IDb blocksDb, [KeyFilter(DbNames.Metadata)] IDb metadataDb, ILogManager logManager, long flushDbInterval = DefaultFlushDbInterval) : base(metadataDb, specProvider, logManager.GetClassLogger()) { - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _syncPeerPool = syncPeerPool ?? throw new ArgumentNullException(nameof(syncPeerPool)); - _syncConfig = syncConfig ?? throw new ArgumentNullException(nameof(syncConfig)); - _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); - _blocksDb = blocksDb ?? throw new ArgumentNullException(nameof(blocksDb)); + _blockTree = blockTree; + _syncPointers = syncPointers; + _syncPeerPool = syncPeerPool; + _syncConfig = syncConfig; + _syncReport = syncReport; + _blocksDb = blocksDb; _flushDbInterval = flushDbInterval; if (!_syncConfig.FastSync) @@ -92,7 +98,7 @@ private void ResetSyncStatusList() _syncStatusList = new SyncStatusList( _blockTree, _pivotNumber, - _blockTree.LowestInsertedBodyNumber, + _syncPointers.LowestInsertedBodyNumber, _syncConfig.AncientBodiesBarrier); } @@ -135,7 +141,7 @@ private void PostFinishCleanUp() token.ThrowIfCancellationRequested(); // Otherwise, the progress does not update correctly - _blockTree.LowestInsertedBodyNumber = _syncStatusList.LowestInsertWithoutGaps; + _syncPointers.LowestInsertedBodyNumber = _syncStatusList.LowestInsertWithoutGaps; UpdateSyncReport(); } @@ -149,7 +155,7 @@ private void PostFinishCleanUp() } if ( - (_blockTree.LowestInsertedBodyNumber ?? long.MaxValue) - _syncStatusList.LowestInsertWithoutGaps > _flushDbInterval || + (_syncPointers.LowestInsertedBodyNumber ?? long.MaxValue) - _syncStatusList.LowestInsertWithoutGaps > _flushDbInterval || _syncStatusList.LowestInsertWithoutGaps <= _barrier // Other state depends on LowestInsertedBodyNumber, so this need to flush or it wont finish ) { @@ -163,7 +169,7 @@ private void Flush() { long lowestInsertedAtPoint = _syncStatusList.LowestInsertWithoutGaps; _blocksDb.Flush(); - _blockTree.LowestInsertedBodyNumber = lowestInsertedAtPoint; + _syncPointers.LowestInsertedBodyNumber = lowestInsertedAtPoint; } public override SyncResponseHandlingResult HandleResponse(BodiesSyncBatch? batch, PeerInfo peer = null) diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs index 7ef192a9a5d..c0d573acc8a 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs @@ -29,7 +29,7 @@ namespace Nethermind.Synchronization.FastBlocks public class ReceiptsSyncFeed : BarrierSyncFeed { - protected override long? LowestInsertedNumber => _receiptStorage.LowestInsertedReceiptBlockNumber; + protected override long? LowestInsertedNumber => _syncPointers.LowestInsertedReceiptBlockNumber; protected override int BarrierWhenStartedMetadataDbKey => MetadataDbKeys.ReceiptsBarrierWhenStarted; protected override long SyncConfigBarrierCalc => _syncConfig.AncientReceiptsBarrierCalc; protected override Func HasPivot => @@ -41,12 +41,13 @@ public class ReceiptsSyncFeed : BarrierSyncFeed private readonly ISyncConfig _syncConfig; private readonly ISyncReport _syncReport; private readonly IReceiptStorage _receiptStorage; + private readonly ISyncPointers _syncPointers; private readonly ISyncPeerPool _syncPeerPool; private SyncStatusList _syncStatusList; private bool ShouldFinish => !_syncConfig.DownloadReceiptsInFastSync || AllDownloaded; - private bool AllDownloaded => (_receiptStorage.LowestInsertedReceiptBlockNumber ?? long.MaxValue) <= _barrier + private bool AllDownloaded => (_syncPointers.LowestInsertedReceiptBlockNumber ?? long.MaxValue) <= _barrier || WithinOldBarrierDefault; public override bool IsFinished => AllDownloaded; @@ -55,6 +56,7 @@ public ReceiptsSyncFeed( ISpecProvider specProvider, IBlockTree blockTree, IReceiptStorage receiptStorage, + ISyncPointers syncPointers, ISyncPeerPool syncPeerPool, ISyncConfig syncConfig, ISyncReport syncReport, @@ -62,11 +64,12 @@ public ReceiptsSyncFeed( ILogManager logManager) : base(metadataDb, specProvider, logManager?.GetClassLogger() ?? default) { - _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); - _syncPeerPool = syncPeerPool ?? throw new ArgumentNullException(nameof(syncPeerPool)); - _syncConfig = syncConfig ?? throw new ArgumentNullException(nameof(syncConfig)); - _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _receiptStorage = receiptStorage; + _syncPointers = syncPointers; + _syncPeerPool = syncPeerPool; + _syncConfig = syncConfig; + _syncReport = syncReport; + _blockTree = blockTree; if (!_syncConfig.FastSync) { @@ -96,7 +99,7 @@ private void ResetSyncStatusList() _syncStatusList = new SyncStatusList( _blockTree, _pivotNumber, - _receiptStorage.LowestInsertedReceiptBlockNumber, + _syncPointers.LowestInsertedReceiptBlockNumber, _syncConfig.AncientReceiptsBarrier); } @@ -136,7 +139,7 @@ private void PostFinishCleanUp() while (!_syncStatusList.TryGetInfosForBatch(_requestSize, (info) => _receiptStorage.HasBlock(info.BlockNumber, info.BlockHash), out infos)) { token.ThrowIfCancellationRequested(); - _receiptStorage.LowestInsertedReceiptBlockNumber = _syncStatusList.LowestInsertWithoutGaps; + _syncPointers.LowestInsertedReceiptBlockNumber = _syncStatusList.LowestInsertWithoutGaps; UpdateSyncReport(); } @@ -150,7 +153,7 @@ private void PostFinishCleanUp() // Array.Reverse(infos); } - _receiptStorage.LowestInsertedReceiptBlockNumber = _syncStatusList.LowestInsertWithoutGaps; + _syncPointers.LowestInsertedReceiptBlockNumber = _syncStatusList.LowestInsertWithoutGaps; return Task.FromResult(batch); } diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs index 23f4001a023..bcaf65ff759 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs @@ -54,7 +54,7 @@ public StateSyncFeed( catch (Exception e) { _logger.Error("Error when preparing a batch", e); - return await Task.FromResult(EmptyBatch); + return EmptyBatch; } } diff --git a/src/Nethermind/Nethermind.Synchronization/ISyncPointers.cs b/src/Nethermind/Nethermind.Synchronization/ISyncPointers.cs new file mode 100644 index 00000000000..1747c4f86f1 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization/ISyncPointers.cs @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Synchronization; + +public interface ISyncPointers +{ + long? LowestInsertedBodyNumber { get; set; } + long? LowestInsertedReceiptBlockNumber { get; set; } +} diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncFeed.cs index 5bbee478f58..d645646e527 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncFeed.cs @@ -44,7 +44,6 @@ private void ChangeState(SyncFeedState newState) public virtual void Finish() { ChangeState(SyncFeedState.Finished); - GC.Collect(2, GCCollectionMode.Aggressive, true, true); } public Task FeedTask => _taskCompletionSource?.Task ?? Task.CompletedTask; public abstract void SyncModeSelectorOnChanged(SyncMode current); diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncModeChangedEventArgs.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncModeChangedEventArgs.cs index 916a8d2bf2d..f531004a4e8 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncModeChangedEventArgs.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncModeChangedEventArgs.cs @@ -15,5 +15,10 @@ public SyncModeChangedEventArgs(SyncMode previous, SyncMode current) public SyncMode Previous { get; } public SyncMode Current { get; } + + public bool WasModeFinished(SyncMode mode) + { + return (Previous & mode) != 0 && (Current & mode) == 0; + } } } diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs index cfb7c3380f6..e605f00643b 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs @@ -13,12 +13,12 @@ namespace Nethermind.Synchronization.Peers { public class SyncPeerAllocation { - public static SyncPeerAllocation FailedAllocation = new(NullStrategy.Instance, AllocationContexts.None); + public static SyncPeerAllocation FailedAllocation = new(NullStrategy.Instance, AllocationContexts.None, null); /// /// this should be used whenever we change IsAllocated property on PeerInfo- /// - private static readonly Lock _allocationLock = new(); + private readonly Lock? _allocationLock; private readonly IPeerAllocationStrategy _peerAllocationStrategy; public AllocationContexts Contexts { get; } @@ -29,14 +29,15 @@ public class SyncPeerAllocation public bool HasPeer => Current is not null; public SyncPeerAllocation(PeerInfo peerInfo, AllocationContexts contexts) - : this(new StaticStrategy(peerInfo), contexts) + : this(new StaticStrategy(peerInfo), contexts, null) { } - public SyncPeerAllocation(IPeerAllocationStrategy peerAllocationStrategy, AllocationContexts contexts) + public SyncPeerAllocation(IPeerAllocationStrategy peerAllocationStrategy, AllocationContexts contexts, Lock? allocationLock = null) { _peerAllocationStrategy = peerAllocationStrategy; Contexts = contexts; + _allocationLock = allocationLock ?? new Lock(); } public void AllocateBestPeer( diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs index 263617effbe..8ab32dca677 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; @@ -37,7 +38,7 @@ public class SyncPeerPool : ISyncPeerPool, IPeerDifficultyRefreshPool private readonly IBlockTree _blockTree; private readonly ILogger _logger; - private readonly BlockingCollection _peerRefreshQueue = new(); + private readonly Channel _peerRefreshQueue = Channel.CreateUnbounded(); private readonly ConcurrentDictionary _peers = new(); @@ -218,7 +219,7 @@ internal IEnumerable ReplaceableAllocations public void RefreshTotalDifficulty(ISyncPeer syncPeer, Hash256 blockHash) { RefreshTotalDiffTask task = new(blockHash, syncPeer); - _peerRefreshQueue.Add(task); + _peerRefreshQueue.Writer.TryWrite(task); } public void AddPeer(ISyncPeer syncPeer) @@ -257,7 +258,7 @@ public void AddPeer(ISyncPeer syncPeer) { if (_logger.IsDebug) _logger.Debug($"Adding {syncPeer.Node:c} to refresh queue"); if (NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportInterestingEvent(syncPeer.Node.Address, "adding node to refresh queue"); - _peerRefreshQueue.Add(new RefreshTotalDiffTask(syncPeer)); + _peerRefreshQueue.Writer.TryWrite(new RefreshTotalDiffTask(syncPeer)); } } @@ -328,7 +329,7 @@ public async Task Allocate( using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _refreshLoopCancellation.Token); - SyncPeerAllocation allocation = new(peerAllocationStrategy, allocationContexts); + SyncPeerAllocation allocation = new(peerAllocationStrategy, allocationContexts, _isAllocatedChecks); while (true) { if (TryAllocateOnce(peerAllocationStrategy, allocationContexts, allocation)) @@ -354,7 +355,6 @@ public async Task Allocate( } } - private bool TryAllocateOnce(IPeerAllocationStrategy peerAllocationStrategy, AllocationContexts allocationContexts, SyncPeerAllocation allocation) { lock (_isAllocatedChecks) @@ -392,7 +392,7 @@ public void Free(SyncPeerAllocation syncPeerAllocation) private async Task RunRefreshPeerLoop() { - foreach (RefreshTotalDiffTask refreshTask in _peerRefreshQueue.GetConsumingEnumerable(_refreshLoopCancellation.Token)) + await foreach (RefreshTotalDiffTask refreshTask in _peerRefreshQueue.Reader.ReadAllAsync(_refreshLoopCancellation.Token)) { ISyncPeer syncPeer = refreshTask.SyncPeer; if (_logger.IsTrace) _logger.Trace($"Refreshing info for {syncPeer}."); @@ -713,7 +713,7 @@ public async ValueTask DisposeAsync() await (_refreshLoopTask ?? Task.CompletedTask); Parallel.ForEach(_peers, p => { p.Value.SyncPeer.Disconnect(DisconnectReason.AppClosing, "App Close"); }); - _peerRefreshQueue.Dispose(); + _peerRefreshQueue.Writer.TryComplete(); _refreshLoopCancellation.Dispose(); _refreshLoopTask?.Dispose(); _signals.Dispose(); diff --git a/src/Nethermind/Nethermind.Synchronization/SyncPointers.cs b/src/Nethermind/Nethermind.Synchronization/SyncPointers.cs new file mode 100644 index 00000000000..f175bc55faf --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization/SyncPointers.cs @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Autofac.Features.AttributeFilters; +using Nethermind.Blockchain.Receipts; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Db; +using Nethermind.Serialization.Rlp; + +namespace Nethermind.Synchronization; + +public class SyncPointers : ISyncPointers +{ + private readonly IDb _blocksDb; + private readonly IDb _defaultReceiptDbColumn; + + private static readonly byte[] LowestInsertedBodyNumberDbEntryAddress = ((long)0).ToBigEndianByteArrayWithoutLeadingZeros(); + + + private long? _lowestInsertedBodyNumber; + public long? LowestInsertedBodyNumber + { + get => _lowestInsertedBodyNumber; + set + { + _lowestInsertedBodyNumber = value; + if (value.HasValue) _blocksDb[LowestInsertedBodyNumberDbEntryAddress] = Rlp.Encode(value.Value).Bytes; + } + } + + private long? _lowestInsertedReceiptBlock; + + public long? LowestInsertedReceiptBlockNumber + { + get => _lowestInsertedReceiptBlock; + set + { + _lowestInsertedReceiptBlock = value; + if (value.HasValue) + { + _defaultReceiptDbColumn.Set(Keccak.Zero, Rlp.Encode(value.Value).Bytes); + } + } + } + + + public SyncPointers([KeyFilter(DbNames.Blocks)] IDb blocksDb, IColumnsDb receiptsDb, IReceiptConfig receiptConfig) + { + _blocksDb = blocksDb; + _defaultReceiptDbColumn = receiptsDb.GetColumnDb(ReceiptsColumns.Default); + + LowestInsertedBodyNumber = _blocksDb[LowestInsertedBodyNumberDbEntryAddress]?.AsRlpValueContext().DecodeLong(); + + byte[] lowestBytes = _defaultReceiptDbColumn.Get(Keccak.Zero); + _lowestInsertedReceiptBlock = lowestBytes is null ? (long?)null : new RlpStream(lowestBytes).DecodeLong(); + + // When not storing receipt, set the lowest inserted receipt to 0 so that old receipt will finish immediately + if (!receiptConfig.StoreReceipts) + { + _lowestInsertedReceiptBlock = 0; + } + } +} diff --git a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs index 4aa227df376..d4a7966ac48 100644 --- a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs +++ b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs @@ -90,10 +90,23 @@ public virtual void Start() SyncModeSelector.Changed += syncReport.SyncModeSelectorOnChanged; + if (syncConfig.GCOnFeedFinished) + { + SyncModeSelector.Changed += GCOnFeedFinished; + } + // Make unit test faster. SyncModeSelector.Update(); } + private void GCOnFeedFinished(object? sender, SyncModeChangedEventArgs e) + { + if (e.WasModeFinished(SyncMode.StateNodes) || e.WasModeFinished(SyncMode.FastReceipts) || e.WasModeFinished(SyncMode.FastBlocks)) + { + GC.Collect(2, GCCollectionMode.Aggressive, true, true); + } + } + private void StartFullSyncComponents() { fullSyncComponent.BlockDownloader.SyncEvent += DownloaderOnSyncEvent; @@ -279,6 +292,7 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() // For blocks. There are two block scope, Fast and Full .AddScoped>() diff --git a/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs b/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs index 4597c2b1cd0..cf9b832a7cb 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs @@ -57,22 +57,6 @@ public void Setup() _inMemoryStorage = new InMemoryReceiptStorage(); } - [Test] - public void should_update_lowest_when_needed_in_memory() - => TestAddAndCheckLowest(_inMemoryStorage, true); - - [Test] - public void should_update_lowest_when_needed_persistent() - => TestAddAndCheckLowest(_persistentStorage, true); - - [Test] - public void should_not_update_lowest_when_not_needed_persistent() - => TestAddAndCheckLowest(_persistentStorage, false); - - [Test] - public void should_not_update_lowest_when_not_needed_in_memory() - => TestAddAndCheckLowest(_inMemoryStorage, false); - [Test] public void should_add_and_fetch_receipt_from_in_memory_storage() => TestAddAndGetReceipt(_inMemoryStorage); @@ -101,20 +85,6 @@ public void should_not_throw_if_receiptFinder_asked_for_not_existing_receipts_by receipts.Should().BeEmpty(); } - private void TestAddAndCheckLowest(IReceiptStorage storage, bool updateLowest) - { - Transaction transaction = GetSignedTransaction(); - Block block = GetBlock(transaction); - TxReceipt receipt = GetReceipt(transaction, block); - storage.Insert(block, receipt); - if (updateLowest) - { - storage.LowestInsertedReceiptBlockNumber = block.Number; - } - - storage.LowestInsertedReceiptBlockNumber.Should().Be(updateLowest ? 1 : null); - } - private void TestAddAndGetReceipt(IReceiptStorage storage, IReceiptFinder receiptFinder = null) { bool recoverSender = receiptFinder is not null; diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index a15eeeca50c..a90a9a393a5 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -56,7 +56,7 @@ public void Setup() var codeDb = new MemDb(); _stateProvider = new WorldState(trieStore, codeDb, _logManager); _blockTree = Substitute.For(); - Block block = Build.A.Block.WithNumber(0).TestObject; + Block block = Build.A.Block.WithNumber(10000000 - 1).TestObject; _blockTree.Head.Returns(block); _blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(10000000).TestObject); @@ -1121,6 +1121,8 @@ public void should_accept_access_list_transactions_only_when_eip2930_enabled([Va if (!eip2930Enabled) { _blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(MainnetSpecProvider.BerlinBlockNumber - 1).TestObject); + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.BerlinBlockNumber - 2).TestObject; + _blockTree.Head.Returns(block); } _txPool = CreatePool(null, new TestSpecProvider(eip2930Enabled ? Berlin.Instance : Istanbul.Instance)); @@ -1134,6 +1136,26 @@ public void should_accept_access_list_transactions_only_when_eip2930_enabled([Va result.Should().Be(eip2930Enabled ? AcceptTxResult.Accepted : AcceptTxResult.Invalid); } + [Test] + public void should_accept_only_when_synced([Values(false, true)] bool isSynced) + { + if (!isSynced) + { + _blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(MainnetSpecProvider.BerlinBlockNumber - 1).TestObject); + Block block = Build.A.Block.WithNumber(1).TestObject; + _blockTree.Head.Returns(block); + } + + _txPool = CreatePool(null, new TestSpecProvider(Berlin.Instance)); + Transaction tx = Build.A.Transaction + .WithChainId(TestBlockchainIds.ChainId) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject; + EnsureSenderBalance(tx); + AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); + _txPool.GetPendingTransactionsCount().Should().Be(isSynced ? 1 : 0); + result.Should().Be(isSynced ? AcceptTxResult.Accepted : AcceptTxResult.Syncing); + } + [Test] public void When_MaxFeePerGas_is_lower_than_MaxPriorityFeePerGas_tx_is_invalid() { diff --git a/src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs b/src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs index 40cc45e94a6..fc2cc0c1a1c 100644 --- a/src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs +++ b/src/Nethermind/Nethermind.TxPool/AcceptTxResult.cs @@ -90,6 +90,11 @@ namespace Nethermind.TxPool /// public static readonly AcceptTxResult NotSupportedTxType = new(15, nameof(NotSupportedTxType)); + /// + /// The node is syncing and cannot accept transactions at this time. + /// + public static readonly AcceptTxResult Syncing = new(503, nameof(Syncing)); + private int Id { get; } private string Code { get; } private string? Message { get; } diff --git a/src/Nethermind/Nethermind.TxPool/IChainHeadInfoProvider.cs b/src/Nethermind/Nethermind.TxPool/IChainHeadInfoProvider.cs index ca89bd82aec..7a34c1fcf8e 100644 --- a/src/Nethermind/Nethermind.TxPool/IChainHeadInfoProvider.cs +++ b/src/Nethermind/Nethermind.TxPool/IChainHeadInfoProvider.cs @@ -26,6 +26,8 @@ public interface IChainHeadInfoProvider public UInt256 CurrentFeePerBlobGas { get; } + bool IsSyncing { get; } + event EventHandler HeadChanged; } } diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index e9786211d4b..3417ede0714 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -194,6 +194,8 @@ public bool TryGetBlobAndProof(byte[] blobVersionedHash, private void OnHeadChange(object? sender, BlockReplacementEventArgs e) { + if (_headInfo.IsSyncing) return; + try { _headBlocksChannel.Writer.TryWrite(e); @@ -408,6 +410,8 @@ public void RemovePeer(PublicKey nodeId) public AcceptTxResult SubmitTx(Transaction tx, TxHandlingOptions handlingOptions) { + if (_headInfo.IsSyncing) return AcceptTxResult.Syncing; + Metrics.PendingTransactionsReceived++; // assign a sequence number to transaction so we can order them by arrival times when