diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs
index b29fcf00088..ad34320f047 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs
@@ -58,7 +58,7 @@ public void GlobalSetup()
inputData: default
);
- _evmState = new EvmState(long.MaxValue, _environment, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot());
+ _evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot(), _environment, new StackAccessTracker());
}
[Benchmark]
diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs
index 97d0d9e6cf8..942d06a4929 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs
@@ -91,7 +91,7 @@ public void GlobalSetup()
inputData: default
);
- _evmState = new EvmState(100_000_000L, _environment, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot());
+ _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot(), _environment, new StackAccessTracker());
}
[Benchmark]
diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs
index b7b8d39945b..c299c991efa 100644
--- a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs
+++ b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs
@@ -102,7 +102,7 @@ public void GlobalSetup()
inputData: default
);
- _evmState = new EvmState(100_000_000L, _environment, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot());
+ _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot(), _environment, new StackAccessTracker());
}
[Benchmark(Baseline = true)]
diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs
index e462d04c288..2a6c1f8cbf5 100644
--- a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs
+++ b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs
@@ -216,25 +216,26 @@ public void Can_dispose_without_init()
public void Can_dispose_after_init()
{
EvmState evmState = CreateEvmState();
- evmState.InitStacks();
+ evmState.InitializeStacks();
evmState.Dispose();
}
private static EvmState CreateEvmState(EvmState parentEvmState = null, bool isContinuation = false) =>
parentEvmState is null
- ? new EvmState(10000,
- new ExecutionEnvironment(),
- ExecutionType.CALL,
- Snapshot.Empty)
- : new EvmState(10000,
- new ExecutionEnvironment(),
+ ? EvmState.RentTopLevel(10000,
ExecutionType.CALL,
Snapshot.Empty,
+ new ExecutionEnvironment(),
+ new StackAccessTracker())
+ : EvmState.RentFrame(10000,
0,
0,
+ ExecutionType.CALL,
+ false,
false,
- parentEvmState.AccessTracker,
- false);
+ Snapshot.Empty,
+ new ExecutionEnvironment(),
+ parentEvmState.AccessTracker);
public class Context { }
}
diff --git a/src/Nethermind/Nethermind.Evm/EvmState.cs b/src/Nethermind/Nethermind.Evm/EvmState.cs
index feb1abdbc87..ead92e96c8a 100644
--- a/src/Nethermind/Nethermind.Evm/EvmState.cs
+++ b/src/Nethermind/Nethermind.Evm/EvmState.cs
@@ -2,196 +2,238 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System;
+using System.Collections.Concurrent;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Nethermind.Core;
using Nethermind.State;
-namespace Nethermind.Evm
+namespace Nethermind.Evm;
+
+///
+/// State for EVM Calls
+///
+[DebuggerDisplay("{ExecutionType} to {Env.ExecutingAccount}, G {GasAvailable} R {Refund} PC {ProgramCounter} OUT {OutputDestination}:{OutputLength}")]
+public sealed class EvmState : IDisposable // TODO: rename to CallState
{
+ private static readonly ConcurrentQueue _statePool = new();
+ private static readonly StackPool _stackPool = new();
+
+ public byte[]? DataStack;
+ public int[]? ReturnStack;
+
+ public long GasAvailable { get; set; }
+ internal long OutputDestination { get; private set; } // TODO: move to CallEnv
+ internal long OutputLength { get; private set; } // TODO: move to CallEnv
+ public long Refund { get; set; }
+
+ public int DataStackHead;
+
+ public int ReturnStackHead;
+ internal ExecutionType ExecutionType { get; private set; } // TODO: move to CallEnv
+ public int ProgramCounter { get; set; }
+ public bool IsTopLevel { get; private set; } // TODO: move to CallEnv
+ private bool _canRestore;
+ public bool IsStatic { get; private set; } // TODO: move to CallEnv
+ public bool IsContinuation { get; set; } // TODO: move to CallEnv
+ public bool IsCreateOnPreExistingAccount { get; private set; } // TODO: move to CallEnv
+
+ private bool _isDisposed = true;
+
+ private EvmPooledMemory _memory;
+ private Snapshot _snapshot;
+ private ExecutionEnvironment _env;
+ private StackAccessTracker _accessTracker;
+
+#if DEBUG
+ private StackTrace? _creationStackTrace;
+#endif
///
- /// State for EVM Calls
+ /// Rent a top level .
///
- [DebuggerDisplay("{ExecutionType} to {Env.ExecutingAccount}, G {GasAvailable} R {Refund} PC {ProgramCounter} OUT {OutputDestination}:{OutputLength}")]
- public class EvmState : IDisposable // TODO: rename to CallState
+ public static EvmState RentTopLevel(
+ long gasAvailable,
+ ExecutionType executionType,
+ in Snapshot snapshot,
+ in ExecutionEnvironment env,
+ in StackAccessTracker accessedItems)
{
- private static readonly StackPool _stackPool = new();
-
- public byte[]? DataStack;
-
- public int[]? ReturnStack;
-
- public StackAccessTracker AccessTracker => _accessTracker;
-
- private readonly StackAccessTracker _accessTracker;
-
- public int DataStackHead = 0;
-
- public int ReturnStackHead = 0;
- private bool _canRestore = true;
- ///
- /// Constructor for a top level .
- ///
- public EvmState(
- long gasAvailable,
- ExecutionEnvironment env,
- ExecutionType executionType,
- Snapshot snapshot,
- in StackAccessTracker accessedItems) : this(gasAvailable,
- env,
- executionType,
- true,
- snapshot,
- 0L,
- 0L,
- false,
- accessedItems,
- false)
- {
- }
- ///
- /// Constructor for a top level .
- ///
- public EvmState(
- long gasAvailable,
- ExecutionEnvironment env,
- ExecutionType executionType,
- Snapshot snapshot) : this(gasAvailable,
- env,
- executionType,
- true,
- snapshot,
- 0L,
- 0L,
- false,
- new StackAccessTracker(),
- false)
- {
- }
- ///
- /// Constructor for a frame beneath top level.
- ///
- internal EvmState(
- long gasAvailable,
- ExecutionEnvironment env,
- ExecutionType executionType,
- Snapshot snapshot,
- long outputDestination,
- long outputLength,
- bool isStatic,
- in StackAccessTracker stateForAccessLists,
- bool isCreateOnPreExistingAccount) :
- this(
- gasAvailable,
- env,
- executionType,
- false,
- snapshot,
- outputDestination,
- outputLength,
- isStatic,
- stateForAccessLists,
- isCreateOnPreExistingAccount)
- {
+ EvmState state = Rent();
+ state.Initialize(
+ gasAvailable,
+ outputDestination: 0L,
+ outputLength: 0L,
+ executionType: executionType,
+ isTopLevel: true,
+ isStatic: false,
+ isCreateOnPreExistingAccount: false,
+ snapshot: snapshot,
+ env: env,
+ stateForAccessLists: accessedItems);
+ return state;
+ }
- }
- private EvmState(
- long gasAvailable,
- ExecutionEnvironment env,
- ExecutionType executionType,
- bool isTopLevel,
- Snapshot snapshot,
- long outputDestination,
- long outputLength,
- bool isStatic,
- in StackAccessTracker stateForAccessLists,
- bool isCreateOnPreExistingAccount)
+ ///
+ /// Constructor for a frame beneath top level.
+ ///
+ public static EvmState RentFrame(
+ long gasAvailable,
+ long outputDestination,
+ long outputLength,
+ ExecutionType executionType,
+ bool isStatic,
+ bool isCreateOnPreExistingAccount,
+ in Snapshot snapshot,
+ in ExecutionEnvironment env,
+ in StackAccessTracker stateForAccessLists)
+ {
+ EvmState state = Rent();
+
+ state.Initialize(
+ gasAvailable,
+ outputDestination,
+ outputLength,
+ executionType,
+ isTopLevel: false,
+ isStatic: isStatic,
+ isCreateOnPreExistingAccount: isCreateOnPreExistingAccount,
+ snapshot: snapshot,
+ env: env,
+ stateForAccessLists: stateForAccessLists);
+
+ return state;
+ }
+
+ private static EvmState Rent() => _statePool.TryDequeue(out EvmState state) ? state : new EvmState();
+
+ private void Initialize(
+ long gasAvailable,
+ long outputDestination,
+ long outputLength,
+ ExecutionType executionType,
+ bool isTopLevel,
+ bool isStatic,
+ bool isCreateOnPreExistingAccount,
+ in Snapshot snapshot,
+ in ExecutionEnvironment env,
+ in StackAccessTracker stateForAccessLists)
+ {
+ GasAvailable = gasAvailable;
+ OutputDestination = outputDestination;
+ OutputLength = outputLength;
+ Refund = 0;
+ DataStackHead = 0;
+ ReturnStackHead = 0;
+ ExecutionType = executionType;
+ ProgramCounter = 0;
+ IsTopLevel = isTopLevel;
+ _canRestore = !isTopLevel;
+ IsStatic = isStatic;
+ IsContinuation = false;
+ IsCreateOnPreExistingAccount = isCreateOnPreExistingAccount;
+ _snapshot = snapshot;
+ _env = env;
+ _accessTracker = new(stateForAccessLists);
+ if (executionType.IsAnyCreate())
{
- GasAvailable = gasAvailable;
- ExecutionType = executionType;
- IsTopLevel = isTopLevel;
- _canRestore = !isTopLevel;
- Snapshot = snapshot;
- Env = env;
- OutputDestination = outputDestination;
- OutputLength = outputLength;
- IsStatic = isStatic;
- IsContinuation = false;
- IsCreateOnPreExistingAccount = isCreateOnPreExistingAccount;
- _accessTracker = new(stateForAccessLists);
- if (executionType.IsAnyCreate())
- {
- _accessTracker.WasCreated(env.ExecutingAccount);
- }
- _accessTracker.TakeSnapshot();
+ _accessTracker.WasCreated(env.ExecutingAccount);
}
+ _accessTracker.TakeSnapshot();
- public Address From
+ // Should be disposed when being initialized
+ if (!_isDisposed)
{
- get
- {
- return ExecutionType switch
- {
- ExecutionType.STATICCALL or ExecutionType.CALL or ExecutionType.CALLCODE or ExecutionType.CREATE or ExecutionType.CREATE2 or ExecutionType.TRANSACTION => Env.Caller,
- ExecutionType.DELEGATECALL => Env.ExecutingAccount,
- _ => throw new ArgumentOutOfRangeException(),
- };
- }
+ ThrowIfNotUninitialized();
}
+ // Mark revived
+ _isDisposed = false;
- public long GasAvailable { get; set; }
- public int ProgramCounter { get; set; }
- public long Refund { get; set; }
+#if DEBUG
+ _creationStackTrace = new();
+#endif
- public Address To => Env.CodeSource ?? Env.ExecutingAccount;
- internal bool IsPrecompile => Env.CodeInfo.IsPrecompile;
- public readonly ExecutionEnvironment Env;
+ [DoesNotReturn]
+ [StackTraceHidden]
+ static void ThrowIfNotUninitialized()
+ {
+ throw new InvalidOperationException("Already in use");
+ }
+ }
- internal ExecutionType ExecutionType { get; } // TODO: move to CallEnv
- public bool IsTopLevel { get; } // TODO: move to CallEnv
- internal long OutputDestination { get; } // TODO: move to CallEnv
- internal long OutputLength { get; } // TODO: move to CallEnv
- public bool IsStatic { get; } // TODO: move to CallEnv
- public bool IsContinuation { get; set; } // TODO: move to CallEnv
- public bool IsCreateOnPreExistingAccount { get; } // TODO: move to CallEnv
- public Snapshot Snapshot { get; } // TODO: move to CallEnv
+ public Address From => ExecutionType switch
+ {
+ ExecutionType.STATICCALL or ExecutionType.CALL or ExecutionType.CALLCODE or ExecutionType.CREATE
+ or ExecutionType.CREATE2 or ExecutionType.TRANSACTION => Env.Caller,
+ ExecutionType.DELEGATECALL => Env.ExecutingAccount,
+ _ => throw new ArgumentOutOfRangeException(),
+ };
+
+ public Address To => Env.CodeSource ?? Env.ExecutingAccount;
+ internal bool IsPrecompile => Env.CodeInfo.IsPrecompile;
+ public ref readonly StackAccessTracker AccessTracker => ref _accessTracker;
+ public ref readonly ExecutionEnvironment Env => ref _env;
+ public ref EvmPooledMemory Memory => ref _memory; // TODO: move to CallEnv
+ public ref readonly Snapshot Snapshot => ref _snapshot; // TODO: move to CallEnv
+
+ public void Dispose()
+ {
+ // Shouldn't be called multiple times
+ Debug.Assert(!_isDisposed);
- private EvmPooledMemory _memory;
- public ref EvmPooledMemory Memory => ref _memory; // TODO: move to CallEnv
+ if (_isDisposed) return;
- public void Dispose()
+ _isDisposed = true;
+ if (DataStack is not null)
{
- if (DataStack is not null)
- {
- // Only Dispose once
- _stackPool.ReturnStacks(DataStack, ReturnStack!);
- DataStack = null;
- ReturnStack = null;
- }
- Restore(); // we are trying to restore when disposing
- Memory.Dispose();
- Memory = default;
+ // Only return if initialized
+ _stackPool.ReturnStacks(DataStack, ReturnStack!);
+ DataStack = null;
+ ReturnStack = null;
}
-
- public void InitStacks()
+ if (_canRestore)
{
- if (DataStack is null)
- {
- (DataStack, ReturnStack) = _stackPool.RentStacks();
- }
+ // if we didn't commit and we are not top level, then we need to restore and drop the changes done in this call
+ _accessTracker.Restore();
}
+ _memory.Dispose();
+ // Blank refs to not hold against GC
+ _memory = default;
+ _accessTracker = default;
+ _env = default;
+ _snapshot = default;
+
+ _statePool.Enqueue(this);
+
+#if DEBUG
+ GC.SuppressFinalize(this);
+#endif
+ }
- public void CommitToParent(EvmState parentState)
+#if DEBUG
+ ~EvmState()
+ {
+ if (!_isDisposed)
{
- parentState.Refund += Refund;
- _canRestore = false; // we can't restore if we committed
+ throw new InvalidOperationException($"{nameof(EvmState)} hasn't been disposed. Created {_creationStackTrace}");
}
+ }
+#endif
+
+ public void InitializeStacks()
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed, this);
- private void Restore()
+ if (DataStack is null)
{
- if (_canRestore) // if we didn't commit and we are not top level, then we need to restore and drop the changes done in this call
- {
- _accessTracker.Restore();
- }
+ (DataStack, ReturnStack) = _stackPool.RentStacks();
}
}
+
+ public void CommitToParent(EvmState parentState)
+ {
+ ObjectDisposedException.ThrowIf(_isDisposed, this);
+
+ parentState.Refund += Refund;
+ _canRestore = false; // we can't restore if we committed
+ }
}
diff --git a/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs b/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs
index 6de077bc191..df941be5596 100644
--- a/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs
+++ b/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs
@@ -1,102 +1,126 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
+using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using Nethermind.Core;
using Nethermind.Core.Collections;
using Nethermind.Core.Eip2930;
using Nethermind.Int256;
-namespace Nethermind.Evm
+namespace Nethermind.Evm;
+
+public struct StackAccessTracker : IDisposable
{
- public struct StackAccessTracker
+ public readonly IReadOnlySet AccessedAddresses => _trackingState.AccessedAddresses;
+ public readonly IReadOnlySet AccessedStorageCells => _trackingState.AccessedStorageCells;
+ public readonly ICollection Logs => _trackingState.Logs;
+ public readonly IReadOnlySet DestroyList => _trackingState.DestroyList;
+ public readonly IReadOnlySet CreateList => _trackingState.CreateList;
+
+ private TrackingState _trackingState;
+
+ private int _addressesSnapshots;
+ private int _storageKeysSnapshots;
+ private int _destroyListSnapshots;
+ private int _logsSnapshots;
+
+ public StackAccessTracker(in StackAccessTracker accessTracker)
{
- public readonly IReadOnlySet AccessedAddresses => _accessedAddresses;
- public readonly IReadOnlySet AccessedStorageCells => _accessedStorageCells;
- public readonly ICollection Logs => _logs;
- public readonly IReadOnlySet DestroyList => _destroyList;
- public readonly IReadOnlySet CreateList => _createList;
- private readonly JournalSet _accessedAddresses;
- private readonly JournalSet _accessedStorageCells;
- private readonly JournalCollection _logs;
- private readonly JournalSet _destroyList;
- private readonly HashSet _createList;
-
- private int _addressesSnapshots;
- private int _storageKeysSnapshots;
- private int _destroyListSnapshots;
- private int _logsSnapshots;
-
- public StackAccessTracker(in StackAccessTracker accessTracker)
- {
- _accessedAddresses = accessTracker._accessedAddresses;
- _accessedStorageCells = accessTracker._accessedStorageCells;
- _logs = accessTracker._logs;
- _destroyList = accessTracker._destroyList;
- _createList = accessTracker._createList;
- }
+ _trackingState = accessTracker._trackingState;
+ }
- public StackAccessTracker()
- {
- _accessedAddresses = new();
- _accessedStorageCells = new();
- _logs = new();
- _destroyList = new();
- _createList = new();
- }
- public readonly bool IsCold(Address? address) => !AccessedAddresses.Contains(address);
+ public StackAccessTracker()
+ {
+ _trackingState = TrackingState.RentState();
+ }
+ public readonly bool IsCold(Address? address) => !_trackingState.AccessedAddresses.Contains(address);
- public readonly bool IsCold(in StorageCell storageCell) => !_accessedStorageCells.Contains(storageCell);
+ public readonly bool IsCold(in StorageCell storageCell) => !_trackingState.AccessedStorageCells.Contains(storageCell);
- public readonly void WarmUp(Address address)
- {
- _accessedAddresses.Add(address);
- }
+ public readonly void WarmUp(Address address)
+ {
+ _trackingState.AccessedAddresses.Add(address);
+ }
- public readonly void WarmUp(in StorageCell storageCell)
- {
- _accessedStorageCells.Add(storageCell);
- }
+ public readonly void WarmUp(in StorageCell storageCell)
+ {
+ _trackingState.AccessedStorageCells.Add(storageCell);
+ }
- public readonly void WarmUp(AccessList? accessList)
+ public readonly void WarmUp(AccessList? accessList)
+ {
+ if (accessList?.IsEmpty == false)
{
- if (accessList?.IsEmpty == false)
+ foreach ((Address address, AccessList.StorageKeysEnumerable storages) in accessList)
{
- foreach ((Address address, AccessList.StorageKeysEnumerable storages) in accessList)
+ _trackingState.AccessedAddresses.Add(address);
+ foreach (UInt256 storage in storages)
{
- _accessedAddresses.Add(address);
- foreach (UInt256 storage in storages)
- {
- _accessedStorageCells.Add(new StorageCell(address, storage));
- }
+ _trackingState.AccessedStorageCells.Add(new StorageCell(address, storage));
}
}
}
+ }
- public readonly void ToBeDestroyed(Address address)
- {
- _destroyList.Add(address);
- }
+ public readonly void ToBeDestroyed(Address address)
+ {
+ _trackingState.DestroyList.Add(address);
+ }
- public readonly void WasCreated(Address address)
- {
- _createList.Add(address);
- }
+ public readonly void WasCreated(Address address)
+ {
+ _trackingState.CreateList.Add(address);
+ }
+
+ public void TakeSnapshot()
+ {
+ _addressesSnapshots = _trackingState.AccessedAddresses.TakeSnapshot();
+ _storageKeysSnapshots = _trackingState.AccessedStorageCells.TakeSnapshot();
+ _destroyListSnapshots = _trackingState.DestroyList.TakeSnapshot();
+ _logsSnapshots = _trackingState.Logs.TakeSnapshot();
+ }
+
+ public readonly void Restore()
+ {
+ _trackingState.Logs.Restore(_logsSnapshots);
+ _trackingState.DestroyList.Restore(_destroyListSnapshots);
+ _trackingState.AccessedAddresses.Restore(_addressesSnapshots);
+ _trackingState.AccessedStorageCells.Restore(_storageKeysSnapshots);
+ }
+
+ public void Dispose()
+ {
+ TrackingState state = _trackingState;
+ _trackingState = null;
+ TrackingState.ResetAndReturn(state);
+ }
- public void TakeSnapshot()
+ private class TrackingState
+ {
+ private static readonly ConcurrentQueue _trackerPool = new();
+ public static TrackingState RentState() => _trackerPool.TryDequeue(out TrackingState tracker) ? tracker : new TrackingState();
+
+ public static void ResetAndReturn(TrackingState state)
{
- _addressesSnapshots = _accessedAddresses.TakeSnapshot();
- _storageKeysSnapshots = _accessedStorageCells.TakeSnapshot();
- _destroyListSnapshots = _destroyList.TakeSnapshot();
- _logsSnapshots = _logs.TakeSnapshot();
+ state.Clear();
+ _trackerPool.Enqueue(state);
}
- public readonly void Restore()
+ public JournalSet AccessedAddresses { get; } = new();
+ public JournalSet AccessedStorageCells { get; } = new();
+ public JournalCollection Logs { get; } = new();
+ public JournalSet DestroyList { get; } = new();
+ public HashSet CreateList { get; } = new();
+
+ private void Clear()
{
- _logs.Restore(_logsSnapshots);
- _destroyList.Restore(_destroyListSnapshots);
- _accessedAddresses.Restore(_addressesSnapshots);
- _accessedStorageCells.Restore(_storageKeysSnapshots);
+ AccessedAddresses.Clear();
+ AccessedStorageCells.Clear();
+ Logs.Clear();
+ DestroyList.Clear();
+ CreateList.Clear();
}
}
}
diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs
index ce3038cf504..9638f58ff7f 100644
--- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs
+++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs
@@ -158,7 +158,9 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon
if (commit) WorldState.Commit(spec, tracer.IsTracingState ? tracer : NullTxTracer.Instance, commitStorageRoots: false);
- StackAccessTracker accessTracker = new();
+ // substate.Logs contains a reference to accessTracker.Logs so we can't Dispose until end of the method
+ using StackAccessTracker accessTracker = new();
+
int delegationRefunds = ProcessDelegations(tx, spec, accessTracker);
ExecutionEnvironment env = BuildExecutionEnvironment(tx, in blCtx, spec, effectiveGasPrice, _codeInfoRepository, accessTracker);
@@ -618,11 +620,11 @@ protected virtual void ExecuteEvmCall(
}
}
- using (EvmState state = new EvmState(
+ using (EvmState state = EvmState.RentTopLevel(
unspentGas,
- env,
tx.IsContractCreation ? ExecutionType.CREATE : ExecutionType.TRANSACTION,
snapshot,
+ env,
accessedItems))
{
diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs
index 88525f10b84..56149f85a78 100644
--- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs
+++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs
@@ -647,7 +647,7 @@ private CallResult ExecuteCall(EvmState vmState, ReadOnlyM
goto Empty;
}
- vmState.InitStacks();
+ vmState.InitializeStacks();
EvmStack stack = new(vmState.DataStackHead, _txTracer, vmState.DataStack.AsSpan());
long gasAvailable = vmState.GasAvailable;
@@ -2229,16 +2229,16 @@ private EvmExceptionType InstructionCall(
}
ExecutionType executionType = GetCallExecutionType(instruction, env.IsPostMerge());
- returnData = new EvmState(
+ returnData = EvmState.RentFrame(
gasLimitUl,
- callEnv,
- executionType,
- snapshot,
outputOffset.ToLong(),
outputLength.ToLong(),
+ executionType,
instruction == Instruction.STATICCALL || vmState.IsStatic,
- vmState.AccessTracker,
- isCreateOnPreExistingAccount: false);
+ isCreateOnPreExistingAccount: false,
+ snapshot: snapshot,
+ env: callEnv,
+ stateForAccessLists: vmState.AccessTracker);
return EvmExceptionType.None;
@@ -2468,16 +2468,16 @@ private EvmExceptionType InstructionSelfDestruct(EvmState vmState, ref
transferValue: value,
value: value
);
- EvmState callState = new(
+ EvmState callState = EvmState.RentFrame(
callGas,
- callEnv,
- instruction == Instruction.CREATE2 ? ExecutionType.CREATE2 : ExecutionType.CREATE,
- snapshot,
0L,
0L,
+ instruction == Instruction.CREATE2 ? ExecutionType.CREATE2 : ExecutionType.CREATE,
vmState.IsStatic,
- vmState.AccessTracker,
- accountExists);
+ accountExists,
+ snapshot,
+ callEnv,
+ vmState.AccessTracker);
return (EvmExceptionType.None, callState);
}