diff --git a/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/EipTests.cs b/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/EipTests.cs deleted file mode 100644 index 824fd6f2a48..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/EipTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Threading.Tasks; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Block.Test.Pyspecs; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class EipTests : BlockchainTestBase -{ - [TestCaseSource(nameof(LoadTests))] - public async Task Test(BlockchainTest test) => await RunTest(test); - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadBlockchainTestsStrategy(), "Pyspecs/eips"); - - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/VMTests.cs b/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/VMTests.cs deleted file mode 100644 index 9bdcec07bdc..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/VMTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Threading.Tasks; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Block.Test.Pyspecs; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class VMTests : BlockchainTestBase -{ - [TestCaseSource(nameof(LoadTests))] - public async Task Test(BlockchainTest test) => await RunTest(test); - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadBlockchainTestsStrategy(), "Pyspecs/vm"); - - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/WithdrawalsTests.cs b/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/WithdrawalsTests.cs deleted file mode 100644 index 28582549fee..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Block.Test/Pyspecs/WithdrawalsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Threading.Tasks; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Block.Test.Pyspecs; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class WithdrawalsTests : BlockchainTestBase -{ - [TestCaseSource(nameof(LoadTests))] - public async Task Test(BlockchainTest test) => await RunTest(test); - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadBlockchainTestsStrategy(), "Pyspecs/withdrawals"); - - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip2537Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip2537Tests.cs index 0127e687e11..23fe74ca1a3 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/Eip2537Tests.cs +++ b/src/Nethermind/Ethereum.Blockchain.Test/Eip2537Tests.cs @@ -1,26 +1,26 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -// using System.Collections.Generic; -// using Ethereum.Test.Base; -// using NUnit.Framework; +using System.Collections.Generic; +using Ethereum.Test.Base; +using NUnit.Framework; -// namespace Ethereum.Blockchain.Test -// { -// [TestFixture] -// [Parallelizable(ParallelScope.All)] -// public class Eip2537Tests : GeneralStateTestBase -// { -// [TestCaseSource(nameof(LoadTests))] -// public void Test(GeneralStateTest test) -// { -// Assert.True(RunTest(test).Pass); -// } +namespace Ethereum.Blockchain.Test +{ + [TestFixture] + [Parallelizable(ParallelScope.All)] + public class Eip2537Tests : GeneralStateTestBase + { + [TestCaseSource(nameof(LoadTests))] + public void Test(GeneralStateTest test) + { + Assert.True(RunTest(test).Pass); + } -// public static IEnumerable LoadTests() -// { -// var loader = new TestsSourceLoader(new LoadGeneralStateTestsStrategy(), "../EIPTests/StateTests/stEIP2537"); -// return (IEnumerable)loader.LoadTests(); -// } -// } -// } + public static IEnumerable LoadTests() + { + var loader = new TestsSourceLoader(new LoadGeneralStateTestsStrategy(), "../EIPTests/StateTests/stEIP2537"); + return (IEnumerable)loader.LoadTests(); + } + } +} diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index f3fabfa27da..e583a78b423 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -25,6 +25,7 @@ using Nethermind.State; using Nethermind.Trie.Pruning; using NUnit.Framework; +using System.Threading.Tasks; namespace Ethereum.Test.Base { @@ -32,7 +33,7 @@ public abstract class GeneralStateTestBase { private static ILogger _logger = new(new ConsoleAsyncLogger(LogLevel.Info)); private static ILogManager _logManager = LimboLogs.Instance; - private static UInt256 _defaultBaseFeeForStateTest = 0xA; + private static readonly UInt256 _defaultBaseFeeForStateTest = 0xA; private readonly TxValidator _txValidator = new(MainnetSpecProvider.Instance.ChainId); [SetUp] @@ -40,7 +41,10 @@ public void Setup() { } - protected void Setup(ILogManager logManager) + [OneTimeSetUp] + public Task OneTimeSetUp() => KzgPolynomialCommitments.InitializeAsync(); + + protected static void Setup(ILogManager logManager) { _logManager = logManager ?? LimboLogs.Instance; _logger = _logManager.GetClassLogger(); @@ -95,7 +99,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) test.CurrentNumber, test.CurrentGasLimit, test.CurrentTimestamp, - Array.Empty()); + []); header.BaseFeePerGas = test.Fork.IsEip1559Enabled ? test.CurrentBaseFee ?? _defaultBaseFeeForStateTest : UInt256.Zero; header.StateRoot = test.PostHash; header.Hash = header.CalculateHash(); @@ -109,8 +113,6 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) Stopwatch stopwatch = Stopwatch.StartNew(); IReleaseSpec? spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber); - if (spec is Cancun) KzgPolynomialCommitments.InitializeAsync(); - if (test.Transaction.ChainId is null) test.Transaction.ChainId = MainnetSpecProvider.Instance.ChainId; if (test.ParentBlobGasUsed is not null && test.ParentExcessBlobGas is not null) @@ -123,7 +125,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) number: test.CurrentNumber - 1, gasLimit: test.CurrentGasLimit, timestamp: test.CurrentTimestamp, - extraData: Array.Empty() + extraData: [] ) { BlobGasUsed = (ulong)test.ParentBlobGasUsed, @@ -137,10 +139,13 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) bool isValid = _txValidator.IsWellFormed(test.Transaction, spec) && IsValidBlock(block, specProvider); if (isValid) + { transactionProcessor.Execute(test.Transaction, new BlockExecutionContext(header), txTracer); + } + stopwatch.Stop(); - stateProvider.Commit(specProvider.GenesisSpec); + stateProvider.Commit(specProvider.GetSpec((ForkActivation)1)); stateProvider.CommitTree(1); // '@winsvega added a 0-wei reward to the miner , so we had to add that into the state test execution phase. He needed it for retesteth.' @@ -148,6 +153,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) { stateProvider.CreateAccount(test.CurrentCoinbase, 0); } + stateProvider.Commit(specProvider.GetSpec((ForkActivation)1)); stateProvider.RecalculateStateRoot(); @@ -199,7 +205,7 @@ private bool IsValidBlock(Block block, ISpecProvider specProvider) private List RunAssertions(GeneralStateTest test, IWorldState stateProvider) { - List differences = new(); + List differences = []; if (test.PostHash != stateProvider.StateRoot) { differences.Add($"STATE ROOT exp: {test.PostHash}, actual: {stateProvider.StateRoot}"); diff --git a/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs index 7fbc3fa0153..dfee892bdd6 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadBlockchainTestsStrategy.cs @@ -38,7 +38,7 @@ private string GetBlockchainTestsDirectory() char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}BlockchainTests"; + return Path.Combine(currentDirectory.Remove(currentDirectory.LastIndexOf("src")), "src", "tests", "BlockchainTests"); } private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) diff --git a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs index 82b5f344d2c..08af330a4e0 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs @@ -39,7 +39,7 @@ private string GetGeneralStateTestsDirectory() char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}EIPTests{pathSeparator}StateTests"; + return Path.Combine(currentDirectory.Remove(currentDirectory.LastIndexOf("src")), "src", "tests", "EIPTests", "StateTests"); } private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) diff --git a/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestFileStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestFileStrategy.cs index 1f94da85149..dd86d693566 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestFileStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestFileStrategy.cs @@ -51,7 +51,7 @@ private string GetGeneralStateTestsDirectory() char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}GeneralStateTests"; + return Path.Combine(currentDirectory.Remove(currentDirectory.LastIndexOf("src")), "src", "tests", "GeneralStateTests"); } } } diff --git a/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs index 265b432d853..5373e3b01af 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadGeneralStateTestsStrategy.cs @@ -36,10 +36,9 @@ public IEnumerable Load(string testsDirectoryName, string wildcar private string GetGeneralStateTestsDirectory() { - char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}GeneralStateTests"; + return Path.Combine(currentDirectory.Remove(currentDirectory.LastIndexOf("src")), "src", "tests", "GeneralStateTests"); } private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) diff --git a/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs index 9c7be901503..e47919bb884 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadLegacyBlockchainTestsStrategy.cs @@ -38,7 +38,7 @@ private string GetLegacyBlockchainTestsDirectory() char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}LegacyTests{pathSeparator}Constantinople{pathSeparator}BlockchainTests"; + return Path.Combine(currentDirectory.Remove(currentDirectory.LastIndexOf("src")), "src", "tests", "LegacyTests", "Constantinople", "BlockchainTests"); } private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) diff --git a/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs index c457994963a..2d815e13047 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadLegacyGeneralStateTestsStrategy.cs @@ -35,10 +35,9 @@ public IEnumerable Load(string testsDirectoryName, string wildcar private string GetLegacyGeneralStateTestsDirectory() { - char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}LegacyTests{pathSeparator}Constantinople{pathSeparator}GeneralStateTests"; + return Path.Combine(currentDirectory.Remove(currentDirectory.LastIndexOf("src")), "src", "tests", "LegacyTests", "Constantinople", "GeneralStateTests"); } private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) diff --git a/src/Nethermind/Nethermind.Evm/AddressExtensions.cs b/src/Nethermind/Nethermind.Evm/AddressExtensions.cs index c52f5453184..d19f03056a5 100644 --- a/src/Nethermind/Nethermind.Evm/AddressExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/AddressExtensions.cs @@ -4,8 +4,10 @@ using System; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Serialization.Rlp; +using Nethermind.State; namespace Nethermind.Evm { @@ -36,5 +38,13 @@ public static Address From(Address deployingAddress, ReadOnlySpan salt, Re ValueHash256 contractAddressKeccak = ValueKeccak.Compute(bytes); return new Address(in contractAddressKeccak); } + + // See https://eips.ethereum.org/EIPS/eip-7610 + public static bool IsNonZeroAccount(this Address contractAddress, IReleaseSpec spec, ICodeInfoRepository codeInfoRepository, IWorldState state) + { + return codeInfoRepository.GetCachedCodeInfo(state, contractAddress, spec).MachineCode.Length != 0 || + state.GetNonce(contractAddress) != 0 || + state.GetStorageRoot(contractAddress) != Keccak.EmptyTreeHash; + } } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 95744638d44..a4367ad17f3 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -185,9 +185,10 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon private static void UpdateMetrics(ExecutionOptions opts, UInt256 effectiveGasPrice) { - if (opts is ExecutionOptions.Commit or ExecutionOptions.None) + if (opts is ExecutionOptions.Commit or ExecutionOptions.None && (effectiveGasPrice[2] | effectiveGasPrice[3]) == 0) { float gasPrice = (float)((double)effectiveGasPrice / 1_000_000_000.0); + Metrics.MinGasPrice = Math.Min(gasPrice, Metrics.MinGasPrice); Metrics.MaxGasPrice = Math.Max(gasPrice, Metrics.MaxGasPrice); @@ -580,26 +581,11 @@ protected virtual void PayFees(Transaction tx, BlockHeader header, IReleaseSpec protected void PrepareAccountForContractDeployment(Address contractAddress, IReleaseSpec spec) { - if (WorldState.AccountExists(contractAddress)) + if (WorldState.AccountExists(contractAddress) && contractAddress.IsNonZeroAccount(spec, _codeInfoRepository, WorldState)) { - CodeInfo codeInfo = _codeInfoRepository.GetCachedCodeInfo(WorldState, contractAddress, spec); - bool codeIsNotEmpty = codeInfo.MachineCode.Length != 0; - bool accountNonceIsNotZero = WorldState.GetNonce(contractAddress) != 0; - - // TODO: verify what should happen if code info is a precompile - // (but this would generally be a hash collision) - if (codeIsNotEmpty || accountNonceIsNotZero) - { - if (Logger.IsTrace) - { - Logger.Trace($"Contract collision at {contractAddress}"); - } - - ThrowTransactionCollisionException(); - } + if (Logger.IsTrace) Logger.Trace($"Contract collision at {contractAddress}"); - // we clean any existing storage (in case of a previously called self destruct) - WorldState.UpdateStorageRoot(contractAddress, Keccak.EmptyTreeHash); + ThrowTransactionCollisionException(); } } diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 12ced688ccb..01e891b07f5 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -27,15 +28,8 @@ namespace Nethermind.Evm; -using System.Collections.Frozen; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; - using Int256; -using Nethermind.Core.Collections; - public class VirtualMachine : IVirtualMachine { public const int MaxCallDepth = 1024; @@ -143,8 +137,7 @@ internal sealed class VirtualMachine : IVirtualMachine where TLogger : private readonly IBlockhashProvider _blockhashProvider; private readonly ISpecProvider _specProvider; private readonly ILogger _logger; - private IWorldState _worldState; - private IWorldState _state = null!; + private IWorldState _state; private readonly Stack _stateStack = new(); private (Address Address, bool ShouldDelete) _parityTouchBugAccount = (Address.FromNumber(3), false); private ReadOnlyMemory _returnDataBuffer = Array.Empty(); @@ -169,7 +162,6 @@ public TransactionSubstate Run(EvmState state, IWorldState worl { _txTracer = txTracer; _state = worldState; - _worldState = worldState; IReleaseSpec spec = _specProvider.GetSpec(state.Env.TxExecutionContext.BlockExecutionContext.Header.Number, state.Env.TxExecutionContext.BlockExecutionContext.Header.Timestamp); EvmState currentState = state; @@ -243,7 +235,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl if (callResult.IsException) { if (typeof(TTracingActions) == typeof(IsTracing)) _txTracer.ReportActionError(callResult.ExceptionType); - _worldState.Restore(currentState.Snapshot); + _state.Restore(currentState.Snapshot); RevertParityTouchBugAccount(spec); @@ -421,7 +413,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl { if (typeof(TLogger) == typeof(IsTracing)) _logger.Trace($"exception ({ex.GetType().Name}) in {currentState.ExecutionType} at depth {currentState.Env.CallDepth} - restoring snapshot"); - _worldState.Restore(currentState.Snapshot); + _state.Restore(currentState.Snapshot); RevertParityTouchBugAccount(spec); @@ -1333,7 +1325,7 @@ private CallResult ExecuteCode externalCode = _codeInfoRepository.GetCachedCodeInfo(_worldState, address, spec).MachineCode; + ReadOnlyMemory externalCode = _codeInfoRepository.GetCachedCodeInfo(_state, address, spec).MachineCode; slice = externalCode.SliceWithZeroPadding(b, (int)result); vmState.Memory.Save(in a, in slice); if (typeof(TTracingInstructions) == typeof(IsTracing)) @@ -2043,7 +2035,7 @@ static void ThrowOperationCanceledException() => [MethodImpl(MethodImplOptions.NoInlining)] private void InstructionExtCodeSize(Address address, ref EvmStack stack, IReleaseSpec spec) where TTracingInstructions : struct, IIsTracing { - ReadOnlyMemory accountCode = _codeInfoRepository.GetCachedCodeInfo(_worldState, address, spec).MachineCode; + ReadOnlyMemory accountCode = _codeInfoRepository.GetCachedCodeInfo(_state, address, spec).MachineCode; UInt256 result = (UInt256)accountCode.Span.Length; stack.PushUInt256(in result); } @@ -2121,7 +2113,7 @@ private EvmExceptionType InstructionCall( !UpdateMemoryCost(vmState, ref gasAvailable, in outputOffset, outputLength) || !UpdateGas(gasExtra, ref gasAvailable)) return EvmExceptionType.OutOfGas; - CodeInfo codeInfo = _codeInfoRepository.GetCachedCodeInfo(_worldState, codeSource, spec); + CodeInfo codeInfo = _codeInfoRepository.GetCachedCodeInfo(_state, codeSource, spec); codeInfo.AnalyseInBackgroundIfRequired(); if (spec.Use63Over64Rule) @@ -2162,7 +2154,7 @@ private EvmExceptionType InstructionCall( return EvmExceptionType.None; } - Snapshot snapshot = _worldState.TakeSnapshot(); + Snapshot snapshot = _state.TakeSnapshot(); _state.SubtractFromBalance(caller, transferValue, spec); if (codeInfo.IsEmpty && typeof(TTracingInstructions) != typeof(IsTracing) && !_txTracer.IsTracingActions) @@ -2406,11 +2398,11 @@ private EvmExceptionType InstructionSelfDestruct(EvmState vmState, ref _state.IncrementNonce(env.ExecutingAccount); - Snapshot snapshot = _worldState.TakeSnapshot(); + Snapshot snapshot = _state.TakeSnapshot(); bool accountExists = _state.AccountExists(contractAddress); - if (accountExists && (_codeInfoRepository.GetCachedCodeInfo(_worldState, contractAddress, spec).MachineCode.Length != 0 || - _state.GetNonce(contractAddress) != 0)) + + if (accountExists && contractAddress.IsNonZeroAccount(spec, _codeInfoRepository, _state)) { /* we get the snapshot before this as there is a possibility with that we will touch an empty account and remove it even if the REVERT operation follows */ if (typeof(TLogger) == typeof(IsTracing)) _logger.Trace($"Contract collision at {contractAddress}"); @@ -2419,11 +2411,7 @@ private EvmExceptionType InstructionSelfDestruct(EvmState vmState, ref return (EvmExceptionType.None, null); } - if (accountExists) - { - _state.UpdateStorageRoot(contractAddress, Keccak.EmptyTreeHash); - } - else if (_state.IsDeadAccount(contractAddress)) + if (_state.IsDeadAccount(contractAddress)) { _state.ClearStorage(contractAddress); } diff --git a/src/Nethermind/Nethermind.State/IReadOnlyStateProvider.cs b/src/Nethermind/Nethermind.State/IReadOnlyStateProvider.cs index 28760632939..7bfe0fa81e6 100644 --- a/src/Nethermind/Nethermind.State/IReadOnlyStateProvider.cs +++ b/src/Nethermind/Nethermind.State/IReadOnlyStateProvider.cs @@ -3,7 +3,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Int256; using Nethermind.Trie; namespace Nethermind.State @@ -33,6 +32,7 @@ public interface IReadOnlyStateProvider : IAccountStateProvider bool IsDeadAccount(Address address); bool IsEmptyAccount(Address address); + bool HasStateForRoot(Hash256 stateRoot); } } diff --git a/src/tests b/src/tests index 661356317ac..ebbaa54c7a9 160000 --- a/src/tests +++ b/src/tests @@ -1 +1 @@ -Subproject commit 661356317ac6df52208d54187e692472a25a01f8 +Subproject commit ebbaa54c7a90e74313b846369fe87e9bd3a58369