diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index 2ba6b3de1ca..734a61aa678 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -28,7 +28,6 @@ using NUnit.Framework; using System.Threading.Tasks; using Ethereum.Test.Base.T8NUtils; -using Microsoft.IdentityModel.Tokens; using Nethermind.Consensus.BeaconBlockRoot; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Withdrawals; @@ -41,7 +40,7 @@ public abstract class GeneralStateTestBase private static ILogger _logger = new(new ConsoleAsyncLogger(LogLevel.Info)); private static ILogManager _logManager = LimboLogs.Instance; private static readonly UInt256 _defaultBaseFeeForStateTest = 0xA; - private readonly TxValidator _txValidator = new(MainnetSpecProvider.Instance.ChainId); + private TxValidator? _txValidator; private readonly BeaconBlockRootHandler _beaconBlockRootHandler = new(); [SetUp] @@ -58,27 +57,43 @@ protected static void Setup(ILogManager logManager) _logger = _logManager.GetClassLogger(); } - protected EthereumTestResult RunTest(GeneralStateTest test) + protected EthereumTestResult RunTest(GeneralStateTest test, bool isGnosis = false) { - return RunTest(test, NullTxTracer.Instance); + return RunTest(test, NullTxTracer.Instance, isGnosis); } - protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) + protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer, bool isGnosis = false) { TestContext.Write($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}"); Assert.IsNull(test.LoadFailure, "test data loading failure"); + _txValidator = new TxValidator(test.StateChainId); + IDb stateDb = new MemDb(); IDb codeDb = new MemDb(); - - ISpecProvider specProvider = new CustomSpecProvider( - ((ForkActivation)0, Frontier.Instance), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier - ((ForkActivation)1, test.Fork)); + ISpecProvider specProvider; + if (isGnosis) + { + specProvider = new CustomSpecProvider( + ((ForkActivation)0, + GnosisSpecProvider.Instance + .GenesisSpec), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier + ((ForkActivation)1, test.Fork)); + } + else + { + specProvider = new CustomSpecProvider( + ((ForkActivation)0, + Frontier + .Instance), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier + ((ForkActivation)1, test.Fork)); + } if (specProvider.GenesisSpec != Frontier.Instance) { Assert.Fail("Expected genesis spec to be Frontier for blockchain tests"); } + IReleaseSpec? spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber); BlockHeader header = test.GetBlockHeader(); @@ -88,6 +103,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) { test.CurrentBaseFee = header.BaseFeePerGas = CalculateBaseFeePerGas(test, parentHeader); } + if (parentHeader != null) { header.ExcessBlobGas = BlobGasCalculator.CalculateExcessBlobGas(parentHeader, spec); @@ -152,11 +168,14 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) compositeBlockTracer.Add(storageTxTracer); if (test.IsTraceEnabled) { - GethLikeBlockFileTracer gethLikeBlockFileTracer = new(block, test.GethTraceOptions, new FileSystem()); + GethLikeBlockFileTracer gethLikeBlockFileTracer = + new(block, test.GethTraceOptions, new FileSystem()); compositeBlockTracer.Add(gethLikeBlockFileTracer); } + blockReceiptsTracer.SetOtherTracer(compositeBlockTracer); } + blockReceiptsTracer.StartNewBlockTrace(block); if (!test.IsStateTest && test.ParentBeaconBlockRoot != null) @@ -169,12 +188,14 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) foreach (var tx in test.Transactions) { - bool isValid = _txValidator.IsWellFormed(tx, spec, out string error) && IsValidBlock(block, specProvider); + bool isValid = _txValidator.IsWellFormed(tx, spec, out string error) && + IsValidBlock(block, specProvider); if (isValid) { blockReceiptsTracer.StartNewTxTrace(tx); TransactionResult transactionResult = transactionProcessor - .Execute(tx, new BlockExecutionContext(header), test.IsT8NTest ? blockReceiptsTracer : txTracer); + .Execute(tx, new BlockExecutionContext(header), + test.IsT8NTest ? blockReceiptsTracer : txTracer); blockReceiptsTracer.EndTxTrace(); if (!test.IsT8NTest) continue; @@ -189,16 +210,21 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) } else if (transactionResult.Error != null) { - transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex, GethErrorMappings.GetErrorMapping(transactionResult.Error, tx.SenderAddress.ToString(true), tx.Nonce, stateProvider.GetNonce(tx.SenderAddress)))); + transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex, + GethErrorMappings.GetErrorMapping(transactionResult.Error, tx.SenderAddress.ToString(true), + tx.Nonce, stateProvider.GetNonce(tx.SenderAddress)))); stateProvider.Reset(); } + txIndex++; } else if (error != null) { - transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex, GethErrorMappings.GetErrorMapping(error))); + transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex, + GethErrorMappings.GetErrorMapping(error))); } } + blockReceiptsTracer.EndBlockTrace(); stopwatch.Stop(); @@ -223,18 +249,21 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) if (test.IsT8NTest) { - testResult.T8NResult = T8NResult.ConstructT8NResult(stateProvider, block, test, storageTxTracer, blockReceiptsTracer, specProvider, header, transactionExecutionReport); + testResult.T8NResult = T8NResult.ConstructT8NResult(stateProvider, block, test, storageTxTracer, + blockReceiptsTracer, specProvider, header, transactionExecutionReport); } return testResult; } - private static IBlockhashProvider GetBlockHashProvider(GeneralStateTest test, BlockHeader header, BlockHeader? parent) + private static IBlockhashProvider GetBlockHashProvider(GeneralStateTest test, BlockHeader header, + BlockHeader? parent) { if (!test.IsT8NTest) { return new TestBlockhashProvider(); } + var t8NBlockHashProvider = new T8NBlockHashProvider(); if (header.Hash != null) t8NBlockHashProvider.Insert(header.Hash, header.Number); @@ -243,6 +272,7 @@ private static IBlockhashProvider GetBlockHashProvider(GeneralStateTest test, Bl { t8NBlockHashProvider.Insert(blockHash.Value, long.Parse(blockHash.Key)); } + return t8NBlockHashProvider; } @@ -252,7 +282,8 @@ private static UInt256 CalculateBaseFeePerGas(GeneralStateTest test, BlockHeader return test.IsT8NTest ? BaseFeeCalculator.Calculate(parentHeader, test.Fork) : _defaultBaseFeeForStateTest; } - private static void InitializeTestPreState(Dictionary pre, WorldState stateProvider, ISpecProvider specProvider) + private static void InitializeTestPreState(Dictionary pre, WorldState stateProvider, + ISpecProvider specProvider) { foreach (KeyValuePair accountState in pre) { @@ -285,15 +316,18 @@ private bool IsValidBlock(Block block, ISpecProvider specProvider) .TestObject; var difficultyCalculator = new EthashDifficultyCalculator(specProvider); - var sealer = new EthashSealValidator(_logManager, difficultyCalculator, new CryptoRandom(), new Ethash(_logManager), Timestamper.Default); + var sealer = new EthashSealValidator(_logManager, difficultyCalculator, new CryptoRandom(), + new Ethash(_logManager), Timestamper.Default); IHeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, _logManager); IUnclesValidator unclesValidator = new UnclesValidator(blockTree, headerValidator, _logManager); - IBlockValidator blockValidator = new BlockValidator(_txValidator, headerValidator, unclesValidator, specProvider, _logManager); + IBlockValidator blockValidator = new BlockValidator(_txValidator, headerValidator, unclesValidator, + specProvider, _logManager); return blockValidator.ValidateOrphanedBlock(block, out _); } - private static void CalculateReward(string? stateReward, bool isStateTest, Block block, WorldState stateProvider, IReleaseSpec spec) + private static void CalculateReward(string? stateReward, bool isStateTest, Block block, + WorldState stateProvider, IReleaseSpec spec) { if (stateReward == null || isStateTest) return; diff --git a/tools/Evm.Test/T8NTests.cs b/tools/Evm.Test/T8NTests.cs index 5ca0f161e95..44580e51fd1 100644 --- a/tools/Evm.Test/T8NTests.cs +++ b/tools/Evm.Test/T8NTests.cs @@ -261,6 +261,7 @@ private void Execute(InputParams inputParams, OutputParams outputParams, int exp 1, inputParams.StateFork, inputParams.StateReward, + false, TraceOptions.Default ); diff --git a/tools/evm/Evm.sln b/tools/evm/Evm.sln index c1b98c47b93..5bef2b9f239 100644 --- a/tools/evm/Evm.sln +++ b/tools/evm/Evm.sln @@ -13,4 +13,6 @@ Global {AAA9AF72-46AE-4535-9698-610C9E94AE06}.Release|Any CPU.ActiveCfg = Release|Any CPU {AAA9AF72-46AE-4535-9698-610C9E94AE06}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection + GlobalSection(NestedProjects) = preSolution + EndGlobalSection EndGlobal diff --git a/tools/evm/Program.cs b/tools/evm/Program.cs index 9e17b9c0b0a..f2256bc84c8 100644 --- a/tools/evm/Program.cs +++ b/tools/evm/Program.cs @@ -1,11 +1,5 @@ using System.CommandLine; using Evm.JsonTypes; -using Evm.T8NTool; -using Nethermind.Core.Exceptions; -using Nethermind.Core.Extensions; -using Nethermind.Evm; -using Nethermind.Serialization.Rlp; -using Nethermind.Specs.Forks; namespace Evm { diff --git a/tools/evm/T8NTool/InputProcessor.cs b/tools/evm/T8NTool/InputProcessor.cs index 45dee7f3365..f84c956de5a 100644 --- a/tools/evm/T8NTool/InputProcessor.cs +++ b/tools/evm/T8NTool/InputProcessor.cs @@ -7,6 +7,7 @@ using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Json; using Nethermind.Serialization.Rlp; +using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -23,6 +24,7 @@ public static GeneralStateTest ConvertToGeneralStateTest(string inputAlloc, string stateFork, string? stateReward, ulong stateChainId, + bool isGnosis, TraceOptions traceOptions) { GethTraceOptions gethTraceOptions = new GethTraceOptions @@ -30,7 +32,8 @@ public static GeneralStateTest ConvertToGeneralStateTest(string inputAlloc, EnableMemory = traceOptions.Memory, DisableStack = traceOptions.NoStack }; - Dictionary allocJson = EthereumJsonSerializer.Deserialize>(File.ReadAllText(inputAlloc)); + Dictionary allocJson = + EthereumJsonSerializer.Deserialize>(File.ReadAllText(inputAlloc)); EnvInfo envInfo = EthereumJsonSerializer.Deserialize(File.ReadAllText(inputEnv)); Transaction[] transactions; @@ -61,11 +64,14 @@ public static GeneralStateTest ConvertToGeneralStateTest(string inputAlloc, throw new T8NException(e, ExitCodes.ErrorConfig); } - ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Frontier.Instance), ((ForkActivation)1, spec)); + ISpecProvider specProvider = isGnosis ? GnosisSpecProvider.Instance + : new CustomSpecProvider(((ForkActivation)0, Frontier.Instance), ((ForkActivation)1, spec)); + if (spec is Paris) { specProvider.UpdateMergeTransitionInfo(envInfo.CurrentNumber, 0); } + envInfo.ApplyChecks(specProvider, spec); GeneralStateTest generalStateTest = new(); @@ -73,13 +79,13 @@ public static GeneralStateTest ConvertToGeneralStateTest(string inputAlloc, generalStateTest.Fork = spec; generalStateTest.Pre = allocJson; generalStateTest.Transactions = transactions; + generalStateTest.StateChainId = isGnosis ? GnosisSpecProvider.Instance.ChainId : MainnetSpecProvider.Instance.ChainId; generalStateTest.CurrentCoinbase = envInfo.CurrentCoinbase; generalStateTest.CurrentGasLimit = envInfo.CurrentGasLimit; generalStateTest.CurrentTimestamp = envInfo.CurrentTimestamp; generalStateTest.CurrentNumber = envInfo.CurrentNumber; generalStateTest.Withdrawals = envInfo.Withdrawals; - generalStateTest.Withdrawals = envInfo.Withdrawals; generalStateTest.CurrentRandom = envInfo.GetCurrentRandomHash256(); generalStateTest.ParentTimestamp = envInfo.ParentTimestamp; generalStateTest.ParentDifficulty = envInfo.ParentDifficulty; diff --git a/tools/evm/T8NTool/T8NTool.cs b/tools/evm/T8NTool/T8NTool.cs index eba84679173..fc101494f14 100644 --- a/tools/evm/T8NTool/T8NTool.cs +++ b/tools/evm/T8NTool/T8NTool.cs @@ -3,6 +3,7 @@ using Ethereum.Test.Base.T8NUtils; using Evm.JsonTypes; using Nethermind.Serialization.Json; +using Nethermind.Specs; namespace Evm.T8NTool; @@ -33,7 +34,9 @@ public T8NOutput Execute( T8NOutput t8NOutput = new(); try { - var t8NExecutionResult = Execute(inputAlloc, inputEnv, inputTxs, stateFork, stateReward, stateChainId, traceOptions); + var isGnosis = GnosisSpecProvider.Instance.ChainId == stateChainId; + var t8NExecutionResult = Execute(inputAlloc, inputEnv, inputTxs, stateFork, stateReward, stateChainId, + isGnosis, traceOptions); if (outputAlloc == "stdout") t8NOutput.Alloc = t8NExecutionResult.Alloc; else if (outputAlloc != null) WriteToFile(outputAlloc, outputBasedir, t8NExecutionResult.Alloc); @@ -72,6 +75,7 @@ public T8NOutput Execute( Console.WriteLine(t8NOutput.ErrorMessage); } } + return t8NOutput; } @@ -82,11 +86,13 @@ private T8NExecutionResult Execute( string stateFork, string? stateReward, ulong stateChainId, + bool isGnosis, TraceOptions traceOptions) { - var generalStateTest = InputProcessor.ConvertToGeneralStateTest(inputAlloc, inputEnv, inputTxs, stateFork, stateReward, stateChainId, traceOptions); + var generalStateTest = InputProcessor.ConvertToGeneralStateTest(inputAlloc, inputEnv, inputTxs, stateFork, + stateReward, stateChainId, isGnosis, traceOptions); - var res = RunTest(generalStateTest); + var res = RunTest(generalStateTest, isGnosis); PostState postState = new PostState(); postState.StateRoot = res.StateRoot;