diff --git a/src/Nethermind/Chains/arena-z-mainnet.json.zst b/src/Nethermind/Chains/arena-z-mainnet.json.zst index 2534fe883df..5c589482f83 100644 Binary files a/src/Nethermind/Chains/arena-z-mainnet.json.zst and b/src/Nethermind/Chains/arena-z-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/automata-mainnet.json.zst b/src/Nethermind/Chains/automata-mainnet.json.zst index c55c4baec93..2361dca88f7 100644 Binary files a/src/Nethermind/Chains/automata-mainnet.json.zst and b/src/Nethermind/Chains/automata-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/base-mainnet.json.zst b/src/Nethermind/Chains/base-mainnet.json.zst index bb65832b987..3bb992fc484 100644 Binary files a/src/Nethermind/Chains/base-mainnet.json.zst and b/src/Nethermind/Chains/base-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/base-sepolia.json.zst b/src/Nethermind/Chains/base-sepolia.json.zst index 06afc0e2b92..d862ac31dad 100644 Binary files a/src/Nethermind/Chains/base-sepolia.json.zst and b/src/Nethermind/Chains/base-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/bob-mainnet.json.zst b/src/Nethermind/Chains/bob-mainnet.json.zst index 81637577e2e..1c815fa48d7 100644 Binary files a/src/Nethermind/Chains/bob-mainnet.json.zst and b/src/Nethermind/Chains/bob-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/boba-mainnet.json.zst b/src/Nethermind/Chains/boba-mainnet.json.zst index 13dcc69c27d..a9e66565108 100644 Binary files a/src/Nethermind/Chains/boba-mainnet.json.zst and b/src/Nethermind/Chains/boba-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/boba-sepolia.json.zst b/src/Nethermind/Chains/boba-sepolia.json.zst index 9fd3afa08a1..8dd9115b076 100644 Binary files a/src/Nethermind/Chains/boba-sepolia.json.zst and b/src/Nethermind/Chains/boba-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/camp-sepolia.json.zst b/src/Nethermind/Chains/camp-sepolia.json.zst index 72fc64fc415..9621f5e824e 100644 Binary files a/src/Nethermind/Chains/camp-sepolia.json.zst and b/src/Nethermind/Chains/camp-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/cyber-mainnet.json.zst b/src/Nethermind/Chains/cyber-mainnet.json.zst index 63389838703..cf022aac8d7 100644 Binary files a/src/Nethermind/Chains/cyber-mainnet.json.zst and b/src/Nethermind/Chains/cyber-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/cyber-sepolia.json.zst b/src/Nethermind/Chains/cyber-sepolia.json.zst index fff35115ca8..10e9c27d8de 100644 Binary files a/src/Nethermind/Chains/cyber-sepolia.json.zst and b/src/Nethermind/Chains/cyber-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/dictionary b/src/Nethermind/Chains/dictionary index d523abde3f4..acd327d0df2 100644 Binary files a/src/Nethermind/Chains/dictionary and b/src/Nethermind/Chains/dictionary differ diff --git a/src/Nethermind/Chains/ethernity-mainnet.json.zst b/src/Nethermind/Chains/ethernity-mainnet.json.zst index fd09aeb4c41..b38f5d9580b 100644 Binary files a/src/Nethermind/Chains/ethernity-mainnet.json.zst and b/src/Nethermind/Chains/ethernity-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/ethernity-sepolia.json.zst b/src/Nethermind/Chains/ethernity-sepolia.json.zst index 8525a63e849..52eca23cd6a 100644 Binary files a/src/Nethermind/Chains/ethernity-sepolia.json.zst and b/src/Nethermind/Chains/ethernity-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/fraxtal-mainnet.json.zst b/src/Nethermind/Chains/fraxtal-mainnet.json.zst index 57062376e4b..fa1fb56cde4 100644 Binary files a/src/Nethermind/Chains/fraxtal-mainnet.json.zst and b/src/Nethermind/Chains/fraxtal-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/funki-mainnet.json.zst b/src/Nethermind/Chains/funki-mainnet.json.zst index 625cb594197..ed92c132ab1 100644 Binary files a/src/Nethermind/Chains/funki-mainnet.json.zst and b/src/Nethermind/Chains/funki-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/funki-sepolia.json.zst b/src/Nethermind/Chains/funki-sepolia.json.zst index 1f14c0b2182..203f2a0d6fb 100644 Binary files a/src/Nethermind/Chains/funki-sepolia.json.zst and b/src/Nethermind/Chains/funki-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/hashkeychain-mainnet.json.zst b/src/Nethermind/Chains/hashkeychain-mainnet.json.zst index 424ad0b3969..8d255065082 100644 Binary files a/src/Nethermind/Chains/hashkeychain-mainnet.json.zst and b/src/Nethermind/Chains/hashkeychain-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/ink-mainnet.json.zst b/src/Nethermind/Chains/ink-mainnet.json.zst index ed82deeb54d..b980d194a1a 100644 Binary files a/src/Nethermind/Chains/ink-mainnet.json.zst and b/src/Nethermind/Chains/ink-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/ink-sepolia.json.zst b/src/Nethermind/Chains/ink-sepolia.json.zst index f7436949157..8050501241a 100644 Binary files a/src/Nethermind/Chains/ink-sepolia.json.zst and b/src/Nethermind/Chains/ink-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/lisk-mainnet.json.zst b/src/Nethermind/Chains/lisk-mainnet.json.zst index daedd2f5f59..df436ecac70 100644 Binary files a/src/Nethermind/Chains/lisk-mainnet.json.zst and b/src/Nethermind/Chains/lisk-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/lisk-sepolia.json.zst b/src/Nethermind/Chains/lisk-sepolia.json.zst index 97a89d050b0..f14f833bb8c 100644 Binary files a/src/Nethermind/Chains/lisk-sepolia.json.zst and b/src/Nethermind/Chains/lisk-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/lyra-mainnet.json.zst b/src/Nethermind/Chains/lyra-mainnet.json.zst index 83e969616d6..0b58849fef7 100644 Binary files a/src/Nethermind/Chains/lyra-mainnet.json.zst and b/src/Nethermind/Chains/lyra-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/metal-mainnet.json.zst b/src/Nethermind/Chains/metal-mainnet.json.zst index 60d2492e6ca..90894d2e1d7 100644 Binary files a/src/Nethermind/Chains/metal-mainnet.json.zst and b/src/Nethermind/Chains/metal-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/metal-sepolia.json.zst b/src/Nethermind/Chains/metal-sepolia.json.zst index 00d777ad454..dfd60bfa253 100644 Binary files a/src/Nethermind/Chains/metal-sepolia.json.zst and b/src/Nethermind/Chains/metal-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/mint-mainnet.json.zst b/src/Nethermind/Chains/mint-mainnet.json.zst index 4eb4d18e2c9..3ddef6f170c 100644 Binary files a/src/Nethermind/Chains/mint-mainnet.json.zst and b/src/Nethermind/Chains/mint-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/mode-mainnet.json.zst b/src/Nethermind/Chains/mode-mainnet.json.zst index 48b2a4aa09e..4fd773468bc 100644 Binary files a/src/Nethermind/Chains/mode-mainnet.json.zst and b/src/Nethermind/Chains/mode-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/mode-sepolia.json.zst b/src/Nethermind/Chains/mode-sepolia.json.zst index 4f3e1f63efb..4245b9c46a1 100644 Binary files a/src/Nethermind/Chains/mode-sepolia.json.zst and b/src/Nethermind/Chains/mode-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/op-mainnet.json.zst b/src/Nethermind/Chains/op-mainnet.json.zst index 0060e154fa4..7bbaca60c0e 100644 Binary files a/src/Nethermind/Chains/op-mainnet.json.zst and b/src/Nethermind/Chains/op-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/op-sepolia.json.zst b/src/Nethermind/Chains/op-sepolia.json.zst index 9aaca6a45de..640b70c7001 100644 Binary files a/src/Nethermind/Chains/op-sepolia.json.zst and b/src/Nethermind/Chains/op-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/orderly-mainnet.json.zst b/src/Nethermind/Chains/orderly-mainnet.json.zst index 0ecef288903..ac4c3aff88e 100644 Binary files a/src/Nethermind/Chains/orderly-mainnet.json.zst and b/src/Nethermind/Chains/orderly-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/ozean-sepolia.json.zst b/src/Nethermind/Chains/ozean-sepolia.json.zst index 5fb29af5d7f..f6dcf754e47 100644 Binary files a/src/Nethermind/Chains/ozean-sepolia.json.zst and b/src/Nethermind/Chains/ozean-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/pivotal-sepolia.json.zst b/src/Nethermind/Chains/pivotal-sepolia.json.zst index b93004104f7..73006de6b99 100644 Binary files a/src/Nethermind/Chains/pivotal-sepolia.json.zst and b/src/Nethermind/Chains/pivotal-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/polynomial-mainnet.json.zst b/src/Nethermind/Chains/polynomial-mainnet.json.zst index c1db2ea82fc..fd7fd46e099 100644 Binary files a/src/Nethermind/Chains/polynomial-mainnet.json.zst and b/src/Nethermind/Chains/polynomial-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/race-mainnet.json.zst b/src/Nethermind/Chains/race-mainnet.json.zst index 8a216683ab8..907253f5a4d 100644 Binary files a/src/Nethermind/Chains/race-mainnet.json.zst and b/src/Nethermind/Chains/race-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/race-sepolia.json.zst b/src/Nethermind/Chains/race-sepolia.json.zst index 3fd0a6089aa..a8169450693 100644 Binary files a/src/Nethermind/Chains/race-sepolia.json.zst and b/src/Nethermind/Chains/race-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/redstone-mainnet.json.zst b/src/Nethermind/Chains/redstone-mainnet.json.zst index b0360bddf10..abc22d4ec08 100644 Binary files a/src/Nethermind/Chains/redstone-mainnet.json.zst and b/src/Nethermind/Chains/redstone-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst b/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst index bc0588206f2..254c38da84b 100644 Binary files a/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst and b/src/Nethermind/Chains/settlus-mainnet-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst b/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst index d02be32e4b4..6257c7afcfd 100644 Binary files a/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst and b/src/Nethermind/Chains/settlus-sepolia-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/shape-mainnet.json.zst b/src/Nethermind/Chains/shape-mainnet.json.zst index 0a8efc0859b..47b9cff79b8 100644 Binary files a/src/Nethermind/Chains/shape-mainnet.json.zst and b/src/Nethermind/Chains/shape-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/shape-sepolia.json.zst b/src/Nethermind/Chains/shape-sepolia.json.zst index 9a67857fc9c..82376a0654b 100644 Binary files a/src/Nethermind/Chains/shape-sepolia.json.zst and b/src/Nethermind/Chains/shape-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/snax-mainnet.json.zst b/src/Nethermind/Chains/snax-mainnet.json.zst index 80d614807f9..46ce5e974fc 100644 Binary files a/src/Nethermind/Chains/snax-mainnet.json.zst and b/src/Nethermind/Chains/snax-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/soneium-mainnet.json.zst b/src/Nethermind/Chains/soneium-mainnet.json.zst index a39062ecc46..df7b6c75277 100644 Binary files a/src/Nethermind/Chains/soneium-mainnet.json.zst and b/src/Nethermind/Chains/soneium-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/soneium-minato-sepolia.json.zst b/src/Nethermind/Chains/soneium-minato-sepolia.json.zst index 43586353af4..3713d8a31ce 100644 Binary files a/src/Nethermind/Chains/soneium-minato-sepolia.json.zst and b/src/Nethermind/Chains/soneium-minato-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/sseed-mainnet.json.zst b/src/Nethermind/Chains/sseed-mainnet.json.zst index 19a971dc3a4..c810e447f87 100644 Binary files a/src/Nethermind/Chains/sseed-mainnet.json.zst and b/src/Nethermind/Chains/sseed-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/swan-mainnet.json.zst b/src/Nethermind/Chains/swan-mainnet.json.zst index f11e3e91a3e..60ca7a6ee23 100644 Binary files a/src/Nethermind/Chains/swan-mainnet.json.zst and b/src/Nethermind/Chains/swan-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/swell-mainnet.json.zst b/src/Nethermind/Chains/swell-mainnet.json.zst index 3d5711bf867..3f861d51105 100644 Binary files a/src/Nethermind/Chains/swell-mainnet.json.zst and b/src/Nethermind/Chains/swell-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/tbn-mainnet.json.zst b/src/Nethermind/Chains/tbn-mainnet.json.zst index 9ec633328b8..33408075171 100644 Binary files a/src/Nethermind/Chains/tbn-mainnet.json.zst and b/src/Nethermind/Chains/tbn-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/tbn-sepolia.json.zst b/src/Nethermind/Chains/tbn-sepolia.json.zst index 4bbca8f1bd1..d64aa601c7f 100644 Binary files a/src/Nethermind/Chains/tbn-sepolia.json.zst and b/src/Nethermind/Chains/tbn-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/unichain-mainnet.json.zst b/src/Nethermind/Chains/unichain-mainnet.json.zst index 9841c6c3ad2..d0a84bf3e46 100644 Binary files a/src/Nethermind/Chains/unichain-mainnet.json.zst and b/src/Nethermind/Chains/unichain-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/unichain-sepolia.json.zst b/src/Nethermind/Chains/unichain-sepolia.json.zst index 823ff07bbab..98e55cca244 100644 Binary files a/src/Nethermind/Chains/unichain-sepolia.json.zst and b/src/Nethermind/Chains/unichain-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/worldchain-mainnet.json.zst b/src/Nethermind/Chains/worldchain-mainnet.json.zst index fd89e32d513..15f774e691c 100644 Binary files a/src/Nethermind/Chains/worldchain-mainnet.json.zst and b/src/Nethermind/Chains/worldchain-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/worldchain-sepolia.json.zst b/src/Nethermind/Chains/worldchain-sepolia.json.zst index 4aef76b18df..cfce048eb93 100644 Binary files a/src/Nethermind/Chains/worldchain-sepolia.json.zst and b/src/Nethermind/Chains/worldchain-sepolia.json.zst differ diff --git a/src/Nethermind/Chains/xterio-eth-mainnet.json.zst b/src/Nethermind/Chains/xterio-eth-mainnet.json.zst index 811e0045e51..c27949dfa61 100644 Binary files a/src/Nethermind/Chains/xterio-eth-mainnet.json.zst and b/src/Nethermind/Chains/xterio-eth-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/zora-mainnet.json.zst b/src/Nethermind/Chains/zora-mainnet.json.zst index 7e3ebc3cc0b..4d36c1b3f64 100644 Binary files a/src/Nethermind/Chains/zora-mainnet.json.zst and b/src/Nethermind/Chains/zora-mainnet.json.zst differ diff --git a/src/Nethermind/Chains/zora-sepolia.json.zst b/src/Nethermind/Chains/zora-sepolia.json.zst index 35fd78bf85d..32a4747ad8d 100644 Binary files a/src/Nethermind/Chains/zora-sepolia.json.zst and b/src/Nethermind/Chains/zora-sepolia.json.zst differ diff --git a/src/Nethermind/Nethermind.Api/IInitConfig.cs b/src/Nethermind/Nethermind.Api/IInitConfig.cs index 8781c46716f..b22657683da 100644 --- a/src/Nethermind/Nethermind.Api/IInitConfig.cs +++ b/src/Nethermind/Nethermind.Api/IInitConfig.cs @@ -90,7 +90,7 @@ public interface IInitConfig : IConfig [ConfigItem(Description = "[TECHNICAL] Exit when block number is reached. Useful for scripting and testing.", DefaultValue = "null", HiddenFromDocs = true)] long? ExitOnBlockNumber { get; set; } - [ConfigItem(Description = "[TECHNICAL] Specify concurrency limit for background task.", DefaultValue = "1", HiddenFromDocs = true)] + [ConfigItem(Description = "[TECHNICAL] Specify concurrency limit for background task.", DefaultValue = "2", HiddenFromDocs = true)] int BackgroundTaskConcurrency { get; set; } [ConfigItem(Description = "[TECHNICAL] Specify max number of background task.", DefaultValue = "1024", HiddenFromDocs = true)] diff --git a/src/Nethermind/Nethermind.Api/IMainProcessingContext.cs b/src/Nethermind/Nethermind.Api/IMainProcessingContext.cs index ff3e6adeb99..ea70ce58696 100644 --- a/src/Nethermind/Nethermind.Api/IMainProcessingContext.cs +++ b/src/Nethermind/Nethermind.Api/IMainProcessingContext.cs @@ -4,8 +4,8 @@ using System.Threading.Tasks; using Nethermind.Consensus.Processing; using Nethermind.Core.ServiceStopper; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; -using Nethermind.State; namespace Nethermind.Api; @@ -21,7 +21,7 @@ public interface IMainProcessingContext : IStoppableService ITransactionProcessor TransactionProcessor { get; } IBlockProcessor BlockProcessor { get; } IBlockchainProcessor BlockchainProcessor { get; } - IVisitingWorldState WorldState { get; } + IWorldState WorldState { get; } Task IStoppableService.StopAsync() => BlockchainProcessor.StopAsync(); string IStoppableService.Description => "blockchain processor"; diff --git a/src/Nethermind/Nethermind.Api/InitConfig.cs b/src/Nethermind/Nethermind.Api/InitConfig.cs index 466d63e91b2..b1e2fff247b 100644 --- a/src/Nethermind/Nethermind.Api/InitConfig.cs +++ b/src/Nethermind/Nethermind.Api/InitConfig.cs @@ -36,7 +36,7 @@ public class InitConfig : IInitConfig public bool DisableMallocOpts { get; set; } = false; public INodeStorage.KeyScheme StateDbKeyScheme { get; set; } = INodeStorage.KeyScheme.Current; public long? ExitOnBlockNumber { get; set; } = null; - public int BackgroundTaskConcurrency { get; set; } = 1; + public int BackgroundTaskConcurrency { get; set; } = 2; public int BackgroundTaskMaxNumber { get; set; } = 1024; public bool InRunnerTest { get; set; } = false; diff --git a/src/Nethermind/Nethermind.Api/MainProcessingContext.cs b/src/Nethermind/Nethermind.Api/MainProcessingContext.cs index b8e71564d7e..27b4b9f512c 100644 --- a/src/Nethermind/Nethermind.Api/MainProcessingContext.cs +++ b/src/Nethermind/Nethermind.Api/MainProcessingContext.cs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Consensus.Processing; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; -using Nethermind.State; namespace Nethermind.Api; @@ -11,7 +11,7 @@ public record MainProcessingContext( ITransactionProcessor TransactionProcessor, IBlockProcessor BlockProcessor, IBlockchainProcessor BlockchainProcessor, - IVisitingWorldState WorldState + IWorldState WorldState ) : IMainProcessingContext { } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs index fd101cf2726..9a6b8b957e5 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs @@ -49,8 +49,10 @@ protected override Block GetGenesisBlock(IWorldState worldState) => new GenesisLoader( ChainSpec, SpecProvider, + StateReader, worldState, - TxProcessor) + TxProcessor, + LogManager) .Load(); } } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs index 4ed576a4333..7a52867ee51 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs @@ -30,14 +30,14 @@ public class ValidatorContractTests private readonly Address _contractAddress = Address.FromNumber(long.MaxValue); private ITransactionProcessor _transactionProcessor; private IReadOnlyTxProcessorSource _readOnlyTxProcessorSource; - private IVisitingWorldState _stateProvider; + private IWorldState _stateProvider; [SetUp] public void SetUp() { _block = new Block(Build.A.BlockHeader.WithStateRoot(TestItem.KeccakA).TestObject, new BlockBody()); _transactionProcessor = Substitute.For(); - _stateProvider = Substitute.For(); + _stateProvider = Substitute.For(); _readOnlyTxProcessorSource = Substitute.For(); _readOnlyTxProcessorSource.Build(_block.Header).Returns(new ReadOnlyTxProcessingScope(_transactionProcessor, _stateProvider)); } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index c5dd6e83726..cfcdeaef145 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -38,7 +38,7 @@ namespace Nethermind.AuRa.Test.Validators; public class ContractBasedValidatorTests { - private IVisitingWorldState _stateProvider; + private IWorldState _stateProvider; private IAbiEncoder _abiEncoder; private ILogManager _logManager; private AuRaParameters.Validator _validator; @@ -62,7 +62,7 @@ public void SetUp() { _validatorStore = new ValidatorStore(new MemDb()); _validSealerStrategy = new ValidSealerStrategy(); - _stateProvider = Substitute.For(); + _stateProvider = Substitute.For(); _abiEncoder = Substitute.For(); _logManager = LimboLogs.Instance; _blockTree = Substitute.For(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs index 212f509e162..ad74b4ea877 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs @@ -60,7 +60,7 @@ private Block GetGenesisBlock(string chainspecPath) ISpecProvider specProvider = Substitute.For(); specProvider.GetSpec(Arg.Any()).Returns(Berlin.Instance); ITransactionProcessor transactionProcessor = Substitute.For(); - GenesisLoader genesisLoader = new(chainSpec, specProvider, stateProvider, transactionProcessor); + GenesisLoader genesisLoader = new(chainSpec, specProvider, worldStateManager.GlobalStateReader, stateProvider, transactionProcessor, LimboLogs.Instance); return genesisLoader.Load(); } diff --git a/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs b/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs index ccad5c1fe58..10469f4b88d 100644 --- a/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs +++ b/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs @@ -6,6 +6,7 @@ using System.Linq; using Nethermind.Blockchain.Tracing; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; @@ -13,60 +14,86 @@ using Nethermind.Evm; using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; +using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; +using Nethermind.Trie; namespace Nethermind.Blockchain { public class GenesisLoader( ChainSpec chainSpec, ISpecProvider specProvider, + IStateReader stateReader, IWorldState stateProvider, - ITransactionProcessor transactionProcessor) + ITransactionProcessor transactionProcessor, + ILogManager logManager, + Hash256? expectedGenesisHash = null + ) { - private readonly ChainSpec _chainSpec = chainSpec ?? throw new ArgumentNullException(nameof(chainSpec)); - private readonly ISpecProvider _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - private readonly IWorldState _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); - private readonly ITransactionProcessor _transactionProcessor = transactionProcessor ?? throw new ArgumentNullException(nameof(transactionProcessor)); + ILogger _logger = logManager.GetClassLogger(); public Block Load() { - Block genesis = _chainSpec.Genesis; + Block genesis = chainSpec.Genesis; Preallocate(genesis); // we no longer need the allocations - 0.5MB RAM, 9000 objects for mainnet - _chainSpec.Allocations = null; + chainSpec.Allocations = null; - if (!_chainSpec.GenesisStateUnavailable) + if (!chainSpec.GenesisStateUnavailable) { - _stateProvider.Commit(_specProvider.GenesisSpec, true); + stateProvider.Commit(specProvider.GenesisSpec, true); - _stateProvider.CommitTree(0); + stateProvider.CommitTree(0); - genesis.Header.StateRoot = _stateProvider.StateRoot; + genesis.Header.StateRoot = stateProvider.StateRoot; } genesis.Header.Hash = genesis.Header.CalculateHash(); + ValidateGenesisHash(expectedGenesisHash, genesis.Header); + return genesis; } + /// + /// If is null then it means that we do not care about the genesis hash (e.g. in some quick testing of private chains)/> + /// + /// + private void ValidateGenesisHash(Hash256? expectedGenesisHash, BlockHeader genesis) + { + if (expectedGenesisHash is not null && genesis.Hash != expectedGenesisHash) + { + if (_logger.IsTrace) _logger.Trace(stateReader.DumpState(genesis.StateRoot!)); + if (_logger.IsWarn) _logger.Warn(genesis.ToString(BlockHeader.Format.Full)); + if (_logger.IsError) _logger.Error($"Unexpected genesis hash, expected {expectedGenesisHash}, but was {genesis.Hash}"); + } + else + { + if (_logger.IsDebug) _logger.Info($"Genesis hash : {genesis.Hash}"); + } + + ThisNodeInfo.AddInfo("Genesis hash :", $"{genesis.Hash}"); + } + private void Preallocate(Block genesis) { - _transactionProcessor.SetBlockExecutionContext(new BlockExecutionContext(genesis.Header, specProvider.GetSpec(genesis.Header))); - foreach ((Address address, ChainSpecAllocation allocation) in _chainSpec.Allocations.OrderBy(static a => a.Key)) + transactionProcessor.SetBlockExecutionContext(new BlockExecutionContext(genesis.Header, specProvider.GetSpec(genesis.Header))); + foreach ((Address address, ChainSpecAllocation allocation) in chainSpec.Allocations.OrderBy(static a => a.Key)) { - _stateProvider.CreateAccount(address, allocation.Balance, allocation.Nonce); + stateProvider.CreateAccount(address, allocation.Balance, allocation.Nonce); if (allocation.Code is not null) { - _stateProvider.InsertCode(address, allocation.Code, _specProvider.GenesisSpec, true); + stateProvider.InsertCode(address, allocation.Code, specProvider.GenesisSpec, true); } if (allocation.Storage is not null) { foreach (KeyValuePair storage in allocation.Storage) { - _stateProvider.Set(new StorageCell(address, storage.Key), + stateProvider.Set(new StorageCell(address, storage.Key), storage.Value.WithoutLeadingZeros().ToArray()); } } @@ -81,7 +108,7 @@ private void Preallocate(Block genesis) }; CallOutputTracer outputTracer = new(); - _transactionProcessor.Execute(constructorTransaction, outputTracer); + transactionProcessor.Execute(constructorTransaction, outputTracer); if (outputTracer.StatusCode != StatusCode.Success) { diff --git a/src/Nethermind/Nethermind.Blockchain/IReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Blockchain/IReadOnlyTxProcessingScope.cs index 6a91be73dee..5bd5bec4ae8 100644 --- a/src/Nethermind/Nethermind.Blockchain/IReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Blockchain/IReadOnlyTxProcessingScope.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; @@ -10,6 +11,6 @@ namespace Nethermind.Blockchain; public interface IReadOnlyTxProcessingScope : IDisposable { ITransactionProcessor TransactionProcessor { get; } - IVisitingWorldState WorldState { get; } + IWorldState WorldState { get; } void Reset() => Dispose(); } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index d8a08e3bc9f..dca9b597943 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -171,6 +171,9 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "_Technical._ Enable storage range split.", DefaultValue = "false", HiddenFromDocs = true)] bool EnableSnapSyncStorageRangeSplit { get; set; } - [ConfigItem(Description = "_Technical._ Max tx in forward sync buffer.", DefaultValue = "200000", HiddenFromDocs = true)] - int MaxTxInForwardSyncBuffer { get; set; } + [ConfigItem(Description = "_Technical._ Estimated size of memory for storing blocks during download.", DefaultValue = "200000000", HiddenFromDocs = true)] + long ForwardSyncDownloadBufferMemoryBudget { get; set; } + + [ConfigItem(Description = "_Technical._ Estimated max size of blocks in block processing queue before stop downloading.", DefaultValue = "200000000", HiddenFromDocs = true)] + long ForwardSyncBlockProcessingQueueMemoryBudget { get; set; } } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index 30c68bb10fd..096d8f57444 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -83,7 +83,8 @@ public string? PivotHash public ulong FastHeadersMemoryBudget { get; set; } = (ulong)128.MB(); public bool EnableSnapSyncStorageRangeSplit { get; set; } = false; - public int MaxTxInForwardSyncBuffer { get; set; } = 20000; + public long ForwardSyncDownloadBufferMemoryBudget { get; set; } = 200.MiB(); + public long ForwardSyncBlockProcessingQueueMemoryBudget { get; set; } = 200.MiB(); public override string ToString() { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/PendingValidatorsDecoder.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/PendingValidatorsDecoder.cs index 22e1a168e92..7dc6dcc2894 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/PendingValidatorsDecoder.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/PendingValidatorsDecoder.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.Linq; using Nethermind.Core; using Nethermind.Serialization.Rlp; @@ -84,6 +83,11 @@ private static (int Total, int Addresses) GetContentLength(PendingValidators ite return (contentLength, addressesLength); } - private static int GetAddressesLength(Address[] addresses) => addresses.Sum(Rlp.LengthOf); + private static int GetAddressesLength(Address[] addresses) + { + const int AddressLengthWithRlpLengthPrefix = 1 + 20; + + return addresses.Length * AddressLengthWithRlpLengthPrefix; + } } } diff --git a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs index 8970392b624..9d19c6e9760 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs @@ -18,7 +18,7 @@ public void Test_WhenDispose_ThenStateRootWillReset() { ReadOnlyTxProcessingScope env = new ReadOnlyTxProcessingScope( Substitute.For(), - Substitute.For()); + Substitute.For()); env.Dispose(); diff --git a/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs b/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs index 7f803c531b3..934446632d7 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/Scheduler/BackgroundTaskSchedulerTests.cs @@ -9,6 +9,7 @@ using Nethermind.Consensus.Scheduler; using Nethermind.Core.Extensions; using Nethermind.Logging; +using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; @@ -18,18 +19,21 @@ namespace Nethermind.Consensus.Test.Scheduler; public class BackgroundTaskSchedulerTests { private IBlockProcessor _blockProcessor; + private IChainHeadInfoProvider _chainHeadInfo; [SetUp] public void Setup() { _blockProcessor = Substitute.For(); + _chainHeadInfo = Substitute.For(); + _chainHeadInfo.IsSyncing.Returns(false); } [Test] public async Task Test_task_will_execute() { TaskCompletionSource tcs = new TaskCompletionSource(); - await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, 1, 65536, LimboLogs.Instance); + await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, _chainHeadInfo, 1, 65536, LimboLogs.Instance); scheduler.ScheduleTask(1, (_, token) => { @@ -43,7 +47,7 @@ public async Task Test_task_will_execute() [Test] public async Task Test_task_will_execute_concurrently_when_configured_so() { - await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, 2, 65536, LimboLogs.Instance); + await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, _chainHeadInfo, 2, 65536, LimboLogs.Instance); int counter = 0; @@ -68,7 +72,7 @@ public async Task Test_task_will_execute_concurrently_when_configured_so() [Test] public async Task Test_task_will_cancel_on_block_processing() { - await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, 2, 65536, LimboLogs.Instance); + await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, _chainHeadInfo, 2, 65536, LimboLogs.Instance); bool wasCancelled = false; @@ -96,7 +100,7 @@ public async Task Test_task_will_cancel_on_block_processing() [Test] public async Task Test_task_that_is_scheduled_during_block_processing_will_continue_after() { - await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, 2, 65536, LimboLogs.Instance); + await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, _chainHeadInfo, 2, 65536, LimboLogs.Instance); _blockProcessor.BlocksProcessing += Raise.EventWith(new BlocksProcessingEventArgs(null)); int executionCount = 0; @@ -119,7 +123,7 @@ public async Task Test_task_that_is_scheduled_during_block_processing_will_conti [Test] public async Task Test_task_that_is_scheduled_during_block_processing_but_deadlined_will_get_called_and_cancelled() { - await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, 2, 65536, LimboLogs.Instance); + await using BackgroundTaskScheduler scheduler = new BackgroundTaskScheduler(_blockProcessor, _chainHeadInfo, 2, 65536, LimboLogs.Instance); _blockProcessor.BlocksProcessing += Raise.EventWith(new BlocksProcessingEventArgs(null)); bool wasCancelled = false; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs index 9d62f9166af..785382c6415 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/AutoReadOnlyTxProcessingEnvFactory.cs @@ -16,11 +16,11 @@ public class AutoReadOnlyTxProcessingEnvFactory(ILifetimeScope parentLifetime, I { public IReadOnlyTxProcessorSource Create() { - IVisitingWorldState worldState = worldStateManager.CreateResettableWorldState(); + IWorldState worldState = worldStateManager.CreateResettableWorldState(); ILifetimeScope childScope = parentLifetime.BeginLifetimeScope((builder) => { builder - .AddSingleton(worldState).AddSingleton(worldState) + .AddSingleton(worldState) .AddSingleton(); }); @@ -29,18 +29,18 @@ public IReadOnlyTxProcessorSource Create() public IReadOnlyTxProcessorSource CreateForWarmingUp(IWorldState worldStateToWarmUp) { - IVisitingWorldState worldState = worldStateManager.CreateWorldStateForWarmingUp(worldStateToWarmUp); + IWorldState worldState = worldStateManager.CreateWorldStateForWarmingUp(worldStateToWarmUp); ILifetimeScope childScope = parentLifetime.BeginLifetimeScope((builder) => { builder - .AddSingleton(worldState).AddSingleton(worldState) + .AddSingleton(worldState) .AddSingleton(); }); return childScope.Resolve(); } - private class AutoReadOnlyTxProcessingEnv(ITransactionProcessor transactionProcessor, IVisitingWorldState worldState, ILifetimeScope lifetimeScope) : IReadOnlyTxProcessorSource, IDisposable + private class AutoReadOnlyTxProcessingEnv(ITransactionProcessor transactionProcessor, IWorldState worldState, ILifetimeScope lifetimeScope) : IReadOnlyTxProcessorSource, IDisposable { public IReadOnlyTxProcessingScope Build(BlockHeader? header) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs index 647cd735fd7..ef7305ce53d 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Blockchain; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; @@ -9,7 +10,7 @@ namespace Nethermind.Consensus.Processing; public class ReadOnlyTxProcessingScope( ITransactionProcessor transactionProcessor, - IVisitingWorldState worldState + IWorldState worldState ) : IReadOnlyTxProcessingScope { public void Dispose() @@ -19,5 +20,5 @@ public void Dispose() } public ITransactionProcessor TransactionProcessor => transactionProcessor; - public IVisitingWorldState WorldState => worldState; + public IWorldState WorldState => worldState; } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs b/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs index a008af09854..b0ea3a22b5d 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ShareableTxProcessingSource.cs @@ -62,6 +62,6 @@ public void Dispose() public ITransactionProcessor TransactionProcessor => _scope.TransactionProcessor; - public IVisitingWorldState WorldState => _scope.WorldState; + public IWorldState WorldState => _scope.WorldState; } } diff --git a/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs b/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs index aac8a86994d..99e855b006a 100644 --- a/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs +++ b/src/Nethermind/Nethermind.Consensus/Scheduler/BackgroundTaskScheduler.cs @@ -11,6 +11,7 @@ using Nethermind.Consensus.Processing; using Nethermind.Core.Extensions; using Nethermind.Logging; +using Nethermind.TxPool; namespace Nethermind.Consensus.Scheduler; @@ -38,11 +39,12 @@ public class BackgroundTaskScheduler : IBackgroundTaskScheduler, IAsyncDisposabl private readonly Task[] _tasksExecutors; private readonly ILogger _logger; private readonly IBlockProcessor _blockProcessor; + private readonly IChainHeadInfoProvider _headInfo; private CancellationTokenSource _blockProcessorCancellationTokenSource; private bool _disposed = false; - public BackgroundTaskScheduler(IBlockProcessor blockProcessor, int concurrency, int capacity, ILogManager logManager) + public BackgroundTaskScheduler(IBlockProcessor blockProcessor, IChainHeadInfoProvider headInfo, int concurrency, int capacity, ILogManager logManager) { ArgumentOutOfRangeException.ThrowIfLessThan(concurrency, 1); ArgumentOutOfRangeException.ThrowIfLessThan(capacity, 1); @@ -55,6 +57,7 @@ public BackgroundTaskScheduler(IBlockProcessor blockProcessor, int concurrency, _taskQueue = Channel.CreateUnboundedPrioritized(); _logger = logManager.GetClassLogger(); _blockProcessor = blockProcessor; + _headInfo = headInfo; _restartQueueSignal = new ManualResetEventSlim(initialState: true); // As channel is unbounded (to be prioritized) we gate capacity with a semaphore _capacity = new SemaphoreSlim(initialCount: capacity); @@ -75,10 +78,15 @@ public BackgroundTaskScheduler(IBlockProcessor blockProcessor, int concurrency, private void BlockProcessorOnBlocksProcessing(object? sender, BlocksProcessingEventArgs e) { - // Reset background queue processing signal, causing it to wait - _restartQueueSignal.Reset(); - // On block processing, we cancel the block process cts, causing current task to get cancelled. - _blockProcessorCancellationTokenSource.Cancel(); + // If we are syncing we don't block background task processing + // as there are potentially no gaps between blocks + if (!_headInfo.IsSyncing) + { + // Reset background queue processing signal, causing it to wait + _restartQueueSignal.Reset(); + // On block processing, we cancel the block process cts, causing current task to get cancelled. + _blockProcessorCancellationTokenSource.Cancel(); + } } private void BlockProcessorOnBlockProcessed(object? sender, BlockProcessedEventArgs e) diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs index a46c5551ea1..0cbfb8156cf 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs @@ -12,7 +12,7 @@ namespace Nethermind.Consensus.Tracing { public class Tracer( - IVisitingWorldState worldState, + IStateReader stateReader, IBlockchainProcessor traceProcessor, IBlockchainProcessor executeProcessor, ProcessingOptions executeOptions = ProcessingOptions.Trace, @@ -38,7 +38,7 @@ public void Accept(ITreeVisitor visitor, Hash256 stateRoot) where TC ArgumentNullException.ThrowIfNull(visitor); ArgumentNullException.ThrowIfNull(stateRoot); - worldState.Accept(visitor, stateRoot); + stateReader.RunTreeVisitor(visitor, stateRoot); } } } diff --git a/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs b/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs new file mode 100644 index 00000000000..5aa6cfa3dbd --- /dev/null +++ b/src/Nethermind/Nethermind.Core.Test/Container/OrderedComponentsTests.cs @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.Linq; +using Autofac; +using FluentAssertions; +using Nethermind.Core.Container; +using NUnit.Framework; + +namespace Nethermind.Core.Test.Container; + +public class OrderedComponentsTests +{ + [Test] + public void TestNestedModuleConsistency() + { + using IContainer ctx = new ContainerBuilder() + .AddModule(new ModuleA()) + .AddLast(_ => new Item("4")) + .Build(); + + ctx.Resolve().Select(item => item.Name).Should().BeEquivalentTo(["1", "2", "3", "4"]); + ctx.Resolve>().Select(item => item.Name).Should().BeEquivalentTo(["1", "2", "3", "4"]); + ctx.Resolve>().Select(item => item.Name).Should().BeEquivalentTo(["1", "2", "3", "4"]); + } + + [Test] + public void TestAddFirst() + { + using IContainer ctx = new ContainerBuilder() + .AddLast(_ => new Item("2")) + .AddLast(_ => new Item("3")) + .AddFirst(_ => new Item("1")) + .Build(); + + ctx.Resolve().Select(item => item.Name).Should().BeEquivalentTo(["1", "2", "3"]); + } + + [Test] + public void TestDisallowIndividualRegistration() + { + Action act = () => new ContainerBuilder() + .AddLast(_ => new Item("1")) + .AddSingleton(_ => new Item("2")) + .Build(); + + act.Should().Throw(); + } + + private class ModuleA : Module + { + protected override void Load(ContainerBuilder builder) => + builder + .AddModule(new ModuleB()) + .AddLast(_ => new Item("3")); + } + + private class ModuleB : Module + { + protected override void Load(ContainerBuilder builder) => + builder + .AddModule(new ModuleC()) + .AddLast(_ => new Item("2")); + } + + + private class ModuleC : Module + { + protected override void Load(ContainerBuilder builder) => + builder + .AddLast(_ => new Item("1")); + } + private record Item(string Name); +} diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/MainBlockProcessingContext.cs b/src/Nethermind/Nethermind.Core.Test/Modules/MainBlockProcessingContext.cs index 0254f58755d..eede677fe6a 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/MainBlockProcessingContext.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/MainBlockProcessingContext.cs @@ -7,6 +7,7 @@ using Nethermind.Api; using Nethermind.Blockchain; using Nethermind.Consensus.Processing; +using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; @@ -23,7 +24,7 @@ public record MainBlockProcessingContext( ILifetimeScope LifetimeScope, IBlockProcessingQueue BlockProcessingQueue, IBlockchainProcessor BlockchainProcessor, - IVisitingWorldState WorldState, + IWorldState WorldState, IBlockProcessor BlockProcessor, ITransactionProcessor TransactionProcessor, GenesisLoader GenesisLoader) : IMainProcessingContext, IAsyncDisposable diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs index 6b8ce72bd32..c141f4418e9 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/PseudoNethermindModule.cs @@ -1,11 +1,11 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.IO.Abstractions; using System.Reflection; using Autofac; using Nethermind.Api; -using Nethermind.Blockchain.Filters; using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Consensus.Scheduler; @@ -13,7 +13,10 @@ using Nethermind.Core.Timers; using Nethermind.Crypto; using Nethermind.Db; +using Nethermind.Evm; +using Nethermind.Evm.State; using Nethermind.Init.Modules; +using Nethermind.Int256; using Nethermind.JsonRpc; using Nethermind.KeyStore; using Nethermind.Logging; @@ -53,6 +56,7 @@ protected override void Load(ContainerBuilder builder) .AddSingleton() .AddSingleton((blockProcessingContext) => new BackgroundTaskScheduler( blockProcessingContext.BlockProcessor, + new ChainHeadInfoMock(), initConfig.BackgroundTaskConcurrency, initConfig.BackgroundTaskMaxNumber, logManager)) @@ -85,4 +89,19 @@ protected override void Load(ContainerBuilder builder) } }); } + + private class ChainHeadInfoMock : IChainHeadInfoProvider + { + public IChainHeadSpecProvider SpecProvider { get; } = null!; + public IReadOnlyStateProvider ReadOnlyStateProvider { get; } = null!; + public ICodeInfoRepository CodeInfoRepository { get; } = null!; + public long HeadNumber { get; } + public long? BlockGasLimit { get; } + public UInt256 CurrentBaseFee { get; } + public UInt256 CurrentFeePerBlobGas { get; } + public ProofVersion CurrentProofVersion { get; } + public bool IsSyncing { get => false; } + public bool IsProcessingBlock { get; } + public event EventHandler HeadChanged { add { } remove { } } + } } diff --git a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs index ffa463c0bfc..d9fcb974266 100644 --- a/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs +++ b/src/Nethermind/Nethermind.Core.Test/Modules/TestBlockProcessingModule.cs @@ -87,7 +87,7 @@ private MainBlockProcessingContext ConfigureMainBlockProcessingContext(ILifetime processingCtxBuilder // These are main block processing specific .AddScoped(mainCodeInfoRepository) - .AddSingleton(mainWorldState).AddSingleton(mainWorldState) + .AddSingleton(mainWorldState) .Bind() .AddScoped() .AddScoped(new BlockchainProcessor.Options diff --git a/src/Nethermind/Nethermind.Core/BlockExtensions.cs b/src/Nethermind/Nethermind.Core/BlockExtensions.cs index c720cc27a2d..07fddd3951b 100644 --- a/src/Nethermind/Nethermind.Core/BlockExtensions.cs +++ b/src/Nethermind/Nethermind.Core/BlockExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Int256; @@ -46,4 +47,18 @@ bool ParentBeforeTTD() /// /// public static bool IsTerminalBlock(this Block block, ISpecProvider specProvider) => block.Header.IsTerminalBlock(specProvider); + + public static int GetTransactionIndex(this Block block, in ValueHash256 txHash) + { + Transaction[] blockTransactions = block.Transactions; + for (int index = 0; index < blockTransactions.Length; index++) + { + if (blockTransactions[index].Hash == txHash) + { + return index; + } + } + + return -1; + } } diff --git a/src/Nethermind/Nethermind.Core/Collections/TypeAsKey.cs b/src/Nethermind/Nethermind.Core/Collections/TypeAsKey.cs new file mode 100644 index 00000000000..eea0bc6ebde --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Collections/TypeAsKey.cs @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; + +namespace Nethermind.Core.Collections; + +public readonly struct TypeAsKey(Type key) : IEquatable +{ + private readonly Type _key = key; + + public static implicit operator Type(TypeAsKey key) => key._key; + public static implicit operator TypeAsKey(Type key) => new(key); + + public bool Equals(TypeAsKey other) => ReferenceEquals(_key, other._key); + public override int GetHashCode() => _key?.GetHashCode() ?? 0; + public override bool Equals(object? obj) => obj is TypeAsKey && Equals((TypeAsKey)obj); +} diff --git a/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs b/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs new file mode 100644 index 00000000000..4315b5c6f8a --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Container/OrderedComponents.cs @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; + +namespace Nethermind.Core.Container; + +public class OrderedComponents +{ + private IList _components = new List(); + public IEnumerable Components => _components; + + public void AddLast(T item) + { + _components.Add(item); + } + + public void AddFirst(T item) + { + _components.Insert(0, item); + } +} diff --git a/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs new file mode 100644 index 00000000000..be286cedbe8 --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Container/OrderedComponentsContainerBuilderExtensions.cs @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.Linq; +using Autofac; +using Autofac.Core; + +namespace Nethermind.Core.Container; + +/// +/// A set of dsl to register components where the order matter. Internally it has an +/// and uses decorators to add the items. The order of invocation matter, but there is explicit method like +/// allowing component that should appear first to appear first. +/// +public static class OrderedComponentsContainerBuilderExtensions +{ + public static ContainerBuilder AddLast(this ContainerBuilder builder, Func factory) => + builder + .EnsureOrderedComponents() + .AddDecorator>((ctx, orderedComponents) => + { + orderedComponents.AddLast(factory(ctx)); + return orderedComponents; + }); + + public static ContainerBuilder AddFirst(this ContainerBuilder builder, Func factory) => + builder + .EnsureOrderedComponents() + .AddDecorator>((ctx, orderedComponents) => + { + orderedComponents.AddFirst(factory(ctx)); + return orderedComponents; + }); + + private static ContainerBuilder EnsureOrderedComponents(this ContainerBuilder builder) + { + string registeredMarker = $"Registerd OrderedComponents For {typeof(T).Name}"; + if (!builder.Properties.TryAdd(registeredMarker, null)) + { + return builder; + } + + // Prevent registering separately which has no explicit ordering + builder.RegisterBuildCallback(scope => + { + if (scope.ComponentRegistry.ServiceRegistrationsFor(new TypedService(typeof(T))).Any()) + { + throw new InvalidOperationException( + $"Service of type {typeof(T).Name} must only be registered with one of DSL in {nameof(OrderedComponentsContainerBuilderExtensions)}"); + } + }); + + // Not a singleton which allow it to work seamlessly with scoped lifetime with additional component + builder.Add>(); + + builder + .Register((ctx) => ctx.Resolve>().Components) + .As>() + .Fixed(); + + builder.Register((ctx) => ctx.Resolve>().Components.ToArray()) + .As>() + .As() + .Fixed(); + + builder.Register((ctx) => ctx.Resolve>().Components.ToList()) + .As>() + .Fixed(); + + return builder; + } +} diff --git a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs index e66ed9ec35d..b33a3e412c4 100644 --- a/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/ContainerBuilderExtensions.cs @@ -7,6 +7,7 @@ using Autofac; using Autofac.Builder; using Autofac.Core; +using Autofac.Core.Registration; using Autofac.Core.Resolving.Pipeline; using Autofac.Features.AttributeFilters; using Nethermind.Core.Container; @@ -478,6 +479,13 @@ private static Func CreateArgResolver(MethodInfo method } return (ctx) => ctx.Resolve(); } + + public static IRegistrationBuilder Fixed(this IRegistrationBuilder reg) + { + // Fixed registration is one where it is always the default. Can't be overridden by later registration. + reg.RegistrationData.Options |= RegistrationOptions.Fixed; + return reg; + } } /// diff --git a/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs b/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs index 7d271adc44f..8d5cb5e9e16 100644 --- a/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs +++ b/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs @@ -116,6 +116,8 @@ public readonly void Dispose() { } private readonly int _index; private readonly int _count; + public int Count => _count; + public StorageKeysEnumerable(AccessList accessList, int index, int count) { _accessList = accessList; diff --git a/src/Nethermind/Nethermind.Core/Eip7594Constants.cs b/src/Nethermind/Nethermind.Core/Eip7594Constants.cs new file mode 100644 index 00000000000..7f4feaa1860 --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Eip7594Constants.cs @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Core; + +/// +/// See EIP-7594 +/// +public static class Eip7594Constants +{ + public const int MaxBlobsPerTx = 6; +} diff --git a/src/Nethermind/Nethermind.Core/Eip7825Constants.cs b/src/Nethermind/Nethermind.Core/Eip7825Constants.cs index 0a3e4bd02bb..df2311605b0 100644 --- a/src/Nethermind/Nethermind.Core/Eip7825Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip7825Constants.cs @@ -7,7 +7,7 @@ namespace Nethermind.Core; public static class Eip7825Constants { - public static readonly long DefaultTxGasLimitCap = 30_000_000; + public static readonly long DefaultTxGasLimitCap = 16_777_216; public static long GetTxGasLimitCap(IReleaseSpec spec) => spec.IsEip7825Enabled ? DefaultTxGasLimitCap : long.MaxValue; } diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index 82263e021f9..a2e8a492935 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -290,6 +290,12 @@ private void CreateMarkerIfCorrupt(RocksDbSharpException rocksDbException) { if (_logger.IsWarn) _logger.Warn($"Corrupted DB detected on path {_fullPath}. Please restart Nethermind to attempt repair."); _fileSystem.File.WriteAllText(CorruptMarkerPath, "marker"); + + // Don't kill tests checking corruption response + if (!rocksDbException.Message.Equals("Corruption: test corruption", StringComparison.Ordinal)) + { + Environment.FailFast("Fast shutdown due to DB corruption. Please restart."); + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/ILEVM/IlEvmTests.cs b/src/Nethermind/Nethermind.Evm.Test/ILEVM/IlEvmTests.cs index 161f503d0cd..4d33ac7bd8f 100644 --- a/src/Nethermind/Nethermind.Evm.Test/ILEVM/IlEvmTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/ILEVM/IlEvmTests.cs @@ -1819,7 +1819,7 @@ public void All_Opcodes_Are_Covered_in_JIT_Tests() List notCovered = new List(); foreach (var opcode in instructions) { - if(!EofInstructionExtensions.IsValid(opcode, false)) + if (!EofInstructionExtensions.IsValid(opcode, false)) { continue; // skip invalid opcodes } diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlCompiler.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlCompiler.cs index 39c39e949e5..d52098c26d2 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlCompiler.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlCompiler.cs @@ -293,7 +293,7 @@ public static Emit EmitEntryPoint(Emit method, foreach (var (programCounter, currentSubsegment) in contractMetadata.SubSegments) { - if(!currentSubsegment.IsReachable) + if (!currentSubsegment.IsReachable) { continue; // skip unreachable segments } diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlEmitter.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlEmitter.cs index 4f87280ebd5..6ae4b7e8766 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlEmitter.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/EvmToIlEmitter.cs @@ -1628,16 +1628,19 @@ internal static void EmitExtcodeSizeInstruction( method.CallSetter(Word.SetInt0, BitConverter.IsLittleEndian); } - private static void EmitGetCachedCodeInfo(Emit method, EnvirementLoader envLoader, Locals locals) + + private static void EmitGetCachedCodeInfo(Emit method, EnvirementLoader envLoader, Locals locals, bool followDelegation = false) { envLoader.LoadCodeInfoRepository(method, locals); envLoader.LoadWorldState(method, locals); method.LoadLocal(locals.address); + method.LoadConstant(followDelegation ? (int)1 : (int)0); envLoader.LoadSpec(method, locals); - method.Call(typeof(CodeInfoRepositoryExtensions).GetMethod(nameof(CodeInfoRepositoryExtensions.GetCachedCodeInfo), [typeof(ICodeInfoRepository), typeof(IWorldState), typeof(Address), typeof(IReleaseSpec)])); + method.LoadLocalAddress(locals.lbool); + method.CallVirtual(typeof(ICodeInfoRepository).GetMethod(nameof(ICodeInfoRepository.GetCachedCodeInfo), [typeof(IWorldState), typeof(Address), typeof(bool), typeof(IReleaseSpec), typeof(Address).MakeByRefType()])); } - internal static Label EmitExtcodeCopyInstruction( + internal static void EmitExtcodeCopyInstruction( Emit method, ICodeInfo codeinfo, Instruction op, IVMConfig ilCompilerConfig, ContractCompilerMetadata contractMetadata, SubSegmentMetadata currentSubSegment, int pc, OpcodeMetadata opcodeMetadata, EnvirementLoader envLoader, Locals locals, Dictionary evmExceptionLabels, (Label returnLabel, Label exitLabel) escapeLabels) { Label endOfOpcode = method.DefineLabel(locals.GetLabelName()); @@ -1703,7 +1706,6 @@ internal static Label EmitExtcodeCopyInstruction( method.Call(typeof(EvmPooledMemory).GetMethod(nameof(EvmPooledMemory.Save), [typeof(UInt256).MakeByRefType(), typeof(ZeroPaddedSpan).MakeByRefType()])); method.MarkLabel(endOfOpcode); - return endOfOpcode; } internal static void EmitExtcodeHashInstruction( @@ -2056,7 +2058,7 @@ internal static void EmitSStoreInstruction( envLoader.LoadSpec(method, locals); - method.CallVirtual(typeof(IReleaseSpec).GetProperty(nameof(IReleaseSpec.UseNetGasMeteringWithAStipendFix)).GetGetMethod()); + method.CallVirtual(typeof(IReleaseSpec).GetProperty(nameof(IReleaseSpec.UseNetGasMetering)).GetGetMethod()); method.BranchIfTrue(metered); envLoader.LoadVmState(method, locals, false); diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/IlAnalyzer.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/IlAnalyzer.cs index 250258140b3..f66ff49b969 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/IlAnalyzer.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/IlAnalyzer.cs @@ -223,7 +223,7 @@ internal static void AnalyzeSegment(byte[] fullcode, Range segmentRange, Diction switch (op) { case Instruction.JUMPDEST: - if(resolvePreviousSegment) + if (resolvePreviousSegment) { subSegment.Start = subsegmentStart; subSegment.RequiredStack = -subSegment.RequiredStack; diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/VirtualMachineDependencies.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/VirtualMachineDependencies.cs index ba0ae63050e..1fddb2ae2b8 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/VirtualMachineDependencies.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/VirtualMachineDependencies.cs @@ -182,7 +182,7 @@ public static EvmExceptionType InstructionCall( // For non-delegate calls, the transfer value is the call value. UInt256 transferValue = instruction is Instruction.DELEGATECALL ? UInt256.Zero : callValue; // Enforce static call restrictions: no value transfer allowed unless it's a CALLCODE. - if (vmState.IsStatic && !transferValue.IsZero && instruction is Instruction.CALL) + if (vmState.IsStatic && !transferValue.IsZero && instruction is not Instruction.CALLCODE) return EvmExceptionType.StaticCallViolation; // Determine caller and target based on the call type. diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs index 3eb9ea59f1a..51576df1a24 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.Math1Param.cs @@ -98,6 +98,8 @@ public struct OpIsZero : IOpMath1Param /// public struct OpCLZ : IOpMath1Param { + static long GasCost => GasCostOf.Low; + public static Word Operation(Word value) => value == default ? Vector256.Create((byte)0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0) : Vector256.Create(0UL, 0UL, 0UL, (ulong)value.CountLeadingZeroBits() << 56).AsByte(); diff --git a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs index a5b83ad31e8..6caeeb3d873 100644 --- a/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs +++ b/src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs @@ -366,10 +366,9 @@ private static bool ChargeAccountAccessGas(ref long gasAvailable, VirtualMachine } // If the account is cold (and not a precompile), charge the cold access cost. - if (vmState.AccessTracker.IsCold(address) && !address.IsPrecompile(spec)) + if (!address.IsPrecompile(spec) && vmState.AccessTracker.WarmUp(address)) { result = UpdateGas(GasCostOf.ColdAccountAccess, ref gasAvailable); - vmState.AccessTracker.WarmUp(address); } else if (chargeForWarm) { @@ -415,10 +414,9 @@ private static bool ChargeStorageAccessGas( } // If the storage cell is still cold, apply the higher cold access cost and mark it as warm. - if (accessTracker.IsCold(in storageCell)) + if (accessTracker.WarmUp(in storageCell)) { result = UpdateGas(GasCostOf.ColdSLoad, ref gasAvailable); - accessTracker.WarmUp(in storageCell); } // For SLOAD operations on already warmed-up storage, apply a lower warm-read cost. else if (storageAccessType == StorageAccessType.SLOAD) diff --git a/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs b/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs index b118838a51f..45a07cb1e6e 100644 --- a/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs +++ b/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs @@ -35,15 +35,11 @@ public StackAccessTracker() public readonly bool IsCold(in StorageCell storageCell) => !_trackingState.AccessedStorageCells.Contains(storageCell); - public readonly void WarmUp(Address address) - { - _trackingState.AccessedAddresses.Add(address); - } + public readonly bool WarmUp(Address address) + => _trackingState.AccessedAddresses.Add(address); - public readonly void WarmUp(in StorageCell storageCell) - { - _trackingState.AccessedStorageCells.Add(storageCell); - } + public readonly bool WarmUp(in StorageCell storageCell) + => _trackingState.AccessedStorageCells.Add(storageCell); public readonly bool WarmUpLargeContract(Address address) => _trackingState.LargeContractList.Add(address); diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 2667769aaa9..1c5f72a16e0 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -1075,10 +1075,10 @@ private CallResult ExecuteCall( _worldState.IncrementNonce(env.ExecutingAccount); } - // IlAnalyzer.Analyse(env.CodeInfo as CodeInfo, ILMode.AOT_MODE, _vmConfig, _logger); - if (_vmConfig.IlEvmEnabledMode is ILMode.AOT_MODE) + if (_vmConfig.IlEvmEnabledMode is ILMode.AOT_MODE && env.CodeInfo.CodeSpan.Length > 0) { + // IlAnalyzer.Analyse(env.CodeInfo as CodeInfo, ILMode.AOT_MODE, _vmConfig, _logger); env.CodeInfo.NoticeExecution(_vmConfig, _logger, Spec); } } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 8f23bd10b5a..7180f8b85f1 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -83,21 +83,28 @@ public void get_transaction_returns_null_when_block_not_found() public void get_transaction_returns_receipt_and_transaction_when_found() { int index = 5; - var receipt = Build.A.Receipt - .WithBlockHash(TestItem.KeccakB) - .WithTransactionHash(TestItem.KeccakA) - .WithIndex(index) - .TestObject; - IEnumerable transactions = Enumerable.Range(0, 10) - .Select(static i => Build.A.Transaction.WithNonce((UInt256)i).TestObject); - var block = Build.A.Block + Transaction[] transactions = Enumerable.Range(0, 10) + .Select(static i => Build.A.Transaction.WithNonce((UInt256)i).WithHash(TestItem.Keccaks[i]).TestObject) + .ToArray(); + Block block = Build.A.Block .WithTransactions(transactions.ToArray()) .TestObject; + TxReceipt[] receipts = block.Transactions.Select((t, i) => Build.A.Receipt + .WithBlockHash(TestItem.KeccakB) + .WithIndex(i) + .WithTransactionHash(t.Hash) + .TestObject + ).ToArray(); + ; _blockTree.FindBlock(TestItem.KeccakB, Arg.Any()).Returns(block); - _receiptStorage.FindBlockHash(TestItem.KeccakA).Returns(TestItem.KeccakB); - _receiptStorage.Get(block).Returns(new[] { receipt }); - _blockchainBridge.GetTransaction(TestItem.KeccakA).Should() - .BeEquivalentTo((receipt, Build.A.Transaction.WithNonce((UInt256)index).TestObject, UInt256.Zero)); + foreach (TxReceipt receipt in receipts) + { + _receiptStorage.FindBlockHash(receipt.TxHash!).Returns(TestItem.KeccakB); + } + _receiptStorage.Get(block).Returns(receipts); + var expectation = (receipts[index], Build.A.Transaction.WithNonce((UInt256)index).WithHash(TestItem.Keccaks[index]).TestObject, UInt256.Zero); + var result = _blockchainBridge.GetTransaction(transactions[index].Hash!); + result.Should().BeEquivalentTo(expectation); } [Test] @@ -193,10 +200,12 @@ public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool .WithType(TxType.Blob) .WithMaxFeePerBlobGas(2) .WithBlobVersionedHashes(2) + .WithHash(txHash) .TestObject : Build.A.Transaction .WithGasPrice(effectiveGasPrice) .WithMaxFeePerGas(effectiveGasPrice) + .WithHash(txHash) .TestObject; Block block = postEip4844 ? Build.A.Block @@ -218,7 +227,7 @@ public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool _blockTree.FindBlock(blockHash, Arg.Is(BlockTreeLookupOptions.RequireCanonical)).Returns(isCanonical ? block : null); _blockTree.FindBlock(blockHash, Arg.Is(BlockTreeLookupOptions.TotalDifficultyNotNeeded)).Returns(block); _receiptStorage.FindBlockHash(txHash).Returns(blockHash); - _receiptStorage.Get(block).Returns(new[] { receipt }); + _receiptStorage.Get(block).Returns([receipt]); (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) result = postEip4844 ? (receipt, new(effectiveGasPrice, 1, 262144), 0) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index d27c1095285..cc023f46a1b 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -80,9 +80,13 @@ private bool TryGetCanonicalTransaction( if (block is not null) { receipts = receiptStorage.Get(block); - receipt = receipts.ForTransaction(txHash); - transaction = block.Transactions[receipt.Index]; - return true; + int txIndex = block.GetTransactionIndex(txHash.ValueHash256); + if (txIndex != -1) + { + transaction = block.Transactions[txIndex]; + receipt = receipts.Length > txIndex && receipts[txIndex].TxHash == txHash ? receipts[txIndex] : null; + return true; + } } } diff --git a/src/Nethermind/Nethermind.Flashbots/Handlers/ValidateBuilderSubmissionHandler.cs b/src/Nethermind/Nethermind.Flashbots/Handlers/ValidateBuilderSubmissionHandler.cs index 484369ac425..d037584a42f 100644 --- a/src/Nethermind/Nethermind.Flashbots/Handlers/ValidateBuilderSubmissionHandler.cs +++ b/src/Nethermind/Nethermind.Flashbots/Handlers/ValidateBuilderSubmissionHandler.cs @@ -3,25 +3,23 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Tracing; -using Nethermind.Flashbots.Data; using Nethermind.Consensus; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Evm; -using Nethermind.Evm.Tracing; +using Nethermind.Evm.State; +using Nethermind.Flashbots.Data; using Nethermind.Int256; using Nethermind.JsonRpc; using Nethermind.Logging; using Nethermind.Merge.Plugin.Data; -using Nethermind.Core.Crypto; -using Nethermind.Evm.State; using Nethermind.State.OverridableEnv; namespace Nethermind.Flashbots.Handlers; @@ -147,7 +145,15 @@ private bool ValidateBlock(Block block, BidTrace message, long registeredGasLimi private bool ValidateBlobsBundle(Transaction[] transactions, BlobsBundleV1 blobsBundle, out string? error) { // get sum of length of blobs of each transaction - int totalBlobsLength = transactions.Sum(t => t.BlobVersionedHashes is not null ? t.BlobVersionedHashes.Length : 0); + int totalBlobsLength = 0; + foreach (Transaction tx in transactions) + { + byte[]?[]? versionedHashes = tx.BlobVersionedHashes; + if (versionedHashes is not null) + { + totalBlobsLength += versionedHashes.Length; + } + } if (totalBlobsLength != blobsBundle.Blobs.Length) { diff --git a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs index 64d2bee5df5..4326995923a 100644 --- a/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs +++ b/src/Nethermind/Nethermind.Init/PruningTrieStateFactory.cs @@ -66,7 +66,7 @@ ILogManager logManager } IKeyValueStoreWithBatching codeDb = dbProvider.CodeDb; - IVisitingWorldState worldState = syncConfig.TrieHealing + IWorldState worldState = syncConfig.TrieHealing ? new HealingWorldState( mainWorldTrieStore, mainNodeStorage, diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 19d0f45588a..eb06e47f99f 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -73,7 +73,7 @@ protected virtual Task InitBlockchain() "- binary data -"); IStateReader stateReader = setApi.StateReader!; - IVisitingWorldState mainWorldState = _api.WorldStateManager!.GlobalWorldState; + IWorldState mainWorldState = _api.WorldStateManager!.GlobalWorldState; PreBlockCaches? preBlockCaches = (mainWorldState as IPreBlockCaches)?.Caches; CodeInfoRepository codeInfoRepository = new(preBlockCaches?.PrecompileCache); IChainHeadInfoProvider chainHeadInfoProvider = @@ -141,6 +141,7 @@ protected virtual Task InitBlockchain() BackgroundTaskScheduler backgroundTaskScheduler = new BackgroundTaskScheduler( mainBlockProcessor, + chainHeadInfoProvider, initConfig.BackgroundTaskConcurrency, initConfig.BackgroundTaskMaxNumber, _api.LogManager); diff --git a/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs b/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs index 174d34ad215..c4c8e54c916 100644 --- a/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs +++ b/src/Nethermind/Nethermind.Init/Steps/LoadGenesisBlock.cs @@ -11,7 +11,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Logging; -using Nethermind.State; namespace Nethermind.Init.Steps { @@ -33,7 +32,6 @@ public LoadGenesisBlock(INethermindApi api) public async Task Execute(CancellationToken _) { _initConfig = _api.Config(); - Hash256? expectedGenesisHash = string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Hash256(_initConfig.GenesisHash); if (_api.BlockTree is null) { @@ -48,8 +46,6 @@ public async Task Execute(CancellationToken _) Load(mainProcessingContext); } - ValidateGenesisHash(expectedGenesisHash, mainProcessingContext.WorldState); - if (!_initConfig.ProcessingEnabled) { if (_logger.IsWarn) _logger.Warn($"Shutting down the blockchain processor due to {nameof(InitConfig)}.{nameof(InitConfig.ProcessingEnabled)} set to false"); @@ -66,8 +62,11 @@ protected virtual void Load(IMainProcessingContext mainProcessingContext) Block genesis = new GenesisLoader( _api.ChainSpec, _api.SpecProvider, + _api.StateReader!, mainProcessingContext.WorldState, - mainProcessingContext.TransactionProcessor) + mainProcessingContext.TransactionProcessor, + _api.LogManager, + string.IsNullOrWhiteSpace(_initConfig?.GenesisHash) ? null : new Hash256(_initConfig.GenesisHash)) .Load(); ManualResetEventSlim genesisProcessedEvent = new(false); @@ -88,28 +87,5 @@ void GenesisProcessed(object? sender, BlockEventArgs args) throw new TimeoutException($"Genesis block was not processed after {_genesisProcessedTimeout.TotalSeconds} seconds. If you are running custom chain with very big genesis file consider increasing {nameof(BlocksConfig)}.{nameof(IBlocksConfig.GenesisTimeoutMs)}."); } } - - /// - /// If is null then it means that we do not care about the genesis hash (e.g. in some quick testing of private chains)/> - /// - /// - private void ValidateGenesisHash(Hash256? expectedGenesisHash, IVisitingWorldState worldState) - { - if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); - - BlockHeader genesis = _api.BlockTree.Genesis ?? throw new NullReferenceException("Genesis block is null"); - if (expectedGenesisHash is not null && genesis.Hash != expectedGenesisHash) - { - if (_logger.IsTrace) _logger.Trace(worldState.DumpState()); - if (_logger.IsWarn) _logger.Warn(genesis.ToString(BlockHeader.Format.Full)); - if (_logger.IsError) _logger.Error($"Unexpected genesis hash, expected {expectedGenesisHash}, but was {genesis.Hash}"); - } - else - { - if (_logger.IsDebug) _logger.Info($"Genesis hash : {genesis.Hash}"); - } - - ThisNodeInfo.AddInfo("Genesis hash :", $"{genesis.Hash}"); - } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs index 2aaab3bcd5d..82de21c147f 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs @@ -9,8 +9,10 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Threading; using Nethermind.JsonRpc.Exceptions; using Nethermind.JsonRpc.Modules; @@ -27,8 +29,11 @@ public class JsonRpcService : IJsonRpcService private readonly ILogger _logger; private readonly IRpcModuleProvider _rpcModuleProvider; private readonly HashSet _methodsLoggingFiltering; + private readonly Lock _propertyInfoModificationLock = new(); private readonly int _maxLoggedRequestParametersCharacters; + private Dictionary _propertyInfoCache = []; + public JsonRpcService(IRpcModuleProvider rpcModuleProvider, ILogManager logManager, IJsonRpcConfig jsonRpcConfig) { _logger = logManager.GetClassLogger(); @@ -196,7 +201,7 @@ private async Task ExecuteAsync(JsonRpcRequest request, string break; case Task task: await task; - resultWrapper = task.GetType().GetProperty("Result")?.GetValue(task) as IResultWrapper; + resultWrapper = GetResultProperty(task)?.GetValue(task) as IResultWrapper; break; } } @@ -244,6 +249,42 @@ private async Task ExecuteAsync(JsonRpcRequest request, string : GetSuccessResponse(methodName, resultWrapper.Data, request.Id, returnAction); } + private PropertyInfo? GetResultProperty(Task task) + { + Type type = task.GetType(); + if (_propertyInfoCache.TryGetValue(type, out PropertyInfo? value)) + { + return value; + } + + return GetResultPropertySlow(type); + } + + private PropertyInfo? GetResultPropertySlow(Type type) + { + lock (_propertyInfoModificationLock) + { + Dictionary current = _propertyInfoCache; + // Re-check inside the lock in case another thread already added it + if (current.TryGetValue(type, out PropertyInfo? value)) + { + return value; + } + + // Copy-on-write: create a new dictionary so we don't mutate + // the one other threads may be reading without locks. + Dictionary propertyInfoCache = new(current); + PropertyInfo? propertyInfo = type.GetProperty("Result"); + propertyInfoCache[type] = propertyInfo; + + // Publish the new cache instance atomically by swapping the reference. + // Readers grabbing _propertyInfoCache will now see the updated dictionary. + _propertyInfoCache = propertyInfoCache; + + return propertyInfo; + } + } + private void LogRequest(string methodName, JsonElement providedParameters, ExpectedParameter[] expectedParameters) { if (_logger.IsTrace && !_methodsLoggingFiltering.Contains(methodName)) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/IContainerBuilderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/IContainerBuilderExtensions.cs index fb38935c7dd..29bd8e076b9 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/IContainerBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/IContainerBuilderExtensions.cs @@ -4,6 +4,7 @@ using System; using Autofac; using Nethermind.Core; +using Nethermind.Core.Container; namespace Nethermind.JsonRpc.Modules; @@ -19,7 +20,7 @@ public static ContainerBuilder RegisterSingletonJsonRpcModule(this Con public static ContainerBuilder RegisterSingletonJsonRpcModule(this ContainerBuilder builder) where T : IRpcModule { return builder - .AddSingleton((ctx) => + .AddLast((ctx) => { Lazy instance = ctx.Resolve>(); return new RpcModuleInfo(typeof(T), new LazyModulePool(new Lazy>(() => @@ -39,7 +40,7 @@ public static ContainerBuilder RegisterBoundedJsonRpcModule( return builder .AddSingleton() .AddSingleton, TFactory>() - .AddSingleton((ctx) => + .AddLast((ctx) => { Lazy> factory = ctx.Resolve>>(); return new RpcModuleInfo(typeof(T), new LazyModulePool(new Lazy>(() => diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs index 58fb16c2923..980e516022e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs @@ -2,57 +2,47 @@ // SPDX-License-Identifier: LGPL-3.0-only using Autofac; -using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Tracing; using Nethermind.Consensus.Validators; using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Evm.State; using Nethermind.Evm.TransactionProcessing; -using Nethermind.State; +using Nethermind.State.OverridableEnv; namespace Nethermind.JsonRpc.Modules.Proof { public class ProofModuleFactory( ILifetimeScope rootLifetimeScope, - IReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory + IOverridableEnvFactory overridableEnvFactory ) : ModuleFactoryBase { public override IProofRpcModule Create() { - // Note: No overridable world scope here. So there aren't any risk of leaking KV store. - IReadOnlyTxProcessingScope txProcessingEnv = readOnlyTxProcessingEnvFactory.Create().Build(null); + IOverridableEnv overridableEnv = overridableEnvFactory.Create(); - ILifetimeScope tracerScope = rootLifetimeScope.BeginLifetimeScope((builder) => - { - builder + ILifetimeScope tracerScope = rootLifetimeScope.BeginLifetimeScope((builder) => builder + .AddModule(overridableEnv) - // Standard read only chain setting - .Bind() - .AddScoped() - .AddDecorator() - .AddScoped(BlockchainProcessor.Options.NoReceipts) - .AddScoped(Always.Valid) // Why? + // Standard read only chain setting + .Bind() + .AddScoped() + .AddDecorator() + .AddScoped(BlockchainProcessor.Options.NoReceipts) + .AddScoped(Always.Valid) // Why? - // Specific for proof rpc - .AddScoped(new InMemoryReceiptStorage()) // Umm.... not `NullReceiptStorage`? - .AddScoped(NoBlockRewards.Instance) - .AddScoped(txProcessingEnv.WorldState).AddScoped(txProcessingEnv.WorldState) + // Specific for proof rpc + .AddScoped(new InMemoryReceiptStorage()) // Umm.... not `NullReceiptStorage`? + .AddScoped(NoBlockRewards.Instance) - .AddScoped() - ; - }); + .AddScoped()); // The tracer need a in memory receipts while the proof RPC does not. // Eh, its a good idea to separate what need block processing and what does not anyway. - ILifetimeScope proofRpcScope = rootLifetimeScope.BeginLifetimeScope((builder) => - { - builder.AddSingleton(tracerScope.Resolve()); - }); + ILifetimeScope proofRpcScope = rootLifetimeScope.BeginLifetimeScope((builder) => builder + .AddSingleton>(tracerScope.Resolve>())); proofRpcScope.Disposer.AddInstanceForAsyncDisposal(tracerScope); rootLifetimeScope.Disposer.AddInstanceForDisposal(proofRpcScope); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs index 0cecb3bce38..dbf22def65b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; +using Nethermind.Blockchain; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Tracing; @@ -18,6 +20,7 @@ using Nethermind.JsonRpc.Data; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.State.OverridableEnv; using Nethermind.State.Proofs; namespace Nethermind.JsonRpc.Modules.Proof @@ -25,39 +28,27 @@ namespace Nethermind.JsonRpc.Modules.Proof /// /// /// - public class ProofRpcModule : IProofRpcModule + public class ProofRpcModule( + IOverridableEnv tracerEnv, + IBlockFinder blockFinder, + IReceiptFinder receiptFinder, + ISpecProvider specProvider) + : IProofRpcModule { - private readonly ILogger _logger; - private readonly ITracer _tracer; - private readonly IBlockFinder _blockFinder; - private readonly IReceiptFinder _receiptFinder; - private readonly ISpecProvider _specProvider; private readonly HeaderDecoder _headerDecoder = new(); private static readonly IRlpStreamDecoder _receiptDecoder = Rlp.GetStreamDecoder(); - public ProofRpcModule( - ITracer tracer, - IBlockFinder blockFinder, - IReceiptFinder receiptFinder, - ISpecProvider specProvider, - ILogManager logManager) - { - _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); - _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); - _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - } - public ResultWrapper proof_call(TransactionForRpc tx, BlockParameter blockParameter) { - SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); + SearchResult searchResult = blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { return ResultWrapper.Fail(searchResult); } BlockHeader sourceHeader = searchResult.Object; + using Scope scope = tracerEnv.BuildAndOverride(sourceHeader); + BlockHeader callHeader = new( sourceHeader.Hash, Keccak.OfAnEmptySequenceRlp, @@ -87,7 +78,7 @@ public ResultWrapper proof_call(TransactionForRpc tx, Block Block block = new(callHeader, new[] { transaction }, []); ProofBlockTracer proofBlockTracer = new(null, transaction.SenderAddress == Address.SystemUser); - _tracer.Trace(block, proofBlockTracer); + scope.Component.Trace(block, proofBlockTracer); CallResultWithProof callResultWithProof = new(); ProofTxTracer proofTxTracer = proofBlockTracer.BuildResult().Single(); @@ -97,33 +88,33 @@ public ResultWrapper proof_call(TransactionForRpc tx, Block // we collect proofs from before execution (after learning which addresses will be touched) // if we wanted to collect post execution proofs then we would need to use BeforeRestore on the tracer - callResultWithProof.Accounts = CollectAccountProofs(sourceHeader.StateRoot, proofTxTracer); + callResultWithProof.Accounts = CollectAccountProofs(scope.Component, sourceHeader.StateRoot, proofTxTracer); return ResultWrapper.Success(callResultWithProof); } public ResultWrapper proof_getTransactionByHash(Hash256 txHash, bool includeHeader) { - Hash256 blockHash = _receiptFinder.FindBlockHash(txHash); + Hash256 blockHash = receiptFinder.FindBlockHash(txHash); if (blockHash is null) { return ResultWrapper.Fail($"{txHash} receipt (transaction) could not be found", ErrorCodes.ResourceNotFound); } - SearchResult searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); + SearchResult searchResult = blockFinder.SearchForBlock(new BlockParameter(blockHash)); if (searchResult.IsError) { return ResultWrapper.Fail(searchResult); } Block block = searchResult.Object; - TxReceipt receipt = _receiptFinder.Get(block).ForTransaction(txHash); + TxReceipt receipt = receiptFinder.Get(block).ForTransaction(txHash); Transaction[] txs = block.Transactions; Transaction transaction = txs[receipt.Index]; TransactionForRpcWithProof txWithProof = new(); - txWithProof.Transaction = TransactionForRpc.FromTransaction(transaction, block.Hash, block.Number, receipt.Index, block.BaseFeePerGas, _specProvider.ChainId); - txWithProof.TxProof = BuildTxProofs(txs, _specProvider.GetSpec(block.Header), receipt.Index); + txWithProof.Transaction = TransactionForRpc.FromTransaction(transaction, block.Hash, block.Number, receipt.Index, block.BaseFeePerGas, specProvider.ChainId); + txWithProof.TxProof = BuildTxProofs(txs, specProvider.GetSpec(block.Header), receipt.Index); if (includeHeader) { txWithProof.BlockHeader = _headerDecoder.Encode(block.Header).Bytes; @@ -134,35 +125,37 @@ public ResultWrapper proof_getTransactionByHash(Hash public ResultWrapper proof_getTransactionReceipt(Hash256 txHash, bool includeHeader) { - Hash256 blockHash = _receiptFinder.FindBlockHash(txHash); + Hash256 blockHash = receiptFinder.FindBlockHash(txHash); if (blockHash is null) { return ResultWrapper.Fail($"{txHash} receipt could not be found", ErrorCodes.ResourceNotFound); } - SearchResult searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); + SearchResult searchResult = blockFinder.SearchForBlock(new BlockParameter(blockHash)); if (searchResult.IsError) { return ResultWrapper.Fail(searchResult); } Block block = searchResult.Object; - TxReceipt receipt = _receiptFinder.Get(block).ForTransaction(txHash); + using Scope scope = tracerEnv.BuildAndOverride(blockFinder.FindParentHeader(block.Header, BlockTreeLookupOptions.None)); + + TxReceipt receipt = receiptFinder.Get(block).ForTransaction(txHash); BlockReceiptsTracer receiptsTracer = new(); receiptsTracer.SetOtherTracer(NullBlockTracer.Instance); - _tracer.Trace(block, receiptsTracer); + scope.Component.Trace(block, receiptsTracer); TxReceipt[] receipts = receiptsTracer.TxReceipts.ToArray(); Transaction[] txs = block.Transactions; ReceiptWithProof receiptWithProof = new(); - IReleaseSpec spec = _specProvider.GetSpec(block.Header); + IReleaseSpec spec = specProvider.GetSpec(block.Header); Transaction? tx = txs.FirstOrDefault(x => x.Hash == txHash); - int logIndexStart = _receiptFinder.Get(block).GetBlockLogFirstIndex(receipt.Index); + int logIndexStart = receiptFinder.Get(block).GetBlockLogFirstIndex(receipt.Index); receiptWithProof.Receipt = new ReceiptForRpc(txHash, receipt, tx?.GetGasInfo(spec, block.Header) ?? new(), logIndexStart); receiptWithProof.ReceiptProof = BuildReceiptProofs(block.Header, receipts, receipt.Index); - receiptWithProof.TxProof = BuildTxProofs(txs, _specProvider.GetSpec(block.Header), receipt.Index); + receiptWithProof.TxProof = BuildTxProofs(txs, specProvider.GetSpec(block.Header), receipt.Index); if (includeHeader) { @@ -172,7 +165,7 @@ public ResultWrapper proof_getTransactionReceipt(Hash256 txHas return ResultWrapper.Success(receiptWithProof); } - private AccountProof[] CollectAccountProofs(Hash256 stateRoot, ProofTxTracer proofTxTracer) + private AccountProof[] CollectAccountProofs(ITracer tracer, Hash256 stateRoot, ProofTxTracer proofTxTracer) { List accountProofs = new(); foreach (Address address in proofTxTracer.Accounts) @@ -181,7 +174,7 @@ private AccountProof[] CollectAccountProofs(Hash256 stateRoot, ProofTxTracer pro .Where(s => s.Address == address) .Select(s => s.Index).ToArray()); - _tracer.Accept(collector, stateRoot); + tracer.Accept(collector, stateRoot); accountProofs.Add(collector.BuildResult()); } @@ -193,7 +186,7 @@ private byte[][] CollectHeaderBytes(ProofTxTracer proofTxTracer, BlockHeader tra List relevantHeaders = new() { tracedBlockHeader }; foreach (Hash256 blockHash in proofTxTracer.BlockHashes) { - relevantHeaders.Add(_blockFinder.FindHeader(blockHash)); + relevantHeaders.Add(blockFinder.FindHeader(blockHash)); } return relevantHeaders @@ -207,7 +200,7 @@ private static byte[][] BuildTxProofs(Transaction[] txs, IReleaseSpec releaseSpe private byte[][] BuildReceiptProofs(BlockHeader blockHeader, TxReceipt[] receipts, int index) { - return ReceiptTrie.CalculateReceiptProofs(_specProvider.GetSpec(blockHeader), receipts, index, _receiptDecoder); + return ReceiptTrie.CalculateReceiptProofs(specProvider.GetSpec(blockHeader), receipts, index, _receiptDecoder); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 0124dfdf416..0108e003645 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -44,8 +44,8 @@ public override ITraceRpcModule Create() ILifetimeScope tracerLifetimeScope = rootLifetimeScope.BeginLifetimeScope((builder) => builder .AddModule(env) - .AddScoped((worldState) => new Tracer( - worldState, + .AddScoped((stateReader) => new Tracer( + stateReader, rpcProcessingScope.Resolve(), validationProcessingScope.Resolve(), traceOptions: ProcessingOptions.TraceTransactions))); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs b/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs index 5b872602043..752459cfcd3 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Metrics.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.ComponentModel; +using System.Runtime.Serialization; using Nethermind.Core.Attributes; namespace Nethermind.Merge.Plugin @@ -26,18 +27,22 @@ public static class Metrics [GaugeMetric] [Description("Number of Blobs requested by engine_getBlobsV1")] + [DataMember(Name = "execution_engine_getblobs_requested_total")] public static int NumberOfRequestedBlobs { get; set; } [GaugeMetric] [Description("Number of Blobs sent by engine_getBlobsV1")] + [DataMember(Name = "execution_engine_getblobs_available_total")] public static int NumberOfSentBlobs { get; set; } [GaugeMetric] [Description("Number of responses to engine_getBlobsV1 and engine_getBlobsV2 with all requested blobs")] + [DataMember(Name = "execution_engine_getblobs_hit_total")] public static int GetBlobsRequestsSuccessTotal { get; set; } [GaugeMetric] [Description("Number of responses to engine_getBlobsVX without all requested blobs")] + [DataMember(Name = "execution_engine_getblobs_miss_total")] public static int GetBlobsRequestsFailureTotal { get; set; } [CounterMetric] diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs index c0795285b97..5b3338f5506 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs @@ -5,6 +5,7 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; +using Nethermind.Consensus.Processing; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; @@ -18,32 +19,38 @@ namespace Nethermind.Merge.Plugin.Synchronization { - public class MergeBlockDownloader : BlockDownloader + public class MergeBlockDownloader( + IBeaconPivot beaconPivot, + IBlockTree blockTree, + IBlockValidator blockValidator, + ISyncReport syncReport, + IReceiptStorage receiptStorage, + ISpecProvider specProvider, + IBetterPeerStrategy betterPeerStrategy, + IFullStateFinder fullStateFinder, + IForwardHeaderProvider forwardHeaderProvider, + ISyncPeerPool syncPeerPool, + IReceiptsRecovery receiptsRecovery, + IBlockProcessingQueue blockProcessingQueue, + ISyncConfig syncConfig, + ILogManager logManager) + : BlockDownloader( + blockTree, + blockValidator, + syncReport, + receiptStorage, + specProvider, + betterPeerStrategy, + fullStateFinder, + forwardHeaderProvider, + syncPeerPool, + receiptsRecovery, + blockProcessingQueue, + syncConfig, + logManager) { - private readonly IBeaconPivot _beaconPivot; - private readonly IBlockTree _blockTree; - private readonly ILogger _logger; - - public MergeBlockDownloader( - IBeaconPivot beaconPivot, - IBlockTree? blockTree, - IBlockValidator? blockValidator, - ISyncReport? syncReport, - IReceiptStorage? receiptStorage, - ISpecProvider specProvider, - IBetterPeerStrategy betterPeerStrategy, - IFullStateFinder fullStateFinder, - IForwardHeaderProvider forwardHeaderProvider, - ISyncPeerPool syncPeerPool, - ISyncConfig syncConfig, - ILogManager logManager) - : base(blockTree, blockValidator, syncReport, receiptStorage, - specProvider, betterPeerStrategy, fullStateFinder, forwardHeaderProvider, syncPeerPool, syncConfig, logManager) - { - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _beaconPivot = beaconPivot; - _logger = logManager.GetClassLogger(); - } + private readonly IBlockTree _blockTree = blockTree; + private readonly ILogger _logger = logManager.GetClassLogger(); protected override BlockTreeSuggestOptions GetSuggestOption(bool shouldProcess, Block currentBlock) { @@ -51,7 +58,7 @@ protected override BlockTreeSuggestOptions GetSuggestOption(bool shouldProcess, shouldProcess ? BlockTreeSuggestOptions.ShouldProcess : BlockTreeSuggestOptions.None; bool isKnownBeaconBlock = _blockTree.IsKnownBeaconBlock(currentBlock.Number, currentBlock.GetOrCalculateHash()); - if (_logger.IsTrace) _logger.Trace($"Current block {currentBlock}, BeaconPivot: {_beaconPivot.PivotNumber}, IsKnownBeaconBlock: {isKnownBeaconBlock}"); + if (_logger.IsTrace) _logger.Trace($"Current block {currentBlock}, BeaconPivot: {beaconPivot.PivotNumber}, IsKnownBeaconBlock: {isKnownBeaconBlock}"); if (isKnownBeaconBlock) { diff --git a/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/base-mainnet.json index 936804423c3..f0d6ffb949c 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": 32550000, - "PivotHash": "0x18401c18220a361498819169d9bfea1ce6a4a81aedbde2359c7898153d6f2c8c" + "PivotNumber": 32780000, + "PivotHash": "0x28f0ac563c5dd0098c6ac3c23aa291e5164c77afcbb0ec6f915b5c2ce782cbf6" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/base-sepolia.json index 77faf7da22a..e72ea30695e 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": 28060000, - "PivotHash": "0x7ad8043c80402730514ce59464c612c022f151dc77cdb984138a64d007c6af7e" + "PivotNumber": 28290000, + "PivotHash": "0xde9a2994afb2da18d22b4051d2a67a7024c4fa2d6277e4e6022064332570b87d" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.json b/src/Nethermind/Nethermind.Runner/configs/chiado.json index 3038ddaba71..ce78beea0b5 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.json +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.json @@ -18,8 +18,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 16590000, - "PivotHash": "0x3cefe8046445de2913a3382af451dc13f4c963746143b3f964c021ee0cfdf00f", + "PivotNumber": 16710000, + "PivotHash": "0xf5e5177ed8b0c340d7d39f31ca73a594b18203095a700868a3e70f673aa0c5b3", "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 7e4e8da2eae..9cb16959521 100644 --- a/src/Nethermind/Nethermind.Runner/configs/energyweb.json +++ b/src/Nethermind/Nethermind.Runner/configs/energyweb.json @@ -13,9 +13,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 36400000, - "PivotHash": "0xa05aab97021365824b0c96f8afe8416d25fe1244b79c78ee69a7dc1e06e5aecd", - "PivotTotalDifficulty": "12386278155922160070066835710516362896611796376", + "PivotNumber": 36510000, + "PivotHash": "0xafe652ac0d78c419917ccdbbbb1cb8c38d790724ef97005cb3e1f821a84d1586", + "PivotTotalDifficulty": "12423709216283463301047806917333857399871718285", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.json b/src/Nethermind/Nethermind.Runner/configs/gnosis.json index ffb19e1fd24..c0d8eab6642 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.json +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.json @@ -14,8 +14,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 40930000, - "PivotHash": "0x6ddb21ab97a184413f4dd0ba8234fc855db80387bb0e81bbda939eae2a4a331e", + "PivotNumber": 41040000, + "PivotHash": "0x15849f57931cf7739eed0cdeb0da8df2ea16810b272dcf6d173dcca1af5cd245", "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 95d65fdbc76..21273eea87b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 18420000, - "PivotHash": "0xffeb9f9ad8c11d66c82bf8990272845aa4921436c9904881e51503ef05282cfd", - "PivotTotalDifficulty": "34109861" + "PivotNumber": 18540000, + "PivotHash": "0x3b79719300301258d503a57790407d64cb4d8dca3207643b6979b5659937dc40", + "PivotTotalDifficulty": "34293024" }, "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 3b0efe6e861..a18c886578e 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.json @@ -12,9 +12,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 12030000, - "PivotHash": "0x457ddc5c999d67d6c2dc9ce8ec311bf1c18872eea4e96c5b373d2b4a843d221a", - "PivotTotalDifficulty": "20461347" + "PivotNumber": 12150000, + "PivotHash": "0x593af9bca041f58a9a41a75d56e61a2796b8b63e872427dc855683e767d62d47", + "PivotTotalDifficulty": "20653978" }, "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 db09cf22b84..b7b48a4f28b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-mainnet.json @@ -17,9 +17,9 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 20600000, - "PivotHash": "0x3bd995cc93ee95a4f22ec785635c5e57bea06d8811e26ade9e361fdb4a179995", - "PivotTotalDifficulty": "41200001", + "PivotNumber": 20800000, + "PivotHash": "0x359161297fb9504f222e5543e2196d7229f3ea869a91a66d10ed6b9f421f038a", + "PivotTotalDifficulty": "41600001", "HeaderStateDistance": 6 }, "JsonRpc": { diff --git a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json index 99451973e7d..1cb54492c84 100644 --- a/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/linea-sepolia.json @@ -17,9 +17,9 @@ }, "Sync": { "SnapSync": true, - "PivotNumber": 15310000, - "PivotHash": "0x3cadcb9db0e8e917e8bb03bfb245be22e0155158b2409e7f3f4528f9aca9f1c4", - "PivotTotalDifficulty": "30620001", + "PivotNumber": 15610000, + "PivotHash": "0x8405842b6afe9749d7c4dae84fbf95ee3febbe11b8291752183c72699f7aba8b", + "PivotTotalDifficulty": "31220001", "HeaderStateDistance": 6 }, "JsonRpc": { diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.json b/src/Nethermind/Nethermind.Runner/configs/mainnet.json index af944dd64bf..a4256abf943 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.json @@ -10,8 +10,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 22855000, - "PivotHash": "0x9505301da162536954c841dfe9e7b31f01e53a33a0f0ebf1986f708494e4219b", + "PivotNumber": 22905000, + "PivotHash": "0x81116f98d56e3f037149f835477e93a36ebb307ae58853b4f1f695878d77dc8f", "PivotTotalDifficulty": "58750003716598352816469", "FastSyncCatchUpHeightDelta": "10000000000", "AncientReceiptsBarrier": 15537394, diff --git a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json index 5ee742d1fd7..2291e055de0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/op-mainnet.json @@ -15,8 +15,8 @@ "FastSyncCatchUpHeightDelta": "10000000000", "AncientBodiesBarrier": 105235063, "AncientReceiptsBarrier": 105235063, - "PivotNumber": 138140000, - "PivotHash": "0x8ca37669a906d7b7fe18bbfb8dba3f14579f0d575cc631e83055c24bcf6a6fbe" + "PivotNumber": 138370000, + "PivotHash": "0x9a4caaacd0359b2b0be23710c96d2af4ca7f403a0d75b312f5833e1b205d36e4" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/op-sepolia.json index 3dd3641d602..9f810e4e1ff 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": 30040000, - "PivotHash": "0x3f1b0214d6b9a4b5dcab05bb28149dbb087613128120e05b971182777305ced0" + "PivotNumber": 30270000, + "PivotHash": "0x2f80ce1ac126baf2ceb86ccd2e157a018530f058edd70532fe92602fee2b00dd" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.json b/src/Nethermind/Nethermind.Runner/configs/sepolia.json index d4ea95b458d..4660987c041 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.json @@ -18,8 +18,8 @@ "FastSync": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 8700000, - "PivotHash": "0x42403383b536689026cef7767119413d85ce41b1c7c622fd3dbf0f18432a00e7", + "PivotNumber": 8750000, + "PivotHash": "0x74560d628a79b7b585db1941d697b489eaaea0ad81634a0b7ff131c784ba90e9", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": 10000000000, "AncientReceiptsBarrier": 1450409, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.json b/src/Nethermind/Nethermind.Runner/configs/volta.json index d94175d0cef..3cd40bd0647 100644 --- a/src/Nethermind/Nethermind.Runner/configs/volta.json +++ b/src/Nethermind/Nethermind.Runner/configs/volta.json @@ -17,9 +17,9 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 32560000, - "PivotHash": "0x84bac5e207fca78d1b109204a332c1cc68560eb9e949832d0b430c7e6ed90954", - "PivotTotalDifficulty": "11079593866945756370367477217978372964624592587", + "PivotNumber": 32680000, + "PivotHash": "0xe8e20981712f6df72b9ff23141ebb068dc2b0ccea48bfe9a99ee46cd5836f90f", + "PivotTotalDifficulty": "11120427750976268985983082170870185149999071660", "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 }, diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json index 796605b3d08..99fb11817ed 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-mainnet.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 16270000, - "PivotHash": "0x7d5188f3defc5a4bf3b562cc7cc8f4ca13bdaa943d303be4e1c4d9b00f7e2cfa" + "PivotNumber": 16500000, + "PivotHash": "0x5cdc5965f8ae1e261705fdce4c4379eb0f7c4eb725fd4b79eac9e473305694dc" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json index f8eb21edc98..d0d0dd22f71 100644 --- a/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json +++ b/src/Nethermind/Nethermind.Runner/configs/worldchain-sepolia.json @@ -13,8 +13,8 @@ "FastSync": true, "SnapSync": true, "FastSyncCatchUpHeightDelta": "10000000000", - "PivotNumber": 15670000, - "PivotHash": "0x8dcaa7f3f4f6cf58820ce0c6b4def07aec85626f12be553a7212d29d988251d8" + "PivotNumber": 15900000, + "PivotHash": "0xc52258828e1f01d64dc6e2455cb51baae4c77a91fed1b27e08760f01badc3e3e" }, "Discovery": { "DiscoveryVersion": "V5" diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs index d3b619a846b..f7fc6028159 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Linq; using Nethermind.Core; namespace Nethermind.Serialization.Rlp; @@ -41,11 +40,44 @@ public int GetBodyLength(BlockBody b) b.Withdrawals is not null ? GetWithdrawalsLength(b.Withdrawals) : null ); - private int GetTxLength(Transaction[] transactions) => transactions.Sum(t => _txDecoder.GetLength(t, RlpBehaviors.None)); + private int GetTxLength(Transaction[] transactions) + { + if (transactions.Length == 0) return 0; + + int sum = 0; + foreach (Transaction tx in transactions) + { + sum += _txDecoder.GetLength(tx, RlpBehaviors.None); + } + + return sum; + } + + private int GetUnclesLength(BlockHeader[] headers) + { + if (headers.Length == 0) return 0; + + int sum = 0; + foreach (BlockHeader header in headers) + { + sum += _headerDecoder.GetLength(header, RlpBehaviors.None); + } - private int GetUnclesLength(BlockHeader[] headers) => headers.Sum(t => _headerDecoder.GetLength(t, RlpBehaviors.None)); + return sum; + } + + private int GetWithdrawalsLength(Withdrawal[] withdrawals) + { + if (withdrawals.Length == 0) return 0; - private int GetWithdrawalsLength(Withdrawal[] withdrawals) => withdrawals.Sum(t => _withdrawalDecoderDecoder.GetLength(t, RlpBehaviors.None)); + int sum = 0; + foreach (Withdrawal withdrawal in withdrawals) + { + sum += _withdrawalDecoderDecoder.GetLength(withdrawal, RlpBehaviors.None); + } + + return sum; + } public BlockBody? Decode(ref Rlp.ValueDecoderContext ctx, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs index 47cd8b2a634..e61b35690cc 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Linq; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Int256; @@ -151,7 +150,7 @@ public void Encode(RlpStream stream, AccessList? item, RlpBehaviors rlpBehaviors // Index2 // ... // IndexN - AccessItemLengths lengths = new(storageKeys.Count()); + AccessItemLengths lengths = new(storageKeys.Count); stream.StartSequence(lengths.ContentLength); { stream.Encode(address); @@ -199,9 +198,15 @@ public AccessItemLengths(int indexesCount) private static int GetContentLength(AccessList accessList) { - return accessList - .Select(static entry => new AccessItemLengths(entry.StorageKeys.Count())) - .Sum(static lengths => lengths.SequenceLength); + int sum = 0; + foreach ((Address Address, AccessList.StorageKeysEnumerable StorageKeys) entry in accessList) + { + int indexesContentLength = entry.StorageKeys.Count * Rlp.LengthOfKeccakRlp; + int contentLength = Rlp.LengthOfSequence(indexesContentLength) + Rlp.LengthOfAddressRlp; + sum += Rlp.LengthOfSequence(contentLength); + } + + return sum; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs index fef56b8bce7..160a8ba2011 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs @@ -313,10 +313,6 @@ void SetBlobScheduleParameters() { releaseSpec.TargetBlobCount = blobSchedule.Target; releaseSpec.MaxBlobCount = blobSchedule.Max; - if (blobSchedule.MaxBlobsPerTx is not null) - { - releaseSpec.MaxBlobsPerTx = blobSchedule.MaxBlobsPerTx.Value; - } releaseSpec.BlobBaseFeeUpdateFraction = blobSchedule.BaseFeeUpdateFraction; } else if (releaseSpec.Eip4844TransitionTimestamp <= releaseStartTimestamp) diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/BlobScheduleSettings.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/BlobScheduleSettings.cs index 248b4399127..37bd350ca76 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/BlobScheduleSettings.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/BlobScheduleSettings.cs @@ -13,8 +13,6 @@ public record class BlobScheduleSettings : IComparable public ulong Max { get; set; } - public ulong? MaxBlobsPerTx { get; set; } - public ulong BaseFeeUpdateFraction { get; set; } public int CompareTo(BlobScheduleSettings? other) => other is null ? 1 : Timestamp.CompareTo(other.Timestamp); diff --git a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs index a50958a7d35..86e628738ab 100644 --- a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs @@ -106,9 +106,7 @@ public bool IsEip1559Enabled public ulong TargetBlobCount { get; set; } public ulong MaxBlobCount { get; set; } - - private ulong? _maxBlobsPerTx; - public ulong MaxBlobsPerTx { get => _maxBlobsPerTx ?? MaxBlobCount; set => _maxBlobsPerTx = value; } + public ulong MaxBlobsPerTx => IsEip7594Enabled ? Math.Min(Eip7594Constants.MaxBlobsPerTx, MaxBlobCount) : MaxBlobCount; public UInt256 BlobBaseFeeUpdateFraction { get; set; } diff --git a/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs b/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs index 8f533ff05e9..09703b8b6e7 100644 --- a/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/TestSpecProvider.cs @@ -31,8 +31,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public IReleaseSpec GenesisSpec { get; set; } - IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => SpecToReturn; - + IReleaseSpec ISpecProvider.GetSpecInternal(ForkActivation forkActivation) => forkActivation.BlockNumber == 0 || forkActivation.BlockNumber < ForkOnBlockNumber ? GenesisSpec : SpecToReturn; public IReleaseSpec SpecToReturn { get; set; } public long? DaoBlockNumber { get; set; } @@ -46,6 +45,8 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public ForkActivation[] TransitionActivations { get; set; } = new ForkActivation[] { (ForkActivation)0 }; public bool AllowTestChainOverride { get; set; } = true; + public long? ForkOnBlockNumber { get; set; } + private TestSpecProvider() { } public static readonly TestSpecProvider Instance = new(); diff --git a/src/Nethermind/Nethermind.State.Test/StateProviderTests.cs b/src/Nethermind/Nethermind.State.Test/StateProviderTests.cs index ecb8b298176..89f27f46714 100644 --- a/src/Nethermind/Nethermind.State.Test/StateProviderTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateProviderTests.cs @@ -63,32 +63,6 @@ public void Eip_158_touch_zero_value_system_account_is_not_deleted() ((WorldState)provider).GetAccount(systemUser).Should().NotBeNull(); } - [Test] - public void Can_dump_state() - { - WorldStateManager worldStateManager = TestWorldStateFactory.CreateForTest(); - IVisitingWorldState provider = worldStateManager.GlobalWorldState; - provider.CreateAccount(TestItem.AddressA, 1.Ether()); - provider.Commit(MuirGlacier.Instance); - provider.CommitTree(0); - - string state = provider.DumpState(); - state.Should().NotBeEmpty(); - } - - [Test] - public void Can_accepts_visitors() - { - WorldStateManager worldStateManager = TestWorldStateFactory.CreateForTest(); - IVisitingWorldState provider = worldStateManager.GlobalWorldState; - provider.CreateAccount(TestItem.AddressA, 1.Ether()); - provider.Commit(MuirGlacier.Instance); - provider.CommitTree(0); - - TrieStatsCollector visitor = new(new MemDb(), LimboLogs.Instance); - provider.Accept(visitor, provider.StateRoot); - } - [Test] public void Empty_commit_restore() { diff --git a/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs b/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs index 5a857604362..8f021ad4654 100644 --- a/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs @@ -16,6 +16,7 @@ using Nethermind.Specs.Forks; using Nethermind.Evm.State; using Nethermind.State; +using Nethermind.Trie; using Nethermind.Trie.Pruning; using NSubstitute; using NUnit.Framework; @@ -362,5 +363,31 @@ public void IsInvalidContractSender_AccountHasDelegatedCodeBut3807IsNotEnabled_R Assert.That(result, Is.False); } + + [Test] + public void Can_accepts_visitors() + { + WorldStateManager worldStateManager = TestWorldStateFactory.CreateForTest(); + IWorldState provider = worldStateManager.GlobalWorldState; + provider.CreateAccount(TestItem.AddressA, 1.Ether()); + provider.Commit(MuirGlacier.Instance); + provider.CommitTree(0); + + TrieStatsCollector visitor = new(new MemDb(), LimboLogs.Instance); + worldStateManager.GlobalStateReader.RunTreeVisitor(visitor, provider.StateRoot); + } + + [Test] + public void Can_dump_state() + { + WorldStateManager worldStateManager = TestWorldStateFactory.CreateForTest(); + IWorldState provider = worldStateManager.GlobalWorldState; + provider.CreateAccount(TestItem.AddressA, 1.Ether()); + provider.Commit(MuirGlacier.Instance); + provider.CommitTree(0); + + string state = worldStateManager.GlobalStateReader.DumpState(provider.StateRoot); + state.Should().NotBeEmpty(); + } } } diff --git a/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs b/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs index 541abe7374a..764d146d52f 100644 --- a/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs +++ b/src/Nethermind/Nethermind.State.Test/WorldStateManagerTests.cs @@ -25,7 +25,7 @@ public class WorldStateManagerTests [Test] public void ShouldProxyGlobalWorldState() { - IVisitingWorldState worldState = Substitute.For(); + IWorldState worldState = Substitute.For(); IPruningTrieStore trieStore = Substitute.For(); IDbProvider dbProvider = TestMemDbProvider.Init(); WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); @@ -36,7 +36,7 @@ public void ShouldProxyGlobalWorldState() [Test] public void ShouldProxyReorgBoundaryEvent() { - IVisitingWorldState worldState = Substitute.For(); + IWorldState worldState = Substitute.For(); IPruningTrieStore trieStore = Substitute.For(); IDbProvider dbProvider = TestMemDbProvider.Init(); WorldStateManager worldStateManager = new WorldStateManager(worldState, trieStore, dbProvider, LimboLogs.Instance); @@ -52,7 +52,7 @@ public void ShouldProxyReorgBoundaryEvent() [TestCase(INodeStorage.KeyScheme.HalfPath, false)] public void ShouldNotSupportHashLookupOnHalfpath(INodeStorage.KeyScheme keyScheme, bool hashSupported) { - IVisitingWorldState worldState = Substitute.For(); + IWorldState worldState = Substitute.For(); IPruningTrieStore trieStore = Substitute.For(); IReadOnlyTrieStore readOnlyTrieStore = Substitute.For(); trieStore.AsReadOnly().Returns(readOnlyTrieStore); diff --git a/src/Nethermind/Nethermind.State/IVisitingWorldState.cs b/src/Nethermind/Nethermind.State/IVisitingWorldState.cs deleted file mode 100644 index 9c910919111..00000000000 --- a/src/Nethermind/Nethermind.State/IVisitingWorldState.cs +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Crypto; -using Nethermind.Evm.State; -using Nethermind.Trie; - -namespace Nethermind.State; - -public interface IVisitingWorldState : IWorldState -{ - /// - /// Runs a visitor over trie. - /// - /// Visitor to run. - /// Root to run on. - /// Options to run visitor. - void Accept(ITreeVisitor visitor, Hash256 stateRoot, VisitingOptions? visitingOptions = null) - where TCtx : struct, INodeContext; -} - -public static class VisitingWorldStateExtensions -{ - public static string DumpState(this IVisitingWorldState stateProvider) - { - TreeDumper dumper = new(); - stateProvider.Accept(dumper, stateProvider.StateRoot); - return dumper.ToString(); - } -} diff --git a/src/Nethermind/Nethermind.State/IWorldStateManager.cs b/src/Nethermind/Nethermind.State/IWorldStateManager.cs index 6f509a8d091..bcfe10baa99 100644 --- a/src/Nethermind/Nethermind.State/IWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/IWorldStateManager.cs @@ -13,7 +13,7 @@ namespace Nethermind.State; public interface IWorldStateManager { - IVisitingWorldState GlobalWorldState { get; } + IWorldState GlobalWorldState { get; } IStateReader GlobalStateReader { get; } ISnapServer? SnapServer { get; } IReadOnlyKeyValueStore? HashServer { get; } @@ -22,14 +22,14 @@ public interface IWorldStateManager /// Used by read only tasks that need to execute blocks. /// /// - IVisitingWorldState CreateResettableWorldState(); + IWorldState CreateResettableWorldState(); /// /// Create a read only world state to warm up another world state /// /// Specify a world state to warm up by the returned world state. /// - IVisitingWorldState CreateWorldStateForWarmingUp(IWorldState forWarmup); + IWorldState CreateWorldStateForWarmingUp(IWorldState forWarmup); event EventHandler? ReorgBoundaryReached; @@ -55,6 +55,6 @@ public interface IWorldStateManager public interface IOverridableWorldScope { IDisposable BeginScope(BlockHeader? header); - IVisitingWorldState WorldState { get; } + IWorldState WorldState { get; } IStateReader GlobalStateReader { get; } } diff --git a/src/Nethermind/Nethermind.State/OverridableEnv/IOverridableEnv.cs b/src/Nethermind/Nethermind.State/OverridableEnv/IOverridableEnv.cs index 7b000ce479a..34f5aa1ac38 100644 --- a/src/Nethermind/Nethermind.State/OverridableEnv/IOverridableEnv.cs +++ b/src/Nethermind/Nethermind.State/OverridableEnv/IOverridableEnv.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using Autofac.Core; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; @@ -32,6 +31,6 @@ public interface IOverridableEnv : IModule /// public interface IOverridableEnv { - Scope BuildAndOverride(BlockHeader header); + Scope BuildAndOverride(BlockHeader? header); Scope BuildAndOverride(BlockHeader header, Dictionary? stateOverride); } diff --git a/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs b/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs index 8b79190f841..bf1ee0b9ced 100644 --- a/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs +++ b/src/Nethermind/Nethermind.State/OverridableEnv/OverridableEnvFactory.cs @@ -66,7 +66,7 @@ private void Reset() protected override void Load(ContainerBuilder builder) => builder - .AddScoped(overridableScope.WorldState).AddScoped(overridableScope.WorldState) + .AddScoped(overridableScope.WorldState) .AddScoped(overridableScope.GlobalStateReader) .AddScoped(this) .AddScoped(codeInfoRepository) diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index 1af2a85dc23..cd3a1e603dc 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -24,7 +24,7 @@ public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore t WorldState = new WorldState(overlayTrieStore, readOnlyDbProvider.CodeDb, logManager, null, true); } - public IVisitingWorldState WorldState { get; } + public IWorldState WorldState { get; } public IDisposable BeginScope(BlockHeader? header) { WorldState.SetBaseBlock(header); diff --git a/src/Nethermind/Nethermind.State/StateReaderExtensions.cs b/src/Nethermind/Nethermind.State/StateReaderExtensions.cs index 6c89c26ddb9..933ec39162b 100644 --- a/src/Nethermind/Nethermind.State/StateReaderExtensions.cs +++ b/src/Nethermind/Nethermind.State/StateReaderExtensions.cs @@ -54,5 +54,12 @@ public static TrieStats CollectStats(this IStateReader stateProvider, Hash256 ro }); return collector.Stats; } + + public static string DumpState(this IStateReader stateReader, Hash256 root) + { + TreeDumper dumper = new(); + stateReader.RunTreeVisitor(dumper, root); + return dumper.ToString(); + } } } diff --git a/src/Nethermind/Nethermind.State/WorldState.cs b/src/Nethermind/Nethermind.State/WorldState.cs index 5e1c6b92f53..2b6f293cf2f 100644 --- a/src/Nethermind/Nethermind.State/WorldState.cs +++ b/src/Nethermind/Nethermind.State/WorldState.cs @@ -25,7 +25,7 @@ namespace Nethermind.State { - public class WorldState : IVisitingWorldState, IPreBlockCaches + public class WorldState : IWorldState, IPreBlockCaches { internal readonly StateProvider _stateProvider; internal readonly PersistentStorageProvider _persistentStorageProvider; diff --git a/src/Nethermind/Nethermind.State/WorldStateManager.cs b/src/Nethermind/Nethermind.State/WorldStateManager.cs index c44dd1ee798..e71c7585e98 100644 --- a/src/Nethermind/Nethermind.State/WorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/WorldStateManager.cs @@ -16,7 +16,7 @@ namespace Nethermind.State; public class WorldStateManager : IWorldStateManager { - private readonly IVisitingWorldState _worldState; + private readonly IWorldState _worldState; private readonly IPruningTrieStore _trieStore; private readonly IReadOnlyTrieStore _readOnlyTrieStore; private readonly ILogManager _logManager; @@ -26,7 +26,7 @@ public class WorldStateManager : IWorldStateManager private readonly ILastNStateRootTracker _lastNStateRootTracker; public WorldStateManager( - IVisitingWorldState worldState, + IWorldState worldState, IPruningTrieStore trieStore, IDbProvider dbProvider, ILogManager logManager, @@ -46,7 +46,7 @@ public WorldStateManager( _lastNStateRootTracker = lastNStateRootTracker; } - public IVisitingWorldState GlobalWorldState => _worldState; + public IWorldState GlobalWorldState => _worldState; public IReadOnlyKeyValueStore? HashServer => _trieStore.Scheme != INodeStorage.KeyScheme.Hash ? null : _trieStore.TrieNodeRlpStore; @@ -68,7 +68,7 @@ public void InitializeNetwork(IPathRecovery pathRecovery) public ISnapServer? SnapServer => _trieStore.Scheme == INodeStorage.KeyScheme.Hash ? null : new SnapServer.SnapServer(_readOnlyTrieStore, _readaOnlyCodeCb, GlobalStateReader, _logManager, _lastNStateRootTracker); - public IVisitingWorldState CreateResettableWorldState() + public IWorldState CreateResettableWorldState() { return new WorldState( _readOnlyTrieStore, @@ -76,7 +76,7 @@ public IVisitingWorldState CreateResettableWorldState() _logManager); } - public IVisitingWorldState CreateWorldStateForWarmingUp(IWorldState forWarmup) + public IWorldState CreateWorldStateForWarmingUp(IWorldState forWarmup) { PreBlockCaches? preBlockCaches = (forWarmup as IPreBlockCaches)?.Caches; return preBlockCaches is not null diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs index eabe15cffc8..03102bb2bc4 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs @@ -39,6 +39,7 @@ using Autofac.Features.AttributeFilters; using Humanizer; using Nethermind.Config; +using Nethermind.Consensus.Processing; using Nethermind.Core.Events; using Nethermind.Core.Test; using Nethermind.Core.Test.Modules; @@ -208,6 +209,32 @@ public async Task Catch_exception_from_forwardHeaderProvider() await act.Should().NotThrowAsync(); } + [Test] + public async Task Skit_spawning_request_when_block_processing_queue_is_high() + { + IForwardHeaderProvider mockForwardHeaderProvider = Substitute.For(); + IBlockProcessingQueue blockProcessingQueue = Substitute.For(); + blockProcessingQueue.Count.Returns(10000); + + await using IContainer node = CreateNode(configProvider: new ConfigProvider(new SyncConfig() + { + FastSync = true + }), + configurer: (builder) => builder + .AddSingleton(mockForwardHeaderProvider) + .AddSingleton(blockProcessingQueue)); + + Context ctx = node.Resolve(); + var request = await ctx.FastSyncFeedComponent.BlockDownloader.PrepareRequest( + DownloaderOptions.Insert, + 0, + CancellationToken.None); + + request.Should().BeNull(); + await mockForwardHeaderProvider.DidNotReceive() + .GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any()); + } + [Test] public async Task Ancestor_lookup_simple() { @@ -492,7 +519,7 @@ public async Task Prune_download_requests_map() await using IContainer node = CreateNode(builder => builder .AddDecorator((_, syncConfig) => { - syncConfig.MaxTxInForwardSyncBuffer = 3200; + syncConfig.ForwardSyncDownloadBufferMemoryBudget = 3200000; return syncConfig; }) .AddSingleton(Always.Invalid)); diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs index 36ce050588e..2050a8d7a52 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs @@ -9,6 +9,7 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; +using Nethermind.Consensus.Processing; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Collections; @@ -47,10 +48,12 @@ public class BlockDownloader : IForwardSyncController private readonly IFullStateFinder _fullStateFinder; private readonly IForwardHeaderProvider _forwardHeaderProvider; private readonly ISyncPeerPool _syncPeerPool; + private readonly IBlockProcessingQueue _processingQueue; private readonly ILogger _logger; // Estimated maximum tx in buffer used to estimate memory limit. Each tx is on average about 1KB. private readonly int _maxTxInBuffer; + private readonly int _maxTxInInProcessingQueue; private const int MinEstimateTxPerBlock = 10; // Header lookup need to be limited, because `IForwardHeaderProvider.GetBlockHeaders` can be slow. @@ -72,31 +75,35 @@ public class BlockDownloader : IForwardSyncController private SemaphoreSlim _requestLock = new(1); public BlockDownloader( - IBlockTree? blockTree, - IBlockValidator? blockValidator, - ISyncReport? syncReport, - IReceiptStorage? receiptStorage, - ISpecProvider? specProvider, + IBlockTree blockTree, + IBlockValidator blockValidator, + ISyncReport syncReport, + IReceiptStorage receiptStorage, + ISpecProvider specProvider, IBetterPeerStrategy betterPeerStrategy, IFullStateFinder fullStateFinder, IForwardHeaderProvider forwardHeaderProvider, ISyncPeerPool syncPeerPool, + IReceiptsRecovery receiptsRecovery, + IBlockProcessingQueue processingQueue, ISyncConfig syncConfig, - ILogManager? logManager) + ILogManager logManager) { - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _blockValidator = blockValidator ?? throw new ArgumentNullException(nameof(blockValidator)); - _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); - _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _betterPeerStrategy = betterPeerStrategy ?? throw new ArgumentNullException(nameof(betterPeerStrategy)); - _fullStateFinder = fullStateFinder ?? throw new ArgumentNullException(nameof(fullStateFinder)); + _blockTree = blockTree; + _blockValidator = blockValidator; + _syncReport = syncReport; + _receiptStorage = receiptStorage; + _specProvider = specProvider; + _betterPeerStrategy = betterPeerStrategy; + _fullStateFinder = fullStateFinder; _forwardHeaderProvider = forwardHeaderProvider; _syncPeerPool = syncPeerPool; - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _maxTxInBuffer = syncConfig.MaxTxInForwardSyncBuffer; - - _receiptsRecovery = new ReceiptsRecovery(new EthereumEcdsa(_specProvider.ChainId), _specProvider); + _logger = logManager.GetClassLogger(); + // Assume that each tx cost about 1kb. + _maxTxInBuffer = (int)(syncConfig.ForwardSyncDownloadBufferMemoryBudget / 1000); + _maxTxInInProcessingQueue = (int)(syncConfig.ForwardSyncBlockProcessingQueueMemoryBudget / 1000); + _receiptsRecovery = receiptsRecovery; + _processingQueue = processingQueue; _blockTree.NewHeadBlock += BlockTreeOnNewHeadBlock; } @@ -145,6 +152,12 @@ private void BlockTreeOnNewHeadBlock(object? sender, BlockEventArgs e) while (true) { + if (_processingQueue.Count > _maxTxInInProcessingQueue / _estimateTxPerBlock) + { + if (_logger.IsTrace) _logger.Trace("Processing queue full"); + return null; + } + using IOwnedReadOnlyList? headers = await _forwardHeaderProvider.GetBlockHeaders(fastSyncLag, HeaderLookupSize + 1, cancellation); if (cancellation.IsCancellationRequested) return null; // check before every heavy operation if (headers is null || headers.Count <= 1) return null; diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index 89639eaac2c..be22cc01daa 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -636,6 +636,21 @@ static SpanSource ThrowNotSupported(TrieNode node) } private void ConnectNodes(TrieNode? node, in TraverseContext traverseContext) + { + // Fast tail-calls into generic + if (_logger.IsTrace) + { + ConnectNodes(node, in traverseContext); + } + else + { + // branch eliminates _loggerTrace statements + ConnectNodes(node, in traverseContext); + } + } + + private void ConnectNodes(TrieNode? node, in TraverseContext traverseContext) + where IsTrace : IFlag { TreePath path = traverseContext.UpdatePathTreePath; bool isRoot = IsNodeStackEmpty(); @@ -648,50 +663,36 @@ private void ConnectNodes(TrieNode? node, in TraverseContext traverseContext) path.TruncateMut(parentOnStack.PathLength); isRoot = IsNodeStackEmpty(); - - if (node.IsLeaf) - { - ThrowTrieExceptionLeftCannotBeParent(node, nextNode); - } - - if (node.IsBranch) + // Use NodeType once to reduce virtual calls + // and switch statement to not add additional long lived local variable + switch (node.NodeType) { - if (!(nextNode is null && !node.IsValidWithOneNodeLess)) - { - if (node.IsSealed) + case NodeType.Branch: + if (!(nextNode is null && !node.IsValidWithOneNodeLess)) { - node = node.Clone(); - } + if (node.IsSealed) + { + node = node.Clone(); + } - node.SetChild(parentOnStack.PathIndex, nextNode); - nextNode = node; - } - else - { - if (node.Value!.Length != 0) - { - // this only happens when we have branches with values - // which is not possible in the Ethereum protocol where keys are of equal lengths - // (it is possible in the more general trie definition) - TrieNode leafFromBranch = TrieNodeFactory.CreateLeaf([], node.Value); - if (_logger.IsTrace) _logger.Trace($"Converting {node} into {leafFromBranch}"); - nextNode = leafFromBranch; + node.SetChild(parentOnStack.PathIndex, nextNode); + nextNode = node; } else { /* all the cases below are when we have a branch that becomes something else - as a result of deleting one of the last two children */ + as a result of deleting one of the last two children */ /* case 1) - extension from branch - this is particularly interesting - we create an extension from - the implicit path in the branch children positions (marked as P) - P B B B B B B B B B B B B B B B - B X - - - - - - - - - - - - - - - case 2) - extended extension - B B B B B B B B B B B B B B B B - E X - - - - - - - - - - - - - - - case 3) - extended leaf - B B B B B B B B B B B B B B B B - L X - - - - - - - - - - - - - - */ + this is particularly interesting - we create an extension from + the implicit path in the branch children positions (marked as P) + P B B B B B B B B B B B B B B B + B X - - - - - - - - - - - - - - + case 2) - extended extension + B B B B B B B B B B B B B B B B + E X - - - - - - - - - - - - - - + case 3) - extended leaf + B B B B B B B B B B B B B B B B + L X - - - - - - - - - - - - - - */ int childNodeIndex = 0; for (int i = 0; i < 16; i++) @@ -708,157 +709,152 @@ L X - - - - - - - - - - - - - - */ if (childNode is null) { /* potential corrupted trie data state when we find a branch that has only one child */ - ThrowTrieExceptionCorruption(); + goto Corruption; } ResolveNode(childNode, in traverseContext, in path); path.TruncateOne(); - if (childNode.IsBranch) + NodeType childType = childNode.NodeType; + if (childType == NodeType.Branch) { - TrieNode extensionFromBranch = - TrieNodeFactory.CreateExtension(_singleByteKeys[childNodeIndex], childNode); - if (_logger.IsTrace) - _logger.Trace( - $"Extending child {childNodeIndex} {childNode} of {node} into {extensionFromBranch}"); + TrieNode extensionFromBranch = TrieNodeFactory.CreateExtension(_singleByteKeys[childNodeIndex], childNode); + if (IsTrace.IsActive) _logger.Trace($"Extending child {childNodeIndex} {childNode} of {node} into {extensionFromBranch}"); nextNode = extensionFromBranch; } - else if (childNode.IsExtension) + else if (childType == NodeType.Extension || childType == NodeType.Leaf) { - /* to test this case we need something like this initially */ - /* R - B B B B B B B B B B B B B B B B - E L - - - - - - - - - - - - - - - E - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - L L - - - - - - - - - - - - - - */ - - /* then we delete the leaf (marked as X) */ - /* R - B B B B B B B B B B B B B B B B - E X - - - - - - - - - - - - - - - E - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - L L - - - - - - - - - - - - - - */ - - /* and we end up with an extended extension (marked with +) - replacing what was previously a top-level branch */ - /* R - + - + - + - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - L L - - - - - - - - - - - - - - */ - byte[] newKey = Bytes.Concat((byte)childNodeIndex, childNode.Key); + TrieNode extendedNode = childNode.CloneWithChangedKey(newKey); - TrieNode extendedExtension = childNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) - _logger.Trace( - $"Extending child {childNodeIndex} {childNode} of {node} into {extendedExtension}"); - nextNode = extendedExtension; - } - else if (childNode.IsLeaf) - { - byte[] newKey = Bytes.Concat((byte)childNodeIndex, childNode.Key); - - TrieNode extendedLeaf = childNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) + if (IsTrace.IsActive) { - _logger.Trace($"Extending branch child {childNodeIndex} {childNode} into {extendedLeaf}"); - _logger.Trace($"Decrementing ref on a leaf extended up to eat a branch {childNode}"); - if (node.IsSealed) + if (childNode.IsExtension) + { + /* to test this case we need something like this initially */ + /* R + B B B B B B B B B B B B B B B B + E L - - - - - - - - - - - - - - + E - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + L L - - - - - - - - - - - - - - */ + + /* then we delete the leaf (marked as X) */ + /* R + B B B B B B B B B B B B B B B B + E X - - - - - - - - - - - - - - + E - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + L L - - - - - - - - - - - - - - */ + + /* and we end up with an extended extension (marked with +) + replacing what was previously a top-level branch */ + /* R + + + + + + - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + L L - - - - - - - - - - - - - - */ + + _logger.Trace($"Extending child {childNodeIndex} {childNode} of {node} into {extendedNode}"); + } + else if (childNode.IsLeaf) { - _logger.Trace($"Decrementing ref on a branch replaced by a leaf {node}"); + _logger.Trace($"Extending branch child {childNodeIndex} {childNode} into {extendedNode}"); + _logger.Trace($"Decrementing ref on a leaf extended up to eat a branch {childNode}"); + if (node.IsSealed) + { + _logger.Trace($"Decrementing ref on a branch replaced by a leaf {node}"); + } } } - - nextNode = extendedLeaf; + nextNode = extendedNode; } else { - ThrowInvalidNodeType(childNode); + node = childNode; + goto InvalidNodeType; } } - } - } - else if (node.IsExtension) - { - if (nextNode is null) - { - ThrowInvalidNullNode(node); - } - - if (nextNode.IsLeaf) - { - byte[] newKey = Bytes.Concat(node.Key, nextNode.Key); - TrieNode extendedLeaf = nextNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) - _logger.Trace($"Combining {node} and {nextNode} into {extendedLeaf}"); + break; + case NodeType.Extension: + if (nextNode is null) + { + goto NullNode; + } - nextNode = extendedLeaf; - } - else if (nextNode.IsExtension) - { - /* to test this case we need something like this initially */ - /* R - E - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - E L - - - - - - - - - - - - - - - E - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - L L - - - - - - - - - - - - - - */ - - /* then we delete the leaf (marked as X) */ - /* R - B B B B B B B B B B B B B B B B - E X - - - - - - - - - - - - - - - E - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - L L - - - - - - - - - - - - - - */ - - /* and we end up with an extended extension replacing what was previously a top-level branch*/ - /* R - E - E - E - - - - - - - - - - - - - - - - B B B B B B B B B B B B B B B B - L L - - - - - - - - - - - - - - */ - - byte[] newKey = Bytes.Concat(node.Key, nextNode.Key); - TrieNode extendedExtension = nextNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) - _logger.Trace($"Combining {node} and {nextNode} into {extendedExtension}"); - - nextNode = extendedExtension; - } - else if (nextNode.IsBranch) - { - if (node.IsSealed) + NodeType nextType = nextNode.NodeType; + if (nextType == NodeType.Branch) { - node = node.Clone(); + if (node.IsSealed) + { + node = node.Clone(); + } + + if (IsTrace.IsActive) _logger.Trace($"Connecting {node} with {nextNode}"); + node.SetChild(0, nextNode); + nextNode = node; } + else if (nextType == NodeType.Extension || nextType == NodeType.Leaf) + { + /* to test the Extension case we need something like this initially */ + /* R + E - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + E L - - - - - - - - - - - - - - + E - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + L L - - - - - - - - - - - - - - */ - if (_logger.IsTrace) _logger.Trace($"Connecting {node} with {nextNode}"); - node.SetChild(0, nextNode); - nextNode = node; - } - else - { - ThrowInvalidNodeType(nextNode); - } - } - else - { - ThrowInvalidNodeType(node); + /* then we delete the leaf (marked as X) */ + /* R + B B B B B B B B B B B B B B B B + E X - - - - - - - - - - - - - - + E - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + L L - - - - - - - - - - - - - - */ + + /* and we end up with an extended extension replacing what was previously a top-level branch*/ + /* R + E + E + E - - - - - - - - - - - - - - - + B B B B B B B B B B B B B B B B + L L - - - - - - - - - - - - - - */ + + byte[] newKey = Bytes.Concat(node.Key, nextNode.Key); + TrieNode extendedNode = nextNode.CloneWithChangedKey(newKey); + if (IsTrace.IsActive) _logger.Trace($"Combining {node} and {nextNode} into {extendedNode}"); + nextNode = extendedNode; + } + else + { + node = nextNode; + goto InvalidNodeType; + } + break; + case NodeType.Leaf: + goto LeafCannotBeParent; + default: + goto InvalidNodeType; } } RootRef = nextNode; + return; + + Corruption: + ThrowTrieExceptionCorruption(); + InvalidNodeType: + ThrowInvalidNodeType(node); + NullNode: + ThrowInvalidNullNode(node); + LeafCannotBeParent: + ThrowTrieExceptionLeafCannotBeParent(node, nextNode); [DoesNotReturn, StackTraceHidden] - static void ThrowTrieExceptionLeftCannotBeParent(TrieNode node, TrieNode nextNode) + static void ThrowTrieExceptionLeafCannotBeParent(TrieNode node, TrieNode nextNode) => throw new TrieException($"{nameof(NodeType.Leaf)} {node} cannot be a parent of {nextNode}"); [DoesNotReturn, StackTraceHidden] diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.Blobs.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.Blobs.cs index e5e7b0481c3..9c92e315abd 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.Blobs.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.Blobs.cs @@ -1020,59 +1020,55 @@ private Transaction CreateBlobTx(PrivateKey sender, UInt256 nonce = default, int .SignedAndResolved(_ethereumEcdsa, sender).TestObject; } - [TestCaseSource(nameof(EvictionAccordingToLimitsTestCaseSource))] - public async Task should_evict_txs_with_too_many_blobs_after_fork(BlobScheduleSettings initial, BlobScheduleSettings updated, int[] blobTxBlobCounts) + [Test] + public async Task should_evict_txs_with_too_many_blobs_after_fork() { - ChainSpecBasedSpecProvider provider = new(new ChainSpec + const int regularMaxBlobCount = 9; + + TestSpecProvider provider = new(new ReleaseSpec + { + IsEip4844Enabled = true, + MaxBlobCount = regularMaxBlobCount, + }) { - Parameters = new ChainParameters + SpecToReturn = new ReleaseSpec { - Eip4844TransitionTimestamp = 0, - BlobSchedule = { - initial with { Timestamp = _blockTree.Head.Timestamp }, - updated with { Timestamp = _blockTree.Head.Timestamp + 1 }, - }, + IsEip4844Enabled = true, + IsEip7594Enabled = true, + MaxBlobCount = regularMaxBlobCount, }, - EngineChainSpecParametersProvider = Substitute.For() - }); + ForkOnBlockNumber = _blockTree.Head.Number + 1, + }; Block head = _blockTree.Head; _blockTree.FindBestSuggestedHeader().Returns(head.Header); - TxPoolConfig txPoolConfig = new() { BlobsSupport = BlobsSupportMode.InMemory, Size = 10 }; - _txPool = CreatePool(txPoolConfig, provider); + _txPool = CreatePool(specProvider: provider); EnsureSenderBalance(TestItem.AddressA, UInt256.MaxValue); - UInt256 nonce = 0; - - foreach (var blobCount in blobTxBlobCounts) - { - _txPool.SubmitTx(CreateBlobTx(TestItem.PrivateKeyA, nonce++, blobCount), TxHandlingOptions.None); - } - - Assert.That(_txPool.GetPendingBlobTransactionsCount(), Is.EqualTo(blobTxBlobCounts.Length)); + _txPool.SubmitTx(CreateBlobTx(TestItem.PrivateKeyA, 0, regularMaxBlobCount), TxHandlingOptions.None); + Assert.That(_txPool.GetPendingBlobTransactionsCount(), Is.EqualTo(1)); await AddBlock(); - return _txPool.GetPendingBlobTransactionsCount(); + Assert.That(_txPool.GetPendingBlobTransactionsCount(), Is.Zero); } - public static IEnumerable EvictionAccordingToLimitsTestCaseSource + [Test] + public void max_blobs_per_tx_should_not_exceed_max_blobs_per_block() { - get + const ulong regularMaxBlobCount = Eip7594Constants.MaxBlobsPerTx - 1; + + TestSpecProvider provider = new(new ReleaseSpec { - static TestCaseData MakeTestCase(string testName, BlobScheduleSettings initial, BlobScheduleSettings updated, int[] blobTxBlobCounts, int finalTxCount) - => new(initial, updated, blobTxBlobCounts) { TestName = $"EvictionAccordingToBlobLimits: {testName}", ExpectedResult = finalTxCount }; - - yield return MakeTestCase("Evicts when per block limit is set", - new BlobScheduleSettings { Max = 6 }, new BlobScheduleSettings { Max = 5 }, [6], 0); - yield return MakeTestCase("Evicts when per tx limit only is set", - new BlobScheduleSettings { Max = 6 }, new BlobScheduleSettings { Max = 6, MaxBlobsPerTx = 3 }, [6], 0); - yield return MakeTestCase("Evicts when per tx limit only is changed", - new BlobScheduleSettings { Max = 6, MaxBlobsPerTx = 3 }, new BlobScheduleSettings { Max = 6, MaxBlobsPerTx = 2 }, [2, 3, 2], 1); - yield return MakeTestCase("Evicts next txs too", - new BlobScheduleSettings { Max = 6 }, new BlobScheduleSettings { Max = 6, MaxBlobsPerTx = 3 }, [6, 3, 3, 3], 0); - } + IsEip4844Enabled = true, + IsEip7594Enabled = true, + MaxBlobCount = regularMaxBlobCount, + }); + + ulong maxBlobsPerTx = provider.GetSpec(_blockTree.Head!.Header).MaxBlobsPerTx; + + Assert.That(maxBlobsPerTx, Is.EqualTo(regularMaxBlobCount)); } } } diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index 7987e6f5d23..279a6fdc54a 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -21,7 +21,6 @@ using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; -using Nethermind.Db; using Nethermind.Evm; using Nethermind.Int256; using Nethermind.Logging; @@ -30,7 +29,6 @@ using Nethermind.Specs.Test; using Nethermind.Evm.State; using Nethermind.State; -using Nethermind.Trie.Pruning; using Nethermind.TxPool.Filters; using NSubstitute; using NUnit.Framework; @@ -1837,13 +1835,14 @@ public void Delegated_account_can_only_have_one_tx_with_current_account_nonce(in } - private static object[] NonceAndRemovedCases = + private static readonly object[] NonceAndRemovedCases = { new object[]{ true, 1, AcceptTxResult.Accepted }, new object[]{ true, 0, AcceptTxResult.Accepted}, new object[]{ false, 0, AcceptTxResult.Accepted}, new object[]{ false, 1, AcceptTxResult.NotCurrentNonceForDelegation}, }; + [TestCaseSource(nameof(NonceAndRemovedCases))] public void Tx_with_conflicting_pending_delegation_is_rejected_then_is_accepted_after_delegation_removal(bool withRemoval, int secondNonce, AcceptTxResult expected) { diff --git a/tools/DocGen/JsonRpcGenerator.cs b/tools/DocGen/JsonRpcGenerator.cs index 00200b8c63f..2478d9e1d30 100644 --- a/tools/DocGen/JsonRpcGenerator.cs +++ b/tools/DocGen/JsonRpcGenerator.cs @@ -1,19 +1,26 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Reflection; using Nethermind.JsonRpc.Modules; using Nethermind.JsonRpc.Modules.Evm; using Nethermind.JsonRpc.Modules.Rpc; using Nethermind.JsonRpc.Modules.Subscribe; using Newtonsoft.Json; using Spectre.Console; +using System.Reflection; namespace Nethermind.DocGen; internal static class JsonRpcGenerator { - private const string _objectTypeName = "*object*"; + private static readonly string[] _assemblies = [ + "Nethermind.Consensus.Clique", + "Nethermind.Era1", + "Nethermind.Flashbots", + "Nethermind.HealthChecks", + "Nethermind.JsonRpc" + ]; + private const string _objectTypeName = "_object_"; internal static void Generate(string path) { @@ -26,8 +33,7 @@ internal static void Generate(string path) typeof(IRpcRpcModule).FullName, typeof(ISubscribeRpcModule).FullName }; - var types = new[] { "Nethermind.JsonRpc", "Nethermind.Consensus.Clique" } - .SelectMany(a => Assembly.Load(a).GetTypes()) + var types = _assemblies.SelectMany(a => Assembly.Load(a).GetTypes()) .Where(t => t.IsInterface && typeof(IRpcModule).IsAssignableFrom(t) && !excluded.Any(x => x is not null && (t.FullName?.Contains(x, StringComparison.Ordinal) ?? false))) .OrderBy(t => t.Name); @@ -42,16 +48,45 @@ internal static void Generate(string path) } } - var i = 0; + var methodMap = new Dictionary>(); foreach (var type in types) - WriteMarkdown(path, type, i++); + { + var attr = type.GetCustomAttribute(); + + if (attr is null) + { + AnsiConsole.MarkupLine($"[yellow]{type.Name} module type is missing[/]"); + continue; + } + + var ns = attr.ModuleType.ToLowerInvariant(); + var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); + + if (!methodMap.TryAdd(ns, methods)) + methodMap[ns] = methodMap[ns].Concat(methods); + } + + if (methodMap.TryGetValue("eth", out IEnumerable? ethMethods)) + { + // Inject the `subscribe` methods into `eth` + methodMap["eth"] = ethMethods! + .Concat(typeof(ISubscribeRpcModule).GetMethods(BindingFlags.Instance | BindingFlags.Public)); + } + + var i = 0; + + foreach (var (ns, methods) in methodMap) + { + methodMap[ns] = methods.OrderBy(m => m.Name); + + WriteMarkdown(path, ns, methodMap[ns], i++); + } } - private static void WriteMarkdown(string path, Type rpcType, int sidebarIndex) + private static void WriteMarkdown(string path, string ns, IEnumerable methods, int sidebarIndex) { - var rpcName = rpcType.Name[1..].Replace("RpcModule", null).ToLowerInvariant(); - var fileName = Path.Join(path, $"{rpcName}.md"); + var fileName = Path.Join(path, $"{ns}.md"); using var stream = File.Open(fileName, FileMode.Create); using var file = new StreamWriter(stream); @@ -59,8 +94,8 @@ private static void WriteMarkdown(string path, Type rpcType, int sidebarIndex) file.WriteLine($""" --- - title: {rpcName} namespace - sidebar_label: {rpcName} + title: {ns} namespace + sidebar_label: {ns} sidebar_position: {sidebarIndex} --- @@ -69,15 +104,6 @@ private static void WriteMarkdown(string path, Type rpcType, int sidebarIndex) """); - IEnumerable methods = rpcType - .GetMethods(BindingFlags.Instance | BindingFlags.Public); - - // Inject the `subscribe` methods into `eth` - if (rpcName.Equals("eth", StringComparison.Ordinal)) - methods = methods.Concat(typeof(ISubscribeRpcModule).GetMethods(BindingFlags.Instance | BindingFlags.Public)); - - methods = methods.OrderBy(m => m.Name); - foreach (var method in methods) { var attr = method.GetCustomAttribute(); @@ -271,7 +297,7 @@ private static void WriteFromFile(StreamWriter file, string fileName) } catch (Exception) { - Console.WriteLine($"Failed copying from {fileName}"); + AnsiConsole.WriteLine($"[red]Failed copying from[/] {fileName}"); } } @@ -283,28 +309,28 @@ private static string GetJsonTypeName(Type type) return GetJsonTypeName(underlyingType); if (type.IsEnum) - return "*integer*"; + return "_integer_"; if (TryGetEnumerableItemType(type, out var itemType, out var isDictionary)) return $"{(isDictionary ? "map" : "array")} of {GetJsonTypeName(itemType!)}"; return type.Name switch { - "Address" => "*string* (address)", + "Address" => "_string_ (address)", "BigInteger" or "Int32" or "Int64" or "Int64&" or "UInt64" - or "UInt256" => "*string* (hex integer)", - "BlockParameter" => "*string* (block number or hash or either of `earliest`, `finalized`, `latest`, `pending`, or `safe`)", + or "UInt256" => "_string_ (hex integer)", + "BlockParameter" => "_string_ (block number or hash or either of `earliest`, `finalized`, `latest`, `pending`, or `safe`)", "Bloom" or "Byte" - or "Byte[]" => "*string* (hex data)", - "Boolean" => "*boolean*", - "Hash256" => "*string* (hash)", - "String" => "*string*", - "TxType" => "*string* (transaction type)", + or "Byte[]" => "_string_ (hex data)", + "Boolean" => "_boolean_", + "Hash256" => "_string_ (hash)", + "String" => "_string_", + "TxType" => "_string_ (transaction type)", _ => _objectTypeName }; }