From 8c5f8eee099cdf676a5f60ea7eba92552d739527 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 20 Aug 2024 20:30:36 +0300 Subject: [PATCH 01/70] Moved `OverridableCodeInfoRepository` to Nethermind.Evm --- .../OverridableCodeInfoRepository.cs | 3 +-- src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) rename src/Nethermind/{Nethermind.Facade => Nethermind.Evm}/OverridableCodeInfoRepository.cs (96%) diff --git a/src/Nethermind/Nethermind.Facade/OverridableCodeInfoRepository.cs b/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs similarity index 96% rename from src/Nethermind/Nethermind.Facade/OverridableCodeInfoRepository.cs rename to src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs index dbe43ddddc7..2ffc7ac5886 100644 --- a/src/Nethermind/Nethermind.Facade/OverridableCodeInfoRepository.cs +++ b/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs @@ -6,11 +6,10 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.CodeAnalysis; using Nethermind.State; -namespace Nethermind.Facade; +namespace Nethermind.Evm; public class OverridableCodeInfoRepository(ICodeInfoRepository codeInfoRepository) : ICodeInfoRepository { diff --git a/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs b/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs index 080e6c2a81b..1039fb6c067 100644 --- a/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs +++ b/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs @@ -1,17 +1,16 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.CodeAnalysis; using Nethermind.Facade.Proxy.Models; using Nethermind.Int256; using Nethermind.State; -using Nethermind.Trie; namespace Nethermind.Facade; From 534392714dde1fb99174ef7b8682bccbdbc62294 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 20 Aug 2024 20:36:06 +0300 Subject: [PATCH 02/70] Made state commit optional during overrides --- .../Simulate/SimulateBridgeHelper.cs | 2 +- .../Nethermind.Facade/StateOverridesExtensions.cs | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs index 59c97ea3c5c..99d5de07d92 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs @@ -40,7 +40,7 @@ private void PrepareState(BlockHeader blockHeader, IReleaseSpec releaseSpec) { stateProvider.StateRoot = parent.StateRoot!; - stateProvider.ApplyStateOverrides(codeInfoRepository, blockStateCall.StateOverrides, releaseSpec, blockHeader.Number); + stateProvider.ApplyStateOverrides(codeInfoRepository, blockStateCall.StateOverrides, releaseSpec, blockHeader.Number, true); IEnumerable
senders = blockStateCall.Calls?.Select(details => details.Transaction.SenderAddress) ?? Enumerable.Empty(); IEnumerable
targets = blockStateCall.Calls?.Select(details => details.Transaction.To!) ?? Enumerable.Empty(); diff --git a/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs b/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs index 1039fb6c067..341ce770ba2 100644 --- a/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs +++ b/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs @@ -21,7 +21,8 @@ public static void ApplyStateOverrides( OverridableCodeInfoRepository overridableCodeInfoRepository, Dictionary? overrides, IReleaseSpec spec, - long blockNumber) + long blockNumber, + bool commit) { if (overrides is not null) { @@ -42,9 +43,12 @@ public static void ApplyStateOverrides( } } - state.Commit(spec); - state.CommitTree(blockNumber); - state.RecalculateStateRoot(); + if (commit) + { + state.Commit(spec); + state.CommitTree(blockNumber); + state.RecalculateStateRoot(); + } } private static void UpdateState(this IWorldState stateProvider, AccountOverride accountOverride, Address address) From d97caa464f1a4efcef4d09bd22e648c91ee6b2f4 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 20 Aug 2024 21:38:03 +0300 Subject: [PATCH 03/70] Allow state overrides for `eth_call`, `eth_estimategas` --- .../Processing/ReadOnlyTxProcessingEnv.cs | 4 +-- .../BlockchainBridgeTests.cs | 2 +- .../Nethermind.Facade/BlockchainBridge.cs | 18 ++++++++----- .../Nethermind.Facade/IBlockchainBridge.cs | 7 ++--- .../Eth/EthRpcModule.TransactionExecutor.cs | 27 ++++++++++--------- .../Modules/Eth/EthRpcModule.cs | 9 ++++--- .../Modules/Eth/ExecutorBase.cs | 9 ++++--- .../Modules/Eth/IEthRpcModule.cs | 4 +-- .../Modules/Eth/SimulateTxExecutor.cs | 11 ++++---- 9 files changed, 51 insertions(+), 40 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 183a594d6d0..1e51094b004 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -29,7 +29,7 @@ protected ITransactionProcessor TransactionProcessor public IVirtualMachine Machine { get; } - public ICodeInfoRepository CodeInfoRepository { get; } + public OverridableCodeInfoRepository CodeInfoRepository { get; } public ReadOnlyTxProcessingEnv( IWorldStateManager worldStateManager, IBlockTree blockTree, @@ -48,7 +48,7 @@ public ReadOnlyTxProcessingEnv( IWorldState? worldStateToWarmUp = null ) : base(worldStateManager, readOnlyBlockTree, specProvider, logManager, worldStateToWarmUp) { - CodeInfoRepository = new CodeInfoRepository((worldStateToWarmUp as IPreBlockCaches)?.Caches.PrecompileCache); + CodeInfoRepository = new(new CodeInfoRepository((worldStateToWarmUp as IPreBlockCaches)?.Caches.PrecompileCache)); Machine = new VirtualMachine(BlockhashProvider, specProvider, CodeInfoRepository, logManager); BlockTree = readOnlyBlockTree ?? throw new ArgumentNullException(nameof(readOnlyBlockTree)); BlockhashProvider = new BlockhashProvider(BlockTree, specProvider, StateProvider, logManager); diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 77fa79f865b..37f6dbd25a7 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -36,7 +36,7 @@ namespace Nethermind.Facade.Test { public class BlockchainBridgeTests { - private BlockchainBridge _blockchainBridge; + private IBlockchainBridge _blockchainBridge; private IBlockTree _blockTree; private ITxPool _txPool; private IReceiptStorage _receiptStorage; diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index b95f0646548..4be3fd237e1 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -26,6 +26,7 @@ using Nethermind.State; using Nethermind.Core.Extensions; using Nethermind.Config; +using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; using Transaction = Nethermind.Core.Transaction; @@ -40,7 +41,7 @@ public interface IBlockchainBridgeFactory [Todo(Improve.Refactor, "I want to remove BlockchainBridge, split it into something with logging, state and tx processing. Then we can start using independent modules.")] public class BlockchainBridge : IBlockchainBridge { - private readonly IReadOnlyTxProcessorSource _processingEnv; + private readonly ReadOnlyTxProcessingEnv _processingEnv; private readonly IBlockTree _blockTree; private readonly IStateReader _stateReader; private readonly ITxPool _txPool; @@ -147,10 +148,10 @@ private bool TryGetCanonicalTransaction( return blockHash is not null ? _receiptFinder.Get(blockHash).ForTransaction(txHash) : null; } - public CallOutput Call(BlockHeader header, Transaction tx, CancellationToken cancellationToken) + public CallOutput Call(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken cancellationToken) { CallOutputTracer callOutputTracer = new(); - TransactionResult tryCallResult = TryCallAndRestore(header, tx, false, + TransactionResult tryCallResult = TryCallAndRestore(header, tx, stateOverride, false, callOutputTracer.WithCancellation(cancellationToken)); return new CallOutput { @@ -183,7 +184,7 @@ public SimulateOutput Simulate(BlockHeader header, SimulatePayload stateOverride, CancellationToken cancellationToken) { using IReadOnlyTxProcessingScope scope = _processingEnv.Build(header.StateRoot!); @@ -191,6 +192,7 @@ public CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMargi TransactionResult tryCallResult = TryCallAndRestore( header, tx, + stateOverride, true, estimateGasTracer.WithCancellation(cancellationToken)); @@ -214,7 +216,7 @@ public CallOutput CreateAccessList(BlockHeader header, Transaction tx, Cancellat tx.GetRecipient(tx.IsContractCreation ? _stateReader.GetNonce(header.StateRoot, tx.SenderAddress) : 0), header.GasBeneficiary) : new(header.GasBeneficiary); - TransactionResult tryCallResult = TryCallAndRestore(header, tx, false, + TransactionResult tryCallResult = TryCallAndRestore(header, tx, null, false, new CompositeTxTracer(callOutputTracer, accessTxTracer).WithCancellation(cancellationToken)); return new CallOutput @@ -230,12 +232,13 @@ public CallOutput CreateAccessList(BlockHeader header, Transaction tx, Cancellat private TransactionResult TryCallAndRestore( BlockHeader blockHeader, Transaction transaction, + Dictionary? stateOverride, bool treatBlockHeaderAsParentBlock, ITxTracer tracer) { try { - return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer); + return CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer); } catch (InsufficientBalanceException ex) { @@ -246,6 +249,7 @@ private TransactionResult TryCallAndRestore( private TransactionResult CallAndRestore( BlockHeader blockHeader, Transaction transaction, + Dictionary? stateOverride, bool treatBlockHeaderAsParentBlock, ITxTracer tracer) { @@ -280,6 +284,8 @@ private TransactionResult CallAndRestore( blockHeader.ExtraData); IReleaseSpec releaseSpec = _specProvider.GetSpec(callHeader); + scope.WorldState.ApplyStateOverrides(_processingEnv.CodeInfoRepository, stateOverride, releaseSpec, blockHeader.Number, false); + callHeader.BaseFeePerGas = treatBlockHeaderAsParentBlock ? BaseFeeCalculator.Calculate(blockHeader, releaseSpec) : blockHeader.BaseFeePerGas; diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 1fd72314d77..5f210536398 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -9,11 +9,11 @@ using Nethermind.Core.Crypto; using Nethermind.Evm; using Nethermind.Facade.Filters; +using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Simulate; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.Trie; -using static Nethermind.Facade.BlockchainBridge; using Block = Nethermind.Core.Block; namespace Nethermind.Facade @@ -27,9 +27,10 @@ public interface IBlockchainBridge : ILogFinder TxReceipt GetReceipt(Hash256 txHash); (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) GetReceiptAndGasInfo(Hash256 txHash); (TxReceipt? Receipt, Transaction? Transaction, UInt256? baseFee) GetTransaction(Hash256 txHash, bool checkTxnPool = true); - CallOutput Call(BlockHeader header, Transaction tx, CancellationToken cancellationToken); + CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken cancellationToken); + CallOutput Call(BlockHeader header, Transaction tx, CancellationToken cancellationToken) => Call(header, tx, null, cancellationToken); SimulateOutput Simulate(BlockHeader header, SimulatePayload payload, CancellationToken cancellationToken); - CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMarginBasisPoints, CancellationToken cancellationToken); + CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMarginBasisPoints, Dictionary stateOverride, CancellationToken cancellationToken); CallOutput CreateAccessList(BlockHeader header, Transaction tx, CancellationToken cancellationToken, bool optimize); ulong GetChainId(); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index 6da17831925..b0300c43a8c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -12,6 +11,7 @@ using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Eth; +using Nethermind.Facade.Proxy.Models; using Nethermind.Int256; using Nethermind.JsonRpc.Data; using Nethermind.Specs.Forks; @@ -29,7 +29,7 @@ private abstract class TxExecutor(IBlockchainBridge blockchainBridge, I protected override Transaction Prepare(TransactionForRpc call) => call.ToTransaction(_blockchainBridge.GetChainId()); - protected override ResultWrapper Execute(BlockHeader header, Transaction tx, CancellationToken token) + protected override ResultWrapper Execute(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) { BlockHeader clonedHeader = header.Clone(); if (NoBaseFee) @@ -40,7 +40,7 @@ protected override ResultWrapper Execute(BlockHeader header, Transactio { return ResultWrapper.Fail("Contract creation without any data provided.", ErrorCodes.InvalidInput); } - return ExecuteTx(clonedHeader, tx, token); + return ExecuteTx(clonedHeader, tx, stateOverride, token); } private static bool ShouldSetBaseFee(TransactionForRpc t) => @@ -49,16 +49,18 @@ private static bool ShouldSetBaseFee(TransactionForRpc t) => public override ResultWrapper Execute( TransactionForRpc transactionCall, - BlockParameter? blockParameter) + BlockParameter? blockParameter, + Dictionary? stateOverride = null) { NoBaseFee = !ShouldSetBaseFee(transactionCall); transactionCall.EnsureDefaults(_rpcConfig.GasCap); - return base.Execute(transactionCall, blockParameter); + return base.Execute(transactionCall, blockParameter, stateOverride); } - public ResultWrapper ExecuteTx(TransactionForRpc transactionCall, BlockParameter? blockParameter) => Execute(transactionCall, blockParameter); + public ResultWrapper ExecuteTx(TransactionForRpc transactionCall, BlockParameter? blockParameter, Dictionary? stateOverride = null) + => Execute(transactionCall, blockParameter, stateOverride); - protected abstract ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, CancellationToken token); + protected abstract ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token); protected ResultWrapper GetInputError(CallOutput result) => ResultWrapper.Fail(result.Error, ErrorCodes.InvalidInput); @@ -67,15 +69,14 @@ protected ResultWrapper GetInputError(CallOutput result) => private class CallTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) : TxExecutor(blockchainBridge, blockFinder, rpcConfig) { - protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, CancellationToken token) + protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) { - CallOutput result = _blockchainBridge.Call(header, tx, token); + CallOutput result = _blockchainBridge.Call(header, tx, stateOverride, token); return result.Error is null ? ResultWrapper.Success(result.OutputData.ToHexString(true)) : TryGetInputError(result) ?? ResultWrapper.Fail("VM execution error.", ErrorCodes.ExecutionError, result.Error); } - } private class EstimateGasTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) @@ -83,9 +84,9 @@ private class EstimateGasTxExecutor(IBlockchainBridge blockchainBridge, IBlockFi { private readonly int _errorMargin = rpcConfig.EstimateErrorMargin; - protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, CancellationToken token) + protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken token) { - CallOutput result = _blockchainBridge.EstimateGas(header, tx, _errorMargin, token); + CallOutput result = _blockchainBridge.EstimateGas(header, tx, _errorMargin, stateOverride, token); if (result.Error is null) { @@ -101,7 +102,7 @@ private class EstimateGasTxExecutor(IBlockchainBridge blockchainBridge, IBlockFi private class CreateAccessListTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig, bool optimize) : TxExecutor(blockchainBridge, blockFinder, rpcConfig) { - protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, CancellationToken token) + protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken token) { CallOutput result = _blockchainBridge.CreateAccessList(header, tx, token, optimize); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index fab8948a40d..9a9674903e0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -20,6 +20,7 @@ using Nethermind.Facade; using Nethermind.Facade.Eth; using Nethermind.Facade.Filters; +using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.JsonRpc.Data; @@ -321,17 +322,17 @@ private async Task> SendTx(Transaction tx, } } - public ResultWrapper eth_call(TransactionForRpc transactionCall, BlockParameter? blockParameter = null) => + public ResultWrapper eth_call(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null) => new CallTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig) - .ExecuteTx(transactionCall, blockParameter); + .ExecuteTx(transactionCall, blockParameter, stateOverride); public ResultWrapper> eth_simulateV1(SimulatePayload payload, BlockParameter? blockParameter = null) => new SimulateTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig, _secondsPerSlot) .Execute(payload, blockParameter); - public ResultWrapper eth_estimateGas(TransactionForRpc transactionCall, BlockParameter? blockParameter) => + public ResultWrapper eth_estimateGas(TransactionForRpc transactionCall, BlockParameter? blockParameter, Dictionary? stateOverride = null) => new EstimateGasTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig) - .ExecuteTx(transactionCall, blockParameter); + .ExecuteTx(transactionCall, blockParameter, stateOverride); public ResultWrapper eth_createAccessList(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, bool optimize = true) => new CreateAccessListTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig, optimize) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs index 2e04d10b455..c44f007bc47 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs @@ -1,10 +1,12 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using System.Threading; using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Facade; +using Nethermind.Facade.Proxy.Models; namespace Nethermind.JsonRpc.Modules.Eth; @@ -23,7 +25,8 @@ protected ExecutorBase(IBlockchainBridge blockchainBridge, IBlockFinder blockFin public virtual ResultWrapper Execute( TRequest call, - BlockParameter? blockParameter) + BlockParameter? blockParameter, + Dictionary? stateOverride = null) { SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) return ResultWrapper.Fail(searchResult); @@ -35,12 +38,12 @@ public virtual ResultWrapper Execute( using CancellationTokenSource cancellationTokenSource = new(_rpcConfig.Timeout); TProcessing? toProcess = Prepare(call); - return Execute(header.Clone(), toProcess, cancellationTokenSource.Token); + return Execute(header.Clone(), toProcess, stateOverride, cancellationTokenSource.Token); } protected abstract TProcessing Prepare(TRequest call); - protected abstract ResultWrapper Execute(BlockHeader header, TProcessing tx, CancellationToken token); + protected abstract ResultWrapper Execute(BlockHeader header, TProcessing tx, Dictionary? stateOverride, CancellationToken token); protected ResultWrapper? TryGetInputError(CallOutput result) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 89c52debbda..576127d7df1 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -151,7 +151,7 @@ public interface IEthRpcModule : IRpcModule Description = "Executes a tx call (does not create a transaction)", IsSharable = false, ExampleResponse = "0x")] - ResultWrapper eth_call([JsonRpcParameter(ExampleValue = "[{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null); + ResultWrapper eth_call([JsonRpcParameter(ExampleValue = "[{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null); [JsonRpcMethod(IsImplemented = true, Description = "Executes a simulation across multiple blocks (does not create a transaction or block)", @@ -164,7 +164,7 @@ ResultWrapper> eth_simulateV1([JsonRpcParamet Description = "Executes a tx call and returns gas used (does not create a transaction)", IsSharable = false, ExampleResponse = "0x")] - ResultWrapper eth_estimateGas([JsonRpcParameter(ExampleValue = "[\"{\"from\": \"0x0001020304050607080910111213141516171819\", \"gasPrice\": \"1048576\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}\"]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null); + ResultWrapper eth_estimateGas([JsonRpcParameter(ExampleValue = "[\"{\"from\": \"0x0001020304050607080910111213141516171819\", \"gasPrice\": \"1048576\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}\"]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null); [JsonRpcMethod(IsImplemented = true, Description = "Creates an [EIP2930](https://eips.ethereum.org/EIPS/eip-2930) type AccessList for the given transaction", diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs index c0bf2db8e26..f7085f25464 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs @@ -3,18 +3,16 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading; using Nethermind.Blockchain.Find; using Nethermind.Config; using Nethermind.Core; -using Nethermind.Core.Collections; using Nethermind.Facade; using Nethermind.Facade.Eth; +using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; -using Nethermind.JsonRpc.Data; namespace Nethermind.JsonRpc.Modules.Eth; @@ -84,7 +82,8 @@ private static void UpdateTxType(TransactionForRpc callTransactionModel) public override ResultWrapper> Execute( SimulatePayload call, - BlockParameter? blockParameter) + BlockParameter? blockParameter, + Dictionary? stateOverride = null) { if (call.BlockStateCalls is null) return ResultWrapper>.Fail("Must contain BlockStateCalls", ErrorCodes.InvalidParams); @@ -198,11 +197,11 @@ .. call.BlockStateCalls.Select(b => (long)(b.BlockOverrides?.Number ?? ulong.Min using CancellationTokenSource cancellationTokenSource = new(_rpcConfig.Timeout); //TODO remove! SimulatePayload toProcess = Prepare(call); - return Execute(header.Clone(), toProcess, cancellationTokenSource.Token); + return Execute(header.Clone(), toProcess, stateOverride, cancellationTokenSource.Token); } protected override ResultWrapper> Execute(BlockHeader header, - SimulatePayload tx, CancellationToken token) + SimulatePayload tx, Dictionary? stateOverride, CancellationToken token) { SimulateOutput results = _blockchainBridge.Simulate(header, tx, token); From 264056f5cc5733cb0b3ef1e2ad4bab45c339957c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 22 Aug 2024 07:48:14 +0300 Subject: [PATCH 04/70] Allow state overrides for `trace_call`, `trace_callMany` --- .../BlockchainProcessorTests.cs | 8 +++---- .../AuRaBlockProcessor.cs | 6 +++-- ...sor.BlockProductionTransactionsExecutor.cs | 8 ++++--- ...sor.BlockValidationTransactionsExecutor.cs | 12 ++++++---- .../Processing/BlockProcessor.cs | 16 ++++++++----- .../Processing/BlockchainProcessor.cs | 18 +++++++------- .../Processing/IBlockProcessor.cs | 12 ++++++---- .../Processing/IBlockchainProcessor.cs | 4 +++- .../Processing/NullBlockProcessor.cs | 4 +++- .../Processing/OneTimeProcessor.cs | 7 +++--- .../TransactionProcessorAdapterExtensions.cs | 6 +++-- .../Nethermind.Consensus/Tracing/ITracer.cs | 5 +++- .../Nethermind.Consensus/Tracing/Tracer.cs | 10 +++++--- .../AccountOverride.cs | 2 +- .../StateOverridesExtensions.cs | 4 +--- .../BuildUpTransactionProcessorAdapter.cs | 6 +++-- ...llAndRestoreTransactionProcessorAdapter.cs | 7 ++++-- .../ChangeableTransactionProcessorAdapter.cs | 6 +++-- .../ExecuteTransactionProcessorAdapter.cs | 6 +++-- .../ITransactionProcessor.cs | 13 ++++++---- .../ITransactionProcessorAdapter.cs | 4 +++- .../TraceTransactionProcessorAdapter.cs | 6 +++-- .../TransactionProcessor.cs | 24 ++++++++++++------- .../Nethermind.Facade/IBlockchainBridge.cs | 1 - .../Proxy/Models/Simulate/BlockStateCall.cs | 1 + .../SimulateReadOnlyBlocksProcessingEnv.cs | 7 +++--- .../Simulate/SimulateTransactionProcessor.cs | 7 +++--- .../EthSimulateTestsBlocksAndTransactions.cs | 1 + .../EthSimulateTestsSimplePrecompiles.cs | 1 - .../TraceStoreRpcModule.cs | 11 +++++---- .../Modules/Eth/ExecutorBase.cs | 1 + .../Modules/Eth/IEthRpcModule.cs | 1 + .../Modules/Eth/SimulateTxExecutor.cs | 1 + .../Modules/Trace/ITraceRpcModule.cs | 9 +++++-- .../Modules/Trace/TraceRpcModule.cs | 23 +++++++++--------- .../AuRaMergeBlockProcessor.cs | 7 ++++-- .../EngineModuleTests.Setup.cs | 7 +++--- .../OptimismBlockProcessor.cs | 7 ++++-- .../OptimismTransactionProcessor.cs | 6 +++-- 39 files changed, 178 insertions(+), 107 deletions(-) rename src/Nethermind/{Nethermind.Facade/Proxy/Models => Nethermind.Evm}/AccountOverride.cs (94%) rename src/Nethermind/{Nethermind.Facade => Nethermind.Evm}/StateOverridesExtensions.cs (97%) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs index a5dc4884c80..a3892d6284c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs @@ -13,13 +13,10 @@ using Nethermind.Core.Attributes; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Blockchain; -using Nethermind.Specs; using Nethermind.Core.Test.Builders; -using Nethermind.Db; using Nethermind.Evm.Tracing; using Nethermind.Logging; -using Nethermind.State.Repositories; -using Nethermind.Db.Blooms; +using Nethermind.Evm; using Nethermind.State; using Nethermind.Trie; using NSubstitute; @@ -73,7 +70,8 @@ public void AllowToFail(Hash256 hash) _allowedToFail.Add(hash); } - public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, IBlockTracer blockTracer) + public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, + IBlockTracer blockTracer, Dictionary? stateOverride) { if (blockTracer != NullBlockTracer.Instance) { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 51190c3dd7e..f30baf3060f 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Find; @@ -74,12 +75,13 @@ public AuRaBlockProcessor( public IAuRaValidator AuRaValidator { get; } - protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) + protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, + Dictionary? stateOverride = null) { ValidateAuRa(block); _contractRewriter?.RewriteContracts(block.Number, _stateProvider, _specProvider.GetSpec(block.Header)); AuRaValidator.OnBlockProcessingStart(block, options); - TxReceipt[] receipts = base.ProcessBlock(block, blockTracer, options); + TxReceipt[] receipts = base.ProcessBlock(block, blockTracer, options, stateOverride); AuRaValidator.OnBlockProcessingEnd(block, receipts, options); Metrics.AuRaStep = block.Header?.AuRaStep ?? 0; return receipts; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs index bd8740c7c2f..686966000ff 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs @@ -70,7 +70,7 @@ event EventHandler? IBlockProductionTransactionsExecutor.Addi } public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, - BlockReceiptsTracer receiptsTracer, IReleaseSpec spec) + BlockReceiptsTracer receiptsTracer, IReleaseSpec spec, Dictionary? stateOverride = null) { IEnumerable transactions = GetTransactions(block); @@ -79,8 +79,9 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction currentTx in transactions) { - TxAction action = ProcessTransaction(block, in blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, in blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock, stateOverride); if (action == TxAction.Stop) break; + stateOverride = null; // Apply override only before the first transaction } _stateProvider.Commit(spec, receiptsTracer); @@ -97,6 +98,7 @@ protected TxAction ProcessTransaction( BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, LinkedHashSet transactionsInBlock, + Dictionary? stateOverride = null, bool addToBlock = true) { AddingTxEventArgs args = @@ -109,7 +111,7 @@ protected TxAction ProcessTransaction( } else { - TransactionResult result = _transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); + TransactionResult result = _transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider, stateOverride); if (result) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs index 6d2299ef920..15702284de0 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -30,7 +31,8 @@ public BlockValidationTransactionsExecutor(ITransactionProcessor transactionProc public event EventHandler? TransactionProcessed; - public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec) + public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, + IReleaseSpec spec, Dictionary? stateOverride = null) { Metrics.ResetBlockStats(); BlockExecutionContext blkCtx = CreateBlockExecutionContext(block); @@ -38,16 +40,18 @@ public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processing { block.TransactionProcessed = i; Transaction currentTx = block.Transactions[i]; - ProcessTransaction(in blkCtx, currentTx, i, receiptsTracer, processingOptions); + ProcessTransaction(in blkCtx, currentTx, i, receiptsTracer, processingOptions, stateOverride); + stateOverride = null; // Apply override only before the first transaction } return receiptsTracer.TxReceipts.ToArray(); } protected virtual BlockExecutionContext CreateBlockExecutionContext(Block block) => new(block.Header); - protected virtual void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) + protected virtual void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, + ProcessingOptions processingOptions, Dictionary? stateOverride = null) { - TransactionResult result = transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, stateProvider); + TransactionResult result = transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, stateProvider, stateOverride); if (!result) ThrowInvalidBlockException(result, blkCtx.Header, currentTx, index); TransactionProcessed?.Invoke(this, new TxProcessedEventArgs(index, currentTx, receiptsTracer.TxReceipts[index])); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index d3ea3d0fea5..b987af53082 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -89,7 +89,8 @@ public event EventHandler TransactionProcessed } // TODO: move to branch processor - public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions options, IBlockTracer blockTracer) + public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions options, IBlockTracer blockTracer, + Dictionary? stateOverride = null) { if (suggestedBlocks.Count == 0) return Array.Empty(); @@ -121,7 +122,7 @@ the previous head state.*/ Task? preWarmTask = suggestedBlock.Transactions.Length < 3 ? null : _preWarmer?.PreWarmCaches(suggestedBlock, preBlockStateRoot!, cancellationTokenSource.Token); - (Block processedBlock, TxReceipt[] receipts) = ProcessOne(suggestedBlock, options, blockTracer); + (Block processedBlock, TxReceipt[] receipts) = ProcessOne(suggestedBlock, options, blockTracer, stateOverride); cancellationTokenSource.Cancel(); preWarmTask?.GetAwaiter().GetResult(); processedBlocks[i] = processedBlock; @@ -212,13 +213,14 @@ private void RestoreBranch(Hash256 branchingPointStateRoot) } // TODO: block processor pipeline - private (Block Block, TxReceipt[] Receipts) ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer) + private (Block Block, TxReceipt[] Receipts) ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer, + Dictionary? stateOverride) { if (_logger.IsTrace) _logger.Trace($"Processing block {suggestedBlock.ToString(Block.Format.Short)} ({options})"); ApplyDaoTransition(suggestedBlock); Block block = PrepareBlockForProcessing(suggestedBlock); - TxReceipt[] receipts = ProcessBlock(block, blockTracer, options); + TxReceipt[] receipts = ProcessBlock(block, blockTracer, options, stateOverride); ValidateProcessedBlock(suggestedBlock, options, block, receipts); if (options.ContainsFlag(ProcessingOptions.StoreReceipts)) { @@ -249,7 +251,9 @@ private bool ShouldComputeStateRoot(BlockHeader header) => protected virtual TxReceipt[] ProcessBlock( Block block, IBlockTracer blockTracer, - ProcessingOptions options) + ProcessingOptions options, + Dictionary? stateOverride = null + ) { IReleaseSpec spec = _specProvider.GetSpec(block.Header); @@ -261,7 +265,7 @@ protected virtual TxReceipt[] ProcessBlock( _stateProvider.Commit(spec, commitStorageRoots: false); - TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, ReceiptsTracer, spec); + TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, ReceiptsTracer, spec, stateOverride); if (spec.IsEip4844Enabled) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index c3cfb0b7234..bf467274aac 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -10,11 +10,11 @@ using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; -using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Attributes; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.ParityStyle; @@ -313,7 +313,7 @@ private void RunProcessingLoop() if (_logger.IsTrace) _logger.Trace($"Processing block {block.ToString(Block.Format.Short)})."); _stats.Start(); - Block processedBlock = Process(block, blockRef.ProcessingOptions, _compositeBlockTracer.GetTracer(), out string? error); + Block processedBlock = Process(block, blockRef.ProcessingOptions, _compositeBlockTracer.GetTracer(), null, out string? error); if (processedBlock is null) { @@ -356,11 +356,12 @@ private void FireProcessingQueueEmpty() int IBlockProcessingQueue.Count => _queueCount; - public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer) + public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride = null) { - return Process(suggestedBlock, options, tracer, out _); + return Process(suggestedBlock, options, tracer, stateOverride, out _); } - public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, out string? error) + + public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride, out string? error) { error = null; if (!RunSimpleChecksAheadOfProcessing(suggestedBlock, options)) @@ -388,7 +389,7 @@ private void FireProcessingQueueEmpty() PrepareBlocksToProcess(suggestedBlock, options, processingBranch); _stopwatch.Restart(); - Block[]? processedBlocks = ProcessBranch(processingBranch, options, tracer, out error); + Block[]? processedBlocks = ProcessBranch(processingBranch, options, tracer, stateOverride, out error); if (processedBlocks is null) { return null; @@ -475,7 +476,7 @@ private void TraceFailingBranch(in ProcessingBranch processingBranch, Processing } } - private Block[]? ProcessBranch(in ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer tracer, out string? error) + private Block[]? ProcessBranch(in ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride, out string? error) { void DeleteInvalidBlocks(in ProcessingBranch processingBranch, Hash256 invalidBlockHash) { @@ -499,7 +500,8 @@ void DeleteInvalidBlocks(in ProcessingBranch processingBranch, Hash256 invalidBl processingBranch.Root, processingBranch.BlocksToProcess, options, - tracer); + tracer, + stateOverride); error = null; } catch (InvalidBlockException ex) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs index 88aba737926..b6e20072016 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs @@ -6,6 +6,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; namespace Nethermind.Consensus.Processing @@ -19,12 +20,13 @@ public interface IBlockProcessor /// List of blocks to be processed. /// Options to use for processor and transaction processor. /// Block tracer to use. By default either or + /// Optional state overrides by address. /// List of processed blocks. - Block[] Process( - Hash256 newBranchStateRoot, + Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, - IBlockTracer blockTracer); + IBlockTracer blockTracer, + Dictionary? stateOverride = null); /// /// Fired when a branch is being processed. @@ -43,7 +45,9 @@ Block[] Process( public interface IBlockTransactionsExecutor { - TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec); + TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec, + Dictionary? stateOverride = null); + event EventHandler TransactionProcessed; } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs index b3703b653f8..e64d8b89d76 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Core; +using Nethermind.Evm; using Nethermind.Evm.Tracing; namespace Nethermind.Consensus.Processing @@ -16,7 +18,7 @@ public interface IBlockchainProcessor : IDisposable Task StopAsync(bool processRemainingBlocks = false); - Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer); + Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride = null); bool IsProcessingBlocks(ulong? maxProcessingInterval); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs index ad47599ff84..3ee5ced90d5 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; namespace Nethermind.Consensus.Processing @@ -15,7 +16,8 @@ private NullBlockProcessor() { } public static IBlockProcessor Instance { get; } = new NullBlockProcessor(); - public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, IBlockTracer blockTracer) + public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, IBlockTracer blockTracer, + Dictionary? stateOverride) { return suggestedBlocks.ToArray(); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs index cdeb4ab6712..bbc58de06e0 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs @@ -2,9 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.State; @@ -35,11 +36,11 @@ public Task StopAsync(bool processRemainingBlocks = false) return _processor.StopAsync(processRemainingBlocks); } - public Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer) + public Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer, Dictionary stateOverride) { lock (_lock) { - return _processor.Process(block, options, tracer); + return _processor.Process(block, options, tracer, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs index bd569caf479..7824be762f0 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm; using Nethermind.Evm.Tracing; @@ -16,7 +17,8 @@ public static TransactionResult ProcessTransaction(this ITransactionProcessorAda Transaction currentTx, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, - IWorldState stateProvider) + IWorldState stateProvider, + Dictionary? stateOverride) { if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce)) { @@ -24,7 +26,7 @@ public static TransactionResult ProcessTransaction(this ITransactionProcessorAda } using ITxTracer tracer = receiptsTracer.StartNewTxTrace(currentTx); - TransactionResult result = transactionProcessor.Execute(currentTx, in blkCtx, receiptsTracer); + TransactionResult result = transactionProcessor.Execute(currentTx, in blkCtx, receiptsTracer, stateOverride); receiptsTracer.EndTxTrace(); return result; } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs index 6306dcd1e8a..7d241f0e8fb 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs @@ -1,8 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Trie; @@ -18,7 +20,8 @@ public interface ITracer /// /// Block to trace. /// Trace to act on block processing events. - void Trace(Block block, IBlockTracer tracer); + /// Optional state overrides by address. + void Trace(Block block, IBlockTracer tracer, Dictionary? stateOverride = null); /// /// Allows to trace and verify arbitrary constructed block. Subtracts gas from sender account diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs index 00c2a85147d..f7c456f2835 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs @@ -2,9 +2,11 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.State; using Nethermind.Trie; @@ -27,7 +29,8 @@ public Tracer(IWorldState stateProvider, IBlockchainProcessor traceProcessor, IB _processingOptions = processingOptions; } - private void Process(Block block, IBlockTracer blockTracer, IBlockchainProcessor processor) + private void Process(Block block, IBlockTracer blockTracer, IBlockchainProcessor processor, + Dictionary? stateOverride = null) { /* We force process since we want to process a block that has already been processed in the past and normally it would be ignored. We also want to make it read only so the state is not modified persistently in any way. */ @@ -36,7 +39,7 @@ We also want to make it read only so the state is not modified persistently in a try { - processor.Process(block, _processingOptions, blockTracer); + processor.Process(block, _processingOptions, blockTracer, stateOverride); } catch (Exception) { @@ -47,7 +50,8 @@ We also want to make it read only so the state is not modified persistently in a blockTracer.EndBlockTrace(); } - public void Trace(Block block, IBlockTracer tracer) => Process(block, tracer, _traceProcessor); + public void Trace(Block block, IBlockTracer tracer, Dictionary? stateOverride = null) => + Process(block, tracer, _traceProcessor, stateOverride); public void Execute(Block block, IBlockTracer tracer) => Process(block, tracer, _executeProcessor); diff --git a/src/Nethermind/Nethermind.Facade/Proxy/Models/AccountOverride.cs b/src/Nethermind/Nethermind.Evm/AccountOverride.cs similarity index 94% rename from src/Nethermind/Nethermind.Facade/Proxy/Models/AccountOverride.cs rename to src/Nethermind/Nethermind.Evm/AccountOverride.cs index 5b8a26ab431..91fe22d9f40 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/Models/AccountOverride.cs +++ b/src/Nethermind/Nethermind.Evm/AccountOverride.cs @@ -6,7 +6,7 @@ using Nethermind.Core.Crypto; using Nethermind.Int256; -namespace Nethermind.Facade.Proxy.Models; +namespace Nethermind.Evm; public class AccountOverride { diff --git a/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs similarity index 97% rename from src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs rename to src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs index 341ce770ba2..768703bc48a 100644 --- a/src/Nethermind/Nethermind.Facade/StateOverridesExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs @@ -6,13 +6,11 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.CodeAnalysis; -using Nethermind.Facade.Proxy.Models; using Nethermind.Int256; using Nethermind.State; -namespace Nethermind.Facade; +namespace Nethermind.Evm; public static class StateOverridesExtensions { diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs index 2ac0a3b8fcb..6da856768ca 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -8,7 +9,8 @@ namespace Nethermind.Evm.TransactionProcessing { public class BuildUpTransactionProcessorAdapter(ITransactionProcessor transactionProcessor) : ITransactionProcessorAdapter { - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => - transactionProcessor.BuildUp(transaction, in blkCtx, txTracer); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) => + transactionProcessor.BuildUp(transaction, in blkCtx, txTracer, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs index 31232e3b7c6..8d713c50b1d 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only // + +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -15,7 +17,8 @@ public CallAndRestoreTransactionProcessorAdapter(ITransactionProcessor transacti _transactionProcessor = transactionProcessor; } - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, in blkCtx, txTracer); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) => + _transactionProcessor.CallAndRestore(transaction, in blkCtx, txTracer, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs index 38d9ccf67c9..7c15af74e83 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -22,7 +23,8 @@ public ChangeableTransactionProcessorAdapter(ITransactionProcessor transactionPr TransactionProcessor = transactionProcessor; } - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => - CurrentAdapter.Execute(transaction, in blkCtx, txTracer); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) => + CurrentAdapter.Execute(transaction, in blkCtx, txTracer, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs index 729db62505e..7b3c85eb04f 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -15,7 +16,8 @@ public ExecuteTransactionProcessorAdapter(ITransactionProcessor transactionProce _transactionProcessor = transactionProcessor; } - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, in blkCtx, txTracer); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) => + _transactionProcessor.Execute(transaction, in blkCtx, txTracer, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs index 96ac8e27948..b04688cd6a5 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -11,21 +12,25 @@ public interface ITransactionProcessor /// /// Execute transaction, commit state /// - TransactionResult Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); + TransactionResult Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, + Dictionary? stateOverride = null); /// /// Call transaction, rollback state /// - TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); + TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, + Dictionary? stateOverride = null); /// /// Execute transaction, keep the state uncommitted /// - TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); + TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, + Dictionary? stateOverride = null); /// /// Call transaction, no validations, commit state /// Will NOT charge gas from sender account, so stateDiff will miss gas fee /// - TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); + TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, + Dictionary? stateOverride = null); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs index ba77066d81a..2802929b690 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -8,6 +9,7 @@ namespace Nethermind.Evm.TransactionProcessing { public interface ITransactionProcessorAdapter { - TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer); + TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, + Dictionary? stateOverride = null); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs index f272308db25..beb6c95a4a4 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; @@ -15,7 +16,8 @@ public TraceTransactionProcessorAdapter(ITransactionProcessor transactionProcess _transactionProcessor = transactionProcessor; } - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, in blkCtx, txTracer); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) => + _transactionProcessor.Trace(transaction, in blkCtx, txTracer, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index f01be3bfdeb..d3882580bcc 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -84,24 +85,26 @@ public TransactionProcessor( Ecdsa = new EthereumEcdsa(specProvider.ChainId); } - public TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => - Execute(transaction, in blCtx, txTracer, ExecutionOptions.CommitAndRestore); + public TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) => + Execute(transaction, in blCtx, txTracer, stateOverride, ExecutionOptions.CommitAndRestore); - public TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) + public TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, + Dictionary? stateOverride = null) { // we need to treat the result of previous transaction as the original value of next transaction // when we do not commit WorldState.TakeSnapshot(true); - return Execute(transaction, in blCtx, txTracer, ExecutionOptions.None); + return Execute(transaction, in blCtx, txTracer, stateOverride, ExecutionOptions.None); } - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => - Execute(transaction, in blCtx, txTracer, ExecutionOptions.Commit); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, Dictionary? stateOverride = null) => + Execute(transaction, in blCtx, txTracer, stateOverride, ExecutionOptions.Commit); - public TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => - Execute(transaction, in blCtx, txTracer, ExecutionOptions.NoValidation); + public TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, Dictionary? stateOverride = null) => + Execute(transaction, in blCtx, txTracer, stateOverride, ExecutionOptions.NoValidation); - protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) + protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, Dictionary? stateOverride, ExecutionOptions opts) { BlockHeader header = blCtx.Header; IReleaseSpec spec = SpecProvider.GetSpec(header); @@ -124,6 +127,9 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon bool deleteCallerAccount = RecoverSenderIfNeeded(tx, spec, opts, effectiveGasPrice); + if (_codeInfoRepository is OverridableCodeInfoRepository overridableCodeInfoRepository) + WorldState.ApplyStateOverrides(overridableCodeInfoRepository, stateOverride, spec, blCtx.Header.Number, false); + if (!(result = ValidateSender(tx, header, spec, tracer, opts))) return result; if (!(result = BuyGas(tx, header, spec, tracer, opts, effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment))) return result; if (!(result = IncrementNonce(tx, header, spec, tracer, opts))) return result; diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 5f210536398..745ec8a3afb 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -9,7 +9,6 @@ using Nethermind.Core.Crypto; using Nethermind.Evm; using Nethermind.Facade.Filters; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Simulate; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/BlockStateCall.cs b/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/BlockStateCall.cs index db4efb549ba..3900900bd7c 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/BlockStateCall.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/BlockStateCall.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Nethermind.Core; +using Nethermind.Evm; namespace Nethermind.Facade.Proxy.Models.Simulate; diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs index 3f70c14789f..1676046bcb3 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; @@ -9,7 +10,6 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Evm; @@ -32,14 +32,15 @@ public class SimulateBlockValidationTransactionsExecutor( protected override BlockExecutionContext CreateBlockExecutionContext(Block block) => blobBaseFeeOverride is not null ? new BlockExecutionContext(block.Header, blobBaseFeeOverride.Value) : base.CreateBlockExecutionContext(block); - protected override void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) + protected override void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, + ProcessingOptions processingOptions, Dictionary? stateOverride = null) { if (!validate) { processingOptions |= ProcessingOptions.ForceProcessing | ProcessingOptions.DoNotVerifyNonce | ProcessingOptions.NoValidation; } - base.ProcessTransaction(in blkCtx, currentTx, index, receiptsTracer, processingOptions); + base.ProcessTransaction(in blkCtx, currentTx, index, receiptsTracer, processingOptions, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs index 9b6ebb52192..343a8de7121 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs @@ -1,12 +1,12 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; -using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; @@ -23,13 +23,14 @@ public class SimulateTransactionProcessor( { protected override bool ShouldValidate(ExecutionOptions opts) => true; - protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) + protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, + Dictionary? stateOverride, ExecutionOptions opts) { if (!validate) { opts |= ExecutionOptions.NoValidation; } - return base.Execute(tx, in blCtx, tracer, opts); + return base.Execute(tx, in blCtx, tracer, stateOverride, opts); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs index 28a28e68803..925d96d70a9 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs @@ -12,6 +12,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Facade.Eth; using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs index b362a5439fd..020049685cd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs @@ -11,7 +11,6 @@ using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Evm.Precompiles; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs index d9267e28112..bb1bd62c44b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs @@ -6,6 +6,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Facade.Eth; using Nethermind.JsonRpc.Data; @@ -52,11 +53,13 @@ public TraceStoreRpcModule(ITraceRpcModule traceModule, _logger = logManager.GetClassLogger(); } - public ResultWrapper trace_call(TransactionForRpc call, string[] traceTypes, BlockParameter? blockParameter = null) => - _traceModule.trace_call(call, traceTypes, blockParameter); + public ResultWrapper trace_call(TransactionForRpc call, string[] traceTypes, BlockParameter? blockParameter = null, + Dictionary? stateOverride = null) => + _traceModule.trace_call(call, traceTypes, blockParameter, stateOverride); - public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null) => - _traceModule.trace_callMany(calls, blockParameter); + public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null, + Dictionary? stateOverride = null) => + _traceModule.trace_callMany(calls, blockParameter, stateOverride); public ResultWrapper trace_rawTransaction(byte[] data, string[] traceTypes) => _traceModule.trace_rawTransaction(data, traceTypes); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs index c44f007bc47..145381f0c17 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs @@ -5,6 +5,7 @@ using System.Threading; using Nethermind.Blockchain.Find; using Nethermind.Core; +using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Proxy.Models; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 576127d7df1..6ce04ce0cb5 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -6,6 +6,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Facade.Eth; using Nethermind.Facade.Filters; using Nethermind.Facade.Proxy.Models.Simulate; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs index f7085f25464..991626de4c3 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs @@ -8,6 +8,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Config; using Nethermind.Core; +using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Eth; using Nethermind.Facade.Proxy.Models; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs index dae0f773487..1c36f911116 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using Nethermind.Blockchain.Find; +using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Facade.Eth; using Nethermind.JsonRpc.Data; @@ -13,10 +15,13 @@ namespace Nethermind.JsonRpc.Modules.Trace public interface ITraceRpcModule : IRpcModule { [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] - ResultWrapper trace_call(TransactionForRpc call, [JsonRpcParameter(Description = "Possible values : [\"VmTrace\", \"StateDiff\", \"Trace\", \"Rewards\", \"All\"]")] string[] traceTypes, BlockParameter? blockParameter = null); + ResultWrapper trace_call(TransactionForRpc call, + [JsonRpcParameter(Description = "Possible values : [\"VmTrace\", \"StateDiff\", \"Trace\", \"Rewards\", \"All\"]")] string[] traceTypes, + BlockParameter? blockParameter = null, Dictionary? stateOverride = null); [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null); + ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, + BlockParameter? blockParameter = null, Dictionary? stateOverride = null); [JsonRpcMethod(Description = "Traces a call to eth_sendRawTransaction without making the call, returning the traces", IsImplemented = true, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 3ee10c8bcb3..7c07ea17cd2 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -11,17 +11,14 @@ using Nethermind.Consensus.Tracing; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; -using Nethermind.Facade; using Nethermind.Facade.Eth; using Nethermind.Int256; using Nethermind.JsonRpc.Data; -using Nethermind.Logging; using Nethermind.Serialization.Rlp; using Nethermind.State; -using Nethermind.Trie; namespace Nethermind.JsonRpc.Modules.Trace { @@ -59,20 +56,20 @@ public static ParityTraceTypes GetParityTypes(string[] types) => /// /// Traces one transaction. Doesn't charge fees. /// - public ResultWrapper trace_call(TransactionForRpc call, string[] traceTypes, BlockParameter? blockParameter = null) + public ResultWrapper trace_call(TransactionForRpc call, string[] traceTypes, BlockParameter? blockParameter = null, Dictionary? stateOverride = null) { blockParameter ??= BlockParameter.Latest; call.EnsureDefaults(_jsonRpcConfig.GasCap); Transaction tx = call.ToTransaction(); - return TraceTx(tx, traceTypes, blockParameter); + return TraceTx(tx, traceTypes, blockParameter, stateOverride); } /// /// Traces list of transactions. Doesn't charge fees. /// - public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null) + public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null, Dictionary? stateOverride = null) { blockParameter ??= BlockParameter.Latest; @@ -100,7 +97,7 @@ public ResultWrapper> trace_callMany(Transa } Block block = new(headerSearch.Object!, txs, Enumerable.Empty()); - IReadOnlyCollection? traces = TraceBlock(block, new ParityLikeBlockTracer(traceTypeByTransaction)); + IReadOnlyCollection? traces = TraceBlock(block, new(traceTypeByTransaction), stateOverride); return ResultWrapper>.Success(traces.Select(t => new ParityTxTraceFromReplay(t))); } @@ -144,7 +141,8 @@ private SearchResult SearchBlockHeaderForTraceCall(BlockParameter b return new SearchResult(header); } - private ResultWrapper TraceTx(Transaction tx, string[] traceTypes, BlockParameter blockParameter) + private ResultWrapper TraceTx(Transaction tx, string[] traceTypes, BlockParameter blockParameter, + Dictionary? stateOverride = null) { SearchResult headerSearch = SearchBlockHeaderForTraceCall(blockParameter); if (headerSearch.IsError) @@ -155,7 +153,7 @@ private ResultWrapper TraceTx(Transaction tx, string[] Block block = new(headerSearch.Object!, new[] { tx }, Enumerable.Empty()); ParityTraceTypes traceTypes1 = GetParityTypes(traceTypes); - IReadOnlyCollection result = TraceBlock(block, new(traceTypes1)); + IReadOnlyCollection result = TraceBlock(block, new(traceTypes1), stateOverride); return ResultWrapper.Success(new ParityTxTraceFromReplay(result.SingleOrDefault())); } @@ -318,11 +316,12 @@ public ResultWrapper> trace_transaction(Hash return ResultWrapper>.Success(ParityTxTraceFromStore.FromTxTrace(txTrace)); } - private IReadOnlyCollection TraceBlock(Block block, ParityLikeBlockTracer tracer) + private IReadOnlyCollection TraceBlock(Block block, ParityLikeBlockTracer tracer, + Dictionary? stateOverride = null) { using CancellationTokenSource cancellationTokenSource = new(_cancellationTokenTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; - _tracer.Trace(block, tracer.WithCancellation(cancellationToken)); + _tracer.Trace(block, tracer.WithCancellation(cancellationToken), stateOverride); return tracer.BuildResult(); } diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs index 1a55b725abd..13c27b4d656 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.AuRa; @@ -12,6 +13,7 @@ using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.State; @@ -53,8 +55,9 @@ public AuRaMergeBlockProcessor( ) { } - protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) => + protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, + Dictionary? stateOverride = null) => block.IsPostMerge ? PostMergeProcessBlock(block, blockTracer, options) - : base.ProcessBlock(block, blockTracer, options); + : base.ProcessBlock(block, blockTracer, options, stateOverride); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index c499adefe37..2f80b6996c8 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Nethermind.Api; using Nethermind.Blockchain; using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Synchronization; @@ -24,6 +23,7 @@ using Nethermind.Core.Timers; using Nethermind.Crypto; using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Facade.Eth; using Nethermind.HealthChecks; @@ -36,7 +36,6 @@ using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; -using Nethermind.State; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; using NSubstitute; @@ -284,7 +283,7 @@ public TestBlockProcessorInterceptor(IBlockProcessor baseBlockProcessor, int del } public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, - IBlockTracer blockTracer) + IBlockTracer blockTracer, Dictionary? stateOverride) { if (DelayMs > 0) { @@ -296,7 +295,7 @@ public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, throw ExceptionToThrow; } - return _blockProcessorImplementation.Process(newBranchStateRoot, suggestedBlocks, processingOptions, blockTracer); + return _blockProcessorImplementation.Process(newBranchStateRoot, suggestedBlocks, processingOptions, blockTracer, stateOverride); } public event EventHandler? BlocksProcessing diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs index 385e7217e3c..8ab34eff0c7 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Processing; @@ -10,6 +11,7 @@ using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.State; @@ -42,9 +44,10 @@ public OptimismBlockProcessor( ReceiptsTracer = new OptimismBlockReceiptTracer(opSpecHelper, stateProvider); } - protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) + protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, + Dictionary? stateOverride = null) { _contractRewriter?.RewriteContract(block.Header, _stateProvider); - return base.ProcessBlock(block, blockTracer, options); + return base.ProcessBlock(block, blockTracer, options, stateOverride); } } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs index aa71d1fae45..c1593cb666d 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm; @@ -25,7 +26,8 @@ public class OptimismTransactionProcessor( { private UInt256? _currentTxL1Cost; - protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) + protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, + Dictionary? stateOverride, ExecutionOptions opts) { if (tx.SupportsBlobs) { @@ -42,7 +44,7 @@ protected override TransactionResult Execute(Transaction tx, in BlockExecutionCo Snapshot snapshot = WorldState.TakeSnapshot(); - TransactionResult result = base.Execute(tx, blCtx, tracer, opts); + TransactionResult result = base.Execute(tx, blCtx, tracer, stateOverride, opts); if (!result && tx.IsDeposit() && result.Error != "block gas limit exceeded") { From 3c19b09f3245608dc9357b910954ca5202793463 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 22 Aug 2024 08:22:54 +0300 Subject: [PATCH 05/70] Simplify `eth_*` overriding code --- src/Nethermind/Nethermind.Facade/BlockchainBridge.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 4be3fd237e1..8f0a9a4edbe 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -284,7 +284,6 @@ private TransactionResult CallAndRestore( blockHeader.ExtraData); IReleaseSpec releaseSpec = _specProvider.GetSpec(callHeader); - scope.WorldState.ApplyStateOverrides(_processingEnv.CodeInfoRepository, stateOverride, releaseSpec, blockHeader.Number, false); callHeader.BaseFeePerGas = treatBlockHeaderAsParentBlock ? BaseFeeCalculator.Calculate(blockHeader, releaseSpec) @@ -300,7 +299,7 @@ private TransactionResult CallAndRestore( callHeader.MixHash = blockHeader.MixHash; callHeader.IsPostMerge = blockHeader.Difficulty == 0; transaction.Hash = transaction.CalculateHash(); - return scope.TransactionProcessor.CallAndRestore(transaction, new(callHeader), tracer); + return scope.TransactionProcessor.CallAndRestore(transaction, new(callHeader), tracer, stateOverride); } public ulong GetChainId() From aeaf7f0ecae941402d4eb8e56099624709c0d7d2 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Fri, 23 Aug 2024 13:04:00 +0300 Subject: [PATCH 06/70] Fix double serialization in RPC tests --- .../Modules/TestRpcBlockchain.cs | 4 ++-- .../Nethermind.JsonRpc.Test/RpcTest.cs | 22 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index ea070b4502f..6beef8cab58 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -174,10 +174,10 @@ protected override async Task Build( return this; } - public Task TestEthRpc(string method, params string[] parameters) => + public Task TestEthRpc(string method, params object[] parameters) => RpcTest.TestSerializedRequest(EthRpcModule, method, parameters); - public Task TestSerializedRequest(T module, string method, params string[] parameters) where T : class, IRpcModule => + public Task TestSerializedRequest(T module, string method, params object[] parameters) where T : class, IRpcModule => RpcTest.TestSerializedRequest(module, method, parameters); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs b/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs index 4bc26918014..999a9abadd8 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs @@ -6,28 +6,24 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; - using FluentAssertions; - using Nethermind.JsonRpc.Modules; using Nethermind.JsonRpc.Test.Modules; using Nethermind.Logging; using Nethermind.Serialization.Json; -using NUnit.Framework; - namespace Nethermind.JsonRpc.Test; public static class RpcTest { - public static async Task TestRequest(T module, string method, params string[] parameters) where T : class, IRpcModule + public static async Task TestRequest(T module, string method, params object?[] parameters) where T : class, IRpcModule { IJsonRpcService service = BuildRpcService(module); JsonRpcRequest request = GetJsonRequest(method, parameters); return await service.SendRequestAsync(request, new JsonRpcContext(RpcEndpoint.Http)); } - public static async Task TestSerializedRequest(T module, string method, params string[] parameters) where T : class, IRpcModule + public static async Task TestSerializedRequest(T module, string method, params object?[] parameters) where T : class, IRpcModule { IJsonRpcService service = BuildRpcService(module); JsonRpcRequest request = GetJsonRequest(method, parameters); @@ -63,9 +59,19 @@ private static IJsonRpcService BuildRpcService(T module) where T : class, IRp return service; } - public static JsonRpcRequest GetJsonRequest(string method, params string[]? parameters) + // Parameters from tests are provided as either already serialized object, raw string, or raw object. + // We need to handle all these cases, while preventing double serialization. + private static string GetSerializedParameter(object? parameter) + { + if (parameter is string serialized and (['[', ..] or ['{', ..] or ['"', ..])) + return serialized; // Already serialized + + return JsonSerializer.Serialize(parameter, EthereumJsonSerializer.JsonOptions); + } + + public static JsonRpcRequest GetJsonRequest(string method, params object?[]? parameters) { - var doc = JsonDocument.Parse(JsonSerializer.Serialize(parameters?.ToArray())); + var doc = JsonDocument.Parse($"[{string.Join(",", parameters?.Select(GetSerializedParameter) ?? [])}]"); var request = new JsonRpcRequest() { JsonRpc = "2.0", From c8fa00624b18ef1890eaba2da1e7685fe2f8f433 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Fri, 23 Aug 2024 13:05:14 +0300 Subject: [PATCH 07/70] Code cleanup --- .../Modules/Eth/EthRpcModule.TransactionExecutor.cs | 2 +- src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index b0300c43a8c..39c67d1102a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -29,7 +29,7 @@ private abstract class TxExecutor(IBlockchainBridge blockchainBridge, I protected override Transaction Prepare(TransactionForRpc call) => call.ToTransaction(_blockchainBridge.GetChainId()); - protected override ResultWrapper Execute(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) + protected override ResultWrapper Execute(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) { BlockHeader clonedHeader = header.Clone(); if (NoBaseFee) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 6ce04ce0cb5..73d731f308e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -152,7 +152,7 @@ public interface IEthRpcModule : IRpcModule Description = "Executes a tx call (does not create a transaction)", IsSharable = false, ExampleResponse = "0x")] - ResultWrapper eth_call([JsonRpcParameter(ExampleValue = "[{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null); + ResultWrapper eth_call([JsonRpcParameter(ExampleValue = "[{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null); [JsonRpcMethod(IsImplemented = true, Description = "Executes a simulation across multiple blocks (does not create a transaction or block)", From 9a7094d2ebf67ac8b282d52471ccee947d13aae8 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 26 Aug 2024 08:40:55 +0300 Subject: [PATCH 08/70] Allow state overrides for `debug_traceCall` --- .../Nethermind.Consensus/Tracing/GethStyleTracer.cs | 11 +++++++---- .../Nethermind.Consensus/Tracing/IGethStyleTracer.cs | 3 ++- .../Modules/DebugModule/DebugBridge.cs | 6 ++++-- .../Modules/DebugModule/DebugRpcModule.cs | 6 ++++-- .../Modules/DebugModule/IDebugBridge.cs | 3 ++- .../Modules/DebugModule/IDebugRpcModule.cs | 4 +++- 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 3e240bef779..8f3e3378131 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -16,6 +16,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.GethStyle.Custom.JavaScript; @@ -71,7 +72,8 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op return TraceBlock(GetBlockToTrace(block), options with { TxHash = txHash }, cancellationToken).FirstOrDefault(); } - public GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) + public GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, + Dictionary stateOverride, CancellationToken cancellationToken) { Block block = _blockTree.FindBlock(blockParameter); if (block is null) throw new InvalidOperationException($"Cannot find block {blockParameter}"); @@ -82,7 +84,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op try { - return Trace(block, tx.Hash, cancellationToken, options); + return Trace(block, tx.Hash, cancellationToken, options, stateOverride); } finally { @@ -189,7 +191,8 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio return tracer.FileNames; } - private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options) + private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options, + Dictionary? stateOverride = null) { ArgumentNullException.ThrowIfNull(txHash); @@ -197,7 +200,7 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio try { - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken)); + _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken), stateOverride); return tracer.BuildResult().SingleOrDefault(); } catch diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs index 4651add653e..a274351e6d5 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs @@ -6,6 +6,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; @@ -18,7 +19,7 @@ public interface IGethStyleTracer GethLikeTxTrace Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); GethLikeTxTrace Trace(Rlp blockRlp, Hash256 txHash, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, Dictionary? stateOverride, CancellationToken cancellationToken); IReadOnlyCollection TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken); IReadOnlyCollection TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken); IEnumerable TraceBlockToFile(Hash256 blockHash, GethTraceOptions options, CancellationToken cancellationToken); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs index dd7d34ebc82..8936004d1d5 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs @@ -16,6 +16,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; using Nethermind.State.Proofs; @@ -151,8 +152,9 @@ public GethLikeTxTrace GetTransactionTrace(Hash256 blockHash, int index, Cancell public GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => _tracer.Trace(blockRlp, transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => - _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, + GethTraceOptions? gethTraceOptions = null, Dictionary? stateOverride = null) => + _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, stateOverride, cancellationToken); public IReadOnlyCollection GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => _tracer.TraceBlock(blockParameter, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs index 9c0b2919d32..b195e2e3acb 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Facade.Eth; namespace Nethermind.JsonRpc.Modules.DebugModule; @@ -68,7 +69,8 @@ public ResultWrapper debug_traceTransaction(Hash256 transaction return ResultWrapper.Success(transactionTrace); } - public ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null) + public ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, + GethTraceOptions? options = null, Dictionary? stateOverride = null) { blockParameter ??= BlockParameter.Latest; call.EnsureDefaults(_jsonRpcConfig.GasCap); @@ -76,7 +78,7 @@ public ResultWrapper debug_traceCall(TransactionForRpc call, Bl using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; - GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(tx, blockParameter, cancellationToken, options); + GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(tx, blockParameter, cancellationToken, options, stateOverride); if (transactionTrace is null) { return ResultWrapper.Fail($"Cannot find transactionTrace for hash: {tx.Hash}", ErrorCodes.ResourceNotFound); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs index 9b8db38d2cf..84f09ecd68e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs @@ -7,6 +7,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; using Nethermind.Synchronization.Reporting; @@ -19,7 +20,7 @@ public interface IDebugBridge GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); GethLikeTxTrace GetTransactionTrace(Hash256 blockHash, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null, Dictionary? stateOverride = null); IReadOnlyCollection GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null); IReadOnlyCollection GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); byte[] GetBlockRlp(BlockParameter param); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index dc0a8bd9014..83c48a63936 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -4,7 +4,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Blockchain.Find; +using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Facade.Eth; using Nethermind.JsonRpc.Data; @@ -31,7 +33,7 @@ public interface IDebugRpcModule : IRpcModule ResultWrapper debug_traceTransaction(Hash256 transactionHash, GethTraceOptions options = null); [JsonRpcMethod(Description = "This method lets you run an eth_call within the context of the given block execution using the final state of parent block as the base. The block can be specified either by hash or by number. It takes the same input object as a eth_call. It returns the same output as debug_traceTransaction.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null); + ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null, Dictionary? stateOverride = null); [JsonRpcMethod(Description = "", IsSharable = true)] ResultWrapper debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int txIndex, GethTraceOptions options = null); From 94c26187ea6a0e2f748d8f89a43a0fc6c2fd95a4 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sun, 1 Sep 2024 03:53:36 +0300 Subject: [PATCH 09/70] Update supported methods to match Reth version --- .../Nethermind.Consensus/Tracing/GethStyleTracer.cs | 10 ++++------ .../Nethermind.Consensus/Tracing/IGethStyleTracer.cs | 2 +- .../Tracing/GethStyle/GethTraceOptions.cs | 6 +++++- .../TraceStoreRpcModule.cs | 5 ++--- .../Modules/DebugModule/DebugBridge.cs | 5 ++--- .../Modules/DebugModule/DebugRpcModule.cs | 6 ++---- .../Modules/DebugModule/IDebugBridge.cs | 2 +- .../Modules/DebugModule/IDebugRpcModule.cs | 2 +- .../Modules/Trace/ITraceRpcModule.cs | 3 +-- .../Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs | 4 ++-- 10 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 8f3e3378131..3516ca61e0c 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -72,8 +72,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op return TraceBlock(GetBlockToTrace(block), options with { TxHash = txHash }, cancellationToken).FirstOrDefault(); } - public GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, - Dictionary stateOverride, CancellationToken cancellationToken) + public GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) { Block block = _blockTree.FindBlock(blockParameter); if (block is null) throw new InvalidOperationException($"Cannot find block {blockParameter}"); @@ -84,7 +83,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op try { - return Trace(block, tx.Hash, cancellationToken, options, stateOverride); + return Trace(block, tx.Hash, cancellationToken, options); } finally { @@ -191,8 +190,7 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio return tracer.FileNames; } - private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options, - Dictionary? stateOverride = null) + private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options) { ArgumentNullException.ThrowIfNull(txHash); @@ -200,7 +198,7 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio try { - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken), stateOverride); + _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken), options.StateOverrides); return tracer.BuildResult().SingleOrDefault(); } catch diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs index a274351e6d5..1fa6d718044 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs @@ -19,7 +19,7 @@ public interface IGethStyleTracer GethLikeTxTrace Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); GethLikeTxTrace Trace(Rlp blockRlp, Hash256 txHash, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, Dictionary? stateOverride, CancellationToken cancellationToken); + GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken); IReadOnlyCollection TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken); IReadOnlyCollection TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken); IEnumerable TraceBlockToFile(Hash256 blockHash, GethTraceOptions options, CancellationToken cancellationToken); diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs index 3a9504af097..950d084634f 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs @@ -2,9 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; - +using Nethermind.Core; using Nethermind.Core.Crypto; namespace Nethermind.Evm.Tracing.GethStyle; @@ -36,5 +37,8 @@ public record GethTraceOptions [JsonPropertyName("tracerConfig")] public JsonElement? TracerConfig { get; init; } + [JsonPropertyName("stateOverrides")] + public Dictionary? StateOverrides { get; init; } + public static GethTraceOptions Default { get; } = new(); } diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs index bb1bd62c44b..c9766b47da6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs @@ -57,9 +57,8 @@ public ResultWrapper trace_call(TransactionForRpc call, Dictionary? stateOverride = null) => _traceModule.trace_call(call, traceTypes, blockParameter, stateOverride); - public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null, - Dictionary? stateOverride = null) => - _traceModule.trace_callMany(calls, blockParameter, stateOverride); + public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null) => + _traceModule.trace_callMany(calls, blockParameter); public ResultWrapper trace_rawTransaction(byte[] data, string[] traceTypes) => _traceModule.trace_rawTransaction(data, traceTypes); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs index 8936004d1d5..79ecc3f0dd0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs @@ -152,9 +152,8 @@ public GethLikeTxTrace GetTransactionTrace(Hash256 blockHash, int index, Cancell public GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => _tracer.Trace(blockRlp, transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, - GethTraceOptions? gethTraceOptions = null, Dictionary? stateOverride = null) => - _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, stateOverride, cancellationToken); + public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); public IReadOnlyCollection GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => _tracer.TraceBlock(blockParameter, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs index b195e2e3acb..9c0b2919d32 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs @@ -18,7 +18,6 @@ using System.Collections.Generic; using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Facade.Eth; namespace Nethermind.JsonRpc.Modules.DebugModule; @@ -69,8 +68,7 @@ public ResultWrapper debug_traceTransaction(Hash256 transaction return ResultWrapper.Success(transactionTrace); } - public ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, - GethTraceOptions? options = null, Dictionary? stateOverride = null) + public ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null) { blockParameter ??= BlockParameter.Latest; call.EnsureDefaults(_jsonRpcConfig.GasCap); @@ -78,7 +76,7 @@ public ResultWrapper debug_traceCall(TransactionForRpc call, Bl using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; - GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(tx, blockParameter, cancellationToken, options, stateOverride); + GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(tx, blockParameter, cancellationToken, options); if (transactionTrace is null) { return ResultWrapper.Fail($"Cannot find transactionTrace for hash: {tx.Hash}", ErrorCodes.ResourceNotFound); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs index 84f09ecd68e..096d7db62ac 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs @@ -20,7 +20,7 @@ public interface IDebugBridge GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); GethLikeTxTrace GetTransactionTrace(Hash256 blockHash, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null, Dictionary? stateOverride = null); + GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); IReadOnlyCollection GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null); IReadOnlyCollection GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); byte[] GetBlockRlp(BlockParameter param); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index 83c48a63936..f5df70a07f8 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -33,7 +33,7 @@ public interface IDebugRpcModule : IRpcModule ResultWrapper debug_traceTransaction(Hash256 transactionHash, GethTraceOptions options = null); [JsonRpcMethod(Description = "This method lets you run an eth_call within the context of the given block execution using the final state of parent block as the base. The block can be specified either by hash or by number. It takes the same input object as a eth_call. It returns the same output as debug_traceTransaction.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null, Dictionary? stateOverride = null); + ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null); [JsonRpcMethod(Description = "", IsSharable = true)] ResultWrapper debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int txIndex, GethTraceOptions options = null); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs index 1c36f911116..94b2d2185f4 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs @@ -20,8 +20,7 @@ ResultWrapper trace_call(TransactionForRpc call, BlockParameter? blockParameter = null, Dictionary? stateOverride = null); [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, - BlockParameter? blockParameter = null, Dictionary? stateOverride = null); + ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null); [JsonRpcMethod(Description = "Traces a call to eth_sendRawTransaction without making the call, returning the traces", IsImplemented = true, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 7c07ea17cd2..51b0b5c1aa1 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -69,7 +69,7 @@ public ResultWrapper trace_call(TransactionForRpc call, /// /// Traces list of transactions. Doesn't charge fees. /// - public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null, Dictionary? stateOverride = null) + public ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null) { blockParameter ??= BlockParameter.Latest; @@ -97,7 +97,7 @@ public ResultWrapper> trace_callMany(Transa } Block block = new(headerSearch.Object!, txs, Enumerable.Empty()); - IReadOnlyCollection? traces = TraceBlock(block, new(traceTypeByTransaction), stateOverride); + IReadOnlyCollection? traces = TraceBlock(block, new(traceTypeByTransaction)); return ResultWrapper>.Success(traces.Select(t => new ParityTxTraceFromReplay(t))); } From eb3700ab9ac85625227c48d637b648a829447bc5 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sun, 1 Sep 2024 03:53:57 +0300 Subject: [PATCH 10/70] Added missing tests --- .../Eth/EthRpcModuleTests.EstimateGas.cs | 60 ++++++++++++++- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 63 +++++++++++++++- .../Modules/TraceRpcModuleTests.cs | 74 ++++++++++++++++++- 3 files changed, 190 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index 0bc1a37fb09..fffa4f58058 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -9,9 +9,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Evm; -using Nethermind.Evm.Tracing; using Nethermind.Facade.Eth; -using Nethermind.JsonRpc.Data; using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -257,4 +255,62 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } + + [TestCase( + "Nonce override doesn't cause failure", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","value":"0x0"}""", + """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", + """{"jsonrpc":"2.0","result":"TODO","id":67}""" + )] + [TestCase( + "Uses account balance from state override", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", + """{"jsonrpc":"2.0","result":"TODO","id":67}""" + )] + [TestCase( + "Executes code from state override", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", + """{"jsonrpc":"2.0","result":"TODO","id":67}""" + )] + [TestCase( + "Executes precompile using overriden address", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", + """{"jsonrpc":"2.0","result":"0xbb8","id":67}""" + )] + public async Task Estimate_gas_with_state_override(string name, string transaction, string stateOverride, string expectedResult) + { + using Context ctx = await Context.Create(); + + string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); + + Assert.That(serialized, Is.EqualTo(expectedResult)); + } + + [TestCase( + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x1"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" + )] + [TestCase( + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" + )] + public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) + { + using Context ctx = await Context.Create(); + + var resultOverrideBefore = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); + + var resultNoOverride = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest"); + + var resultOverrideAfter = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); + + Assert.Multiple(() => + { + Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); + Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); + }); + } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index ed73767fcf1..cb46cea3ee6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -9,7 +9,6 @@ using Nethermind.Core.Test.Builders; using Nethermind.Evm; using Nethermind.Facade.Eth; -using Nethermind.JsonRpc.Data; using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -282,4 +281,66 @@ public async Task Eth_call_with_revert() Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32015,\"message\":\"VM execution error.\",\"data\":\"revert\"},\"id\":67}")); } + + [TestCase( + "Nonce override doesn't cause failure", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","value":"0x0"}""", + """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", + """{"jsonrpc":"2.0","result":"0x","id":67}""" + )] + [TestCase( + "Uses account balance from state override", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", + """{"jsonrpc":"2.0","result":"0x","id":67}""" + )] + [TestCase( + "Executes code from state override", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", + """{"jsonrpc":"2.0","result":"0x00000000000000000000000000000000000000000000003635c9adc5de9f09e5","id":67}""" + )] + [TestCase( + "Executes precompile using overriden address", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", + """{"jsonrpc":"2.0","result":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","id":67}""" + )] + public async Task Eth_call_with_state_override(string name, string transaction, string stateOverride, string expectedResult) + { + using Context ctx = await Context.Create(); + + Address sender = new("0x7f554713be84160fdf0178cc8df86f5aabd33397"); + ctx.Test.ReadOnlyState.AccountExists(sender).Should().BeFalse(); + + string serialized = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); + + Assert.That(serialized, Is.EqualTo(expectedResult)); + ctx.Test.ReadOnlyState.AccountExists(sender).Should().BeFalse(); + } + + [TestCase( + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x1"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" + )] + [TestCase( + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" + )] + public async Task Eth_call_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) + { + using Context ctx = await Context.Create(); + + var resultOverrideBefore = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); + + var resultNoOverride = await ctx.Test.TestEthRpc("eth_call", transaction, "latest"); + + var resultOverrideAfter = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); + + Assert.Multiple(() => + { + Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); + Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); + }); + } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 1fab4d08e2b..1e26de4bda0 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -13,9 +13,7 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Int256; -using Nethermind.JsonRpc.Modules.Eth; using Nethermind.JsonRpc.Modules.Trace; -using Nethermind.Logging; using NUnit.Framework; using Nethermind.Blockchain.Find; using Nethermind.Consensus.Processing; @@ -23,9 +21,7 @@ using Nethermind.Consensus.Tracing; using Nethermind.Consensus.Validators; using Nethermind.Core.Crypto; -using Nethermind.Db; using Nethermind.Evm; -using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade.Eth; using Nethermind.Serialization.Json; @@ -855,4 +851,74 @@ public async Task Trace_replayBlockTransactions_stateDiff() state[TestItem.AddressA].Balance!.After.Should().Be(accountA.Balance - 21000 * tx.GasPrice - tx.Value); state[TestItem.AddressF].Balance!.After.Should().Be(accountF.Balance + tx.Value); } + + [TestCase( + "Nonce increments from state override", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","value":"0x0"}""", + "stateDiff", + """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", + """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"balance":"=","code":"=","nonce":{"*":{"from":"0x123","to":"0x124"}},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" + )] + [TestCase( + "Uses account balance from state override", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + "stateDiff", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", + """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"*":{"from":"0x100","to":"0x0"}},"code":"=","nonce":{"\u002B":"0x1"},"storage":{}},"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f":{"balance":{"\u002B":"0x100"},"code":"=","nonce":{"\u002B":"0x0"},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" + )] + [TestCase( + "Executes code from state override", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + "trace", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", + """{"jsonrpc":"2.0","result":{"output":"0x00000000000000000000000000000000000000000000003635c9adc5de9f09e5","stateDiff":null,"trace":[{"action":{"callType":"call","from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","gas":"0x5f58d48","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","value":"0x0"},"result":{"gasUsed":"0x2df","output":"0x00000000000000000000000000000000000000000000003635c9adc5de9f09e5"},"subtraces":0,"traceAddress":[],"type":"call"}],"vmTrace":null},"id":67}""" + )] + [TestCase( + "Executes precompile using overriden address", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + "trace", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", + """{"jsonrpc":"2.0","result":{"output":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","stateDiff":null,"trace":[{"action":{"callType":"call","from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","gas":"0x5f58878","input":"0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4000000000000000000000000000000000000000000000000000000000000001c7b8b1991eb44757bc688016d27940df8fb971d7c87f77a6bc4e938e3202c44037e9267b0aeaa82fa765361918f2d8abd9cdd86e64aa6f2b81d3c4e0b69a7b055","to":"0x0000000000000000000000000000000000123456","value":"0x0"},"result":{"gasUsed":"0xbb8","output":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"},"subtraces":0,"traceAddress":[],"type":"call"}],"vmTrace":null},"id":67}""" + )] + public async Task Trace_call_with_state_override(string name, string transaction, string traceType, string stateOverride, string expectedResult) + { + Context context = new(); + await context.Build(); + string serialized = await RpcTest.TestSerializedRequest( + context.TraceRpcModule, + "trace_call", transaction, new[] { traceType }, "latest", stateOverride); + + Assert.That(serialized, Is.EqualTo(expectedResult), serialized.Replace("\"", "\\\"")); + } + + [TestCase( + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x0"}""", + """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"balance":"0x123", "nonce": "0x123"}}""" + )] + [TestCase( + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" + )] + public async Task Trace_call_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) + { + Context context = new(); + await context.Build(); + + var traceTypes = new[] { "stateDiff" }; + + var resultOverrideBefore = await RpcTest.TestSerializedRequest(context.TraceRpcModule, "trace_call", + transaction, traceTypes, null, stateOverride); + + var resultNoOverride = await RpcTest.TestSerializedRequest(context.TraceRpcModule, "trace_call", + transaction, traceTypes, null); + + var resultOverrideAfter = await RpcTest.TestSerializedRequest(context.TraceRpcModule, "trace_call", + transaction, traceTypes, null, stateOverride); + + Assert.Multiple(() => + { + Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); + Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); + }); + } } From 58886b61b4ba5b6d4bf9fbfa44152f0bc1a4ac1f Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 3 Sep 2024 01:54:26 +0300 Subject: [PATCH 11/70] Normalize block error --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 2 +- .../Modules/Eth/EthRpcModuleTests.cs | 6 +++--- .../Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index cb46cea3ee6..d547837c4fd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -148,7 +148,7 @@ public async Task Eth_call_with_blockhash_ok() string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "{\"blockHash\":\"0xf0b3f69cbd4e1e8d9b0ef02ff5d1384d18e19d251a4052f5f90bab190c5e8937\"}"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"0xf0b3f69cbd4e1e8d9b0ef02ff5d1384d18e19d251a4052f5f90bab190c5e8937 could not be found\"},\"id\":67}")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 0xf0b3f69cbd4e1e8d9b0ef02ff5d1384d18e19d251a4052f5f90bab190c5e8937 could not be found\"},\"id\":67}")); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index c5b2ae5db1a..e966b3adeb1 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -521,8 +521,8 @@ void HandleNewBlock(object? sender, BlockReplacementEventArgs e) [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"latest\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")] [TestCase("{\"fromBlock\":\"earliest\",\"toBlock\":\"pending\",\"address\":[\"0x00000000000000000001\", \"0x00000000000000000001\"],\"topics\":[\"0x00000000000000000000000000000001\", \"0x00000000000000000000000000000002\"]}", "{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")] [TestCase("{\"topics\":[null, [\"0x00000000000000000000000000000001\", \"0x00000000000000000000000000000002\"]]}", "{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")] - [TestCase("{\"fromBlock\":\"0x10\",\"toBlock\":\"latest\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"16 could not be found\"},\"id\":67}")] - [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"0x11\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"17 could not be found\"},\"id\":67}")] + [TestCase("{\"fromBlock\":\"0x10\",\"toBlock\":\"latest\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 16 could not be found\"},\"id\":67}")] + [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"0x11\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 17 could not be found\"},\"id\":67}")] [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"0x1\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"From block 2 is later than to block 1.\"},\"id\":67}")] public async Task Eth_get_logs(string parameter, string expected) { @@ -787,7 +787,7 @@ public async Task Eth_get_account_incorrect_block() string serialized = await ctx.Test.TestEthRpc("eth_getAccount", account_address, "0xffff"); - serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"65535 could not be found\"},\"id\":67}"); + serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 65535 could not be found\"},\"id\":67}"); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs index 277c77dc501..a518024cae0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs @@ -39,7 +39,7 @@ public static SearchResult SearchForHeader(this IBlockFinder blockF } return header is null && !allowNulls - ? new SearchResult($"{blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound) + ? new SearchResult($"Block {blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound) : new SearchResult(header); } From 76eea556e8fca56ed4296d3ffe189ccedf278346 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 3 Sep 2024 04:57:38 +0300 Subject: [PATCH 12/70] Tests fixes --- .../Modules/Eth/EthRpcModuleTests.EstimateGas.cs | 12 ++++++------ .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 10 +++++----- .../Modules/TraceRpcModuleTests.cs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index fffa4f58058..2cde75983cb 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -258,13 +258,13 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en [TestCase( "Nonce override doesn't cause failure", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","value":"0x0"}""", - """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""", """{"jsonrpc":"2.0","result":"TODO","id":67}""" )] [TestCase( "Uses account balance from state override", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x100"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", """{"jsonrpc":"2.0","result":"TODO","id":67}""" )] @@ -276,8 +276,8 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en )] [TestCase( "Executes precompile using overriden address", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", - """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", """{"jsonrpc":"2.0","result":"0xbb8","id":67}""" )] public async Task Estimate_gas_with_state_override(string name, string transaction, string stateOverride, string expectedResult) @@ -290,7 +290,7 @@ public async Task Estimate_gas_with_state_override(string name, string transacti } [TestCase( - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x1"}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x123"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index d547837c4fd..f91e8dfb7b0 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -284,13 +284,13 @@ public async Task Eth_call_with_revert() [TestCase( "Nonce override doesn't cause failure", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","value":"0x0"}""", - """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""", """{"jsonrpc":"2.0","result":"0x","id":67}""" )] [TestCase( "Uses account balance from state override", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x100"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", """{"jsonrpc":"2.0","result":"0x","id":67}""" )] @@ -302,8 +302,8 @@ public async Task Eth_call_with_revert() )] [TestCase( "Executes precompile using overriden address", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", - """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", """{"jsonrpc":"2.0","result":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","id":67}""" )] public async Task Eth_call_with_state_override(string name, string transaction, string stateOverride, string expectedResult) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 1e26de4bda0..78618060209 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -854,7 +854,7 @@ public async Task Trace_replayBlockTransactions_stateDiff() [TestCase( "Nonce increments from state override", - """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","value":"0x0"}""", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000"}""", "stateDiff", """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"balance":"=","code":"=","nonce":{"*":{"from":"0x123","to":"0x124"}},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" @@ -892,7 +892,7 @@ public async Task Trace_call_with_state_override(string name, string transaction } [TestCase( - """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x0"}""", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000"}""", """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( From 1dee3c0d7d6ef100023e9d94ce0d43b3d561744f Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 3 Sep 2024 13:51:17 +0300 Subject: [PATCH 13/70] Adjust insufficient-balance handling when simulating transaction --- src/Nethermind/Nethermind.Facade/BlockchainBridge.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 8f0a9a4edbe..2c947a52d40 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -175,6 +175,10 @@ public SimulateOutput Simulate(BlockHeader header, SimulatePayload Date: Tue, 3 Sep 2024 13:52:06 +0300 Subject: [PATCH 14/70] Fix chain-id missing in one of the RPC transaction conversions --- src/Nethermind/Nethermind.Facade/Eth/TransactionForRpc.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Facade/Eth/TransactionForRpc.cs b/src/Nethermind/Nethermind.Facade/Eth/TransactionForRpc.cs index d51ed363156..4381d787804 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/TransactionForRpc.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/TransactionForRpc.cs @@ -176,7 +176,7 @@ public TransactionForRpc() { } return tx; } - public Transaction ToTransaction(ulong? chainId = null) => ToTransaction(); + public Transaction ToTransaction(ulong? chainId = null) => ToTransaction(chainId); public T ToTransaction(ulong? chainId = null) where T : Transaction, new() { From 51d6aa6ebf9be42626d1ac1e7350b554c6d924e1 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 4 Sep 2024 03:44:28 +0300 Subject: [PATCH 15/70] Fix for `Eth_call_with_accessList` test --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index f91e8dfb7b0..7a9b2e62fc9 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -189,7 +189,7 @@ public async Task Eth_call_with_accessList() TransactionForRpc transaction = test.JsonSerializer.Deserialize( - $"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}"); + $$"""{"from": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", "type":"0x1", "data": "{{code.ToHexString(true)}}"}"""); transaction.AccessList = accessList; string serialized = await test.TestEthRpc("eth_call", test.JsonSerializer.Serialize(transaction), "0x0"); From 3e5f964c51a349d56bc817ef721ebb16e1957b2f Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 4 Sep 2024 04:32:48 +0300 Subject: [PATCH 16/70] State overrides for `eth_call` using `SimulateTxExecutor` --- .../Proxy/Models/Simulate/Error.cs | 2 +- .../Eth/EthRpcModule.TransactionExecutor.cs | 100 ++++++++++++++++-- .../Modules/Eth/EthRpcModule.cs | 3 +- 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/Error.cs b/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/Error.cs index a53bdd9a9e5..6819d2772e4 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/Error.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/Models/Simulate/Error.cs @@ -7,5 +7,5 @@ public class Error { public int Code { get; set; } public string Message { get; set; } - public string Data { get; set; } + public string? Data { get; set; } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index 39c67d1102a..d1a2a7a8ed5 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -11,7 +11,7 @@ using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Eth; -using Nethermind.Facade.Proxy.Models; +using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.JsonRpc.Data; using Nethermind.Specs.Forks; @@ -22,11 +22,91 @@ namespace Nethermind.JsonRpc.Modules.Eth public partial class EthRpcModule { // Single call executor - private abstract class TxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) - : ExecutorBase(blockchainBridge, blockFinder, rpcConfig) + private abstract class SimulateCallExecutor( + IBlockchainBridge blockchainBridge, + IBlockFinder blockFinder, + IJsonRpcConfig rpcConfig, + ulong? secondsPerSlot = null + ) : SimulateTxExecutor(blockchainBridge, blockFinder, rpcConfig, secondsPerSlot) { private bool NoBaseFee { get; set; } + protected override ResultWrapper> Execute( + BlockHeader header, SimulatePayload payload, + Dictionary? stateOverride, CancellationToken token + ) + { + Transaction tx = GetSingleTransaction(payload); + + if (NoBaseFee) + { + header.BaseFeePerGas = 0; + } + if (tx.IsContractCreation && tx.DataLength == 0) + { + return ResultWrapper>.Fail( + "Contract creation without any data provided.", ErrorCodes.InvalidInput + ); + } + + return base.Execute(header, payload, stateOverride, token); + } + + private static Transaction GetSingleTransaction(SimulatePayload payload) => + payload.BlockStateCalls!.Single().Calls!.Single().Transaction; + + private static SimulatePayload GetPayload( + TransactionForRpc transactionCall, Dictionary? stateOverride = null + ) => new() + { + Validation = false, + TraceTransfers = false, + ReturnFullTransactionObjects = false, + BlockStateCalls = + [ + new() + { + Calls = [transactionCall], + StateOverrides = stateOverride, + BlockOverrides = null + } + ] + }; + + private static bool ShouldSetBaseFee(TransactionForRpc t) => + // x?.IsZero == false <=> x > 0 + t.GasPrice?.IsZero == false || t.MaxFeePerGas?.IsZero == false || t.MaxPriorityFeePerGas?.IsZero == false; + + public ResultWrapper ExecuteCall( + TransactionForRpc transactionCall, + BlockParameter? blockParameter, + Dictionary? stateOverride = null) + { + NoBaseFee = !ShouldSetBaseFee(transactionCall); + + SimulatePayload payload = GetPayload(transactionCall, stateOverride); + ResultWrapper> result = base.Execute(payload, blockParameter); + + if (result.Result.Error != null) + return ResultWrapper.Fail(result.Result.Error, result.ErrorCode == 0 ? ErrorCodes.InvalidInput : result.ErrorCode); + + SimulateCallResult? simulateResult = result.Data?.SingleOrDefault()?.Calls.SingleOrDefault(); + + if (simulateResult == null) + return ResultWrapper.Fail("Internal error"); + + return GetResult(simulateResult); + } + + protected abstract ResultWrapper GetResult(SimulateCallResult simulateResult); + } + + private abstract class TxExecutor : ExecutorBase + { + private bool NoBaseFee { get; set; } + + protected TxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) : base(blockchainBridge, blockFinder, rpcConfig) { } + protected override Transaction Prepare(TransactionForRpc call) => call.ToTransaction(_blockchainBridge.GetChainId()); protected override ResultWrapper Execute(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) @@ -66,16 +146,16 @@ protected ResultWrapper GetInputError(CallOutput result) => ResultWrapper.Fail(result.Error, ErrorCodes.InvalidInput); } - private class CallTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) - : TxExecutor(blockchainBridge, blockFinder, rpcConfig) + private class CallTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig, ulong? secondsPerSlot = null) : SimulateCallExecutor(blockchainBridge, blockFinder, rpcConfig, secondsPerSlot) { - protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) + protected override ResultWrapper GetResult(SimulateCallResult simulateResult) { - CallOutput result = _blockchainBridge.Call(header, tx, stateOverride, token); + var data = simulateResult.ReturnData?.ToHexString(true); + var error = simulateResult.Error; - return result.Error is null - ? ResultWrapper.Success(result.OutputData.ToHexString(true)) - : TryGetInputError(result) ?? ResultWrapper.Fail("VM execution error.", ErrorCodes.ExecutionError, result.Error); + return error is null + ? ResultWrapper.Success(data) + : ResultWrapper.Fail(error.Data ?? "VM execution error.", error.Code, error.Message); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 9a9674903e0..d185d0a7375 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -20,7 +20,6 @@ using Nethermind.Facade; using Nethermind.Facade.Eth; using Nethermind.Facade.Filters; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.JsonRpc.Data; @@ -324,7 +323,7 @@ private async Task> SendTx(Transaction tx, public ResultWrapper eth_call(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null) => new CallTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig) - .ExecuteTx(transactionCall, blockParameter, stateOverride); + .ExecuteCall(transactionCall, blockParameter, stateOverride); public ResultWrapper> eth_simulateV1(SimulatePayload payload, BlockParameter? blockParameter = null) => new SimulateTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig, _secondsPerSlot) From 4de78ab5b41b2ce2ae8ce61cb626f6f511aa8253 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 30 Sep 2024 23:25:55 +0300 Subject: [PATCH 17/70] State overrides for `eth_estimateGas` using `OverridableWorldState` --- .../Nethermind.Api/NethermindApi.cs | 8 ++++- .../Contract/ValidatorContractTests.cs | 6 +++- .../Validators/ContractBasedValidatorTests.cs | 6 +++- .../ReadOnlyTxProcessingScopeTests.cs | 3 ++ .../Processing/ReadOnlyTxProcessingEnv.cs | 5 +++- .../Processing/ReadOnlyTxProcessingScope.cs | 7 +++++ .../IOverridableCodeInfoRepository.cs | 9 ++++++ .../OverridableCodeInfoRepository.cs | 4 ++- .../IReadOnlyTxProcessingScope.cs | 2 ++ .../Nethermind.Facade/BlockchainBridge.cs | 30 ++++++++++++++----- .../Modules/TestRpcBlockchain.cs | 13 ++++---- .../OverlayWorldStateManager.cs | 25 ++++++++-------- .../Nethermind.State/OverridableWorldState.cs | 30 +++++++++++++++++++ .../Pruning/OverlayTrieStore.cs | 4 ++- 14 files changed, 122 insertions(+), 30 deletions(-) create mode 100644 src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs create mode 100644 src/Nethermind/Nethermind.State/OverridableWorldState.cs diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index e07aa13ba9e..b8a7e7b4dfd 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -75,9 +75,15 @@ public IBlockchainBridge CreateBlockchainBridge() { ReadOnlyBlockTree readOnlyTree = BlockTree!.AsReadOnly(); + IReadOnlyDbProvider editableDbProvider = new ReadOnlyDbProvider(DbProvider, true); + var overlayTrieStore = new OverlayTrieStore(editableDbProvider.StateDb, WorldStateManager!.TrieStore, LogManager); + var overridableWorldStateManager = new OverlayWorldStateManager( + editableDbProvider, overlayTrieStore, LogManager, useOverridableWorldState: true + ); + // TODO: reuse the same trie cache here ReadOnlyTxProcessingEnv readOnlyTxProcessingEnv = new( - WorldStateManager!, + overridableWorldStateManager, readOnlyTree, SpecProvider, LogManager); diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs index ae1a5040a4f..b9130822955 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs @@ -27,6 +27,8 @@ public class ValidatorContractTests { private Block _block; private readonly Address _contractAddress = Address.FromNumber(long.MaxValue); + private IOverridableCodeInfoRepository _codeInfoRepository; + private IStateReader _stateReader; private ITransactionProcessor _transactionProcessor; private IReadOnlyTxProcessorSource _readOnlyTxProcessorSource; private IWorldState _stateProvider; @@ -35,11 +37,13 @@ public class ValidatorContractTests public void SetUp() { _block = new Block(Build.A.BlockHeader.TestObject, new BlockBody()); + _codeInfoRepository = Substitute.For(); + _stateReader = Substitute.For(); _transactionProcessor = Substitute.For(); _stateProvider = Substitute.For(); _stateProvider.StateRoot.Returns(TestItem.KeccakA); _readOnlyTxProcessorSource = Substitute.For(); - _readOnlyTxProcessorSource.Build(TestItem.KeccakA).Returns(new ReadOnlyTxProcessingScope(_transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); + _readOnlyTxProcessorSource.Build(TestItem.KeccakA).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _stateReader, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); } [Test] diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index 3902182d6e8..90f37f680f8 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -44,6 +44,8 @@ public class ContractBasedValidatorTests private AuRaParameters.Validator _validator; private Block _block; private BlockHeader _parentHeader; + private IOverridableCodeInfoRepository _codeInfoRepository; + private IStateReader _stateReader; private ITransactionProcessor _transactionProcessor; private IAuRaBlockFinalizationManager _blockFinalizationManager; private static readonly Address _contractAddress = Address.FromNumber(1000); @@ -75,12 +77,14 @@ public void SetUp() }; _block = new Block(Build.A.BlockHeader.WithNumber(1).WithAura(1, Array.Empty()).TestObject, new BlockBody()); + _codeInfoRepository = Substitute.For(); + _stateReader = Substitute.For(); _transactionProcessor = Substitute.For(); _stateProvider.StateRoot.Returns(TestItem.KeccakA); _stateProvider.IsContract(_contractAddress).Returns(true); _readOnlyTxProcessorSource = Substitute.For(); - _readOnlyTxProcessorSource.Build(Arg.Any()).Returns(new ReadOnlyTxProcessingScope(_transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); + _readOnlyTxProcessorSource.Build(Arg.Any()).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _stateReader, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); _blockTree.Head.Returns(_block); _abiEncoder diff --git a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs index 399523f0e56..49d5ffdb44c 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs @@ -3,6 +3,7 @@ using Nethermind.Consensus.Processing; using Nethermind.Core.Test.Builders; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; using NSubstitute; @@ -16,6 +17,8 @@ public class ReadOnlyTxProcessingScopeTests public void Test_WhenDispose_ThenStateRootWillRevert() { ReadOnlyTxProcessingScope env = new ReadOnlyTxProcessingScope( + Substitute.For(), + Substitute.For(), Substitute.For(), Substitute.For(), TestItem.KeccakB diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 1e51094b004..91f6cbbad92 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -27,6 +27,8 @@ protected ITransactionProcessor TransactionProcessor } } + public IWorldStateManager WorldStateManager { get; } + public IVirtualMachine Machine { get; } public OverridableCodeInfoRepository CodeInfoRepository { get; } @@ -52,6 +54,7 @@ public ReadOnlyTxProcessingEnv( Machine = new VirtualMachine(BlockhashProvider, specProvider, CodeInfoRepository, logManager); BlockTree = readOnlyBlockTree ?? throw new ArgumentNullException(nameof(readOnlyBlockTree)); BlockhashProvider = new BlockhashProvider(BlockTree, specProvider, StateProvider, logManager); + WorldStateManager = worldStateManager; _logManager = logManager; } @@ -65,7 +68,7 @@ public IReadOnlyTxProcessingScope Build(Hash256 stateRoot) { Hash256 originalStateRoot = StateProvider.StateRoot; StateProvider.StateRoot = stateRoot; - return new ReadOnlyTxProcessingScope(TransactionProcessor, StateProvider, originalStateRoot); + return new ReadOnlyTxProcessingScope(CodeInfoRepository, StateReader, TransactionProcessor, StateProvider, originalStateRoot); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs index bf14441b48b..01415a872fc 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs @@ -2,12 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; namespace Nethermind.Consensus.Processing; public class ReadOnlyTxProcessingScope( + IOverridableCodeInfoRepository codeInfoRepository, + IStateReader stateReader, ITransactionProcessor transactionProcessor, IWorldState worldState, Hash256 originalStateRoot @@ -17,8 +20,12 @@ public void Dispose() { worldState.StateRoot = originalStateRoot; worldState.Reset(); + (worldState as OverridableWorldState)?.ResetOverrides(); + CodeInfoRepository.ResetOverrides(); } + public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; + public IStateReader StateReader => stateReader; public ITransactionProcessor TransactionProcessor => transactionProcessor; public IWorldState WorldState => worldState; } diff --git a/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs b/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs new file mode 100644 index 00000000000..45b7dae2975 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Evm; + +public interface IOverridableCodeInfoRepository : ICodeInfoRepository +{ + public void ResetOverrides(); +} diff --git a/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs b/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs index 2ffc7ac5886..92a2894c0e4 100644 --- a/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs +++ b/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs @@ -11,7 +11,7 @@ namespace Nethermind.Evm; -public class OverridableCodeInfoRepository(ICodeInfoRepository codeInfoRepository) : ICodeInfoRepository +public class OverridableCodeInfoRepository(ICodeInfoRepository codeInfoRepository) : IOverridableCodeInfoRepository { private readonly Dictionary _codeOverwrites = new(); @@ -40,4 +40,6 @@ public void SetCodeOverwrite( _codeOverwrites[key] = value; } + + public void ResetOverrides() => _codeOverwrites.Clear(); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs index ce7bb61e8c3..d7dfd4e61c1 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs @@ -8,6 +8,8 @@ namespace Nethermind.Evm.TransactionProcessing; public interface IReadOnlyTxProcessingScope : IDisposable { + IOverridableCodeInfoRepository CodeInfoRepository { get; } + IStateReader StateReader { get; } ITransactionProcessor TransactionProcessor { get; } IWorldState WorldState { get; } } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 2c947a52d40..4092f361274 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -26,7 +26,6 @@ using Nethermind.State; using Nethermind.Core.Extensions; using Nethermind.Config; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; using Transaction = Nethermind.Core.Transaction; @@ -192,13 +191,17 @@ public CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMargi { using IReadOnlyTxProcessingScope scope = _processingEnv.Build(header.StateRoot!); + scope.WorldState.ApplyStateOverrides(_processingEnv.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number, true); + header.StateRoot = scope.WorldState.StateRoot; + EstimateGasTracer estimateGasTracer = new(); TransactionResult tryCallResult = TryCallAndRestore( header, tx, stateOverride, true, - estimateGasTracer.WithCancellation(cancellationToken)); + estimateGasTracer.WithCancellation(cancellationToken), + scope); GasEstimator gasEstimator = new(scope.TransactionProcessor, scope.WorldState, _specProvider, _blocksConfig); @@ -238,11 +241,14 @@ private TransactionResult TryCallAndRestore( Transaction transaction, Dictionary? stateOverride, bool treatBlockHeaderAsParentBlock, - ITxTracer tracer) + ITxTracer tracer, + IReadOnlyTxProcessingScope? scope = null) { try { - return CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer); + return scope == null + ? CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer) + : CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer, scope); } catch (InsufficientBalanceException ex) { @@ -257,10 +263,20 @@ private TransactionResult CallAndRestore( bool treatBlockHeaderAsParentBlock, ITxTracer tracer) { - transaction.SenderAddress ??= Address.SystemUser; + using IReadOnlyTxProcessingScope scope = _processingEnv.Build(blockHeader.StateRoot!); + return CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer, scope); + } - Hash256 stateRoot = blockHeader.StateRoot!; - using IReadOnlyTxProcessingScope scope = _processingEnv.Build(stateRoot); + private TransactionResult CallAndRestore( + BlockHeader blockHeader, + Transaction transaction, + Dictionary? stateOverride, + bool treatBlockHeaderAsParentBlock, + ITxTracer tracer, + IReadOnlyTxProcessingScope scope) + { + transaction.SenderAddress ??= Address.SystemUser; + Hash256? stateRoot = blockHeader.StateRoot!; if (transaction.Nonce == 0) { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index 6beef8cab58..f338c55f0cf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -31,7 +31,9 @@ using Nethermind.Config; using Nethermind.Db; using Nethermind.Facade.Simulate; +using Nethermind.State; using Nethermind.Synchronization.ParallelSync; +using Nethermind.Trie.Pruning; using NSubstitute; namespace Nethermind.JsonRpc.Test.Modules @@ -146,11 +148,12 @@ protected override async Task Build( IFilterManager filterManager = new FilterManager(filterStore, BlockProcessor, TxPool, LimboLogs.Instance); var dbProvider = new ReadOnlyDbProvider(DbProvider, false); IReadOnlyBlockTree? roBlockTree = BlockTree!.AsReadOnly(); - ReadOnlyTxProcessingEnv processingEnv = new( - WorldStateManager, - roBlockTree, - SpecProvider, - LimboLogs.Instance); + + IReadOnlyDbProvider editableDbProvider = new ReadOnlyDbProvider(DbProvider, true); + OverlayTrieStore overlayTrieStore = new(editableDbProvider.StateDb, WorldStateManager!.TrieStore, LogManager); + var reusableWorldStateManager = new OverlayWorldStateManager(editableDbProvider, overlayTrieStore, LogManager, true); + ReadOnlyTxProcessingEnv processingEnv = new(reusableWorldStateManager, roBlockTree, SpecProvider, LimboLogs.Instance); + SimulateReadOnlyBlocksProcessingEnvFactory simulateProcessingEnvFactory = new SimulateReadOnlyBlocksProcessingEnvFactory( WorldStateManager, roBlockTree, diff --git a/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs index a4dda8fdd65..52771408aca 100644 --- a/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs @@ -12,7 +12,8 @@ namespace Nethermind.State; public class OverlayWorldStateManager( IReadOnlyDbProvider dbProvider, OverlayTrieStore overlayTrieStore, - ILogManager? logManager) + ILogManager? logManager, + bool useOverridableWorldState = false) : IWorldStateManager { private readonly IDb _codeDb = dbProvider.GetDb(DbNames.Code); @@ -29,17 +30,17 @@ public class OverlayWorldStateManager( public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) { - PreBlockCaches? preBlockCaches = (forWarmup as IPreBlockCaches)?.Caches; - return preBlockCaches is not null - ? new WorldState( - new PreCachedTrieStore(overlayTrieStore, preBlockCaches.RlpCache), - _codeDb, - logManager, - preBlockCaches) - : new WorldState( - overlayTrieStore, - _codeDb, - logManager); + // TODO consider refactoring or adding + if (useOverridableWorldState && forWarmup is not null) + throw new NotSupportedException("Overridable world state with warm up is not supported."); + + ITrieStore trieStore = overlayTrieStore; + if ((forWarmup as IPreBlockCaches)?.Caches is { } preBlockCaches) + trieStore = new PreCachedTrieStore(trieStore, preBlockCaches.RlpCache); + + return useOverridableWorldState + ? new Nethermind.State.OverridableWorldState((OverlayTrieStore)trieStore, _codeDb, logManager) + : new WorldState(trieStore, _codeDb, logManager); } public event EventHandler? ReorgBoundaryReached diff --git a/src/Nethermind/Nethermind.State/OverridableWorldState.cs b/src/Nethermind/Nethermind.State/OverridableWorldState.cs new file mode 100644 index 00000000000..40b15bd94e1 --- /dev/null +++ b/src/Nethermind/Nethermind.State/OverridableWorldState.cs @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Logging; +using Nethermind.Trie.Pruning; + +namespace Nethermind.State; + +// TODO improve naming? +public class OverridableWorldState : WorldState +{ + private readonly OverlayTrieStore _trieStore; + + public OverridableWorldState( + OverlayTrieStore trieStore, IKeyValueStore? codeDb, ILogManager? logManager + ) : base(trieStore, codeDb, logManager) => + _trieStore = trieStore; + + public OverridableWorldState( + OverlayTrieStore trieStore, IKeyValueStore? codeDb, ILogManager? logManager, PreBlockCaches? preBlockCaches, + bool populatePreBlockCache = true + ) : base(trieStore, codeDb, logManager, preBlockCaches, populatePreBlockCache) => + _trieStore = trieStore; + + /// + /// Resets changes applied via + /// + public void ResetOverrides() => _trieStore.ResetOverrides(); +} diff --git a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs index 50977e6ec5d..9c83df3e34c 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Logging; @@ -24,4 +23,7 @@ public override TrieNode FindCachedOrUnknown(Hash256? address, in TreePath path, public override byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None) => base.TryLoadRlp(address, in path, hash, flags) ?? store.TryLoadRlp(address, in path, hash, flags); + + // TODO clarify is ClearCache is reliable enough to use + public void ResetOverrides() => ClearCache(); } From 3e1d83a31f4ce928db3354dae59d0ca35b82f0b1 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 2 Oct 2024 23:40:05 +0300 Subject: [PATCH 18/70] Adjusted eth_estimateGas test values --- .../Eth/EthRpcModuleTests.EstimateGas.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index 2cde75983cb..f9b36c331d3 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -260,29 +260,30 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en "Nonce override doesn't cause failure", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""", - """{"jsonrpc":"2.0","result":"TODO","id":67}""" + """{"jsonrpc":"2.0","result":"0x5208","id":67}""" // ETH transfer (intrinsic transaction cost) )] [TestCase( "Uses account balance from state override", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x100"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", - """{"jsonrpc":"2.0","result":"TODO","id":67}""" + """{"jsonrpc":"2.0","result":"0x5208","id":67}""" // ETH transfer (intrinsic transaction cost) )] [TestCase( "Executes code from state override", - """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", - """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", - """{"jsonrpc":"2.0","result":"TODO","id":67}""" + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0x60fe47b1112233445566778899001122334455667788990011223344556677889900112233445566778899001122"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""", + """{"jsonrpc":"2.0","result":"0xabdd","id":67}""" // Store uint256 (cold access) + few other light instructions + intrinsic transaction cost )] [TestCase( "Executes precompile using overriden address", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", - """{"jsonrpc":"2.0","result":"0xbb8","id":67}""" + """{"jsonrpc":"2.0","result":"0x6440","id":67}""" // EcRecover call + intrinsic transaction cost )] public async Task Estimate_gas_with_state_override(string name, string transaction, string stateOverride, string expectedResult) { - using Context ctx = await Context.Create(); + TestSpecProvider specProvider = new(Prague.Instance); + using Context ctx = await Context.Create(specProvider); string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); @@ -294,8 +295,8 @@ public async Task Estimate_gas_with_state_override(string name, string transacti """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", - """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0x60fe47b1112233445566778899001122334455667788990011223344556677889900112233445566778899001122"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""" )] public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) { From 18825c8aefcf49a501d4b7f7e71793e3a4eacbef Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 2 Oct 2024 23:41:13 +0300 Subject: [PATCH 19/70] Simplify changes --- .../Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs | 4 +--- .../Validators/ContractBasedValidatorTests.cs | 4 +--- .../ReadOnlyTxProcessingScopeTests.cs | 1 - .../Processing/ReadOnlyTxProcessingEnv.cs | 2 +- .../Processing/ReadOnlyTxProcessingScope.cs | 5 +---- .../TransactionProcessing/IReadOnlyTxProcessingScope.cs | 2 -- 6 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs index b9130822955..fb741de4844 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs @@ -28,7 +28,6 @@ public class ValidatorContractTests private Block _block; private readonly Address _contractAddress = Address.FromNumber(long.MaxValue); private IOverridableCodeInfoRepository _codeInfoRepository; - private IStateReader _stateReader; private ITransactionProcessor _transactionProcessor; private IReadOnlyTxProcessorSource _readOnlyTxProcessorSource; private IWorldState _stateProvider; @@ -38,12 +37,11 @@ public void SetUp() { _block = new Block(Build.A.BlockHeader.TestObject, new BlockBody()); _codeInfoRepository = Substitute.For(); - _stateReader = Substitute.For(); _transactionProcessor = Substitute.For(); _stateProvider = Substitute.For(); _stateProvider.StateRoot.Returns(TestItem.KeccakA); _readOnlyTxProcessorSource = Substitute.For(); - _readOnlyTxProcessorSource.Build(TestItem.KeccakA).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _stateReader, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); + _readOnlyTxProcessorSource.Build(TestItem.KeccakA).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); } [Test] diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index 90f37f680f8..d420791f422 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -45,7 +45,6 @@ public class ContractBasedValidatorTests private Block _block; private BlockHeader _parentHeader; private IOverridableCodeInfoRepository _codeInfoRepository; - private IStateReader _stateReader; private ITransactionProcessor _transactionProcessor; private IAuRaBlockFinalizationManager _blockFinalizationManager; private static readonly Address _contractAddress = Address.FromNumber(1000); @@ -78,13 +77,12 @@ public void SetUp() _block = new Block(Build.A.BlockHeader.WithNumber(1).WithAura(1, Array.Empty()).TestObject, new BlockBody()); _codeInfoRepository = Substitute.For(); - _stateReader = Substitute.For(); _transactionProcessor = Substitute.For(); _stateProvider.StateRoot.Returns(TestItem.KeccakA); _stateProvider.IsContract(_contractAddress).Returns(true); _readOnlyTxProcessorSource = Substitute.For(); - _readOnlyTxProcessorSource.Build(Arg.Any()).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _stateReader, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); + _readOnlyTxProcessorSource.Build(Arg.Any()).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); _blockTree.Head.Returns(_block); _abiEncoder diff --git a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs index 49d5ffdb44c..44ac8c2b47f 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs @@ -18,7 +18,6 @@ public void Test_WhenDispose_ThenStateRootWillRevert() { ReadOnlyTxProcessingScope env = new ReadOnlyTxProcessingScope( Substitute.For(), - Substitute.For(), Substitute.For(), Substitute.For(), TestItem.KeccakB diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 91f6cbbad92..7dbf2b43fea 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -68,7 +68,7 @@ public IReadOnlyTxProcessingScope Build(Hash256 stateRoot) { Hash256 originalStateRoot = StateProvider.StateRoot; StateProvider.StateRoot = stateRoot; - return new ReadOnlyTxProcessingScope(CodeInfoRepository, StateReader, TransactionProcessor, StateProvider, originalStateRoot); + return new ReadOnlyTxProcessingScope(CodeInfoRepository, TransactionProcessor, StateProvider, originalStateRoot); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs index 01415a872fc..a2f87bb9635 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs @@ -10,7 +10,6 @@ namespace Nethermind.Consensus.Processing; public class ReadOnlyTxProcessingScope( IOverridableCodeInfoRepository codeInfoRepository, - IStateReader stateReader, ITransactionProcessor transactionProcessor, IWorldState worldState, Hash256 originalStateRoot @@ -21,11 +20,9 @@ public void Dispose() worldState.StateRoot = originalStateRoot; worldState.Reset(); (worldState as OverridableWorldState)?.ResetOverrides(); - CodeInfoRepository.ResetOverrides(); + codeInfoRepository.ResetOverrides(); } - public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; - public IStateReader StateReader => stateReader; public ITransactionProcessor TransactionProcessor => transactionProcessor; public IWorldState WorldState => worldState; } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs index d7dfd4e61c1..ce7bb61e8c3 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs @@ -8,8 +8,6 @@ namespace Nethermind.Evm.TransactionProcessing; public interface IReadOnlyTxProcessingScope : IDisposable { - IOverridableCodeInfoRepository CodeInfoRepository { get; } - IStateReader StateReader { get; } ITransactionProcessor TransactionProcessor { get; } IWorldState WorldState { get; } } From d900a5a2741a96e867907c1da37357bda5bc3e06 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 00:01:32 +0300 Subject: [PATCH 20/70] Use custom `OverridableWorldStateManager` --- .../Nethermind.Api/NethermindApi.cs | 7 +-- .../Modules/TestRpcBlockchain.cs | 13 +++-- .../OverlayWorldStateManager.cs | 11 +--- .../OverridableWorldStateManager.cs | 50 +++++++++++++++++++ 4 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index b8a7e7b4dfd..4a262b905e0 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -74,12 +74,7 @@ public NethermindApi(IConfigProvider configProvider, IJsonSerializer jsonSeriali public IBlockchainBridge CreateBlockchainBridge() { ReadOnlyBlockTree readOnlyTree = BlockTree!.AsReadOnly(); - - IReadOnlyDbProvider editableDbProvider = new ReadOnlyDbProvider(DbProvider, true); - var overlayTrieStore = new OverlayTrieStore(editableDbProvider.StateDb, WorldStateManager!.TrieStore, LogManager); - var overridableWorldStateManager = new OverlayWorldStateManager( - editableDbProvider, overlayTrieStore, LogManager, useOverridableWorldState: true - ); + OverridableWorldStateManager overridableWorldStateManager = new(DbProvider!, WorldStateManager!.TrieStore, LogManager); // TODO: reuse the same trie cache here ReadOnlyTxProcessingEnv readOnlyTxProcessingEnv = new( diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index f338c55f0cf..9767fefccdf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -33,7 +33,6 @@ using Nethermind.Facade.Simulate; using Nethermind.State; using Nethermind.Synchronization.ParallelSync; -using Nethermind.Trie.Pruning; using NSubstitute; namespace Nethermind.JsonRpc.Test.Modules @@ -148,12 +147,12 @@ protected override async Task Build( IFilterManager filterManager = new FilterManager(filterStore, BlockProcessor, TxPool, LimboLogs.Instance); var dbProvider = new ReadOnlyDbProvider(DbProvider, false); IReadOnlyBlockTree? roBlockTree = BlockTree!.AsReadOnly(); - - IReadOnlyDbProvider editableDbProvider = new ReadOnlyDbProvider(DbProvider, true); - OverlayTrieStore overlayTrieStore = new(editableDbProvider.StateDb, WorldStateManager!.TrieStore, LogManager); - var reusableWorldStateManager = new OverlayWorldStateManager(editableDbProvider, overlayTrieStore, LogManager, true); - ReadOnlyTxProcessingEnv processingEnv = new(reusableWorldStateManager, roBlockTree, SpecProvider, LimboLogs.Instance); - + OverridableWorldStateManager overridableWorldStateManager = new(DbProvider, WorldStateManager.TrieStore, LogManager); + ReadOnlyTxProcessingEnv processingEnv = new( + overridableWorldStateManager, + roBlockTree, + SpecProvider, + LimboLogs.Instance); SimulateReadOnlyBlocksProcessingEnvFactory simulateProcessingEnvFactory = new SimulateReadOnlyBlocksProcessingEnvFactory( WorldStateManager, roBlockTree, diff --git a/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs index 52771408aca..a5c6af79e8f 100644 --- a/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs @@ -12,8 +12,7 @@ namespace Nethermind.State; public class OverlayWorldStateManager( IReadOnlyDbProvider dbProvider, OverlayTrieStore overlayTrieStore, - ILogManager? logManager, - bool useOverridableWorldState = false) + ILogManager? logManager) : IWorldStateManager { private readonly IDb _codeDb = dbProvider.GetDb(DbNames.Code); @@ -30,17 +29,11 @@ public class OverlayWorldStateManager( public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) { - // TODO consider refactoring or adding - if (useOverridableWorldState && forWarmup is not null) - throw new NotSupportedException("Overridable world state with warm up is not supported."); - ITrieStore trieStore = overlayTrieStore; if ((forWarmup as IPreBlockCaches)?.Caches is { } preBlockCaches) trieStore = new PreCachedTrieStore(trieStore, preBlockCaches.RlpCache); - return useOverridableWorldState - ? new Nethermind.State.OverridableWorldState((OverlayTrieStore)trieStore, _codeDb, logManager) - : new WorldState(trieStore, _codeDb, logManager); + return new WorldState(trieStore, _codeDb, logManager); } public event EventHandler? ReorgBoundaryReached diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs new file mode 100644 index 00000000000..d0e5c553e22 --- /dev/null +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Db; +using Nethermind.Logging; +using Nethermind.Trie.Pruning; + +namespace Nethermind.State; + +public class OverridableWorldStateManager : IWorldStateManager +{ + private readonly IDb _codeDb; + private readonly StateReader _reader; + private readonly WorldState _state; + + private readonly OverlayTrieStore _overlayTrieStore; + private readonly ILogManager? _logManager; + + public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore trieStore, ILogManager? logManager) + { + dbProvider = new ReadOnlyDbProvider(dbProvider, true); + OverlayTrieStore overlayTrieStore = new(dbProvider.StateDb, trieStore, logManager); + + _logManager = logManager; + _codeDb = dbProvider.GetDb(DbNames.Code); + _reader = new(overlayTrieStore, dbProvider.GetDb(DbNames.Code), logManager); + _state = new(overlayTrieStore, dbProvider.GetDb(DbNames.Code), logManager); + _overlayTrieStore = overlayTrieStore; + } + + public IWorldState GlobalWorldState => _state; + public IStateReader GlobalStateReader => _reader; + public IReadOnlyTrieStore TrieStore => _overlayTrieStore.AsReadOnly(); + + public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) + { + // TODO add if needed? + if (forWarmup is not null) + throw new NotSupportedException("Overridable world state with warm up is not supported."); + + return new OverridableWorldState(_overlayTrieStore, _codeDb, _logManager); + } + + public event EventHandler? ReorgBoundaryReached + { + add => _overlayTrieStore.ReorgBoundaryReached += value; + remove => _overlayTrieStore.ReorgBoundaryReached -= value; + } +} From 95fb2eda9118e29bdbcd0120d58179ad57dcd67c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 00:38:35 +0300 Subject: [PATCH 21/70] Simplify changes --- .../StateOverridesExtensions.cs | 12 ++++------ .../Nethermind.Facade/BlockchainBridge.cs | 24 ++++++++++++------- .../Simulate/SimulateBridgeHelper.cs | 2 +- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs index 768703bc48a..8dc4d4b124f 100644 --- a/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs @@ -19,8 +19,7 @@ public static void ApplyStateOverrides( OverridableCodeInfoRepository overridableCodeInfoRepository, Dictionary? overrides, IReleaseSpec spec, - long blockNumber, - bool commit) + long blockNumber) { if (overrides is not null) { @@ -41,12 +40,9 @@ public static void ApplyStateOverrides( } } - if (commit) - { - state.Commit(spec); - state.CommitTree(blockNumber); - state.RecalculateStateRoot(); - } + state.Commit(spec); + state.CommitTree(blockNumber); + state.RecalculateStateRoot(); } private static void UpdateState(this IWorldState stateProvider, AccountOverride accountOverride, Address address) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 4092f361274..5a514d7cc36 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -189,10 +189,7 @@ public SimulateOutput Simulate(BlockHeader header, SimulatePayload stateOverride, CancellationToken cancellationToken) { - using IReadOnlyTxProcessingScope scope = _processingEnv.Build(header.StateRoot!); - - scope.WorldState.ApplyStateOverrides(_processingEnv.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number, true); - header.StateRoot = scope.WorldState.StateRoot; + using IReadOnlyTxProcessingScope scope = BuildProcessingScope(header, stateOverride); EstimateGasTracer estimateGasTracer = new(); TransactionResult tryCallResult = TryCallAndRestore( @@ -200,11 +197,9 @@ public CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMargi tx, stateOverride, true, - estimateGasTracer.WithCancellation(cancellationToken), - scope); + estimateGasTracer.WithCancellation(cancellationToken)); - GasEstimator gasEstimator = new(scope.TransactionProcessor, scope.WorldState, - _specProvider, _blocksConfig); + GasEstimator gasEstimator = new(scope.TransactionProcessor, scope.WorldState, _specProvider, _blocksConfig); long estimate = gasEstimator.Estimate(tx, header, estimateGasTracer, errorMargin, cancellationToken); return new CallOutput @@ -332,6 +327,19 @@ private UInt256 GetNonce(Hash256 stateRoot, Address address) return _stateReader.GetNonce(stateRoot, address); } + private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary? stateOverride) + { + IReadOnlyTxProcessingScope? scope = _processingEnv.Build(header.StateRoot!); + + if (stateOverride != null) + { + scope.WorldState.ApplyStateOverrides(_processingEnv.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); + header.StateRoot = scope.WorldState.StateRoot; + } + return scope; + } + + public bool FilterExists(int filterId) => _filterStore.FilterExists(filterId); public FilterType GetFilterType(int filterId) => _filterStore.GetFilterType(filterId); public FilterLog[] GetFilterLogs(int filterId) => _filterManager.GetLogs(filterId); diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs index 99d5de07d92..59c97ea3c5c 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateBridgeHelper.cs @@ -40,7 +40,7 @@ private void PrepareState(BlockHeader blockHeader, IReleaseSpec releaseSpec) { stateProvider.StateRoot = parent.StateRoot!; - stateProvider.ApplyStateOverrides(codeInfoRepository, blockStateCall.StateOverrides, releaseSpec, blockHeader.Number, true); + stateProvider.ApplyStateOverrides(codeInfoRepository, blockStateCall.StateOverrides, releaseSpec, blockHeader.Number); IEnumerable
senders = blockStateCall.Calls?.Select(details => details.Transaction.SenderAddress) ?? Enumerable.Empty(); IEnumerable
targets = blockStateCall.Calls?.Select(details => details.Transaction.To!) ?? Enumerable.Empty(); From b4df9a7806f557ef3298974e68f1f31cfc9a3f13 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 00:38:52 +0300 Subject: [PATCH 22/70] `eth_estimateGas` test improvements --- .../Modules/Eth/EthRpcModuleTests.EstimateGas.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index f9b36c331d3..3ac57e95b4a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -291,14 +291,21 @@ public async Task Estimate_gas_with_state_override(string name, string transacti } [TestCase( + "When balance and nonce is overriden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x123"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( + "When address code is overriden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0x60fe47b1112233445566778899001122334455667788990011223344556677889900112233445566778899001122"}""", """{"0xc200000000000000000000000000000000000000":{"code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""" )] - public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) + [TestCase( + "When precompile address is changed", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" + )] + public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(string name, string transaction, string stateOverride) { using Context ctx = await Context.Create(); From 8cbbe33464a57a4a54e2b7d64b53dfcc71fdc44f Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 01:09:28 +0300 Subject: [PATCH 23/70] State overrides for `eth_call` using `OverridableWorldState` --- .../Nethermind.Facade/BlockchainBridge.cs | 3 +- .../Eth/EthRpcModule.TransactionExecutor.cs | 100 ++---------------- .../Modules/Eth/EthRpcModule.cs | 3 +- 3 files changed, 14 insertions(+), 92 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 5a514d7cc36..c543687bd15 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -150,8 +150,9 @@ private bool TryGetCanonicalTransaction( public CallOutput Call(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken cancellationToken) { CallOutputTracer callOutputTracer = new(); + using IReadOnlyTxProcessingScope scope = BuildProcessingScope(header, stateOverride); TransactionResult tryCallResult = TryCallAndRestore(header, tx, stateOverride, false, - callOutputTracer.WithCancellation(cancellationToken)); + callOutputTracer.WithCancellation(cancellationToken), scope); return new CallOutput { Error = tryCallResult.Success ? callOutputTracer.Error : tryCallResult.Error, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index d1a2a7a8ed5..39c67d1102a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -11,7 +11,7 @@ using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Eth; -using Nethermind.Facade.Proxy.Models.Simulate; +using Nethermind.Facade.Proxy.Models; using Nethermind.Int256; using Nethermind.JsonRpc.Data; using Nethermind.Specs.Forks; @@ -22,91 +22,11 @@ namespace Nethermind.JsonRpc.Modules.Eth public partial class EthRpcModule { // Single call executor - private abstract class SimulateCallExecutor( - IBlockchainBridge blockchainBridge, - IBlockFinder blockFinder, - IJsonRpcConfig rpcConfig, - ulong? secondsPerSlot = null - ) : SimulateTxExecutor(blockchainBridge, blockFinder, rpcConfig, secondsPerSlot) + private abstract class TxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) + : ExecutorBase(blockchainBridge, blockFinder, rpcConfig) { private bool NoBaseFee { get; set; } - protected override ResultWrapper> Execute( - BlockHeader header, SimulatePayload payload, - Dictionary? stateOverride, CancellationToken token - ) - { - Transaction tx = GetSingleTransaction(payload); - - if (NoBaseFee) - { - header.BaseFeePerGas = 0; - } - if (tx.IsContractCreation && tx.DataLength == 0) - { - return ResultWrapper>.Fail( - "Contract creation without any data provided.", ErrorCodes.InvalidInput - ); - } - - return base.Execute(header, payload, stateOverride, token); - } - - private static Transaction GetSingleTransaction(SimulatePayload payload) => - payload.BlockStateCalls!.Single().Calls!.Single().Transaction; - - private static SimulatePayload GetPayload( - TransactionForRpc transactionCall, Dictionary? stateOverride = null - ) => new() - { - Validation = false, - TraceTransfers = false, - ReturnFullTransactionObjects = false, - BlockStateCalls = - [ - new() - { - Calls = [transactionCall], - StateOverrides = stateOverride, - BlockOverrides = null - } - ] - }; - - private static bool ShouldSetBaseFee(TransactionForRpc t) => - // x?.IsZero == false <=> x > 0 - t.GasPrice?.IsZero == false || t.MaxFeePerGas?.IsZero == false || t.MaxPriorityFeePerGas?.IsZero == false; - - public ResultWrapper ExecuteCall( - TransactionForRpc transactionCall, - BlockParameter? blockParameter, - Dictionary? stateOverride = null) - { - NoBaseFee = !ShouldSetBaseFee(transactionCall); - - SimulatePayload payload = GetPayload(transactionCall, stateOverride); - ResultWrapper> result = base.Execute(payload, blockParameter); - - if (result.Result.Error != null) - return ResultWrapper.Fail(result.Result.Error, result.ErrorCode == 0 ? ErrorCodes.InvalidInput : result.ErrorCode); - - SimulateCallResult? simulateResult = result.Data?.SingleOrDefault()?.Calls.SingleOrDefault(); - - if (simulateResult == null) - return ResultWrapper.Fail("Internal error"); - - return GetResult(simulateResult); - } - - protected abstract ResultWrapper GetResult(SimulateCallResult simulateResult); - } - - private abstract class TxExecutor : ExecutorBase - { - private bool NoBaseFee { get; set; } - - protected TxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) : base(blockchainBridge, blockFinder, rpcConfig) { } - protected override Transaction Prepare(TransactionForRpc call) => call.ToTransaction(_blockchainBridge.GetChainId()); protected override ResultWrapper Execute(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) @@ -146,16 +66,16 @@ protected ResultWrapper GetInputError(CallOutput result) => ResultWrapper.Fail(result.Error, ErrorCodes.InvalidInput); } - private class CallTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig, ulong? secondsPerSlot = null) : SimulateCallExecutor(blockchainBridge, blockFinder, rpcConfig, secondsPerSlot) + private class CallTxExecutor(IBlockchainBridge blockchainBridge, IBlockFinder blockFinder, IJsonRpcConfig rpcConfig) + : TxExecutor(blockchainBridge, blockFinder, rpcConfig) { - protected override ResultWrapper GetResult(SimulateCallResult simulateResult) + protected override ResultWrapper ExecuteTx(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken token) { - var data = simulateResult.ReturnData?.ToHexString(true); - var error = simulateResult.Error; + CallOutput result = _blockchainBridge.Call(header, tx, stateOverride, token); - return error is null - ? ResultWrapper.Success(data) - : ResultWrapper.Fail(error.Data ?? "VM execution error.", error.Code, error.Message); + return result.Error is null + ? ResultWrapper.Success(result.OutputData.ToHexString(true)) + : TryGetInputError(result) ?? ResultWrapper.Fail("VM execution error.", ErrorCodes.ExecutionError, result.Error); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index d185d0a7375..9a9674903e0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -20,6 +20,7 @@ using Nethermind.Facade; using Nethermind.Facade.Eth; using Nethermind.Facade.Filters; +using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.JsonRpc.Data; @@ -323,7 +324,7 @@ private async Task> SendTx(Transaction tx, public ResultWrapper eth_call(TransactionForRpc transactionCall, BlockParameter? blockParameter = null, Dictionary? stateOverride = null) => new CallTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig) - .ExecuteCall(transactionCall, blockParameter, stateOverride); + .ExecuteTx(transactionCall, blockParameter, stateOverride); public ResultWrapper> eth_simulateV1(SimulatePayload payload, BlockParameter? blockParameter = null) => new SimulateTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig, _secondsPerSlot) From e078fcfccbb9951d25ff50a9b4bcc35774808c72 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 01:10:01 +0300 Subject: [PATCH 24/70] `eth_call` test improvements --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 7a9b2e62fc9..a31161ebc7c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -320,14 +320,21 @@ public async Task Eth_call_with_state_override(string name, string transaction, } [TestCase( + "When balance and nonce is overriden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x1"}""", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( + "When address code is overriden", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" )] - public async Task Eth_call_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) + [TestCase( + "When precompile address is changed", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" + )] + public async Task Eth_call_with_state_override_does_not_affect_other_calls(string name, string transaction, string stateOverride) { using Context ctx = await Context.Create(); From 4f9383d13a42f4be08ab6756289452ed75a28f61 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 07:47:05 +0300 Subject: [PATCH 25/70] Remove old implementation `stateOverride` parameters --- .../AuRaBlockProcessor.cs | 5 ++--- ...ocessor.BlockProductionTransactionsExecutor.cs | 6 ++---- ...ocessor.BlockValidationTransactionsExecutor.cs | 9 ++++----- .../Processing/BlockProcessor.cs | 11 ++++------- .../Processing/BlockchainProcessor.cs | 15 +++++++-------- .../Processing/IBlockProcessor.cs | 7 ++----- .../Processing/IBlockchainProcessor.cs | 2 +- .../Processing/NullBlockProcessor.cs | 3 +-- .../Processing/OneTimeProcessor.cs | 4 ++-- .../TransactionProcessorAdapterExtensions.cs | 6 ++---- .../Tracing/GethStyleTracer.cs | 2 +- .../Nethermind.Consensus/Tracing/ITracer.cs | 3 +-- .../Nethermind.Consensus/Tracing/Tracer.cs | 8 +++----- .../BuildUpTransactionProcessorAdapter.cs | 5 ++--- .../ChangeableTransactionProcessorAdapter.cs | 5 ++--- .../ITransactionProcessor.cs | 12 ++++-------- .../ITransactionProcessorAdapter.cs | 3 +-- .../TransactionProcessing/TransactionProcessor.cs | 8 ++------ .../Nethermind.Facade/BlockchainBridge.cs | 10 ++++------ .../SimulateReadOnlyBlocksProcessingEnv.cs | 4 ++-- .../Simulate/SimulateTransactionProcessor.cs | 5 ++--- .../Modules/Trace/TraceRpcModule.cs | 2 +- .../AuRaMergeBlockProcessor.cs | 2 +- .../EngineModuleTests.Setup.cs | 4 ++-- .../Nethermind.Optimism/OptimismBlockProcessor.cs | 5 ++--- .../OptimismTransactionProcessor.cs | 5 ++--- 26 files changed, 59 insertions(+), 92 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 5ac2e4df0a0..345724aa533 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -85,13 +85,12 @@ public AuRaBlockProcessor( public IAuRaValidator AuRaValidator { get; } - protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, - Dictionary? stateOverride = null) + protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) { ValidateAuRa(block); _contractRewriter?.RewriteContracts(block.Number, _stateProvider, _specProvider.GetSpec(block.Header)); AuRaValidator.OnBlockProcessingStart(block, options); - TxReceipt[] receipts = base.ProcessBlock(block, blockTracer, options, stateOverride); + TxReceipt[] receipts = base.ProcessBlock(block, blockTracer, options); AuRaValidator.OnBlockProcessingEnd(block, receipts, options); Metrics.AuRaStep = block.Header?.AuRaStep ?? 0; return receipts; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs index b390535bed3..9725e29b7fd 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs @@ -64,7 +64,7 @@ event EventHandler? IBlockProductionTransactionsExecutor.Addi } public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, - BlockReceiptsTracer receiptsTracer, IReleaseSpec spec, Dictionary? stateOverride = null) + BlockReceiptsTracer receiptsTracer, IReleaseSpec spec) { IEnumerable transactions = GetTransactions(block); @@ -73,9 +73,8 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction currentTx in transactions) { - TxAction action = ProcessTransaction(block, in blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock, stateOverride); + TxAction action = ProcessTransaction(block, in blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; - stateOverride = null; // Apply override only before the first transaction } stateProvider.Commit(spec, receiptsTracer); @@ -92,7 +91,6 @@ protected TxAction ProcessTransaction( BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, LinkedHashSet transactionsInBlock, - Dictionary? stateOverride = null, bool addToBlock = true) { AddingTxEventArgs args = txPicker.CanAddTransaction(block, currentTx, transactionsInBlock, stateProvider); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs index 15702284de0..dfb10e28f06 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs @@ -32,7 +32,7 @@ public BlockValidationTransactionsExecutor(ITransactionProcessor transactionProc public event EventHandler? TransactionProcessed; public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, - IReleaseSpec spec, Dictionary? stateOverride = null) + IReleaseSpec spec) { Metrics.ResetBlockStats(); BlockExecutionContext blkCtx = CreateBlockExecutionContext(block); @@ -40,8 +40,7 @@ public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processing { block.TransactionProcessed = i; Transaction currentTx = block.Transactions[i]; - ProcessTransaction(in blkCtx, currentTx, i, receiptsTracer, processingOptions, stateOverride); - stateOverride = null; // Apply override only before the first transaction + ProcessTransaction(in blkCtx, currentTx, i, receiptsTracer, processingOptions); } return receiptsTracer.TxReceipts.ToArray(); } @@ -49,9 +48,9 @@ public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processing protected virtual BlockExecutionContext CreateBlockExecutionContext(Block block) => new(block.Header); protected virtual void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, - ProcessingOptions processingOptions, Dictionary? stateOverride = null) + ProcessingOptions processingOptions) { - TransactionResult result = transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, stateProvider, stateOverride); + TransactionResult result = transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, stateProvider); if (!result) ThrowInvalidBlockException(result, blkCtx.Header, currentTx, index); TransactionProcessed?.Invoke(this, new TxProcessedEventArgs(index, currentTx, receiptsTracer.TxReceipts[index])); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index e29407223bc..adf73519275 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -82,8 +82,7 @@ public event EventHandler TransactionProcessed } // TODO: move to branch processor - public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions options, IBlockTracer blockTracer, - Dictionary? stateOverride = null) + public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions options, IBlockTracer blockTracer) { if (suggestedBlocks.Count == 0) return Array.Empty(); @@ -249,14 +248,13 @@ private void RestoreBranch(Hash256 branchingPointStateRoot) } // TODO: block processor pipeline - private (Block Block, TxReceipt[] Receipts) ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer, - Dictionary? stateOverride) + private (Block Block, TxReceipt[] Receipts) ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer) { if (_logger.IsTrace) _logger.Trace($"Processing block {suggestedBlock.ToString(Block.Format.Short)} ({options})"); ApplyDaoTransition(suggestedBlock); Block block = PrepareBlockForProcessing(suggestedBlock); - TxReceipt[] receipts = ProcessBlock(block, blockTracer, options, stateOverride); + TxReceipt[] receipts = ProcessBlock(block, blockTracer, options); ValidateProcessedBlock(suggestedBlock, options, block, receipts); if (options.ContainsFlag(ProcessingOptions.StoreReceipts)) { @@ -286,8 +284,7 @@ private bool ShouldComputeStateRoot(BlockHeader header) => protected virtual TxReceipt[] ProcessBlock( Block block, IBlockTracer blockTracer, - ProcessingOptions options, - Dictionary? stateOverride = null + ProcessingOptions options ) { BlockHeader header = block.Header; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index c299db12ec3..f4e0d10c254 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -320,7 +320,7 @@ private void RunProcessingLoop() if (_logger.IsTrace) _logger.Trace($"Processing block {block.ToString(Block.Format.Short)})."); _stats.Start(); - Block processedBlock = Process(block, blockRef.ProcessingOptions, _compositeBlockTracer.GetTracer(), null, out string? error); + Block processedBlock = Process(block, blockRef.ProcessingOptions, _compositeBlockTracer.GetTracer(), out string? error); if (processedBlock is null) { @@ -365,12 +365,12 @@ private void FireProcessingQueueEmpty() int IBlockProcessingQueue.Count => _queueCount; - public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride = null) + public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer) { - return Process(suggestedBlock, options, tracer, stateOverride, out _); + return Process(suggestedBlock, options, tracer, out _); } - public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride, out string? error) + public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, out string? error) { error = null; if (!RunSimpleChecksAheadOfProcessing(suggestedBlock, options)) @@ -398,7 +398,7 @@ private void FireProcessingQueueEmpty() PrepareBlocksToProcess(suggestedBlock, options, processingBranch); _stopwatch.Restart(); - Block[]? processedBlocks = ProcessBranch(processingBranch, options, tracer, stateOverride, out error); + Block[]? processedBlocks = ProcessBranch(processingBranch, options, tracer, out error); if (processedBlocks is null) { return null; @@ -485,7 +485,7 @@ private void TraceFailingBranch(in ProcessingBranch processingBranch, Processing } } - private Block[]? ProcessBranch(in ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride, out string? error) + private Block[]? ProcessBranch(in ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer tracer, out string? error) { void DeleteInvalidBlocks(in ProcessingBranch processingBranch, Hash256 invalidBlockHash) { @@ -509,8 +509,7 @@ void DeleteInvalidBlocks(in ProcessingBranch processingBranch, Hash256 invalidBl processingBranch.Root, processingBranch.BlocksToProcess, options, - tracer, - stateOverride); + tracer); error = null; } catch (InvalidBlockException ex) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs index 499d023fc54..a3c7439ab3c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs @@ -21,13 +21,11 @@ public interface IBlockProcessor /// List of blocks to be processed. /// Options to use for processor and transaction processor. /// Block tracer to use. By default either or - /// Optional state overrides by address. /// List of processed blocks. Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, - IBlockTracer blockTracer, - Dictionary? stateOverride = null); + IBlockTracer blockTracer); /// /// Fired when a branch is being processed. @@ -51,8 +49,7 @@ Block[] Process(Hash256 newBranchStateRoot, public interface IBlockTransactionsExecutor { - TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec, - Dictionary? stateOverride = null); + TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec); event EventHandler TransactionProcessed; } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs index e64d8b89d76..6a768769790 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs @@ -18,7 +18,7 @@ public interface IBlockchainProcessor : IDisposable Task StopAsync(bool processRemainingBlocks = false); - Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer, Dictionary? stateOverride = null); + Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer); bool IsProcessingBlocks(ulong? maxProcessingInterval); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs index 77af3597be5..27b8b466f1b 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs @@ -16,8 +16,7 @@ private NullBlockProcessor() { } public static IBlockProcessor Instance { get; } = new NullBlockProcessor(); - public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, IBlockTracer blockTracer, - Dictionary? stateOverride) + public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, IBlockTracer blockTracer) { return suggestedBlocks.ToArray(); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs index bbc58de06e0..b62fd732ccc 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs @@ -36,11 +36,11 @@ public Task StopAsync(bool processRemainingBlocks = false) return _processor.StopAsync(processRemainingBlocks); } - public Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer, Dictionary stateOverride) + public Block? Process(Block block, ProcessingOptions options, IBlockTracer tracer) { lock (_lock) { - return _processor.Process(block, options, tracer, stateOverride); + return _processor.Process(block, options, tracer); } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs index 4f2f389c68b..f0dbbdcd45e 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm; using Nethermind.Evm.Tracing; @@ -17,8 +16,7 @@ public static TransactionResult ProcessTransaction(this ITransactionProcessorAda Transaction currentTx, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, - IWorldState stateProvider, - Dictionary? stateOverride) + IWorldState stateProvider) { if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce) && currentTx.SenderAddress != Address.SystemUser) { @@ -26,7 +24,7 @@ public static TransactionResult ProcessTransaction(this ITransactionProcessorAda } using ITxTracer tracer = receiptsTracer.StartNewTxTrace(currentTx); - TransactionResult result = transactionProcessor.Execute(currentTx, in blkCtx, receiptsTracer, stateOverride); + TransactionResult result = transactionProcessor.Execute(currentTx, in blkCtx, receiptsTracer); receiptsTracer.EndTxTrace(); return result; } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 3516ca61e0c..912a8adf2e3 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -198,7 +198,7 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio try { - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken), options.StateOverrides); + _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken)); return tracer.BuildResult().SingleOrDefault(); } catch diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs index 7d241f0e8fb..406a7ee9b9e 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs @@ -20,8 +20,7 @@ public interface ITracer /// /// Block to trace. /// Trace to act on block processing events. - /// Optional state overrides by address. - void Trace(Block block, IBlockTracer tracer, Dictionary? stateOverride = null); + void Trace(Block block, IBlockTracer tracer); /// /// Allows to trace and verify arbitrary constructed block. Subtracts gas from sender account diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs index f7c456f2835..c7935ea4afa 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs @@ -29,8 +29,7 @@ public Tracer(IWorldState stateProvider, IBlockchainProcessor traceProcessor, IB _processingOptions = processingOptions; } - private void Process(Block block, IBlockTracer blockTracer, IBlockchainProcessor processor, - Dictionary? stateOverride = null) + private void Process(Block block, IBlockTracer blockTracer, IBlockchainProcessor processor) { /* We force process since we want to process a block that has already been processed in the past and normally it would be ignored. We also want to make it read only so the state is not modified persistently in any way. */ @@ -39,7 +38,7 @@ We also want to make it read only so the state is not modified persistently in a try { - processor.Process(block, _processingOptions, blockTracer, stateOverride); + processor.Process(block, _processingOptions, blockTracer); } catch (Exception) { @@ -50,8 +49,7 @@ We also want to make it read only so the state is not modified persistently in a blockTracer.EndBlockTrace(); } - public void Trace(Block block, IBlockTracer tracer, Dictionary? stateOverride = null) => - Process(block, tracer, _traceProcessor, stateOverride); + public void Trace(Block block, IBlockTracer tracer) => Process(block, tracer, _traceProcessor); public void Execute(Block block, IBlockTracer tracer) => Process(block, tracer, _executeProcessor); diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs index 6da856768ca..725546d03a5 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs @@ -9,8 +9,7 @@ namespace Nethermind.Evm.TransactionProcessing { public class BuildUpTransactionProcessorAdapter(ITransactionProcessor transactionProcessor) : ITransactionProcessorAdapter { - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, - Dictionary? stateOverride = null) => - transactionProcessor.BuildUp(transaction, in blkCtx, txTracer, stateOverride); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => + transactionProcessor.BuildUp(transaction, in blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs index 7c15af74e83..594f07f3865 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs @@ -23,8 +23,7 @@ public ChangeableTransactionProcessorAdapter(ITransactionProcessor transactionPr TransactionProcessor = transactionProcessor; } - public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, - Dictionary? stateOverride = null) => - CurrentAdapter.Execute(transaction, in blkCtx, txTracer, stateOverride); + public TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => + CurrentAdapter.Execute(transaction, in blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs index b04688cd6a5..e96538a1dd0 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs @@ -12,25 +12,21 @@ public interface ITransactionProcessor /// /// Execute transaction, commit state /// - TransactionResult Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, - Dictionary? stateOverride = null); + TransactionResult Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); /// /// Call transaction, rollback state /// - TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, - Dictionary? stateOverride = null); + TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); /// /// Execute transaction, keep the state uncommitted /// - TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, - Dictionary? stateOverride = null); + TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); /// /// Call transaction, no validations, commit state /// Will NOT charge gas from sender account, so stateDiff will miss gas fee /// - TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, - Dictionary? stateOverride = null); + TransactionResult Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs index 2802929b690..0aab55f32ca 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs @@ -9,7 +9,6 @@ namespace Nethermind.Evm.TransactionProcessing { public interface ITransactionProcessorAdapter { - TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer, - Dictionary? stateOverride = null); + TransactionResult Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 10c581a8f31..e0ed64fda21 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -98,8 +98,7 @@ protected TransactionProcessorBase( public TransactionResult CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => ExecuteCore(transaction, in blCtx, txTracer, ExecutionOptions.CommitAndRestore); - public TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer, - Dictionary? stateOverride = null) + public TransactionResult BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) { // we need to treat the result of previous transaction as the original value of next transaction // when we do not commit @@ -124,7 +123,7 @@ private TransactionResult ExecuteCore(Transaction tx, in BlockExecutionContext b return Execute(tx, in blCtx, tracer, opts); } - protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, Dictionary? stateOverride, ExecutionOptions opts) + protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) { BlockHeader header = blCtx.Header; IReleaseSpec spec = GetSpec(tx, header); @@ -145,9 +144,6 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon bool deleteCallerAccount = RecoverSenderIfNeeded(tx, spec, opts, effectiveGasPrice); - if (_codeInfoRepository is OverridableCodeInfoRepository overridableCodeInfoRepository) - WorldState.ApplyStateOverrides(overridableCodeInfoRepository, stateOverride, spec, blCtx.Header.Number, false); - if (!(result = ValidateSender(tx, header, spec, tracer, opts))) return result; if (!(result = BuyGas(tx, header, spec, tracer, opts, effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment, out UInt256 blobBaseFee))) return result; if (!(result = IncrementNonce(tx, header, spec, tracer, opts))) return result; diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index c543687bd15..1d16b2e793a 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -243,8 +243,8 @@ private TransactionResult TryCallAndRestore( try { return scope == null - ? CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer) - : CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer, scope); + ? CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer) + : CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, scope); } catch (InsufficientBalanceException ex) { @@ -255,18 +255,16 @@ private TransactionResult TryCallAndRestore( private TransactionResult CallAndRestore( BlockHeader blockHeader, Transaction transaction, - Dictionary? stateOverride, bool treatBlockHeaderAsParentBlock, ITxTracer tracer) { using IReadOnlyTxProcessingScope scope = _processingEnv.Build(blockHeader.StateRoot!); - return CallAndRestore(blockHeader, transaction, stateOverride, treatBlockHeaderAsParentBlock, tracer, scope); + return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, scope); } private TransactionResult CallAndRestore( BlockHeader blockHeader, Transaction transaction, - Dictionary? stateOverride, bool treatBlockHeaderAsParentBlock, ITxTracer tracer, IReadOnlyTxProcessingScope scope) @@ -315,7 +313,7 @@ private TransactionResult CallAndRestore( callHeader.MixHash = blockHeader.MixHash; callHeader.IsPostMerge = blockHeader.Difficulty == 0; transaction.Hash = transaction.CalculateHash(); - return scope.TransactionProcessor.CallAndRestore(transaction, new(callHeader), tracer, stateOverride); + return scope.TransactionProcessor.CallAndRestore(transaction, new(callHeader), tracer); } public ulong GetChainId() diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs index c4eee368be6..1d3172b87e0 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs @@ -34,14 +34,14 @@ protected override BlockExecutionContext CreateBlockExecutionContext(Block block blobBaseFeeOverride is not null ? new BlockExecutionContext(block.Header, blobBaseFeeOverride.Value) : base.CreateBlockExecutionContext(block); protected override void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, - ProcessingOptions processingOptions, Dictionary? stateOverride = null) + ProcessingOptions processingOptions) { if (!validate) { processingOptions |= ProcessingOptions.ForceProcessing | ProcessingOptions.DoNotVerifyNonce | ProcessingOptions.NoValidation; } - base.ProcessTransaction(in blkCtx, currentTx, index, receiptsTracer, processingOptions, stateOverride); + base.ProcessTransaction(in blkCtx, currentTx, index, receiptsTracer, processingOptions); } } diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs index 17b87175cd4..f668f15da6c 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs @@ -23,14 +23,13 @@ public sealed class SimulateTransactionProcessor( { protected override bool ShouldValidate(ExecutionOptions opts) => true; - protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, - Dictionary? stateOverride, ExecutionOptions opts) + protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) { if (!validate) { opts |= ExecutionOptions.NoValidation; } - return base.Execute(tx, in blCtx, tracer, stateOverride, opts); + return base.Execute(tx, in blCtx, tracer, opts); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index d4cd052a85f..096601bd1c9 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -321,7 +321,7 @@ private IReadOnlyCollection TraceBlock(Block block, ParityLik { using CancellationTokenSource cancellationTokenSource = new(_cancellationTokenTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; - _tracer.Trace(block, tracer.WithCancellation(cancellationToken), stateOverride); + _tracer.Trace(block, tracer.WithCancellation(cancellationToken)); return tracer.BuildResult(); } diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs index 1936e0a3049..040d08486f6 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs @@ -62,5 +62,5 @@ public class AuRaMergeBlockProcessor( protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) => block.IsPostMerge ? PostMergeProcessBlock(block, blockTracer, options) - : base.ProcessBlock(block, blockTracer, options, stateOverride); + : base.ProcessBlock(block, blockTracer, options); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index 97d513c5284..5162f5f4ff7 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -308,7 +308,7 @@ public TestBlockProcessorInterceptor(IBlockProcessor baseBlockProcessor, int del } public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, - IBlockTracer blockTracer, Dictionary? stateOverride) + IBlockTracer blockTracer) { if (DelayMs > 0) { @@ -320,7 +320,7 @@ public Block[] Process(Hash256 newBranchStateRoot, List suggestedBlocks, throw ExceptionToThrow; } - return _blockProcessorImplementation.Process(newBranchStateRoot, suggestedBlocks, processingOptions, blockTracer, stateOverride); + return _blockProcessorImplementation.Process(newBranchStateRoot, suggestedBlocks, processingOptions, blockTracer); } public event EventHandler? BlocksProcessing diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs index 2aa280f92a0..1e1289bf720 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs @@ -58,10 +58,9 @@ public OptimismBlockProcessor( ReceiptsTracer = new OptimismBlockReceiptTracer(opSpecHelper, stateProvider); } - protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options, - Dictionary? stateOverride = null) + protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) { _contractRewriter?.RewriteContract(block.Header, _stateProvider); - return base.ProcessBlock(block, blockTracer, options, stateOverride); + return base.ProcessBlock(block, blockTracer, options); } } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs index e1288422a32..89bc5d52d64 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs @@ -26,8 +26,7 @@ public sealed class OptimismTransactionProcessor( { private UInt256? _currentTxL1Cost; - protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, - Dictionary? stateOverride, ExecutionOptions opts) + protected override TransactionResult Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) { if (tx.SupportsBlobs) { @@ -44,7 +43,7 @@ protected override TransactionResult Execute(Transaction tx, in BlockExecutionCo Snapshot snapshot = WorldState.TakeSnapshot(); - TransactionResult result = base.Execute(tx, blCtx, tracer, stateOverride, opts); + TransactionResult result = base.Execute(tx, blCtx, tracer, opts); if (!result && tx.IsDeposit() && result.Error != "block gas limit exceeded") { From 5bf6c58b491debbf5abf04efc6617822156d8999 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 07:52:55 +0300 Subject: [PATCH 26/70] Code cleanup --- src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index d0e5c553e22..04dd3a78563 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; From bd28e704499a9283ed7efacf5797ccd889cb5471 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 08:04:43 +0300 Subject: [PATCH 27/70] Revert unneeded changes --- .../Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs | 1 - .../BlockProcessor.BlockValidationTransactionsExecutor.cs | 7 ++----- .../Nethermind.Consensus/Processing/BlockProcessor.cs | 3 +-- .../Nethermind.Consensus/Processing/BlockchainProcessor.cs | 2 -- .../Nethermind.Consensus/Processing/IBlockProcessor.cs | 5 ++--- .../Processing/IBlockchainProcessor.cs | 2 -- .../Nethermind.Consensus/Processing/NullBlockProcessor.cs | 1 - .../Nethermind.Consensus/Processing/OneTimeProcessor.cs | 3 +-- .../Nethermind.Consensus/Tracing/GethStyleTracer.cs | 1 - .../Nethermind.Consensus/Tracing/IGethStyleTracer.cs | 1 - src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs | 2 -- src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs | 2 -- .../BuildUpTransactionProcessorAdapter.cs | 1 - .../CallAndRestoreTransactionProcessorAdapter.cs | 2 -- .../ChangeableTransactionProcessorAdapter.cs | 1 - .../ExecuteTransactionProcessorAdapter.cs | 1 - .../TransactionProcessing/ITransactionProcessor.cs | 1 - .../TransactionProcessing/ITransactionProcessorAdapter.cs | 1 - .../TraceTransactionProcessorAdapter.cs | 1 - .../TransactionProcessing/TransactionProcessor.cs | 1 - .../Simulate/SimulateReadOnlyBlocksProcessingEnv.cs | 5 ++--- .../Simulate/SimulateTransactionProcessor.cs | 2 +- .../Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs | 1 - .../Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs | 1 + .../Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs | 1 - .../Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs | 1 - .../Modules/DebugModule/IDebugRpcModule.cs | 2 -- .../Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs | 1 - .../Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs | 1 - .../Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs | 2 -- .../EngineModuleTests.Setup.cs | 2 +- .../Nethermind.Optimism/OptimismBlockProcessor.cs | 1 - .../Nethermind.Optimism/OptimismTransactionProcessor.cs | 1 - src/Nethermind/Nethermind.State/OverridableWorldState.cs | 1 - 34 files changed, 11 insertions(+), 50 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 345724aa533..22253956f3d 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.BeaconBlockRoot; using Nethermind.Blockchain.Blocks; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs index dfb10e28f06..6d2299ef920 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -31,8 +30,7 @@ public BlockValidationTransactionsExecutor(ITransactionProcessor transactionProc public event EventHandler? TransactionProcessed; - public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, - IReleaseSpec spec) + public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec) { Metrics.ResetBlockStats(); BlockExecutionContext blkCtx = CreateBlockExecutionContext(block); @@ -47,8 +45,7 @@ public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processing protected virtual BlockExecutionContext CreateBlockExecutionContext(Block block) => new(block.Header); - protected virtual void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, - ProcessingOptions processingOptions) + protected virtual void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) { TransactionResult result = transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, stateProvider); if (!result) ThrowInvalidBlockException(result, blkCtx.Header, currentTx, index); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index adf73519275..a152ed5e551 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -284,8 +284,7 @@ private bool ShouldComputeStateRoot(BlockHeader header) => protected virtual TxReceipt[] ProcessBlock( Block block, IBlockTracer blockTracer, - ProcessingOptions options - ) + ProcessingOptions options) { BlockHeader header = block.Header; IReleaseSpec spec = _specProvider.GetSpec(header); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index f4e0d10c254..6598b9798a8 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -17,7 +17,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Memory; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.ParityStyle; @@ -369,7 +368,6 @@ private void FireProcessingQueueEmpty() { return Process(suggestedBlock, options, tracer, out _); } - public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer, out string? error) { error = null; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs index a3c7439ab3c..c8dbed52213 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockProcessor.cs @@ -6,7 +6,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; @@ -22,7 +21,8 @@ public interface IBlockProcessor /// Options to use for processor and transaction processor. /// Block tracer to use. By default either or /// List of processed blocks. - Block[] Process(Hash256 newBranchStateRoot, + Block[] Process( + Hash256 newBranchStateRoot, List suggestedBlocks, ProcessingOptions processingOptions, IBlockTracer blockTracer); @@ -50,7 +50,6 @@ Block[] Process(Hash256 newBranchStateRoot, public interface IBlockTransactionsExecutor { TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec); - event EventHandler TransactionProcessed; } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs index 6a768769790..b3703b653f8 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs @@ -2,10 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Evm; using Nethermind.Evm.Tracing; namespace Nethermind.Consensus.Processing diff --git a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs index 27b8b466f1b..6a5814c9b76 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/NullBlockProcessor.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing; namespace Nethermind.Consensus.Processing diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs index b62fd732ccc..cdeb4ab6712 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs @@ -2,10 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Evm; +using Nethermind.Db; using Nethermind.Evm.Tracing; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 912a8adf2e3..3e240bef779 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -16,7 +16,6 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.GethStyle.Custom.JavaScript; diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs index 1fa6d718044..4651add653e 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs @@ -6,7 +6,6 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs index 406a7ee9b9e..6306dcd1e8a 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/ITracer.cs @@ -1,10 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Trie; diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs index c7935ea4afa..00c2a85147d 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs @@ -2,11 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.State; using Nethermind.Trie; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs index 725546d03a5..2ac0a3b8fcb 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs index b07961b0aae..46316db20c8 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only // - -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs index 594f07f3865..38d9ccf67c9 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs index 16aef3fe033..8dc2274bc54 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs index e96538a1dd0..96ac8e27948 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs index 0aab55f32ca..ba77066d81a 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs index 5ff3e0700c4..12f2daf3168 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index e0ed64fda21..b21e56d310d 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs index 1d3172b87e0..5196c1850ac 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.BeaconBlockRoot; using Nethermind.Blockchain.Blocks; @@ -11,6 +10,7 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Evm; @@ -33,8 +33,7 @@ public class SimulateBlockValidationTransactionsExecutor( protected override BlockExecutionContext CreateBlockExecutionContext(Block block) => blobBaseFeeOverride is not null ? new BlockExecutionContext(block.Header, blobBaseFeeOverride.Value) : base.CreateBlockExecutionContext(block); - protected override void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, - ProcessingOptions processingOptions) + protected override void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) { if (!validate) { diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs index f668f15da6c..705a68ec071 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateTransactionProcessor.cs @@ -1,12 +1,12 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs index af34bdbbeac..97ed038d6d9 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs @@ -14,7 +14,6 @@ using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Facade.Eth; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.JsonRpc.Modules.Eth; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs index 020049685cd..b362a5439fd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsSimplePrecompiles.cs @@ -11,6 +11,7 @@ using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Evm.Precompiles; +using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs index 79ecc3f0dd0..dd7d34ebc82 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs @@ -16,7 +16,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Db; -using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; using Nethermind.State.Proofs; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs index 096d7db62ac..9b8db38d2cf 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs @@ -7,7 +7,6 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; using Nethermind.Synchronization.Reporting; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index f5df70a07f8..dc0a8bd9014 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -4,9 +4,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Blockchain.Find; -using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Facade.Eth; using Nethermind.JsonRpc.Data; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs index 145381f0c17..1721a52d804 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/ExecutorBase.cs @@ -7,7 +7,6 @@ using Nethermind.Core; using Nethermind.Evm; using Nethermind.Facade; -using Nethermind.Facade.Proxy.Models; namespace Nethermind.JsonRpc.Modules.Eth; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs index 991626de4c3..dfb320b0c28 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs @@ -11,7 +11,6 @@ using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Eth; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Facade.Simulate; diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs index 040d08486f6..8054855b51f 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.BeaconBlockRoot; using Nethermind.Blockchain.Receipts; @@ -15,7 +14,6 @@ using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index 5162f5f4ff7..fb20a057b19 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -25,7 +25,6 @@ using Nethermind.Core.Timers; using Nethermind.Crypto; using Nethermind.Db; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade.Eth; @@ -40,6 +39,7 @@ using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; +using Nethermind.State; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; using NSubstitute; diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs index 1e1289bf720..0c87d77e2a9 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs @@ -11,7 +11,6 @@ using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs index 89bc5d52d64..481c655d757 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm; diff --git a/src/Nethermind/Nethermind.State/OverridableWorldState.cs b/src/Nethermind/Nethermind.State/OverridableWorldState.cs index 40b15bd94e1..9e673f7a1c6 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldState.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldState.cs @@ -7,7 +7,6 @@ namespace Nethermind.State; -// TODO improve naming? public class OverridableWorldState : WorldState { private readonly OverlayTrieStore _trieStore; From a1bd302c41e9b00fd6fe232cc9816a5ea5cbdef5 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 09:01:54 +0300 Subject: [PATCH 28/70] Use `IOverridableCodeInfoRepository` interface instead of the implementation --- .../Processing/ReadOnlyTxProcessingScope.cs | 1 + .../Nethermind.Evm/IOverridableCodeInfoRepository.cs | 6 ++++++ src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs | 4 ++-- .../TransactionProcessing/IReadOnlyTxProcessingScope.cs | 1 + src/Nethermind/Nethermind.Facade/BlockchainBridge.cs | 4 ++-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs index a2f87bb9635..161a87cb675 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs @@ -23,6 +23,7 @@ public void Dispose() codeInfoRepository.ResetOverrides(); } + public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; public ITransactionProcessor TransactionProcessor => transactionProcessor; public IWorldState WorldState => worldState; } diff --git a/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs b/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs index 45b7dae2975..19e14f63b35 100644 --- a/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs +++ b/src/Nethermind/Nethermind.Evm/IOverridableCodeInfoRepository.cs @@ -1,9 +1,15 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Evm.CodeAnalysis; +using Nethermind.State; + namespace Nethermind.Evm; public interface IOverridableCodeInfoRepository : ICodeInfoRepository { + void SetCodeOverwrite(IWorldState worldState, IReleaseSpec vmSpec, Address key, CodeInfo value, Address? redirectAddress = null); public void ResetOverrides(); } diff --git a/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs index 8dc4d4b124f..14e0fd6b7e5 100644 --- a/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs @@ -16,7 +16,7 @@ public static class StateOverridesExtensions { public static void ApplyStateOverrides( this IWorldState state, - OverridableCodeInfoRepository overridableCodeInfoRepository, + IOverridableCodeInfoRepository overridableCodeInfoRepository, Dictionary? overrides, IReleaseSpec spec, long blockNumber) @@ -68,7 +68,7 @@ void ApplyState(Dictionary diff) private static void UpdateCode( this IWorldState stateProvider, - OverridableCodeInfoRepository overridableCodeInfoRepository, + IOverridableCodeInfoRepository overridableCodeInfoRepository, IReleaseSpec currentSpec, AccountOverride accountOverride, Address address) diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs index ce7bb61e8c3..5e5ead62383 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs @@ -8,6 +8,7 @@ namespace Nethermind.Evm.TransactionProcessing; public interface IReadOnlyTxProcessingScope : IDisposable { + IOverridableCodeInfoRepository CodeInfoRepository { get; } ITransactionProcessor TransactionProcessor { get; } IWorldState WorldState { get; } } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 1d16b2e793a..622df45af68 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -40,7 +40,7 @@ public interface IBlockchainBridgeFactory [Todo(Improve.Refactor, "I want to remove BlockchainBridge, split it into something with logging, state and tx processing. Then we can start using independent modules.")] public class BlockchainBridge : IBlockchainBridge { - private readonly ReadOnlyTxProcessingEnv _processingEnv; + private readonly IReadOnlyTxProcessorSource _processingEnv; private readonly IBlockTree _blockTree; private readonly IStateReader _stateReader; private readonly ITxPool _txPool; @@ -332,7 +332,7 @@ private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dict if (stateOverride != null) { - scope.WorldState.ApplyStateOverrides(_processingEnv.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); + scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); header.StateRoot = scope.WorldState.StateRoot; } return scope; From 15f0e3984448a55d0f50568f97bb3fda7694f243 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 09:33:25 +0300 Subject: [PATCH 29/70] Get rid of `NotSupportedException` --- .../Nethermind.State/OverridableWorldStateManager.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index 04dd3a78563..66149837e34 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -35,11 +35,8 @@ public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore t public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) { - // TODO add if needed? - if (forWarmup is not null) - throw new NotSupportedException("Overridable world state with warm up is not supported."); - - return new OverridableWorldState(_overlayTrieStore, _codeDb, _logManager); + PreBlockCaches? preBlockCaches = (forWarmup as IPreBlockCaches)?.Caches; + return new OverridableWorldState(_overlayTrieStore, _codeDb, _logManager, preBlockCaches); } public event EventHandler? ReorgBoundaryReached From f05b7d21f6949b439bf4f5f7dec1dad7571c478c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 09:44:26 +0300 Subject: [PATCH 30/70] Revert "Get rid of `NotSupportedException`" This reverts commit 15f0e3984448a55d0f50568f97bb3fda7694f243. --- .../Nethermind.State/OverridableWorldStateManager.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index 66149837e34..04dd3a78563 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -35,8 +35,11 @@ public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore t public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) { - PreBlockCaches? preBlockCaches = (forWarmup as IPreBlockCaches)?.Caches; - return new OverridableWorldState(_overlayTrieStore, _codeDb, _logManager, preBlockCaches); + // TODO add if needed? + if (forWarmup is not null) + throw new NotSupportedException("Overridable world state with warm up is not supported."); + + return new OverridableWorldState(_overlayTrieStore, _codeDb, _logManager); } public event EventHandler? ReorgBoundaryReached From cc3cb4c2b8507c7b6b1dfb1d051927b5e795972c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 3 Oct 2024 22:13:22 +0300 Subject: [PATCH 31/70] Simplify tests --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 4 ---- .../Modules/Trace/ParityStyleTracerTests.cs | 11 +++++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 7d8105c0e4a..fc379ade244 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -310,13 +310,9 @@ public async Task Eth_call_with_state_override(string name, string transaction, { using Context ctx = await Context.Create(); - Address sender = new("0x7f554713be84160fdf0178cc8df86f5aabd33397"); - ctx.Test.ReadOnlyState.AccountExists(sender).Should().BeFalse(); - string serialized = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); Assert.That(serialized, Is.EqualTo(expectedResult)); - ctx.Test.ReadOnlyState.AccountExists(sender).Should().BeFalse(); } [TestCase( diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index f9b10675107..9b8595c7ebf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -41,6 +41,7 @@ public class ParityStyleTracerTests private Tracer? _tracer; private IPoSSwitcher? _poSSwitcher; private IStateReader _stateReader; + private TraceRpcModule _traceRpcModule; private readonly IJsonRpcConfig _jsonRpcConfig = new JsonRpcConfig(); [SetUp] @@ -85,6 +86,7 @@ public void Setup() _processor.Process(genesis, ProcessingOptions.None, NullBlockTracer.Instance); _tracer = new Tracer(stateProvider, _processor, _processor); + _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader); } [TearDown] @@ -93,16 +95,14 @@ public void Setup() [Test] public void Can_trace_raw_parity_style() { - TraceRpcModule traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader); - ResultWrapper result = traceRpcModule.trace_rawTransaction(Bytes.FromHexString("f889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f"), new[] { "trace" }); + ResultWrapper result = _traceRpcModule.trace_rawTransaction(Bytes.FromHexString("f889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f"), new[] { "trace" }); Assert.That(result.Data, Is.Not.Null); } [Test] public void Can_trace_raw_parity_style_berlin_tx() { - TraceRpcModule traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader); - ResultWrapper result = traceRpcModule.trace_rawTransaction(Bytes.FromHexString("01f85b821e8e8204d7847735940083030d408080853a60005500c080a0f43e70c79190701347517e283ef63753f6143a5225cbb500b14d98eadfb7616ba070893923d8a1fc97499f426524f9e82f8e0322dfac7c3d7e8a9eee515f0bcdc4"), new[] { "trace" }); + ResultWrapper result = _traceRpcModule.trace_rawTransaction(Bytes.FromHexString("01f85b821e8e8204d7847735940083030d408080853a60005500c080a0f43e70c79190701347517e283ef63753f6143a5225cbb500b14d98eadfb7616ba070893923d8a1fc97499f426524f9e82f8e0322dfac7c3d7e8a9eee515f0bcdc4"), new[] { "trace" }); Assert.That(result.Data, Is.Not.Null); } @@ -114,8 +114,7 @@ public void Should_return_correct_block_reward(bool isPostMerge) _blockTree!.SuggestBlock(block).Should().Be(AddBlockResult.Added); _poSSwitcher!.IsPostMerge(Arg.Any()).Returns(isPostMerge); - TraceRpcModule traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader); - ParityTxTraceFromStore[] result = traceRpcModule.trace_block(new BlockParameter(block.Number)).Data.ToArray(); + ParityTxTraceFromStore[] result = _traceRpcModule.trace_block(new BlockParameter(block.Number)).Data.ToArray(); if (isPostMerge) { result.Length.Should().Be(1); From 82d7345eedeee4a20a113a2e7c38940c9f2ab97d Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sat, 5 Oct 2024 04:10:15 +0300 Subject: [PATCH 32/70] Update `trace_call` overrides tests --- .../Modules/TraceRpcModuleTests.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index b5112623e92..f712e27710d 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -852,24 +852,24 @@ public async Task Trace_replayBlockTransactions_stateDiff() [TestCase( "Nonce increments from state override", - """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000"}""", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", "stateDiff", - """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"nonce":"0x123"}}""", - """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"balance":"=","code":"=","nonce":{"*":{"from":"0x123","to":"0x124"}},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""", + """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"=","code":"=","nonce":{"*":{"from":"0x123","to":"0x124"}},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" )] [TestCase( "Uses account balance from state override", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", "stateDiff", """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""", - """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"*":{"from":"0x100","to":"0x0"}},"code":"=","nonce":{"\u002B":"0x1"},"storage":{}},"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f":{"balance":{"\u002B":"0x100"},"code":"=","nonce":{"\u002B":"0x0"},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" + """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"*":{"from":"0x100","to":"0x0"}},"code":"=","nonce":{"*":{"from":"0x0","to":"0x1"}},"storage":{}},"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f":{"balance":{"\u002B":"0x100"},"code":"=","nonce":{"\u002B":"0x0"},"storage":{}}},"trace":[],"vmTrace":null},"id":67}""" )] [TestCase( "Executes code from state override", - """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", - "trace", - """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", - """{"jsonrpc":"2.0","result":{"output":"0x00000000000000000000000000000000000000000000003635c9adc5de9f09e5","stateDiff":null,"trace":[{"action":{"callType":"call","from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","gas":"0x5f58d48","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","value":"0x0"},"result":{"gasUsed":"0x2df","output":"0x00000000000000000000000000000000000000000000003635c9adc5de9f09e5"},"subtraces":0,"traceAddress":[],"type":"call"}],"vmTrace":null},"id":67}""" + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0x60fe47b1112233445566778899001122334455667788990011223344556677889900112233445566778899001122"}""", + "stateDiff", + """{"0xc200000000000000000000000000000000000000":{"code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""", + """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"\u002B":"0x0"},"code":"=","nonce":{"\u002B":"0x1"},"storage":{}},"0xc200000000000000000000000000000000000000":{"balance":"=","code":"=","nonce":"=","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":{"*":{"from":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0x1122334455667788990011223344556677889900112233445566778899001122"}}}}},"trace":[],"vmTrace":null},"id":67}""" )] [TestCase( "Executes precompile using overriden address", @@ -881,7 +881,7 @@ public async Task Trace_replayBlockTransactions_stateDiff() public async Task Trace_call_with_state_override(string name, string transaction, string traceType, string stateOverride, string expectedResult) { Context context = new(); - await context.Build(); + await context.Build(new TestSpecProvider(Prague.Instance)); string serialized = await RpcTest.TestSerializedRequest( context.TraceRpcModule, "trace_call", transaction, new[] { traceType }, "latest", stateOverride); From df1e146fa5a5964e13ef84e90bbac3e284086ef5 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sat, 5 Oct 2024 04:11:05 +0300 Subject: [PATCH 33/70] Fix for "Account is null when updating storage hash" on code override --- src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs index 14e0fd6b7e5..fa786cc88fd 100644 --- a/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/StateOverridesExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -75,6 +76,8 @@ private static void UpdateCode( { if (accountOverride.Code is not null) { + stateProvider.InsertCode(address, accountOverride.Code, currentSpec); + overridableCodeInfoRepository.SetCodeOverwrite( stateProvider, currentSpec, From e35f7e457a8e265f8835ac881e676fd7790b4c8c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sat, 5 Oct 2024 05:09:04 +0300 Subject: [PATCH 34/70] [WIP] State overrides for `trace_call` using `OverridableWorldState` --- .../Steps/RegisterRpcModules.cs | 2 ++ .../Modules/TestRpcBlockchain.cs | 2 ++ .../Modules/Trace/ParityStyleTracerTests.cs | 3 ++- .../Modules/TraceRpcModuleTests.cs | 4 ++-- .../Modules/Trace/TraceModuleFactory.cs | 8 +++---- .../Modules/Trace/TraceRpcModule.cs | 23 ++++++++++++++++++- .../Rpc/OptimismTraceModuleFactory.cs | 3 +++ .../Rpc/RegisterOptimismRpcModules.cs | 2 ++ 8 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index db5341d33b4..5fae7546c6b 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -250,6 +250,7 @@ protected virtual void RegisterEthRpcModule(IRpcModuleProvider rpcModuleProvider protected ModuleFactoryBase CreateTraceModuleFactory() { StepDependencyException.ThrowIfNull(_api.WorldStateManager); + StepDependencyException.ThrowIfNull(_api.DbProvider); StepDependencyException.ThrowIfNull(_api.BlockTree); StepDependencyException.ThrowIfNull(_api.RewardCalculatorSource); StepDependencyException.ThrowIfNull(_api.ReceiptStorage); @@ -257,6 +258,7 @@ protected ModuleFactoryBase CreateTraceModuleFactory() return new TraceModuleFactory( _api.WorldStateManager, + _api.DbProvider, _api.BlockTree, _jsonRpcConfig, _api.BlockPreprocessor, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index 9767fefccdf..a3aab10da2e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -46,6 +46,7 @@ public class TestRpcBlockchain : TestBlockchain public ITxSender TxSender { get; private set; } = null!; public IReceiptFinder ReceiptFinder { get; private set; } = null!; public IGasPriceOracle GasPriceOracle { get; private set; } = null!; + public OverridableWorldStateManager OverridableWorldStateManager { get; private set; } = null!; public IKeyStore KeyStore { get; } = new MemKeyStore(TestItem.PrivateKeys, Path.Combine("testKeyStoreDir", Path.GetRandomFileName())); public IWallet TestWallet { get; } = @@ -172,6 +173,7 @@ protected override async Task Build( GasPriceOracle ??= new GasPriceOracle(BlockFinder, SpecProvider, LogManager); FeeHistoryOracle ??= new FeeHistoryOracle(BlockTree, ReceiptStorage, SpecProvider); EthRpcModule = _ethRpcModuleBuilder(this); + OverridableWorldStateManager = overridableWorldStateManager; return this; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index 9b8595c7ebf..d754ed8870d 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -85,8 +85,9 @@ public void Setup() _blockTree.SuggestBlock(genesis); _processor.Process(genesis, ProcessingOptions.None, NullBlockTracer.Instance); + IReadOnlyTxProcessorSource readOnlyTxProcessingSource = Substitute.For(); _tracer = new Tracer(stateProvider, _processor, _processor); - _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader); + _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader, readOnlyTxProcessingSource, specProvider); } [TearDown] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index f712e27710d..27ccc06ffa3 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -47,7 +47,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) new(Blockchain.EthereumEcdsa, Blockchain.SpecProvider); IReceiptFinder receiptFinder = new FullInfoReceiptFinder(Blockchain.ReceiptStorage, receiptsRecovery, Blockchain.BlockFinder); ReadOnlyTxProcessingEnv txProcessingEnv = - new(Blockchain.WorldStateManager, Blockchain.BlockTree.AsReadOnly(), Blockchain.SpecProvider, Blockchain.LogManager); + new(Blockchain.OverridableWorldStateManager, Blockchain.BlockTree.AsReadOnly(), Blockchain.SpecProvider, Blockchain.LogManager); IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(Keccak.EmptyTreeHash); RewardCalculator rewardCalculatorSource = new(Blockchain.SpecProvider); @@ -74,7 +74,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) ReadOnlyChainProcessingEnv executeProcessingEnv = CreateChainProcessingEnv(executeBlockTransactionsExecutor); Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor); - TraceRpcModule = new TraceRpcModule(receiptFinder, tracer, Blockchain.BlockFinder, JsonRpcConfig, txProcessingEnv.StateReader); + TraceRpcModule = new TraceRpcModule(receiptFinder, tracer, Blockchain.BlockFinder, JsonRpcConfig, txProcessingEnv, Blockchain.SpecProvider); for (int i = 1; i < 10; i++) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 1ec63377195..77f1f818177 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus; @@ -16,12 +15,12 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.State; -using Nethermind.Trie.Pruning; namespace Nethermind.JsonRpc.Modules.Trace; public class TraceModuleFactory( IWorldStateManager worldStateManager, + IDbProvider dbProvider, IBlockTree blockTree, IJsonRpcConfig jsonRpcConfig, IBlockPreprocessorStep recoveryStep, @@ -31,7 +30,7 @@ public class TraceModuleFactory( IPoSSwitcher poSSwitcher, ILogManager logManager) : ModuleFactoryBase { - protected readonly IWorldStateManager _worldStateManager = worldStateManager; + protected readonly IWorldStateManager _worldStateManager = new OverridableWorldStateManager(dbProvider, worldStateManager.TrieStore, logManager); protected readonly IReadOnlyBlockTree _blockTree = blockTree.AsReadOnly(); protected readonly IJsonRpcConfig _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); protected readonly IReceiptStorage _receiptStorage = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); @@ -72,7 +71,6 @@ public override ITraceRpcModule Create() Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor); - return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv.StateReader); + return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv, specProvider); } - } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 096601bd1c9..5b341480206 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -8,12 +8,15 @@ using FastEnumUtility; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; +using Nethermind.Consensus.Processing; using Nethermind.Consensus.Tracing; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; +using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade.Eth; using Nethermind.Int256; using Nethermind.JsonRpc.Data; @@ -39,17 +42,24 @@ public class TraceRpcModule : ITraceRpcModule private readonly IJsonRpcConfig _jsonRpcConfig; private readonly TimeSpan _cancellationTokenTimeout; private readonly IStateReader _stateReader; + private readonly IReadOnlyTxProcessorSource _env; + private readonly ISpecProvider _specProvider; - public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, IStateReader stateReader) + public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, IStateReader? stateReader, IReadOnlyTxProcessorSource? env, ISpecProvider? specProvider) { _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader)); + _env = env ?? throw new ArgumentNullException(nameof(env)); + _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _cancellationTokenTimeout = TimeSpan.FromMilliseconds(_jsonRpcConfig.Timeout); } + public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, ReadOnlyTxProcessingEnv? env, ISpecProvider? specProvider) + : this(receiptFinder, tracer, blockFinder, jsonRpcConfig, env?.StateReader, env, specProvider) { } + public static ParityTraceTypes GetParityTypes(string[] types) => types.Select(s => FastEnum.Parse(s, true)).Aggregate((t1, t2) => t1 | t2); @@ -321,7 +331,10 @@ private IReadOnlyCollection TraceBlock(Block block, ParityLik { using CancellationTokenSource cancellationTokenSource = new(_cancellationTokenTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; + + using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(block.Header, stateOverride) : null; _tracer.Trace(block, tracer.WithCancellation(cancellationToken)); + return tracer.BuildResult(); } @@ -335,5 +348,13 @@ private IReadOnlyCollection ExecuteBlock(Block block, ParityL private static ResultWrapper GetStateFailureResult(BlockHeader header) => ResultWrapper.Fail($"No state available for block {header.ToString(BlockHeader.Format.FullHashAndNumber)}", ErrorCodes.ResourceUnavailable); + + private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) + { + IReadOnlyTxProcessingScope scope = _env.Build(header.StateRoot!); + scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); + header.StateRoot = scope.WorldState.StateRoot; + return scope; + } } } diff --git a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs index 8a1b5da4d21..cf15106e8bb 100644 --- a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs @@ -9,6 +9,7 @@ using Nethermind.Consensus.Validators; using Nethermind.Consensus.Withdrawals; using Nethermind.Core.Specs; +using Nethermind.Db; using Nethermind.Evm.TransactionProcessing; using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules.Trace; @@ -19,6 +20,7 @@ namespace Nethermind.Optimism.Rpc; public class OptimismTraceModuleFactory( IWorldStateManager worldStateManager, + IDbProvider dbProvider, IBlockTree blockTree, IJsonRpcConfig jsonRpcConfig, IBlockPreprocessorStep recoveryStep, @@ -32,6 +34,7 @@ public class OptimismTraceModuleFactory( Create2DeployerContractRewriter contractRewriter, IWithdrawalProcessor withdrawalProcessor) : TraceModuleFactory( worldStateManager, + dbProvider, blockTree, jsonRpcConfig, recoveryStep, diff --git a/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs b/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs index 04da5fca22e..73706c7aace 100644 --- a/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs +++ b/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs @@ -94,6 +94,7 @@ protected override void RegisterEthRpcModule(IRpcModuleProvider rpcModuleProvide protected override void RegisterTraceRpcModule(IRpcModuleProvider rpcModuleProvider) { StepDependencyException.ThrowIfNull(_api.WorldStateManager); + StepDependencyException.ThrowIfNull(_api.DbProvider); StepDependencyException.ThrowIfNull(_api.BlockTree); StepDependencyException.ThrowIfNull(_api.ReceiptStorage); StepDependencyException.ThrowIfNull(_api.RewardCalculatorSource); @@ -104,6 +105,7 @@ protected override void RegisterTraceRpcModule(IRpcModuleProvider rpcModuleProvi OptimismTraceModuleFactory traceModuleFactory = new( _api.WorldStateManager, + _api.DbProvider, _api.BlockTree, _jsonRpcConfig, _api.BlockPreprocessor, From d4f75c5bae79128e9022b66fcfd3ed0b1bbaa131 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sat, 5 Oct 2024 23:53:45 +0300 Subject: [PATCH 35/70] Code cleanup --- src/Nethermind/Nethermind.Facade/BlockchainBridge.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index a62370fb7cf..b9d65311caa 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -152,7 +152,7 @@ public CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride, bool treatBlockHeaderAsParentBlock, ITxTracer tracer, IReadOnlyTxProcessingScope? scope = null) From 606b5696dc7bda45aa32a853a1f6adbc76b35bed Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 9 Oct 2024 22:54:00 +0300 Subject: [PATCH 36/70] Change `trace_call` and `trace_rawTransaction` to use specified block instead of previous one --- .../Modules/TraceRpcModuleTests.cs | 60 +++++++++++++++++++ .../Modules/Trace/TraceRpcModule.cs | 22 +++++-- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 27ccc06ffa3..bb56b47a9a6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -21,7 +21,9 @@ using Nethermind.Consensus.Tracing; using Nethermind.Consensus.Validators; using Nethermind.Core.Crypto; +using Nethermind.Crypto; using Nethermind.Evm; +using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade.Eth; using Nethermind.Serialization.Json; @@ -29,6 +31,7 @@ using Nethermind.Specs.Test; using Nethermind.JsonRpc.Data; using Nethermind.JsonRpc.Modules; +using Nethermind.Serialization.Rlp; namespace Nethermind.JsonRpc.Test.Modules; @@ -675,6 +678,63 @@ public async Task Trace_call_without_blockParameter_provided_test() Assert.That(traces.Data.Action.To, Is.EqualTo(TestItem.AddressC)); } + [Test] + public async Task Trace_call_runs_on_top_of_specified_block() + { + Context context = new(); + await context.Build(); + TestRpcBlockchain blockchain = context.Blockchain; + + PrivateKey addressKey = Build.A.PrivateKey.TestObject; + Address address = addressKey.Address; + UInt256 balance = 100.Ether(), send = balance / 2; + + await blockchain.AddFunds(address, balance); + Hash256 lastBlockHash = blockchain.BlockTree.Head!.Hash!; + + string[] traceTypes = ["stateDiff"]; + Transaction transaction = Build.A.Transaction + .SignedAndResolved(addressKey) + .WithTo(TestItem.AddressC) + .WithValue(send) + .TestObject; + + ResultWrapper traces = context.TraceRpcModule.trace_call( + new(transaction), traceTypes, new(lastBlockHash) + ); + + ParityAccountStateChange? stateChanges = traces.Data.StateChanges?.GetValueOrDefault(address); + stateChanges?.Balance?.Should().BeEquivalentTo(new ParityStateChange(balance, balance - send)); + } + + [Test] + public async Task Trace_rawTransaction_runs_on_top_of_specified_block() + { + Context context = new(); + await context.Build(); + TestRpcBlockchain blockchain = context.Blockchain; + + PrivateKey addressKey = Build.A.PrivateKey.TestObject; + Address address = addressKey.Address; + UInt256 balance = 100.Ether(), send = balance / 2; + + await blockchain.AddFunds(address, balance); + + string[] traceTypes = ["stateDiff"]; + Transaction transaction = Build.A.Transaction + .WithTo(TestItem.AddressC) + .WithValue(send) + .SignedAndResolved(addressKey) + .TestObject; + + ResultWrapper traces = context.TraceRpcModule.trace_rawTransaction( + TxDecoder.Instance.Encode(transaction).Bytes, traceTypes + ); + + ParityAccountStateChange? stateChanges = traces.Data.StateChanges?.GetValueOrDefault(address); + stateChanges?.Balance?.Should().BeEquivalentTo(new ParityStateChange(balance, balance - send)); + } + [Test] public async Task Trace_call_simple_tx_test() { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 5b341480206..15e7ace3caf 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -13,6 +13,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; @@ -160,10 +161,22 @@ private ResultWrapper TraceTx(Transaction tx, string[] return ResultWrapper.Fail(headerSearch); } - Block block = new(headerSearch.Object!, new[] { tx }, Enumerable.Empty()); + BlockHeader header = headerSearch.Object!.Clone(); + + // Fake next-block header to force BlockProcessor to start from instead of - 1 + // TODO consider alternative approaches to achieve this + BlockHeader nextHeader = header.Clone(); + nextHeader.Number = header.Number + 1; + nextHeader.ParentHash = header.Hash; + nextHeader.MaybeParent = new (header); + + Block block = new(nextHeader, [tx], []); + nextHeader.Hash = block.CalculateHash(); + + using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(header, stateOverride) : null; ParityTraceTypes traceTypes1 = GetParityTypes(traceTypes); - IReadOnlyCollection result = TraceBlock(block, new(traceTypes1), stateOverride); + IReadOnlyCollection result = TraceBlock(block, new(traceTypes1)); return ResultWrapper.Success(new ParityTxTraceFromReplay(result.SingleOrDefault())); } @@ -326,15 +339,12 @@ public ResultWrapper> trace_transaction(Hash return ResultWrapper>.Success(ParityTxTraceFromStore.FromTxTrace(txTrace)); } - private IReadOnlyCollection TraceBlock(Block block, ParityLikeBlockTracer tracer, - Dictionary? stateOverride = null) + private IReadOnlyCollection TraceBlock(Block block, ParityLikeBlockTracer tracer) { using CancellationTokenSource cancellationTokenSource = new(_cancellationTokenTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; - using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(block.Header, stateOverride) : null; _tracer.Trace(block, tracer.WithCancellation(cancellationToken)); - return tracer.BuildResult(); } From 3c3f6b03666d2010da7500a14ca07a44c908d52b Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Fri, 11 Oct 2024 07:56:43 +0300 Subject: [PATCH 37/70] Test fix --- .../Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index bb56b47a9a6..c43f751e6d5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -951,18 +951,20 @@ public async Task Trace_call_with_state_override(string name, string transaction [TestCase( """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000"}""", + "stateDiff", """{"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099":{"balance":"0x123", "nonce": "0x123"}}""" )] [TestCase( """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + "trace", """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" )] - public async Task Trace_call_with_state_override_does_not_affect_other_calls(string transaction, string stateOverride) + public async Task Trace_call_with_state_override_does_not_affect_other_calls(string transaction, string traceType, string stateOverride) { Context context = new(); await context.Build(); - var traceTypes = new[] { "stateDiff" }; + var traceTypes = new[] { traceType }; var resultOverrideBefore = await RpcTest.TestSerializedRequest(context.TraceRpcModule, "trace_call", transaction, traceTypes, null, stateOverride); From eba8bf048f15f490d5ae6ff7360c3ef2f261aa81 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Fri, 11 Oct 2024 07:59:40 +0300 Subject: [PATCH 38/70] Code cleanup --- .../Nethermind.Evm/OverridableCodeInfoRepository.cs | 2 +- .../Nethermind.Facade.Test/BlockchainBridgeTests.cs | 8 ++++---- .../Nethermind.Facade/BlockchainBridgeContract.cs | 2 +- src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs | 3 +-- .../Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs | 2 +- .../Nethermind.State/OverridableWorldStateManager.cs | 1 - 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs b/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs index c5343fee137..0342586f261 100644 --- a/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs +++ b/src/Nethermind/Nethermind.Evm/OverridableCodeInfoRepository.cs @@ -50,6 +50,6 @@ public bool TryGetDelegation(IReadOnlyStateProvider worldState, Address address, public ValueHash256 GetExecutableCodeHash(IWorldState worldState, Address address) => codeInfoRepository.GetExecutableCodeHash(worldState, address); - + public void ResetOverrides() => _codeOverwrites.Clear(); } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 523c185ef3d..b36d2615327 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -157,7 +157,7 @@ public void Call_uses_valid_post_merge_and_random_value() Transaction tx = Build.A.Transaction.TestObject; - _blockchainBridge.Call(header, tx, CancellationToken.None); + _blockchainBridge.Call(header, tx); _transactionProcessor.Received().CallAndRestore( tx, Arg.Is(blkCtx => @@ -173,7 +173,7 @@ public void Call_uses_valid_block_number() BlockHeader header = Build.A.BlockHeader.WithNumber(10).TestObject; Transaction tx = new() { GasLimit = Transaction.BaseTxGasCost }; - _blockchainBridge.Call(header, tx, CancellationToken.None); + _blockchainBridge.Call(header, tx); _transactionProcessor.Received().CallAndRestore( tx, Arg.Is(blkCtx => blkCtx.Header.Number == 10), @@ -188,7 +188,7 @@ public void Call_uses_valid_mix_hash() BlockHeader header = Build.A.BlockHeader.WithMixHash(TestItem.KeccakA).TestObject; Transaction tx = new() { GasLimit = Transaction.BaseTxGasCost }; - _blockchainBridge.Call(header, tx, CancellationToken.None); + _blockchainBridge.Call(header, tx); _transactionProcessor.Received().CallAndRestore( tx, Arg.Is(blkCtx => blkCtx.Header.MixHash == TestItem.KeccakA), @@ -203,7 +203,7 @@ public void Call_uses_valid_beneficiary() BlockHeader header = Build.A.BlockHeader.WithBeneficiary(TestItem.AddressB).TestObject; Transaction tx = new() { GasLimit = Transaction.BaseTxGasCost }; - _blockchainBridge.Call(header, tx, CancellationToken.None); + _blockchainBridge.Call(header, tx); _transactionProcessor.Received().CallAndRestore( tx, Arg.Is(blkCtx => blkCtx.Header.Beneficiary == TestItem.AddressB), diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridgeContract.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridgeContract.cs index 438bb096bd0..abe697c2540 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridgeContract.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridgeContract.cs @@ -36,7 +36,7 @@ public ConstantBridgeContract(Contract contract, IBlockchainBridge blockchainBri public override object[] Call(CallInfo callInfo) { var transaction = GenerateTransaction(callInfo); - var result = _blockchainBridge.Call(callInfo.ParentHeader, transaction, CancellationToken.None); + var result = _blockchainBridge.Call(callInfo.ParentHeader, transaction); if (!string.IsNullOrEmpty(result.Error)) { throw new AbiException(result.Error); diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 90c7098c8fc..70a83f3a52d 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -27,8 +27,7 @@ public interface IBlockchainBridge : ILogFinder TxReceipt GetReceipt(Hash256 txHash); (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) GetReceiptAndGasInfo(Hash256 txHash); (TxReceipt? Receipt, Transaction? Transaction, UInt256? baseFee) GetTransaction(Hash256 txHash, bool checkTxnPool = true); - CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken cancellationToken); - CallOutput Call(BlockHeader header, Transaction tx, CancellationToken cancellationToken) => Call(header, tx, null, cancellationToken); + CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride = null, CancellationToken cancellationToken = default); SimulateOutput Simulate(BlockHeader header, SimulatePayload payload, CancellationToken cancellationToken); CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMarginBasisPoints, Dictionary stateOverride, CancellationToken cancellationToken); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 15e7ace3caf..f0d1ebc29d1 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -168,7 +168,7 @@ private ResultWrapper TraceTx(Transaction tx, string[] BlockHeader nextHeader = header.Clone(); nextHeader.Number = header.Number + 1; nextHeader.ParentHash = header.Hash; - nextHeader.MaybeParent = new (header); + nextHeader.MaybeParent = new(header); Block block = new(nextHeader, [tx], []); nextHeader.Hash = block.CalculateHash(); diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index 04dd3a78563..1483cc500bc 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -35,7 +35,6 @@ public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore t public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) { - // TODO add if needed? if (forWarmup is not null) throw new NotSupportedException("Overridable world state with warm up is not supported."); From 4ee465823a0b673af9695e81e2479401950a2897 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Fri, 11 Oct 2024 22:33:44 +0300 Subject: [PATCH 39/70] Fix unit tests --- .../Modules/Trace/TraceRpcModule.cs | 73 +++++++++---------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index f0d1ebc29d1..7d67b75681b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -84,15 +84,21 @@ public ResultWrapper> trace_callMany(Transa { blockParameter ??= BlockParameter.Latest; - SearchResult headerSearch = SearchBlockHeaderForTraceCall(blockParameter); + SearchResult headerSearch = _blockFinder.SearchForHeader(blockParameter); if (headerSearch.IsError) { return ResultWrapper>.Fail(headerSearch); } - if (!_stateReader.HasStateForBlock(headerSearch.Object)) + BlockHeader header = headerSearch.Object!; + if (headerSearch.Object!.IsGenesis) + { + header = GenerateFakeNextHeader(header); + } + + if (!_stateReader.HasStateForBlock(header)) { - return GetStateFailureResult>(headerSearch.Object); + return GetStateFailureResult>(header); } Dictionary traceTypeByTransaction = new(calls.Length); @@ -107,7 +113,7 @@ public ResultWrapper> trace_callMany(Transa traceTypeByTransaction.Add(tx.Hash, traceTypes); } - Block block = new(headerSearch.Object!, txs, Enumerable.Empty()); + Block block = new(header, txs, Enumerable.Empty()); IReadOnlyCollection? traces = TraceBlock(block, new(traceTypeByTransaction)); return ResultWrapper>.Success(traces.Select(t => new ParityTxTraceFromReplay(t))); } @@ -121,57 +127,44 @@ public ResultWrapper trace_rawTransaction(byte[] data, return TraceTx(tx, traceTypes, BlockParameter.Latest); } - private SearchResult SearchBlockHeaderForTraceCall(BlockParameter blockParameter) + /// + /// Generates fake next-block header to force to start from the specified header instead of header - 1. + /// + private static BlockHeader GenerateFakeNextHeader(BlockHeader header) { - SearchResult headerSearch = _blockFinder.SearchForHeader(blockParameter); - if (headerSearch.IsError) + UInt256 baseFee = header.BaseFeePerGas; + var nextHeader = new BlockHeader( + header.Hash!, + Keccak.OfAnEmptySequenceRlp, + Address.Zero, + header.Difficulty, + header.Number + 1, + header.GasLimit, + header.Timestamp + 1, + header.ExtraData, + header.BlobGasUsed, + header.ExcessBlobGas) { - return headerSearch; - } - - BlockHeader header = headerSearch.Object; - if (header!.IsGenesis) - { - UInt256 baseFee = header.BaseFeePerGas; - header = new BlockHeader( - header.Hash!, - Keccak.OfAnEmptySequenceRlp, - Address.Zero, - header.Difficulty, - header.Number + 1, - header.GasLimit, - header.Timestamp + 1, - header.ExtraData, - header.BlobGasUsed, - header.ExcessBlobGas); - - header.TotalDifficulty = 2 * header.Difficulty; - header.BaseFeePerGas = baseFee; - } + MaybeParent = new(header), + TotalDifficulty = 2 * header.Difficulty, + BaseFeePerGas = baseFee + }; - return new SearchResult(header); + return nextHeader; } private ResultWrapper TraceTx(Transaction tx, string[] traceTypes, BlockParameter blockParameter, Dictionary? stateOverride = null) { - SearchResult headerSearch = SearchBlockHeaderForTraceCall(blockParameter); + SearchResult headerSearch = _blockFinder.SearchForHeader(blockParameter); if (headerSearch.IsError) { return ResultWrapper.Fail(headerSearch); } BlockHeader header = headerSearch.Object!.Clone(); - - // Fake next-block header to force BlockProcessor to start from instead of - 1 - // TODO consider alternative approaches to achieve this - BlockHeader nextHeader = header.Clone(); - nextHeader.Number = header.Number + 1; - nextHeader.ParentHash = header.Hash; - nextHeader.MaybeParent = new(header); - + BlockHeader nextHeader = GenerateFakeNextHeader(header); Block block = new(nextHeader, [tx], []); - nextHeader.Hash = block.CalculateHash(); using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(header, stateOverride) : null; From 9c0244b0a7f938f0aab51bb25c791f0f3c6a3280 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sat, 12 Oct 2024 01:05:39 +0300 Subject: [PATCH 40/70] Switch to `ProcessingOptions.ForceState` instead of generating fake header & fix starting block for `trace_callMany` --- .../Processing/BlockchainProcessor.cs | 6 ++- .../Processing/ProcessingOptions.cs | 11 +++++- .../Nethermind.Consensus/Tracing/Tracer.cs | 16 ++++---- .../Modules/TraceRpcModuleTests.cs | 39 +++++++++++++++++-- .../Modules/Trace/TraceModuleFactory.cs | 3 +- .../Modules/Trace/TraceRpcModule.cs | 34 +--------------- 6 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index 6598b9798a8..6a49eb42ed7 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -632,8 +632,10 @@ private ProcessingBranch PrepareProcessingBranch(Block suggestedBlock, Processin break; } - branchingPoint = _blockTree.FindParentHeader(toBeProcessed.Header, - BlockTreeLookupOptions.TotalDifficultyNotNeeded); + branchingPoint = options.ContainsFlag(ProcessingOptions.ForceState) + ? toBeProcessed.Header + : _blockTree.FindParentHeader(toBeProcessed.Header, BlockTreeLookupOptions.TotalDifficultyNotNeeded); + if (branchingPoint is null) { // genesis block diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs index 555e1c9e1dd..24642ffb366 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs @@ -51,7 +51,10 @@ public enum ProcessingOptions /// MarkAsProcessed = 128, - All = 255, + /// + /// Forces to run on top of specified block state, instead of reverting to the previous one. + /// + ForceState = 1 << 8, /// /// Combination of switches for block producers when they preprocess block for state root calculation. @@ -63,6 +66,12 @@ public enum ProcessingOptions /// Trace = ForceProcessing | ReadOnlyChain | DoNotVerifyNonce | NoValidation, + /// + /// EVM tracing needs to process one or more transactions on top of the specified block (instead of the previous one) + /// without storing the data on chain. + /// + TraceTransactions = Trace | ForceState, + /// /// Processing options for engine_NewPayload /// diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs index 00c2a85147d..df6c3c721bd 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/Tracer.cs @@ -16,18 +16,20 @@ public class Tracer : ITracer private readonly IWorldState _stateProvider; private readonly IBlockchainProcessor _traceProcessor; private readonly IBlockchainProcessor _executeProcessor; - private readonly ProcessingOptions _processingOptions; + private readonly ProcessingOptions _executeOptions; + private readonly ProcessingOptions _traceOptions; public Tracer(IWorldState stateProvider, IBlockchainProcessor traceProcessor, IBlockchainProcessor executeProcessor, - ProcessingOptions processingOptions = ProcessingOptions.Trace) + ProcessingOptions executeOptions = ProcessingOptions.Trace, ProcessingOptions traceOptions = ProcessingOptions.Trace) { _traceProcessor = traceProcessor; _executeProcessor = executeProcessor; _stateProvider = stateProvider; - _processingOptions = processingOptions; + _executeOptions = executeOptions; + _traceOptions = traceOptions; } - private void Process(Block block, IBlockTracer blockTracer, IBlockchainProcessor processor) + private void Process(Block block, IBlockTracer blockTracer, IBlockchainProcessor processor, ProcessingOptions options) { /* We force process since we want to process a block that has already been processed in the past and normally it would be ignored. We also want to make it read only so the state is not modified persistently in any way. */ @@ -36,7 +38,7 @@ We also want to make it read only so the state is not modified persistently in a try { - processor.Process(block, _processingOptions, blockTracer); + processor.Process(block, options, blockTracer); } catch (Exception) { @@ -47,9 +49,9 @@ We also want to make it read only so the state is not modified persistently in a blockTracer.EndBlockTrace(); } - public void Trace(Block block, IBlockTracer tracer) => Process(block, tracer, _traceProcessor); + public void Trace(Block block, IBlockTracer tracer) => Process(block, tracer, _traceProcessor, _traceOptions); - public void Execute(Block block, IBlockTracer tracer) => Process(block, tracer, _executeProcessor); + public void Execute(Block block, IBlockTracer tracer) => Process(block, tracer, _executeProcessor, _executeOptions); public void Accept(ITreeVisitor visitor, Hash256 stateRoot) { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index c43f751e6d5..38069a01a3f 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -76,7 +76,8 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) ReadOnlyChainProcessingEnv traceProcessingEnv = CreateChainProcessingEnv(rpcBlockTransactionsExecutor); ReadOnlyChainProcessingEnv executeProcessingEnv = CreateChainProcessingEnv(executeBlockTransactionsExecutor); - Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor); + Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, + traceOptions: ProcessingOptions.TraceTransactions); TraceRpcModule = new TraceRpcModule(receiptFinder, tracer, Blockchain.BlockFinder, JsonRpcConfig, txProcessingEnv, Blockchain.SpecProvider); for (int i = 1; i < 10; i++) @@ -84,7 +85,9 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) List transactions = new(); for (int j = 0; j < i; j++) { - transactions.Add(Core.Test.Builders.Build.A.Transaction.WithNonce(Blockchain.State.GetNonce(TestItem.AddressB) + (UInt256)j) + transactions.Add(Core.Test.Builders.Build.A.Transaction + .WithTo(Address.Zero) + .WithNonce(Blockchain.State.GetNonce(TestItem.AddressB) + (UInt256)j) .SignedAndResolved(Blockchain.EthereumEcdsa, TestItem.PrivateKeyB).TestObject); } await Blockchain.AddBlock(transactions.ToArray()); @@ -707,6 +710,36 @@ public async Task Trace_call_runs_on_top_of_specified_block() stateChanges?.Balance?.Should().BeEquivalentTo(new ParityStateChange(balance, balance - send)); } + [Test] + public async Task Trace_callMany_runs_on_top_of_specified_block() + { + Context context = new(); + await context.Build(); + TestRpcBlockchain blockchain = context.Blockchain; + + PrivateKey addressKey = Build.A.PrivateKey.TestObject; + Address address = addressKey.Address; + UInt256 balance = 100.Ether(), send = balance / 2; + + await blockchain.AddFunds(address, balance); + Hash256 lastBlockHash = blockchain.BlockTree.Head!.Hash!; + + string[] traceTypes = ["stateDiff"]; + Transaction transaction = Build.A.Transaction + .SignedAndResolved(addressKey) + .WithTo(TestItem.AddressC) + .WithValue(send) + .TestObject; + + ResultWrapper> traces = context.TraceRpcModule.trace_callMany( + [new() { Transaction = new(transaction), TraceTypes = traceTypes }], + new(lastBlockHash) + ); + + ParityAccountStateChange? stateChanges = traces.Data.Single().StateChanges?.GetValueOrDefault(address); + stateChanges?.Balance?.Should().BeEquivalentTo(new ParityStateChange(balance, balance - send)); + } + [Test] public async Task Trace_rawTransaction_runs_on_top_of_specified_block() { @@ -831,7 +864,7 @@ public async Task Trace_callMany_accumulates_state_changes() context.TraceRpcModule, "trace_callMany", calls); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"output\":null,\"stateDiff\":{\"0x0000000000000000000000000000000000000000\":{\"balance\":{\"*\":{\"from\":\"0x24\",\"to\":\"0x25\"}},\"code\":\"=\",\"nonce\":\"=\",\"storage\":{}},\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\":{\"balance\":{\"*\":{\"from\":\"0x3635c9adc5de9f09e5\",\"to\":\"0x3635c9adc5de9f09e4\"}},\"code\":\"=\",\"nonce\":{\"*\":{\"from\":\"0x3\",\"to\":\"0x4\"}},\"storage\":{}}},\"trace\":[],\"vmTrace\":null},{\"output\":null,\"stateDiff\":{\"0x0000000000000000000000000000000000000000\":{\"balance\":{\"*\":{\"from\":\"0x25\",\"to\":\"0x26\"}},\"code\":\"=\",\"nonce\":\"=\",\"storage\":{}},\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\":{\"balance\":{\"*\":{\"from\":\"0x3635c9adc5de9f09e4\",\"to\":\"0x3635c9adc5de9f09e3\"}},\"code\":\"=\",\"nonce\":{\"*\":{\"from\":\"0x4\",\"to\":\"0x5\"}},\"storage\":{}}},\"trace\":[],\"vmTrace\":null}],\"id\":67}"), serialized.Replace("\"", "\\\"")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"output\":null,\"stateDiff\":{\"0x0000000000000000000000000000000000000000\":{\"balance\":{\"*\":{\"from\":\"0x2d\",\"to\":\"0x2e\"}},\"code\":\"=\",\"nonce\":\"=\",\"storage\":{}},\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\":{\"balance\":{\"*\":{\"from\":\"0x3635c9adc5de9f09e5\",\"to\":\"0x3635c9adc5de9f09e4\"}},\"code\":\"=\",\"nonce\":{\"*\":{\"from\":\"0x3\",\"to\":\"0x4\"}},\"storage\":{}}},\"trace\":[],\"vmTrace\":null},{\"output\":null,\"stateDiff\":{\"0x0000000000000000000000000000000000000000\":{\"balance\":{\"*\":{\"from\":\"0x2e\",\"to\":\"0x2f\"}},\"code\":\"=\",\"nonce\":\"=\",\"storage\":{}},\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\":{\"balance\":{\"*\":{\"from\":\"0x3635c9adc5de9f09e4\",\"to\":\"0x3635c9adc5de9f09e3\"}},\"code\":\"=\",\"nonce\":{\"*\":{\"from\":\"0x4\",\"to\":\"0x5\"}},\"storage\":{}}},\"trace\":[],\"vmTrace\":null}],\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 77f1f818177..1565ee4d215 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -69,7 +69,8 @@ public override ITraceRpcModule Create() ReadOnlyChainProcessingEnv traceProcessingEnv = CreateChainProcessingEnv(rpcBlockTransactionsExecutor, scope, rewardCalculator); ReadOnlyChainProcessingEnv executeProcessingEnv = CreateChainProcessingEnv(executeBlockTransactionsExecutor, scope, rewardCalculator); - Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor); + Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, + traceOptions: ProcessingOptions.TraceTransactions); return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv, specProvider); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 7d67b75681b..05a92d5f208 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -91,11 +91,6 @@ public ResultWrapper> trace_callMany(Transa } BlockHeader header = headerSearch.Object!; - if (headerSearch.Object!.IsGenesis) - { - header = GenerateFakeNextHeader(header); - } - if (!_stateReader.HasStateForBlock(header)) { return GetStateFailureResult>(header); @@ -127,32 +122,6 @@ public ResultWrapper trace_rawTransaction(byte[] data, return TraceTx(tx, traceTypes, BlockParameter.Latest); } - /// - /// Generates fake next-block header to force to start from the specified header instead of header - 1. - /// - private static BlockHeader GenerateFakeNextHeader(BlockHeader header) - { - UInt256 baseFee = header.BaseFeePerGas; - var nextHeader = new BlockHeader( - header.Hash!, - Keccak.OfAnEmptySequenceRlp, - Address.Zero, - header.Difficulty, - header.Number + 1, - header.GasLimit, - header.Timestamp + 1, - header.ExtraData, - header.BlobGasUsed, - header.ExcessBlobGas) - { - MaybeParent = new(header), - TotalDifficulty = 2 * header.Difficulty, - BaseFeePerGas = baseFee - }; - - return nextHeader; - } - private ResultWrapper TraceTx(Transaction tx, string[] traceTypes, BlockParameter blockParameter, Dictionary? stateOverride = null) { @@ -163,8 +132,7 @@ private ResultWrapper TraceTx(Transaction tx, string[] } BlockHeader header = headerSearch.Object!.Clone(); - BlockHeader nextHeader = GenerateFakeNextHeader(header); - Block block = new(nextHeader, [tx], []); + Block block = new(header, [tx], []); using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(header, stateOverride) : null; From 023ab9c0431877b7e932e25510345670072249c9 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sat, 12 Oct 2024 01:06:29 +0300 Subject: [PATCH 41/70] Rename `ForceState` to `ForceSameBlock` --- .../Nethermind.Consensus/Processing/BlockchainProcessor.cs | 2 +- .../Nethermind.Consensus/Processing/ProcessingOptions.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index 6a49eb42ed7..f28b917a7a9 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -632,7 +632,7 @@ private ProcessingBranch PrepareProcessingBranch(Block suggestedBlock, Processin break; } - branchingPoint = options.ContainsFlag(ProcessingOptions.ForceState) + branchingPoint = options.ContainsFlag(ProcessingOptions.ForceSameBlock) ? toBeProcessed.Header : _blockTree.FindParentHeader(toBeProcessed.Header, BlockTreeLookupOptions.TotalDifficultyNotNeeded); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs index 24642ffb366..2f6b76bb48d 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs @@ -54,7 +54,7 @@ public enum ProcessingOptions /// /// Forces to run on top of specified block state, instead of reverting to the previous one. /// - ForceState = 1 << 8, + ForceSameBlock = 1 << 8, /// /// Combination of switches for block producers when they preprocess block for state root calculation. @@ -70,7 +70,7 @@ public enum ProcessingOptions /// EVM tracing needs to process one or more transactions on top of the specified block (instead of the previous one) /// without storing the data on chain. /// - TraceTransactions = Trace | ForceState, + TraceTransactions = Trace | ForceSameBlock, /// /// Processing options for engine_NewPayload From e15e6256dea0358f04a653eafb74b8639c316b76 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sun, 13 Oct 2024 04:15:11 +0300 Subject: [PATCH 42/70] Change `debug_traceCall` to run on top of specified block instead of previous one --- .../Nethermind.Consensus/Tracing/GethStyleTracer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 3e240bef779..6b6e3df379b 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -82,7 +82,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op try { - return Trace(block, tx.Hash, cancellationToken, options); + return Trace(block, tx.Hash, cancellationToken, options, ProcessingOptions.TraceTransactions); } finally { @@ -189,7 +189,8 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio return tracer.FileNames; } - private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options) + private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options, + ProcessingOptions processingOptions = ProcessingOptions.Trace) { ArgumentNullException.ThrowIfNull(txHash); @@ -197,7 +198,7 @@ public IEnumerable TraceBadBlockToFile(Hash256 blockHash, GethTraceOptio try { - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken)); + _processor.Process(block, processingOptions, tracer.WithCancellation(cancellationToken)); return tracer.BuildResult().SingleOrDefault(); } catch From 45963087460d418771089c305c549e450e827407 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Sun, 13 Oct 2024 04:27:10 +0300 Subject: [PATCH 43/70] State overrides for `debug_traceCall` using `OverridableWorldState` --- .../Tracing/GethStyleTracer.cs | 17 ++++++++++++++++- .../Modules/DebugModule/DebugModuleFactory.cs | 5 +++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 6b6e3df379b..4c614f6bc83 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -16,6 +16,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.GethStyle.Custom.JavaScript; @@ -36,6 +37,7 @@ public class GethStyleTracer : IGethStyleTracer private readonly IWorldState _worldState; private readonly IReceiptStorage _receiptStorage; private readonly IFileSystem _fileSystem; + private readonly ReadOnlyTxProcessingEnv _env; public GethStyleTracer(IBlockchainProcessor processor, IWorldState worldState, @@ -44,7 +46,8 @@ public GethStyleTracer(IBlockchainProcessor processor, IBlockStore badBlockStore, ISpecProvider specProvider, ChangeableTransactionProcessorAdapter transactionProcessorAdapter, - IFileSystem fileSystem) + IFileSystem fileSystem, + ReadOnlyTxProcessingEnv env) { _processor = processor ?? throw new ArgumentNullException(nameof(processor)); _worldState = worldState; @@ -54,6 +57,7 @@ public GethStyleTracer(IBlockchainProcessor processor, _specProvider = specProvider; _transactionProcessorAdapter = transactionProcessorAdapter; _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); + _env = env ?? throw new ArgumentNullException(nameof(env)); } public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken) @@ -82,6 +86,9 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op try { + Dictionary? stateOverride = options.StateOverrides; + using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(block.Header, stateOverride) : null; + return Trace(block, tx.Hash, cancellationToken, options, ProcessingOptions.TraceTransactions); } finally @@ -254,4 +261,12 @@ private static Block GetBlockToTrace(Rlp blockRlp) return block; } + + private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) + { + IReadOnlyTxProcessingScope scope = _env.Build(header.StateRoot!); + scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); + header.StateRoot = scope.WorldState.StateRoot; + return scope; + } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index a394e5a36ea..3e70783e1fd 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -59,7 +59,6 @@ public DebugModuleFactory( IFileSystem fileSystem, ILogManager logManager) { - _worldStateManager = worldStateManager; _dbProvider = dbProvider.AsReadOnly(false); _blockTree = blockTree.AsReadOnly(); _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); @@ -75,6 +74,7 @@ public DebugModuleFactory( _badBlockStore = badBlockStore; _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _logger = logManager.GetClassLogger(); + _worldStateManager = new OverridableWorldStateManager(dbProvider, worldStateManager.TrieStore, logManager); } public override IDebugRpcModule Create() @@ -109,7 +109,8 @@ public override IDebugRpcModule Create() _badBlockStore, _specProvider, transactionProcessorAdapter, - _fileSystem); + _fileSystem, + txEnv); DebugBridge debugBridge = new( _configProvider, From acefb560fea2fd1aacec7778f273347302bd03f8 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 14 Oct 2024 04:22:40 +0300 Subject: [PATCH 44/70] Move `ReadOnlyTxProcessing*` changes to new `OverridableTxProcessing*` classes --- .../Nethermind.Api/NethermindApi.cs | 6 +-- .../Contract/ValidatorContractTests.cs | 4 +- .../Validators/ContractBasedValidatorTests.cs | 4 +- .../ReadOnlyTxProcessingScopeTests.cs | 2 - .../Processing/OverridableTxProcessingEnv.cs | 47 +++++++++++++++++++ .../OverridableTxProcessingScope.cs | 29 ++++++++++++ .../Processing/ReadOnlyTxProcessingEnv.cs | 11 ++--- .../Processing/ReadOnlyTxProcessingScope.cs | 5 -- .../Tracing/GethStyleTracer.cs | 10 ++-- .../IOverridableTxProcessingScope.cs | 14 ++++++ .../IOverridableTxProcessorSource.cs | 12 +++++ .../IReadOnlyTxProcessingScope.cs | 1 - .../BlockchainBridgeTests.cs | 28 +++++------ .../Nethermind.Facade/BlockchainBridge.cs | 18 +++---- .../Modules/TestRpcBlockchain.cs | 2 +- .../Modules/Trace/ParityStyleTracerTests.cs | 4 +- .../Modules/TraceRpcModuleTests.cs | 2 +- .../Modules/DebugModule/DebugModuleFactory.cs | 6 +-- .../Modules/Trace/TraceModuleFactory.cs | 9 ++-- .../Modules/Trace/TraceRpcModule.cs | 13 +++-- .../Rpc/OptimismTraceModuleFactory.cs | 2 +- 21 files changed, 158 insertions(+), 71 deletions(-) create mode 100644 src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs create mode 100644 src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs create mode 100644 src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs create mode 100644 src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index 8da2a3c2ae9..85ad370d990 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -79,10 +79,10 @@ public IBlockchainBridge CreateBlockchainBridge() OverridableWorldStateManager overridableWorldStateManager = new(DbProvider!, WorldStateManager!.TrieStore, LogManager); // TODO: reuse the same trie cache here - ReadOnlyTxProcessingEnv readOnlyTxProcessingEnv = new( + OverridableTxProcessingEnv txProcessingEnv = new( overridableWorldStateManager, readOnlyTree, - SpecProvider, + SpecProvider!, LogManager); SimulateReadOnlyBlocksProcessingEnvFactory simulateReadOnlyBlocksProcessingEnvFactory = @@ -97,7 +97,7 @@ public IBlockchainBridge CreateBlockchainBridge() IBlocksConfig blocksConfig = ConfigProvider.GetConfig(); return new BlockchainBridge( - readOnlyTxProcessingEnv, + txProcessingEnv, simulateReadOnlyBlocksProcessingEnvFactory, TxPool, ReceiptFinder, diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs index fb741de4844..ae1a5040a4f 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs @@ -27,7 +27,6 @@ public class ValidatorContractTests { private Block _block; private readonly Address _contractAddress = Address.FromNumber(long.MaxValue); - private IOverridableCodeInfoRepository _codeInfoRepository; private ITransactionProcessor _transactionProcessor; private IReadOnlyTxProcessorSource _readOnlyTxProcessorSource; private IWorldState _stateProvider; @@ -36,12 +35,11 @@ public class ValidatorContractTests public void SetUp() { _block = new Block(Build.A.BlockHeader.TestObject, new BlockBody()); - _codeInfoRepository = Substitute.For(); _transactionProcessor = Substitute.For(); _stateProvider = Substitute.For(); _stateProvider.StateRoot.Returns(TestItem.KeccakA); _readOnlyTxProcessorSource = Substitute.For(); - _readOnlyTxProcessorSource.Build(TestItem.KeccakA).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); + _readOnlyTxProcessorSource.Build(TestItem.KeccakA).Returns(new ReadOnlyTxProcessingScope(_transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); } [Test] diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index d420791f422..3902182d6e8 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -44,7 +44,6 @@ public class ContractBasedValidatorTests private AuRaParameters.Validator _validator; private Block _block; private BlockHeader _parentHeader; - private IOverridableCodeInfoRepository _codeInfoRepository; private ITransactionProcessor _transactionProcessor; private IAuRaBlockFinalizationManager _blockFinalizationManager; private static readonly Address _contractAddress = Address.FromNumber(1000); @@ -76,13 +75,12 @@ public void SetUp() }; _block = new Block(Build.A.BlockHeader.WithNumber(1).WithAura(1, Array.Empty()).TestObject, new BlockBody()); - _codeInfoRepository = Substitute.For(); _transactionProcessor = Substitute.For(); _stateProvider.StateRoot.Returns(TestItem.KeccakA); _stateProvider.IsContract(_contractAddress).Returns(true); _readOnlyTxProcessorSource = Substitute.For(); - _readOnlyTxProcessorSource.Build(Arg.Any()).Returns(new ReadOnlyTxProcessingScope(_codeInfoRepository, _transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); + _readOnlyTxProcessorSource.Build(Arg.Any()).Returns(new ReadOnlyTxProcessingScope(_transactionProcessor, _stateProvider, Keccak.EmptyTreeHash)); _blockTree.Head.Returns(_block); _abiEncoder diff --git a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs index 44ac8c2b47f..399523f0e56 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/ReadOnlyTxProcessingScopeTests.cs @@ -3,7 +3,6 @@ using Nethermind.Consensus.Processing; using Nethermind.Core.Test.Builders; -using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; using NSubstitute; @@ -17,7 +16,6 @@ public class ReadOnlyTxProcessingScopeTests public void Test_WhenDispose_ThenStateRootWillRevert() { ReadOnlyTxProcessingScope env = new ReadOnlyTxProcessingScope( - Substitute.For(), Substitute.For(), Substitute.For(), TestItem.KeccakB diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs new file mode 100644 index 00000000000..30766dfdde4 --- /dev/null +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain; +using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; +using Nethermind.Evm; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.Logging; +using Nethermind.State; + +namespace Nethermind.Consensus.Processing; + +public class OverridableTxProcessingEnv : ReadOnlyTxProcessingEnvBase, IReadOnlyTxProcessorSource, IOverridableTxProcessorSource +{ + protected new OverridableWorldState StateProvider { get; } + protected OverridableWorldStateManager WorldStateManager { get; } + protected OverridableCodeInfoRepository CodeInfoRepository { get; } + protected IVirtualMachine Machine { get; } + protected ITransactionProcessor TransactionProcessor { get; init; } + + public OverridableTxProcessingEnv( + OverridableWorldStateManager worldStateManager, + IReadOnlyBlockTree readOnlyBlockTree, + ISpecProvider specProvider, + ILogManager? logManager, + IWorldState? worldStateToWarmUp = null + ) : base(worldStateManager, readOnlyBlockTree, specProvider, logManager, worldStateToWarmUp) + { + WorldStateManager = worldStateManager; + StateProvider = (OverridableWorldState)base.StateProvider; + CodeInfoRepository = new(new CodeInfoRepository((worldStateToWarmUp as IPreBlockCaches)?.Caches.PrecompileCache)); + Machine = new VirtualMachine(BlockhashProvider, specProvider, CodeInfoRepository, logManager); + TransactionProcessor = new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, LogManager); + } + + IReadOnlyTxProcessingScope IReadOnlyTxProcessorSource.Build(Hash256 stateRoot) => Build(stateRoot); + + IOverridableTxProcessingScope IOverridableTxProcessorSource.Build(Hash256 stateRoot) => Build(stateRoot); + + public OverridableTxProcessingScope Build(Hash256 stateRoot) + { + Hash256 originalStateRoot = StateProvider.StateRoot; + StateProvider.StateRoot = stateRoot; + return new(CodeInfoRepository, TransactionProcessor, StateProvider, originalStateRoot); + } +} diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs new file mode 100644 index 00000000000..e9aee7439e8 --- /dev/null +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core.Crypto; +using Nethermind.Evm; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.State; + +namespace Nethermind.Consensus.Processing; + +public class OverridableTxProcessingScope( + IOverridableCodeInfoRepository codeInfoRepository, + ITransactionProcessor transactionProcessor, + OverridableWorldState worldState, + Hash256 originalStateRoot +) : IReadOnlyTxProcessingScope, IOverridableTxProcessingScope +{ + public void Dispose() + { + worldState.StateRoot = originalStateRoot; + worldState.Reset(); + worldState.ResetOverrides(); + codeInfoRepository.ResetOverrides(); + } + + public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; + public ITransactionProcessor TransactionProcessor => transactionProcessor; + public IWorldState WorldState => worldState; +} diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 131c1293c28..5d0e0673524 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -27,11 +27,9 @@ protected ITransactionProcessor TransactionProcessor } } - public IWorldStateManager WorldStateManager { get; } - public IVirtualMachine Machine { get; } - public OverridableCodeInfoRepository CodeInfoRepository { get; } + public ICodeInfoRepository CodeInfoRepository { get; } public ReadOnlyTxProcessingEnv( IWorldStateManager worldStateManager, IBlockTree blockTree, @@ -50,11 +48,10 @@ public ReadOnlyTxProcessingEnv( IWorldState? worldStateToWarmUp = null ) : base(worldStateManager, readOnlyBlockTree, specProvider, logManager, worldStateToWarmUp) { - CodeInfoRepository = new(new CodeInfoRepository((worldStateToWarmUp as IPreBlockCaches)?.Caches.PrecompileCache)); + CodeInfoRepository = new CodeInfoRepository((worldStateToWarmUp as IPreBlockCaches)?.Caches.PrecompileCache); Machine = new VirtualMachine(BlockhashProvider, specProvider, CodeInfoRepository, logManager); BlockTree = readOnlyBlockTree ?? throw new ArgumentNullException(nameof(readOnlyBlockTree)); BlockhashProvider = new BlockhashProvider(BlockTree, specProvider, StateProvider, logManager); - WorldStateManager = worldStateManager; _logManager = logManager; } @@ -62,11 +59,11 @@ public ReadOnlyTxProcessingEnv( protected virtual ITransactionProcessor CreateTransactionProcessor() => new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, _logManager); - public IReadOnlyTxProcessingScope Build(Hash256 stateRoot) + public virtual IReadOnlyTxProcessingScope Build(Hash256 stateRoot) { Hash256 originalStateRoot = StateProvider.StateRoot; StateProvider.StateRoot = stateRoot; - return new ReadOnlyTxProcessingScope(CodeInfoRepository, TransactionProcessor, StateProvider, originalStateRoot); + return new ReadOnlyTxProcessingScope(TransactionProcessor, StateProvider, originalStateRoot); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs index 161a87cb675..bf14441b48b 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingScope.cs @@ -2,14 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core.Crypto; -using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; namespace Nethermind.Consensus.Processing; public class ReadOnlyTxProcessingScope( - IOverridableCodeInfoRepository codeInfoRepository, ITransactionProcessor transactionProcessor, IWorldState worldState, Hash256 originalStateRoot @@ -19,11 +17,8 @@ public void Dispose() { worldState.StateRoot = originalStateRoot; worldState.Reset(); - (worldState as OverridableWorldState)?.ResetOverrides(); - codeInfoRepository.ResetOverrides(); } - public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; public ITransactionProcessor TransactionProcessor => transactionProcessor; public IWorldState WorldState => worldState; } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 4c614f6bc83..55594920d81 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -37,7 +37,7 @@ public class GethStyleTracer : IGethStyleTracer private readonly IWorldState _worldState; private readonly IReceiptStorage _receiptStorage; private readonly IFileSystem _fileSystem; - private readonly ReadOnlyTxProcessingEnv _env; + private readonly IOverridableTxProcessorSource _env; public GethStyleTracer(IBlockchainProcessor processor, IWorldState worldState, @@ -47,7 +47,7 @@ public GethStyleTracer(IBlockchainProcessor processor, ISpecProvider specProvider, ChangeableTransactionProcessorAdapter transactionProcessorAdapter, IFileSystem fileSystem, - ReadOnlyTxProcessingEnv env) + IOverridableTxProcessorSource env) { _processor = processor ?? throw new ArgumentNullException(nameof(processor)); _worldState = worldState; @@ -87,7 +87,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op try { Dictionary? stateOverride = options.StateOverrides; - using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(block.Header, stateOverride) : null; + using IOverridableTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(block.Header, stateOverride) : null; return Trace(block, tx.Hash, cancellationToken, options, ProcessingOptions.TraceTransactions); } @@ -262,9 +262,9 @@ private static Block GetBlockToTrace(Rlp blockRlp) return block; } - private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) + private IOverridableTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) { - IReadOnlyTxProcessingScope scope = _env.Build(header.StateRoot!); + IOverridableTxProcessingScope scope = _env.Build(header.StateRoot!); scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); header.StateRoot = scope.WorldState.StateRoot; return scope; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs new file mode 100644 index 00000000000..d24a269aee6 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.State; + +namespace Nethermind.Evm.TransactionProcessing; + +public interface IOverridableTxProcessingScope : IDisposable +{ + IWorldState WorldState { get; } + IOverridableCodeInfoRepository CodeInfoRepository { get; } + ITransactionProcessor TransactionProcessor { get; } +} diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs new file mode 100644 index 00000000000..5eba2931768 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core.Crypto; +using Nethermind.State; + +namespace Nethermind.Evm.TransactionProcessing; + +public interface IOverridableTxProcessorSource +{ + IOverridableTxProcessingScope Build(Hash256 stateRoot); +} diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs index 5e5ead62383..ce7bb61e8c3 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IReadOnlyTxProcessingScope.cs @@ -8,7 +8,6 @@ namespace Nethermind.Evm.TransactionProcessing; public interface IReadOnlyTxProcessingScope : IDisposable { - IOverridableCodeInfoRepository CodeInfoRepository { get; } ITransactionProcessor TransactionProcessor { get; } IWorldState WorldState { get; } } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index b36d2615327..349cdfd8c86 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -49,17 +49,17 @@ public class BlockchainBridgeTests private ISpecProvider _specProvider; private IDbProvider _dbProvider; - private class TestReadOnlyTxProcessingEnv : ReadOnlyTxProcessingEnv + private class TestReadOnlyTxProcessingEnv : OverridableTxProcessingEnv { public TestReadOnlyTxProcessingEnv( - IWorldStateManager worldStateManager, - IBlockTree blockTree, + OverridableWorldStateManager worldStateManager, + IReadOnlyBlockTree blockTree, ISpecProvider specProvider, ILogManager logManager, ITransactionProcessor transactionProcessor) : base(worldStateManager, blockTree, specProvider, logManager) { - _transactionProcessor = transactionProcessor; + TransactionProcessor = transactionProcessor; } } @@ -80,19 +80,19 @@ public async Task SetUp() ReadOnlyDbProvider dbProvider = new ReadOnlyDbProvider(_dbProvider, false); IReadOnlyTrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); - IWorldStateManager readOnlyWorldStateManager = - new ReadOnlyWorldStateManager(dbProvider, trieStore, LimboLogs.Instance); + OverridableWorldStateManager worldStateManager = + new OverridableWorldStateManager(dbProvider, trieStore, LimboLogs.Instance); IReadOnlyBlockTree readOnlyBlockTree = _blockTree.AsReadOnly(); - ReadOnlyTxProcessingEnv processingEnv = new TestReadOnlyTxProcessingEnv( - readOnlyWorldStateManager, + TestReadOnlyTxProcessingEnv processingEnv = new( + worldStateManager, readOnlyBlockTree, _specProvider, LimboLogs.Instance, _transactionProcessor); SimulateReadOnlyBlocksProcessingEnvFactory simulateProcessingEnvFactory = new SimulateReadOnlyBlocksProcessingEnvFactory( - readOnlyWorldStateManager, + worldStateManager, readOnlyBlockTree, new ReadOnlyDbProvider(_dbProvider, true), _specProvider, @@ -217,17 +217,17 @@ public void Bridge_head_is_correct(long headNumber) ReadOnlyDbProvider dbProvider = new ReadOnlyDbProvider(_dbProvider, false); IReadOnlyTrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); - IWorldStateManager readOnlyWorldStateManager = - new ReadOnlyWorldStateManager(dbProvider, trieStore, LimboLogs.Instance); + OverridableWorldStateManager worldStateManager = + new(dbProvider, trieStore, LimboLogs.Instance); IReadOnlyBlockTree roBlockTree = _blockTree.AsReadOnly(); - ReadOnlyTxProcessingEnv processingEnv = new( - readOnlyWorldStateManager, + OverridableTxProcessingEnv processingEnv = new( + worldStateManager, roBlockTree, _specProvider, LimboLogs.Instance); SimulateReadOnlyBlocksProcessingEnvFactory simulateProcessingEnv = new SimulateReadOnlyBlocksProcessingEnvFactory( - readOnlyWorldStateManager, + worldStateManager, roBlockTree, new ReadOnlyDbProvider(_dbProvider, true), _specProvider, diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index b9d65311caa..6cc5dc99f1a 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -41,7 +41,7 @@ public interface IBlockchainBridgeFactory [Todo(Improve.Refactor, "I want to remove BlockchainBridge, split it into something with logging, state and tx processing. Then we can start using independent modules.")] public class BlockchainBridge : IBlockchainBridge { - private readonly IReadOnlyTxProcessorSource _processingEnv; + private readonly IOverridableTxProcessorSource _processingEnv; private readonly IBlockTree _blockTree; private readonly IStateReader _stateReader; private readonly ITxPool _txPool; @@ -55,7 +55,7 @@ public class BlockchainBridge : IBlockchainBridge private readonly IBlocksConfig _blocksConfig; private readonly SimulateBridgeHelper _simulateBridgeHelper; - public BlockchainBridge(ReadOnlyTxProcessingEnv processingEnv, + public BlockchainBridge(OverridableTxProcessingEnv processingEnv, SimulateReadOnlyBlocksProcessingEnvFactory simulateProcessingEnvFactory, ITxPool? txPool, IReceiptFinder? receiptStorage, @@ -151,7 +151,7 @@ private bool TryGetCanonicalTransaction( public CallOutput Call(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken cancellationToken) { CallOutputTracer callOutputTracer = new(); - using IReadOnlyTxProcessingScope scope = BuildProcessingScope(header, stateOverride); + using IOverridableTxProcessingScope scope = BuildProcessingScope(header, stateOverride); TransactionResult tryCallResult = TryCallAndRestore(header, tx, false, callOutputTracer.WithCancellation(cancellationToken), scope); return new CallOutput @@ -191,7 +191,7 @@ public SimulateOutput Simulate(BlockHeader header, SimulatePayload stateOverride, CancellationToken cancellationToken) { - using IReadOnlyTxProcessingScope scope = BuildProcessingScope(header, stateOverride); + using IOverridableTxProcessingScope scope = BuildProcessingScope(header, stateOverride); EstimateGasTracer estimateGasTracer = new(); TransactionResult tryCallResult = TryCallAndRestore( @@ -237,7 +237,7 @@ private TransactionResult TryCallAndRestore( Transaction transaction, bool treatBlockHeaderAsParentBlock, ITxTracer tracer, - IReadOnlyTxProcessingScope? scope = null) + IOverridableTxProcessingScope? scope = null) { try { @@ -257,7 +257,7 @@ private TransactionResult CallAndRestore( bool treatBlockHeaderAsParentBlock, ITxTracer tracer) { - using IReadOnlyTxProcessingScope scope = _processingEnv.Build(blockHeader.StateRoot!); + using IOverridableTxProcessingScope? scope = _processingEnv.Build(blockHeader.StateRoot!); return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, scope); } @@ -266,7 +266,7 @@ private TransactionResult CallAndRestore( Transaction transaction, bool treatBlockHeaderAsParentBlock, ITxTracer tracer, - IReadOnlyTxProcessingScope scope) + IOverridableTxProcessingScope scope) { transaction.SenderAddress ??= Address.SystemUser; Hash256? stateRoot = blockHeader.StateRoot!; @@ -325,9 +325,9 @@ private UInt256 GetNonce(Hash256 stateRoot, Address address) return _stateReader.GetNonce(stateRoot, address); } - private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary? stateOverride) + private IOverridableTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary? stateOverride) { - IReadOnlyTxProcessingScope? scope = _processingEnv.Build(header.StateRoot!); + IOverridableTxProcessingScope scope = _processingEnv.Build(header.StateRoot!); if (stateOverride != null) { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index a3aab10da2e..b3b795b69ae 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -149,7 +149,7 @@ protected override async Task Build( var dbProvider = new ReadOnlyDbProvider(DbProvider, false); IReadOnlyBlockTree? roBlockTree = BlockTree!.AsReadOnly(); OverridableWorldStateManager overridableWorldStateManager = new(DbProvider, WorldStateManager.TrieStore, LogManager); - ReadOnlyTxProcessingEnv processingEnv = new( + OverridableTxProcessingEnv processingEnv = new( overridableWorldStateManager, roBlockTree, SpecProvider, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index d754ed8870d..30df4c6138f 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -85,9 +85,9 @@ public void Setup() _blockTree.SuggestBlock(genesis); _processor.Process(genesis, ProcessingOptions.None, NullBlockTracer.Instance); - IReadOnlyTxProcessorSource readOnlyTxProcessingSource = Substitute.For(); + IOverridableTxProcessorSource txProcessingSource = Substitute.For(); _tracer = new Tracer(stateProvider, _processor, _processor); - _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader, readOnlyTxProcessingSource, specProvider); + _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader, txProcessingSource, specProvider); } [TearDown] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 38069a01a3f..aec4f6d309a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -49,7 +49,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) ReceiptsRecovery receiptsRecovery = new(Blockchain.EthereumEcdsa, Blockchain.SpecProvider); IReceiptFinder receiptFinder = new FullInfoReceiptFinder(Blockchain.ReceiptStorage, receiptsRecovery, Blockchain.BlockFinder); - ReadOnlyTxProcessingEnv txProcessingEnv = + OverridableTxProcessingEnv txProcessingEnv = new(Blockchain.OverridableWorldStateManager, Blockchain.BlockTree.AsReadOnly(), Blockchain.SpecProvider, Blockchain.LogManager); IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(Keccak.EmptyTreeHash); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index 3e70783e1fd..e3720545237 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -25,7 +25,7 @@ namespace Nethermind.JsonRpc.Modules.DebugModule; public class DebugModuleFactory : ModuleFactoryBase { - private readonly IWorldStateManager _worldStateManager; + private readonly OverridableWorldStateManager _worldStateManager; private readonly IJsonRpcConfig _jsonRpcConfig; private readonly IBlockValidator _blockValidator; private readonly IRewardCalculatorSource _rewardCalculatorSource; @@ -74,12 +74,12 @@ public DebugModuleFactory( _badBlockStore = badBlockStore; _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _logger = logManager.GetClassLogger(); - _worldStateManager = new OverridableWorldStateManager(dbProvider, worldStateManager.TrieStore, logManager); + _worldStateManager = new(dbProvider, worldStateManager.TrieStore, logManager); } public override IDebugRpcModule Create() { - ReadOnlyTxProcessingEnv txEnv = new( + OverridableTxProcessingEnv txEnv = new( _worldStateManager, _blockTree, _specProvider, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 1565ee4d215..cf335ad1109 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -30,7 +30,7 @@ public class TraceModuleFactory( IPoSSwitcher poSSwitcher, ILogManager logManager) : ModuleFactoryBase { - protected readonly IWorldStateManager _worldStateManager = new OverridableWorldStateManager(dbProvider, worldStateManager.TrieStore, logManager); + protected readonly OverridableWorldStateManager _worldStateManager = new(dbProvider, worldStateManager.TrieStore, logManager); protected readonly IReadOnlyBlockTree _blockTree = blockTree.AsReadOnly(); protected readonly IJsonRpcConfig _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); protected readonly IReceiptStorage _receiptStorage = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); @@ -40,7 +40,8 @@ public class TraceModuleFactory( protected readonly IRewardCalculatorSource _rewardCalculatorSource = rewardCalculatorSource ?? throw new ArgumentNullException(nameof(rewardCalculatorSource)); protected readonly IPoSSwitcher _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher)); - protected virtual ReadOnlyTxProcessingEnv CreateTxProcessingEnv() => new(_worldStateManager, _blockTree, _specProvider, _logManager); + private OverridableTxProcessingEnv CreateOverridableTxProcessingEnv() => new(_worldStateManager, _blockTree, _specProvider, _logManager); + protected virtual IReadOnlyTxProcessorSource CreateTxProcessingEnv() => CreateOverridableTxProcessingEnv(); protected virtual ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new( scope, @@ -56,7 +57,7 @@ public class TraceModuleFactory( public override ITraceRpcModule Create() { - ReadOnlyTxProcessingEnv txProcessingEnv = CreateTxProcessingEnv(); + OverridableTxProcessingEnv txProcessingEnv = CreateOverridableTxProcessingEnv(); IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(Keccak.EmptyTreeHash); IRewardCalculator rewardCalculator = @@ -72,6 +73,6 @@ public override ITraceRpcModule Create() Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, traceOptions: ProcessingOptions.TraceTransactions); - return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv, specProvider); + return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv.StateReader, txProcessingEnv, specProvider); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 05a92d5f208..a6f33c42442 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -13,7 +13,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; @@ -43,10 +42,10 @@ public class TraceRpcModule : ITraceRpcModule private readonly IJsonRpcConfig _jsonRpcConfig; private readonly TimeSpan _cancellationTokenTimeout; private readonly IStateReader _stateReader; - private readonly IReadOnlyTxProcessorSource _env; + private readonly IOverridableTxProcessorSource _env; private readonly ISpecProvider _specProvider; - public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, IStateReader? stateReader, IReadOnlyTxProcessorSource? env, ISpecProvider? specProvider) + public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, IStateReader? stateReader, IOverridableTxProcessorSource? env, ISpecProvider? specProvider) { _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); @@ -58,7 +57,7 @@ public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFind _cancellationTokenTimeout = TimeSpan.FromMilliseconds(_jsonRpcConfig.Timeout); } - public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, ReadOnlyTxProcessingEnv? env, ISpecProvider? specProvider) + public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, OverridableTxProcessingEnv? env, ISpecProvider? specProvider) : this(receiptFinder, tracer, blockFinder, jsonRpcConfig, env?.StateReader, env, specProvider) { } public static ParityTraceTypes GetParityTypes(string[] types) => @@ -134,7 +133,7 @@ private ResultWrapper TraceTx(Transaction tx, string[] BlockHeader header = headerSearch.Object!.Clone(); Block block = new(header, [tx], []); - using IReadOnlyTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(header, stateOverride) : null; + using IOverridableTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(header, stateOverride) : null; ParityTraceTypes traceTypes1 = GetParityTypes(traceTypes); IReadOnlyCollection result = TraceBlock(block, new(traceTypes1)); @@ -320,9 +319,9 @@ private IReadOnlyCollection ExecuteBlock(Block block, ParityL private static ResultWrapper GetStateFailureResult(BlockHeader header) => ResultWrapper.Fail($"No state available for block {header.ToString(BlockHeader.Format.FullHashAndNumber)}", ErrorCodes.ResourceUnavailable); - private IReadOnlyTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) + private IOverridableTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) { - IReadOnlyTxProcessingScope scope = _env.Build(header.StateRoot!); + IOverridableTxProcessingScope scope = _env.Build(header.StateRoot!); scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); header.StateRoot = scope.WorldState.StateRoot; return scope; diff --git a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs index cf15106e8bb..8098b9cc3b0 100644 --- a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs @@ -44,7 +44,7 @@ public class OptimismTraceModuleFactory( poSSwitcher, logManager) { - protected override ReadOnlyTxProcessingEnv CreateTxProcessingEnv() => + protected override IReadOnlyTxProcessorSource CreateTxProcessingEnv() => new OptimismReadOnlyTxProcessingEnv(_worldStateManager, _blockTree, _specProvider, _logManager, l1CostHelper, opSpecHelper); protected override ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new OptimismReadOnlyChainProcessingEnv( From b0ce7d4503dbf04e18c34b1c92e7e5913332a490 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 14 Oct 2024 05:42:11 +0300 Subject: [PATCH 45/70] Helper method `BuildAndOverride` --- .../Processing/OverridableTxProcessingEnv.cs | 11 +++++++ .../Tracing/GethStyleTracer.cs | 10 +----- .../IOverridableTxProcessorSource.cs | 4 ++- .../Nethermind.Facade/BlockchainBridge.cs | 32 +++---------------- .../Modules/Trace/ParityStyleTracerTests.cs | 2 +- .../Modules/TraceRpcModuleTests.cs | 2 +- .../Modules/Trace/TraceModuleFactory.cs | 2 +- .../Modules/Trace/TraceRpcModule.cs | 18 +++-------- 8 files changed, 26 insertions(+), 55 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs index 30766dfdde4..fc4ca308432 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs @@ -1,7 +1,10 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; using Nethermind.Blockchain; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Evm; @@ -44,4 +47,12 @@ public OverridableTxProcessingScope Build(Hash256 stateRoot) StateProvider.StateRoot = stateRoot; return new(CodeInfoRepository, TransactionProcessor, StateProvider, originalStateRoot); } + + IOverridableTxProcessingScope IOverridableTxProcessorSource.BuildAndOverride(BlockHeader header, Dictionary stateOverride) + { + OverridableTxProcessingScope scope = Build(header.StateRoot ?? throw new ArgumentException($"Block {header.Hash} state root is null", nameof(header))); + scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, SpecProvider.GetSpec(header), header.Number); + header.StateRoot = scope.WorldState.StateRoot; + return scope; + } } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 55594920d81..9a0275d0db2 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -87,7 +87,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op try { Dictionary? stateOverride = options.StateOverrides; - using IOverridableTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(block.Header, stateOverride) : null; + using IOverridableTxProcessingScope? scope = stateOverride != null ? _env.BuildAndOverride(block.Header, stateOverride) : null; return Trace(block, tx.Hash, cancellationToken, options, ProcessingOptions.TraceTransactions); } @@ -261,12 +261,4 @@ private static Block GetBlockToTrace(Rlp blockRlp) return block; } - - private IOverridableTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) - { - IOverridableTxProcessingScope scope = _env.Build(header.StateRoot!); - scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); - header.StateRoot = scope.WorldState.StateRoot; - return scope; - } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs index 5eba2931768..0f99901438d 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs @@ -1,12 +1,14 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; +using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.State; namespace Nethermind.Evm.TransactionProcessing; public interface IOverridableTxProcessorSource { IOverridableTxProcessingScope Build(Hash256 stateRoot); + IOverridableTxProcessingScope BuildAndOverride(BlockHeader header, Dictionary stateOverride); } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 6cc5dc99f1a..408d7de62be 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -151,7 +151,7 @@ private bool TryGetCanonicalTransaction( public CallOutput Call(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken cancellationToken) { CallOutputTracer callOutputTracer = new(); - using IOverridableTxProcessingScope scope = BuildProcessingScope(header, stateOverride); + using IOverridableTxProcessingScope scope = _processingEnv.BuildAndOverride(header, stateOverride); TransactionResult tryCallResult = TryCallAndRestore(header, tx, false, callOutputTracer.WithCancellation(cancellationToken), scope); return new CallOutput @@ -191,7 +191,7 @@ public SimulateOutput Simulate(BlockHeader header, SimulatePayload stateOverride, CancellationToken cancellationToken) { - using IOverridableTxProcessingScope scope = BuildProcessingScope(header, stateOverride); + using IOverridableTxProcessingScope scope = _processingEnv.BuildAndOverride(header, stateOverride); EstimateGasTracer estimateGasTracer = new(); TransactionResult tryCallResult = TryCallAndRestore( @@ -241,9 +241,8 @@ private TransactionResult TryCallAndRestore( { try { - return scope == null - ? CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer) - : CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, scope); + return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, + scope ?? _processingEnv.Build(blockHeader.StateRoot!)); } catch (InsufficientBalanceException ex) { @@ -251,16 +250,6 @@ private TransactionResult TryCallAndRestore( } } - private TransactionResult CallAndRestore( - BlockHeader blockHeader, - Transaction transaction, - bool treatBlockHeaderAsParentBlock, - ITxTracer tracer) - { - using IOverridableTxProcessingScope? scope = _processingEnv.Build(blockHeader.StateRoot!); - return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, scope); - } - private TransactionResult CallAndRestore( BlockHeader blockHeader, Transaction transaction, @@ -325,19 +314,6 @@ private UInt256 GetNonce(Hash256 stateRoot, Address address) return _stateReader.GetNonce(stateRoot, address); } - private IOverridableTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary? stateOverride) - { - IOverridableTxProcessingScope scope = _processingEnv.Build(header.StateRoot!); - - if (stateOverride != null) - { - scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); - header.StateRoot = scope.WorldState.StateRoot; - } - return scope; - } - - public bool FilterExists(int filterId) => _filterStore.FilterExists(filterId); public FilterType GetFilterType(int filterId) => _filterStore.GetFilterType(filterId); public FilterLog[] GetFilterLogs(int filterId) => _filterManager.GetLogs(filterId); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index 30df4c6138f..d23371246fa 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -87,7 +87,7 @@ public void Setup() IOverridableTxProcessorSource txProcessingSource = Substitute.For(); _tracer = new Tracer(stateProvider, _processor, _processor); - _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader, txProcessingSource, specProvider); + _traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, _stateReader, txProcessingSource); } [TearDown] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index aec4f6d309a..d01632dc974 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -78,7 +78,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, traceOptions: ProcessingOptions.TraceTransactions); - TraceRpcModule = new TraceRpcModule(receiptFinder, tracer, Blockchain.BlockFinder, JsonRpcConfig, txProcessingEnv, Blockchain.SpecProvider); + TraceRpcModule = new TraceRpcModule(receiptFinder, tracer, Blockchain.BlockFinder, JsonRpcConfig, txProcessingEnv); for (int i = 1; i < 10; i++) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index cf335ad1109..c76a7f7a2fb 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -73,6 +73,6 @@ public override ITraceRpcModule Create() Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, traceOptions: ProcessingOptions.TraceTransactions); - return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv.StateReader, txProcessingEnv, specProvider); + return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv.StateReader, txProcessingEnv); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index a6f33c42442..0a7774a8332 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -43,9 +43,8 @@ public class TraceRpcModule : ITraceRpcModule private readonly TimeSpan _cancellationTokenTimeout; private readonly IStateReader _stateReader; private readonly IOverridableTxProcessorSource _env; - private readonly ISpecProvider _specProvider; - public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, IStateReader? stateReader, IOverridableTxProcessorSource? env, ISpecProvider? specProvider) + public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, IStateReader? stateReader, IOverridableTxProcessorSource? env) { _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); @@ -53,12 +52,11 @@ public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFind _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader)); _env = env ?? throw new ArgumentNullException(nameof(env)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _cancellationTokenTimeout = TimeSpan.FromMilliseconds(_jsonRpcConfig.Timeout); } - public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, OverridableTxProcessingEnv? env, ISpecProvider? specProvider) - : this(receiptFinder, tracer, blockFinder, jsonRpcConfig, env?.StateReader, env, specProvider) { } + public TraceRpcModule(IReceiptFinder? receiptFinder, ITracer? tracer, IBlockFinder? blockFinder, IJsonRpcConfig? jsonRpcConfig, OverridableTxProcessingEnv? env) + : this(receiptFinder, tracer, blockFinder, jsonRpcConfig, env?.StateReader, env) { } public static ParityTraceTypes GetParityTypes(string[] types) => types.Select(s => FastEnum.Parse(s, true)).Aggregate((t1, t2) => t1 | t2); @@ -133,7 +131,7 @@ private ResultWrapper TraceTx(Transaction tx, string[] BlockHeader header = headerSearch.Object!.Clone(); Block block = new(header, [tx], []); - using IOverridableTxProcessingScope? scope = stateOverride != null ? BuildProcessingScope(header, stateOverride) : null; + using IOverridableTxProcessingScope? scope = stateOverride != null ? _env.BuildAndOverride(header, stateOverride) : null; ParityTraceTypes traceTypes1 = GetParityTypes(traceTypes); IReadOnlyCollection result = TraceBlock(block, new(traceTypes1)); @@ -318,13 +316,5 @@ private IReadOnlyCollection ExecuteBlock(Block block, ParityL private static ResultWrapper GetStateFailureResult(BlockHeader header) => ResultWrapper.Fail($"No state available for block {header.ToString(BlockHeader.Format.FullHashAndNumber)}", ErrorCodes.ResourceUnavailable); - - private IOverridableTxProcessingScope BuildProcessingScope(BlockHeader header, Dictionary stateOverride) - { - IOverridableTxProcessingScope scope = _env.Build(header.StateRoot!); - scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, _specProvider.GetSpec(header), header.Number); - header.StateRoot = scope.WorldState.StateRoot; - return scope; - } } } From 5758a4f21093e16cc2f3912974c6aa06110f0f21 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 14 Oct 2024 05:55:47 +0300 Subject: [PATCH 46/70] Code cleanup --- src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs index a5c6af79e8f..7b0fc9a6da7 100644 --- a/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverlayWorldStateManager.cs @@ -29,9 +29,9 @@ public class OverlayWorldStateManager( public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) { - ITrieStore trieStore = overlayTrieStore; - if ((forWarmup as IPreBlockCaches)?.Caches is { } preBlockCaches) - trieStore = new PreCachedTrieStore(trieStore, preBlockCaches.RlpCache); + ITrieStore trieStore = (forWarmup as IPreBlockCaches)?.Caches is { } preBlockCaches + ? new PreCachedTrieStore(overlayTrieStore, preBlockCaches.RlpCache) + : overlayTrieStore; return new WorldState(trieStore, _codeDb, logManager); } From 34b27a37d684885677d87dadf51ca9288273678c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 14 Oct 2024 06:02:48 +0300 Subject: [PATCH 47/70] Revert "Normalize block error" This reverts commit 58886b61b4ba5b6d4bf9fbfa44152f0bc1a4ac1f. --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 2 +- .../Modules/Eth/EthRpcModuleTests.cs | 6 +++--- .../Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index fc379ade244..afba93656c6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -148,7 +148,7 @@ public async Task Eth_call_with_blockhash_ok() string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "{\"blockHash\":\"0xf0b3f69cbd4e1e8d9b0ef02ff5d1384d18e19d251a4052f5f90bab190c5e8937\"}"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 0xf0b3f69cbd4e1e8d9b0ef02ff5d1384d18e19d251a4052f5f90bab190c5e8937 could not be found\"},\"id\":67}")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"0xf0b3f69cbd4e1e8d9b0ef02ff5d1384d18e19d251a4052f5f90bab190c5e8937 could not be found\"},\"id\":67}")); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 88aabcf325e..843406aad94 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -525,8 +525,8 @@ void HandleNewBlock(object? sender, BlockReplacementEventArgs e) [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"latest\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")] [TestCase("{\"fromBlock\":\"earliest\",\"toBlock\":\"pending\",\"address\":[\"0x00000000000000000001\", \"0x00000000000000000001\"],\"topics\":[\"0x00000000000000000000000000000001\", \"0x00000000000000000000000000000002\"]}", "{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")] [TestCase("{\"topics\":[null, [\"0x00000000000000000000000000000001\", \"0x00000000000000000000000000000002\"]]}", "{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")] - [TestCase("{\"fromBlock\":\"0x10\",\"toBlock\":\"latest\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 16 could not be found\"},\"id\":67}")] - [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"0x11\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 17 could not be found\"},\"id\":67}")] + [TestCase("{\"fromBlock\":\"0x10\",\"toBlock\":\"latest\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"16 could not be found\"},\"id\":67}")] + [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"0x11\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"17 could not be found\"},\"id\":67}")] [TestCase("{\"fromBlock\":\"0x2\",\"toBlock\":\"0x1\",\"address\":\"0x00000000000000000001\",\"topics\":[\"0x00000000000000000000000000000001\"]}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"From block 2 is later than to block 1.\"},\"id\":67}")] public async Task Eth_get_logs(string parameter, string expected) { @@ -791,7 +791,7 @@ public async Task Eth_get_account_incorrect_block() string serialized = await ctx.Test.TestEthRpc("eth_getAccount", account_address, "0xffff"); - serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"Block 65535 could not be found\"},\"id\":67}"); + serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"65535 could not be found\"},\"id\":67}"); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs index a518024cae0..277c77dc501 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs @@ -39,7 +39,7 @@ public static SearchResult SearchForHeader(this IBlockFinder blockF } return header is null && !allowNulls - ? new SearchResult($"Block {blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound) + ? new SearchResult($"{blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound) : new SearchResult(header); } From fe6097748844962d4cd8e5c4b88cf9803edf42a3 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 14 Oct 2024 07:05:41 +0300 Subject: [PATCH 48/70] Simple build fix --- .../Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 885496c6812..7bb0452bfde 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -66,7 +66,7 @@ public void GlobalSetup() stateProvider.Commit(spec); stateProvider.CommitTree(0); - WorldStateManager stateManager = new WorldStateManager(stateProvider, trieStore, dbProvider, LimboLogs.Instance); + OverridableWorldStateManager stateManager = new(dbProvider, trieStore.AsReadOnly(), LimboLogs.Instance); StateReader stateReader = new(trieStore, codeDb, LimboLogs.Instance); @@ -135,7 +135,7 @@ TransactionProcessor transactionProcessor new ReceiptsRecovery(ecdsa, specProvider)); BlockchainBridge bridge = new( - new ReadOnlyTxProcessingEnv( + new OverridableTxProcessingEnv( stateManager, new ReadOnlyBlockTree(blockTree), specProvider, From 3e683cf4d689bb6ea94ed1003bd168dfc29b7a3c Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 02:43:11 +0300 Subject: [PATCH 49/70] Fix tests --- .../Modules/Eth/EthRpcModuleTests.EstimateGas.cs | 11 +++++++++-- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 11 +++++++++-- .../Modules/TraceRpcModuleTests.cs | 11 +++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index a55131b3890..fa07c897b72 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Core; @@ -282,8 +283,11 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", """{"jsonrpc":"2.0","result":"0x6440","id":67}""" // EcRecover call + intrinsic transaction cost )] - public async Task Estimate_gas_with_state_override(string name, string transaction, string stateOverride, string expectedResult) + public async Task Estimate_gas_with_state_override(string name, string transactionJson, string stateOverrideJson, string expectedResult) { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + TestSpecProvider specProvider = new(Prague.Instance); using Context ctx = await Context.Create(specProvider); @@ -307,8 +311,11 @@ public async Task Estimate_gas_with_state_override(string name, string transacti """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" )] - public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(string name, string transaction, string stateOverride) + public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(string name, string transactionJson, string stateOverrideJson) { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + using Context ctx = await Context.Create(); var resultOverrideBefore = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index aab0cc617bc..512a38884ca 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Core; @@ -319,8 +320,11 @@ public async Task Eth_call_with_revert() """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", """{"jsonrpc":"2.0","result":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","id":67}""" )] - public async Task Eth_call_with_state_override(string name, string transaction, string stateOverride, string expectedResult) + public async Task Eth_call_with_state_override(string name, string transactionJson, string stateOverrideJson, string expectedResult) { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + using Context ctx = await Context.Create(); string serialized = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); @@ -343,8 +347,11 @@ public async Task Eth_call_with_state_override(string name, string transaction, """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" )] - public async Task Eth_call_with_state_override_does_not_affect_other_calls(string name, string transaction, string stateOverride) + public async Task Eth_call_with_state_override_does_not_affect_other_calls(string name, string transactionJson, string stateOverrideJson) { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + using Context ctx = await Context.Create(); var resultOverrideBefore = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index aded3ef26b1..7393869f7d1 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain; @@ -974,8 +975,11 @@ public async Task Trace_replayBlockTransactions_stateDiff() """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0x0000000000000000000000000000000000123456", "code": "0x"}}""", """{"jsonrpc":"2.0","result":{"output":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099","stateDiff":null,"trace":[{"action":{"callType":"call","from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","gas":"0x5f58878","input":"0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4000000000000000000000000000000000000000000000000000000000000001c7b8b1991eb44757bc688016d27940df8fb971d7c87f77a6bc4e938e3202c44037e9267b0aeaa82fa765361918f2d8abd9cdd86e64aa6f2b81d3c4e0b69a7b055","to":"0x0000000000000000000000000000000000123456","value":"0x0"},"result":{"gasUsed":"0xbb8","output":"0x000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"},"subtraces":0,"traceAddress":[],"type":"call"}],"vmTrace":null},"id":67}""" )] - public async Task Trace_call_with_state_override(string name, string transaction, string traceType, string stateOverride, string expectedResult) + public async Task Trace_call_with_state_override(string name, string transactionJson, string traceType, string stateOverrideJson, string expectedResult) { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + Context context = new(); await context.Build(new TestSpecProvider(Prague.Instance)); string serialized = await RpcTest.TestSerializedRequest( @@ -995,8 +999,11 @@ public async Task Trace_call_with_state_override(string name, string transaction "trace", """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" )] - public async Task Trace_call_with_state_override_does_not_affect_other_calls(string transaction, string traceType, string stateOverride) + public async Task Trace_call_with_state_override_does_not_affect_other_calls(string transactionJson, string traceType, string stateOverrideJson) { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + Context context = new(); await context.Build(); From 1651413c4e4e90ac5a6f3caf0d2f9f20a042cea9 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 03:03:51 +0300 Subject: [PATCH 50/70] Code cleanup --- .../Processing/ReadOnlyTxProcessingEnv.cs | 2 +- src/Nethermind/Nethermind.Facade/BlockchainBridge.cs | 5 ++--- src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs | 2 +- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 2 +- src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs | 2 ++ .../Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs | 2 -- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 5d0e0673524..5e7d4ea28da 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -59,7 +59,7 @@ public ReadOnlyTxProcessingEnv( protected virtual ITransactionProcessor CreateTransactionProcessor() => new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, _logManager); - public virtual IReadOnlyTxProcessingScope Build(Hash256 stateRoot) + public IReadOnlyTxProcessingScope Build(Hash256 stateRoot) { Hash256 originalStateRoot = StateProvider.StateRoot; StateProvider.StateRoot = stateRoot; diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 408d7de62be..1a95dec6e3f 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -148,7 +148,7 @@ private bool TryGetCanonicalTransaction( return blockHash is not null ? _receiptFinder.Get(blockHash).ForTransaction(txHash) : null; } - public CallOutput Call(BlockHeader header, Transaction tx, Dictionary stateOverride, CancellationToken cancellationToken) + public CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken cancellationToken) { CallOutputTracer callOutputTracer = new(); using IOverridableTxProcessingScope scope = _processingEnv.BuildAndOverride(header, stateOverride); @@ -189,7 +189,7 @@ public SimulateOutput Simulate(BlockHeader header, SimulatePayload stateOverride, CancellationToken cancellationToken) + public CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMargin, Dictionary? stateOverride, CancellationToken cancellationToken) { using IOverridableTxProcessingScope scope = _processingEnv.BuildAndOverride(header, stateOverride); @@ -286,7 +286,6 @@ private TransactionResult CallAndRestore( blockHeader.ExtraData); IReleaseSpec releaseSpec = _specProvider.GetSpec(callHeader); - callHeader.BaseFeePerGas = treatBlockHeaderAsParentBlock ? BaseFeeCalculator.Calculate(blockHeader, releaseSpec) : blockHeader.BaseFeePerGas; diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 70a83f3a52d..459dd3f3de1 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -29,7 +29,7 @@ public interface IBlockchainBridge : ILogFinder (TxReceipt? Receipt, Transaction? Transaction, UInt256? baseFee) GetTransaction(Hash256 txHash, bool checkTxnPool = true); CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride = null, CancellationToken cancellationToken = default); SimulateOutput Simulate(BlockHeader header, SimulatePayload payload, CancellationToken cancellationToken); - CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMarginBasisPoints, Dictionary stateOverride, CancellationToken cancellationToken); + CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMarginBasisPoints, Dictionary? stateOverride = null, CancellationToken cancellationToken = default); CallOutput CreateAccessList(BlockHeader header, Transaction tx, CancellationToken cancellationToken, bool optimize); ulong GetChainId(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 512a38884ca..d9ad794c148 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -203,7 +203,7 @@ public async Task Eth_call_with_accessList() AccessListTransactionForRpc transaction = test.JsonSerializer.Deserialize( - $$"""{"from": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", "type":"0x1", "data": "{{code.ToHexString(true)}}"}"""); + $"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}"); transaction.AccessList = accessList; string serialized = await test.TestEthRpc("eth_call", transaction, "0x0"); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs b/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs index 20b1eb6c6b8..5a235eb5bb2 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs @@ -4,7 +4,9 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; + using FluentAssertions; + using Nethermind.JsonRpc.Modules; using Nethermind.JsonRpc.Test.Modules; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index ae39ed831de..05df3a6ff8d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -16,7 +16,6 @@ using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Evm.TransactionProcessing; -using Nethermind.Facade; using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Int256; using Nethermind.JsonRpc.Data; @@ -301,7 +300,6 @@ private IReadOnlyCollection TraceBlock(Block block, ParityLik { using CancellationTokenSource cancellationTokenSource = new(_cancellationTokenTimeout); CancellationToken cancellationToken = cancellationTokenSource.Token; - _tracer.Trace(block, tracer.WithCancellation(cancellationToken)); return tracer.BuildResult(); } From e935178ea63e8ea4f386f3e1a399eff73a3520f9 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 03:06:35 +0300 Subject: [PATCH 51/70] Allow null `stateOverride` in `BuildAndOverride` --- .../Processing/OverridableTxProcessingEnv.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs index fc4ca308432..dcac1aca53b 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs @@ -48,11 +48,14 @@ public OverridableTxProcessingScope Build(Hash256 stateRoot) return new(CodeInfoRepository, TransactionProcessor, StateProvider, originalStateRoot); } - IOverridableTxProcessingScope IOverridableTxProcessorSource.BuildAndOverride(BlockHeader header, Dictionary stateOverride) + IOverridableTxProcessingScope IOverridableTxProcessorSource.BuildAndOverride(BlockHeader header, Dictionary? stateOverride) { OverridableTxProcessingScope scope = Build(header.StateRoot ?? throw new ArgumentException($"Block {header.Hash} state root is null", nameof(header))); - scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, SpecProvider.GetSpec(header), header.Number); - header.StateRoot = scope.WorldState.StateRoot; + if (stateOverride != null) + { + scope.WorldState.ApplyStateOverrides(scope.CodeInfoRepository, stateOverride, SpecProvider.GetSpec(header), header.Number); + header.StateRoot = scope.WorldState.StateRoot; + } return scope; } } From a54ac7100612a2599e79c13f6fd38c2541defb72 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 04:25:56 +0300 Subject: [PATCH 52/70] Rename `DebugModuleMockedTests` -> `DebugModuleTests` --- .../Modules/{DebugModuleTests.cs => DebugModuleMockedTests.cs} | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename src/Nethermind/Nethermind.JsonRpc.Test/Modules/{DebugModuleTests.cs => DebugModuleMockedTests.cs} (99%) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs similarity index 99% rename from src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs rename to src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs index fed0e3ccfba..e60238e5d5b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs @@ -31,8 +31,9 @@ namespace Nethermind.JsonRpc.Test.Modules; +// Tests with mocked IDebugBridge [Parallelizable(ParallelScope.Self)] -public class DebugModuleTests +public class DebugModuleMockedTests { private readonly IJsonRpcConfig jsonRpcConfig = new JsonRpcConfig(); private readonly ISpecProvider specProvider = Substitute.For(); From 78c379ffe0c7402fb9419ca84a58ed7e47ebecdc Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 05:58:25 +0300 Subject: [PATCH 53/70] Tests for `debug_traceCall` state override --- .../Blockchain/TestBlockchain.cs | 1 + .../Modules/DebugModuleTests.cs | 160 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 2af6892ee13..cc50f949219 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -77,6 +77,7 @@ public IBlockFinder BlockFinder public IWorldState State { get; set; } = null!; public IReadOnlyStateProvider ReadOnlyState { get; private set; } = null!; public IDb StateDb => DbProvider.StateDb; + public IDb BlocksDb => DbProvider.BlocksDb; public TrieStore TrieStore { get; set; } = null!; public IBlockProducer BlockProducer { get; private set; } = null!; public IBlockProducerRunner BlockProducerRunner { get; protected set; } = null!; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs new file mode 100644 index 00000000000..2e3009a81b5 --- /dev/null +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs @@ -0,0 +1,160 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO.Abstractions; +using System.Text.Json; +using System.Threading.Tasks; +using FluentAssertions; +using Nethermind.Blockchain.Blocks; +using Nethermind.Blockchain.Receipts; +using Nethermind.Config; +using Nethermind.Consensus.Rewards; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.JsonRpc.Modules.DebugModule; +using Nethermind.Synchronization.ParallelSync; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.JsonRpc.Test.Modules; + +[Parallelizable(ParallelScope.Self)] +public class DebugModuleTests +{ + private class Context : IDisposable + { + public IDebugRpcModule DebugRpcModule { get; } + public TestRpcBlockchain Blockchain { get; } + + private Context(TestRpcBlockchain blockchain, IDebugRpcModule debugRpcModule) + { + DebugRpcModule = debugRpcModule; + Blockchain = blockchain; + } + + public static async Task Create(ISpecProvider? specProvider = null, bool isAura = false) + { + TestRpcBlockchain blockchain = await TestRpcBlockchain.ForTest(isAura ? SealEngineType.AuRa : SealEngineType.NethDev).Build(specProvider); + + IConfigProvider configProvider = Substitute.For(); + IReceiptsMigration receiptsMigration = Substitute.For(); + ISyncModeSelector syncModeSelector = Substitute.For(); + var factory = new DebugModuleFactory( + blockchain.WorldStateManager, + blockchain.DbProvider, + blockchain.BlockTree, + blockchain.RpcConfig, + blockchain.BlockValidator, + blockchain.BlockPreprocessorStep, + NoBlockRewards.Instance, + blockchain.ReceiptStorage, + receiptsMigration, + configProvider, + blockchain.SpecProvider, + syncModeSelector, + new BlockStore(blockchain.BlocksDb), + new FileSystem(), + blockchain.LogManager + ); + + IDebugRpcModule debugRpcModule = factory.Create(); + + return new(blockchain, debugRpcModule); + } + + public void Dispose() => Blockchain.Dispose(); + } + + [TestCase( + "Nonce override doesn't cause failure", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""" + )] + [TestCase( + "Uses account balance from state override", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x100"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" + )] + [TestCase( + "Executes code from state override", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", + "00000000000000000000000000000000000000000000003635c9adc5de9f09e5" + )] + [TestCase( + "Executes precompile using overriden address", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", + "000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099" + )] + public async Task Debug_traceCall_with_state_override(string name, string transactionJson, string stateOverrideJson, string? expectedValue = null) + { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + + using Context ctx = await Context.Create(); + + JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", + transaction, null, new { stateOverrides = stateOverride } + ); + + GethLikeTxTrace trace = response.Should().BeOfType() + .Which.Result.Should().BeOfType() + .Subject; + + if (expectedValue != null) + Convert.ToHexString(trace.ReturnValue).Should().BeEquivalentTo(expectedValue); + } + + [TestCase( + "When balance is overriden", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" + )] + [TestCase( + "When address code is overriden", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" + )] + [TestCase( + "When precompile address is changed", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" + )] + public async Task debug_traceCall_with_state_override_does_not_affect_other_calls(string name, string transactionJson, string stateOverrideJson) + { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + + using Context ctx = await Context.Create(); + + var resultOverrideBefore = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + { + stateOverrides = stateOverride, + enableMemory = false, disableStorage = true, disableStack = true, + tracer = "callTracer", tracerConfig = new { withLog = false } + }); + + var resultNoOverride = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + { + // configuration to minimize number of fields being compared + enableMemory = false, disableStorage = true, disableStack = true, + tracer = "callTracer", tracerConfig = new { withLog = false } + }); + + var resultOverrideAfter = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + { + stateOverrides = stateOverride, + enableMemory = false, disableStorage = true, disableStack = true, + tracer = "callTracer", tracerConfig = new { withLog = false } + }); + + Assert.Multiple(() => + { + Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); + Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); + }); + } +} From e0563c377ec47ce0453732231875ce58f6727574 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 06:01:48 +0300 Subject: [PATCH 54/70] Few more `debug_*` tests --- .../Modules/DebugModuleTests.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs index 2e3009a81b5..6c782b9c774 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs @@ -11,8 +11,12 @@ using Nethermind.Config; using Nethermind.Consensus.Rewards; using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Core.Test.Builders; using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.Int256; using Nethermind.JsonRpc.Modules.DebugModule; using Nethermind.Synchronization.ParallelSync; using NSubstitute; @@ -67,6 +71,43 @@ public static async Task Create(ISpecProvider? specProvider = null, boo public void Dispose() => Blockchain.Dispose(); } + [Test] + public async Task Debug_traceCall_fails_when_not_enough_balance() + { + using Context ctx = await Context.Create(); + + Address address = Build.An.Address.TestObject; + UInt256 balance = 100.Ether(), send = balance / 2; + + JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", + new { from = $"{address}", to = $"{TestItem.AddressC}", value = send.ToString("X") } + ); + + response.Should().BeOfType() + .Which.Error?.Message?.Should().Contain("insufficient funds"); + } + + [Test] + public async Task Debug_traceCall_runs_on_top_of_specified_block() + { + using Context ctx = await Context.Create(); + TestRpcBlockchain blockchain = ctx.Blockchain; + + Address address = Build.An.Address.TestObject; + UInt256 balance = 100.Ether(); + + await blockchain.AddFunds(address, balance / 2); + await blockchain.AddFunds(address, balance / 2); + Hash256 lastBlockHash = blockchain.BlockTree.Head!.Hash!; + + JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", + new { from = $"{address}", to = $"{TestItem.AddressC}", value = balance.ToString("X") }, + $"{lastBlockHash}" + ); + + response.Should().BeOfType(); + } + [TestCase( "Nonce override doesn't cause failure", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", From 4c39610620695710cd73517e5ca97e4d550fbf30 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 15 Oct 2024 06:03:33 +0300 Subject: [PATCH 55/70] Code cleanup --- .../Modules/DebugModuleTests.cs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs index 6c782b9c774..775ba7f3868 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -174,22 +174,31 @@ public async Task debug_traceCall_with_state_override_does_not_affect_other_call var resultOverrideBefore = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new { stateOverrides = stateOverride, - enableMemory = false, disableStorage = true, disableStack = true, - tracer = "callTracer", tracerConfig = new { withLog = false } + enableMemory = false, + disableStorage = true, + disableStack = true, + tracer = "callTracer", + tracerConfig = new { withLog = false } }); var resultNoOverride = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new { // configuration to minimize number of fields being compared - enableMemory = false, disableStorage = true, disableStack = true, - tracer = "callTracer", tracerConfig = new { withLog = false } + enableMemory = false, + disableStorage = true, + disableStack = true, + tracer = "callTracer", + tracerConfig = new { withLog = false } }); var resultOverrideAfter = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new { stateOverrides = stateOverride, - enableMemory = false, disableStorage = true, disableStack = true, - tracer = "callTracer", tracerConfig = new { withLog = false } + enableMemory = false, + disableStorage = true, + disableStack = true, + tracer = "callTracer", + tracerConfig = new { withLog = false } }); Assert.Multiple(() => From d7a8e8c530dd7fb2c13eecdc65b3c2b5044ea96e Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 21 Oct 2024 12:32:07 +0300 Subject: [PATCH 56/70] Add `OptimismOverridableTxProcessingEnv` --- .../Processing/OverridableTxProcessingEnv.cs | 9 ++++- .../BlockchainBridgeTests.cs | 21 ++++------ .../Modules/Trace/TraceModuleFactory.cs | 5 +-- .../OptimismOverridableTxProcessingEnv.cs | 38 +++++++++++++++++++ .../Rpc/OptimismTraceModuleFactory.cs | 4 +- 5 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs index dcac1aca53b..b7acf2fe981 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs @@ -16,11 +16,13 @@ namespace Nethermind.Consensus.Processing; public class OverridableTxProcessingEnv : ReadOnlyTxProcessingEnvBase, IReadOnlyTxProcessorSource, IOverridableTxProcessorSource { + private readonly Lazy _transactionProcessorLazy; + protected new OverridableWorldState StateProvider { get; } protected OverridableWorldStateManager WorldStateManager { get; } protected OverridableCodeInfoRepository CodeInfoRepository { get; } protected IVirtualMachine Machine { get; } - protected ITransactionProcessor TransactionProcessor { get; init; } + protected ITransactionProcessor TransactionProcessor => _transactionProcessorLazy.Value; public OverridableTxProcessingEnv( OverridableWorldStateManager worldStateManager, @@ -34,11 +36,14 @@ public OverridableTxProcessingEnv( StateProvider = (OverridableWorldState)base.StateProvider; CodeInfoRepository = new(new CodeInfoRepository((worldStateToWarmUp as IPreBlockCaches)?.Caches.PrecompileCache)); Machine = new VirtualMachine(BlockhashProvider, specProvider, CodeInfoRepository, logManager); - TransactionProcessor = new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, LogManager); + _transactionProcessorLazy = new(CreateTransactionProcessor); } IReadOnlyTxProcessingScope IReadOnlyTxProcessorSource.Build(Hash256 stateRoot) => Build(stateRoot); + protected virtual ITransactionProcessor CreateTransactionProcessor() => + new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, LogManager); + IOverridableTxProcessingScope IOverridableTxProcessorSource.Build(Hash256 stateRoot) => Build(stateRoot); public OverridableTxProcessingScope Build(Hash256 stateRoot) diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 349cdfd8c86..42f2e968dc7 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -4,12 +4,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Filters; -using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Processing; using Nethermind.Core; @@ -49,18 +47,15 @@ public class BlockchainBridgeTests private ISpecProvider _specProvider; private IDbProvider _dbProvider; - private class TestReadOnlyTxProcessingEnv : OverridableTxProcessingEnv + private class TestReadOnlyTxProcessingEnv( + OverridableWorldStateManager worldStateManager, + IReadOnlyBlockTree blockTree, + ISpecProvider specProvider, + ILogManager logManager, + ITransactionProcessor transactionProcessor) + : OverridableTxProcessingEnv(worldStateManager, blockTree, specProvider, logManager) { - public TestReadOnlyTxProcessingEnv( - OverridableWorldStateManager worldStateManager, - IReadOnlyBlockTree blockTree, - ISpecProvider specProvider, - ILogManager logManager, - ITransactionProcessor transactionProcessor) : - base(worldStateManager, blockTree, specProvider, logManager) - { - TransactionProcessor = transactionProcessor; - } + protected override ITransactionProcessor CreateTransactionProcessor() => transactionProcessor; } [SetUp] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index c76a7f7a2fb..375e60320c6 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -40,8 +40,7 @@ public class TraceModuleFactory( protected readonly IRewardCalculatorSource _rewardCalculatorSource = rewardCalculatorSource ?? throw new ArgumentNullException(nameof(rewardCalculatorSource)); protected readonly IPoSSwitcher _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher)); - private OverridableTxProcessingEnv CreateOverridableTxProcessingEnv() => new(_worldStateManager, _blockTree, _specProvider, _logManager); - protected virtual IReadOnlyTxProcessorSource CreateTxProcessingEnv() => CreateOverridableTxProcessingEnv(); + protected virtual OverridableTxProcessingEnv CreateTxProcessingEnv() => new(_worldStateManager, _blockTree, _specProvider, _logManager); protected virtual ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new( scope, @@ -57,7 +56,7 @@ public class TraceModuleFactory( public override ITraceRpcModule Create() { - OverridableTxProcessingEnv txProcessingEnv = CreateOverridableTxProcessingEnv(); + OverridableTxProcessingEnv txProcessingEnv = CreateTxProcessingEnv(); IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(Keccak.EmptyTreeHash); IRewardCalculator rewardCalculator = diff --git a/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs new file mode 100644 index 00000000000..6acb4be0fa7 --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Blockchain; +using Nethermind.Consensus.Processing; +using Nethermind.Core.Specs; +using Nethermind.Evm; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.Logging; +using Nethermind.State; + +namespace Nethermind.Optimism; + +public class OptimismOverridableTxProcessingEnv( + OverridableWorldStateManager worldStateManager, + IReadOnlyBlockTree readOnlyBlockTree, + ISpecProvider specProvider, + ILogManager logManager, + IL1CostHelper l1CostHelper, + IOptimismSpecHelper opSpecHelper, + IWorldState? worldStateToWarmUp = null) : OverridableTxProcessingEnv( + worldStateManager, + readOnlyBlockTree, + specProvider, + logManager, + worldStateToWarmUp +) +{ + protected override ITransactionProcessor CreateTransactionProcessor() + { + ArgumentNullException.ThrowIfNull(LogManager); + + BlockhashProvider blockhashProvider = new(BlockTree, SpecProvider, StateProvider, LogManager); + VirtualMachine virtualMachine = new(blockhashProvider, SpecProvider, CodeInfoRepository, LogManager); + return new OptimismTransactionProcessor(SpecProvider, StateProvider, virtualMachine, LogManager, l1CostHelper, opSpecHelper, CodeInfoRepository); + } +} diff --git a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs index 8098b9cc3b0..4f023c25ac6 100644 --- a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs @@ -44,8 +44,8 @@ public class OptimismTraceModuleFactory( poSSwitcher, logManager) { - protected override IReadOnlyTxProcessorSource CreateTxProcessingEnv() => - new OptimismReadOnlyTxProcessingEnv(_worldStateManager, _blockTree, _specProvider, _logManager, l1CostHelper, opSpecHelper); + protected override OverridableTxProcessingEnv CreateTxProcessingEnv() => + new OptimismOverridableTxProcessingEnv(_worldStateManager, _blockTree, _specProvider, _logManager, l1CostHelper, opSpecHelper); protected override ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new OptimismReadOnlyChainProcessingEnv( scope, From 0650883c337c233094bcf013f37c701192baf26a Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 21 Oct 2024 12:32:29 +0300 Subject: [PATCH 57/70] Remove `IReadOnlyTxProcessorSource` implementation from `OverridableTxProcessingEnv` --- .../Processing/OverridableTxProcessingEnv.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs index b7acf2fe981..bbd5bcef20f 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs @@ -14,7 +14,7 @@ namespace Nethermind.Consensus.Processing; -public class OverridableTxProcessingEnv : ReadOnlyTxProcessingEnvBase, IReadOnlyTxProcessorSource, IOverridableTxProcessorSource +public class OverridableTxProcessingEnv : ReadOnlyTxProcessingEnvBase, IOverridableTxProcessorSource { private readonly Lazy _transactionProcessorLazy; @@ -39,7 +39,6 @@ public OverridableTxProcessingEnv( _transactionProcessorLazy = new(CreateTransactionProcessor); } - IReadOnlyTxProcessingScope IReadOnlyTxProcessorSource.Build(Hash256 stateRoot) => Build(stateRoot); protected virtual ITransactionProcessor CreateTransactionProcessor() => new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, LogManager); From 2754255aecf533c9acd94508c5bafcc5cb54a696 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Mon, 21 Oct 2024 14:43:15 +0300 Subject: [PATCH 58/70] Code cleanup --- .../Processing/OverridableTxProcessingScope.cs | 2 +- .../IOverridableTxProcessingScope.cs | 7 +------ .../IOverridableTxProcessorSource.cs | 2 +- .../Nethermind.Facade/BlockchainBridge.cs | 14 ++++++++------ .../Modules/Trace/TraceModuleFactory.cs | 2 +- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs index e9aee7439e8..692cad747ee 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs @@ -13,7 +13,7 @@ public class OverridableTxProcessingScope( ITransactionProcessor transactionProcessor, OverridableWorldState worldState, Hash256 originalStateRoot -) : IReadOnlyTxProcessingScope, IOverridableTxProcessingScope +) : IOverridableTxProcessingScope { public void Dispose() { diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs index d24a269aee6..9f0ed17a089 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessingScope.cs @@ -1,14 +1,9 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using Nethermind.State; - namespace Nethermind.Evm.TransactionProcessing; -public interface IOverridableTxProcessingScope : IDisposable +public interface IOverridableTxProcessingScope : IReadOnlyTxProcessingScope { - IWorldState WorldState { get; } IOverridableCodeInfoRepository CodeInfoRepository { get; } - ITransactionProcessor TransactionProcessor { get; } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs index 0f99901438d..324fff8d409 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IOverridableTxProcessorSource.cs @@ -10,5 +10,5 @@ namespace Nethermind.Evm.TransactionProcessing; public interface IOverridableTxProcessorSource { IOverridableTxProcessingScope Build(Hash256 stateRoot); - IOverridableTxProcessingScope BuildAndOverride(BlockHeader header, Dictionary stateOverride); + IOverridableTxProcessingScope BuildAndOverride(BlockHeader header, Dictionary? stateOverride); } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 1a95dec6e3f..537f4929570 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -150,8 +150,9 @@ private bool TryGetCanonicalTransaction( public CallOutput Call(BlockHeader header, Transaction tx, Dictionary? stateOverride, CancellationToken cancellationToken) { - CallOutputTracer callOutputTracer = new(); using IOverridableTxProcessingScope scope = _processingEnv.BuildAndOverride(header, stateOverride); + + CallOutputTracer callOutputTracer = new(); TransactionResult tryCallResult = TryCallAndRestore(header, tx, false, callOutputTracer.WithCancellation(cancellationToken), scope); return new CallOutput @@ -198,7 +199,8 @@ public CallOutput EstimateGas(BlockHeader header, Transaction tx, int errorMargi header, tx, true, - estimateGasTracer.WithCancellation(cancellationToken)); + estimateGasTracer.WithCancellation(cancellationToken), + scope); GasEstimator gasEstimator = new(scope.TransactionProcessor, scope.WorldState, _specProvider, _blocksConfig); long estimate = gasEstimator.Estimate(tx, header, estimateGasTracer, errorMargin, cancellationToken); @@ -220,7 +222,8 @@ public CallOutput CreateAccessList(BlockHeader header, Transaction tx, Cancellat : new(header.GasBeneficiary); TransactionResult tryCallResult = TryCallAndRestore(header, tx, false, - new CompositeTxTracer(callOutputTracer, accessTxTracer).WithCancellation(cancellationToken)); + new CompositeTxTracer(callOutputTracer, accessTxTracer).WithCancellation(cancellationToken), + _processingEnv.Build(header.StateRoot!)); return new CallOutput { @@ -237,12 +240,11 @@ private TransactionResult TryCallAndRestore( Transaction transaction, bool treatBlockHeaderAsParentBlock, ITxTracer tracer, - IOverridableTxProcessingScope? scope = null) + IOverridableTxProcessingScope scope) { try { - return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, - scope ?? _processingEnv.Build(blockHeader.StateRoot!)); + return CallAndRestore(blockHeader, transaction, treatBlockHeaderAsParentBlock, tracer, scope); } catch (InsufficientBalanceException ex) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 375e60320c6..c67f301f839 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -72,6 +72,6 @@ public override ITraceRpcModule Create() Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, traceOptions: ProcessingOptions.TraceTransactions); - return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv.StateReader, txProcessingEnv); + return new TraceRpcModule(_receiptStorage, tracer, _blockTree, _jsonRpcConfig, txProcessingEnv); } } From 4e307c7293b3832d569f6aeb17c55be11fb835b5 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 10:37:11 +0300 Subject: [PATCH 59/70] Code formatting --- .../Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs index 6acb4be0fa7..573a07c3c5c 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; From 2a2e66d37241637a046c7701641540d524303bf8 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 11:44:12 +0300 Subject: [PATCH 60/70] Skip commit set validation in `OverlayTrieStore` --- .../Nethermind.Trie/Pruning/OverlayTrieStore.cs | 7 +++++++ src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs | 13 ++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs index 9c83df3e34c..177b272442c 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs @@ -24,6 +24,13 @@ public override TrieNode FindCachedOrUnknown(Hash256? address, in TreePath path, public override byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None) => base.TryLoadRlp(address, in path, hash, flags) ?? store.TryLoadRlp(address, in path, hash, flags); +#if DEBUG + protected override void VerifyNewCommitSet(long blockNumber) + { + // Skip checks, as override can be applied using the same number or without a state root + } +#endif + // TODO clarify is ClearCache is reliable enough to use public void ResetOverrides() => ClearCache(); } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index b5c6bbcab66..cd4a4937e5c 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -699,14 +699,21 @@ private static ConcurrentQueue CreateQueueAtomic(ref ConcurrentQ return prior ?? instance; } +#if DEBUG + protected virtual void VerifyNewCommitSet(long blockNumber) + { + // TODO: this throws on reorgs, does it not? let us recreate it in test + Debug.Assert(_lastCommitSet == null || blockNumber == _lastCommitSet.BlockNumber + 1 || _lastCommitSet.BlockNumber == 0, "Newly begun block is not a successor of the last one."); + Debug.Assert(_lastCommitSet == null || _lastCommitSet.IsSealed, "Not sealed when beginning new block"); + } +#endif + private BlockCommitSet CreateCommitSet(long blockNumber) { if (_logger.IsDebug) _logger.Debug($"Beginning new {nameof(BlockCommitSet)} - {blockNumber}"); - // TODO: this throws on reorgs, does it not? let us recreate it in test #if DEBUG - Debug.Assert(_lastCommitSet == null || blockNumber == _lastCommitSet.BlockNumber + 1 || _lastCommitSet.BlockNumber == 0, $"Newly begun block is not a successor of the last one."); - Debug.Assert(_lastCommitSet == null || _lastCommitSet.IsSealed, "Not sealed when beginning new block"); + VerifyNewCommitSet(blockNumber); #endif BlockCommitSet commitSet = new(blockNumber); From a5385c62c2d077856f8821daca0cc18156b3553e Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 12:56:29 +0300 Subject: [PATCH 61/70] Clear in-memory database on `ResetOverrides` --- .../BlockchainBridgeTests.cs | 7 ++---- .../Nethermind.State/OverridableWorldState.cs | 22 +++++++++++-------- .../OverridableWorldStateManager.cs | 4 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 42f2e968dc7..7232165c584 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -72,11 +72,9 @@ public async Task SetUp() _ethereumEcdsa = Substitute.For(); _specProvider = MainnetSpecProvider.Instance; - ReadOnlyDbProvider dbProvider = new ReadOnlyDbProvider(_dbProvider, false); IReadOnlyTrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); - OverridableWorldStateManager worldStateManager = - new OverridableWorldStateManager(dbProvider, trieStore, LimboLogs.Instance); + OverridableWorldStateManager worldStateManager = new(_dbProvider, trieStore, LimboLogs.Instance); IReadOnlyBlockTree readOnlyBlockTree = _blockTree.AsReadOnly(); TestReadOnlyTxProcessingEnv processingEnv = new( @@ -209,11 +207,10 @@ public void Call_uses_valid_beneficiary() [TestCase(0)] public void Bridge_head_is_correct(long headNumber) { - ReadOnlyDbProvider dbProvider = new ReadOnlyDbProvider(_dbProvider, false); IReadOnlyTrieStore trieStore = new TrieStore(_dbProvider.StateDb, LimboLogs.Instance).AsReadOnly(); OverridableWorldStateManager worldStateManager = - new(dbProvider, trieStore, LimboLogs.Instance); + new(_dbProvider, trieStore, LimboLogs.Instance); IReadOnlyBlockTree roBlockTree = _blockTree.AsReadOnly(); OverridableTxProcessingEnv processingEnv = new( worldStateManager, diff --git a/src/Nethermind/Nethermind.State/OverridableWorldState.cs b/src/Nethermind/Nethermind.State/OverridableWorldState.cs index 9e673f7a1c6..c5dbeaadc0a 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldState.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldState.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Db; using Nethermind.Logging; using Nethermind.Trie.Pruning; @@ -10,20 +11,23 @@ namespace Nethermind.State; public class OverridableWorldState : WorldState { private readonly OverlayTrieStore _trieStore; + private readonly IReadOnlyDb _codeDb; public OverridableWorldState( - OverlayTrieStore trieStore, IKeyValueStore? codeDb, ILogManager? logManager - ) : base(trieStore, codeDb, logManager) => - _trieStore = trieStore; - - public OverridableWorldState( - OverlayTrieStore trieStore, IKeyValueStore? codeDb, ILogManager? logManager, PreBlockCaches? preBlockCaches, - bool populatePreBlockCache = true - ) : base(trieStore, codeDb, logManager, preBlockCaches, populatePreBlockCache) => + OverlayTrieStore trieStore, IReadOnlyDb codeDb, ILogManager? logManager, + PreBlockCaches? preBlockCaches = null, bool populatePreBlockCache = true + ) : base(trieStore, codeDb, logManager, preBlockCaches, populatePreBlockCache) + { _trieStore = trieStore; + _codeDb = codeDb; + } /// /// Resets changes applied via /// - public void ResetOverrides() => _trieStore.ResetOverrides(); + public void ResetOverrides() + { + _trieStore.ResetOverrides(); + _codeDb.ClearTempChanges(); + } } diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index 1483cc500bc..5445ee22090 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -10,7 +10,7 @@ namespace Nethermind.State; public class OverridableWorldStateManager : IWorldStateManager { - private readonly IDb _codeDb; + private readonly IReadOnlyDb _codeDb; private readonly StateReader _reader; private readonly WorldState _state; @@ -23,7 +23,7 @@ public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore t OverlayTrieStore overlayTrieStore = new(dbProvider.StateDb, trieStore, logManager); _logManager = logManager; - _codeDb = dbProvider.GetDb(DbNames.Code); + _codeDb = (IReadOnlyDb)dbProvider.GetDb(DbNames.Code); _reader = new(overlayTrieStore, dbProvider.GetDb(DbNames.Code), logManager); _state = new(overlayTrieStore, dbProvider.GetDb(DbNames.Code), logManager); _overlayTrieStore = overlayTrieStore; From 5072a6fdba47e4a20a661001c6978db454fafe2e Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 13:02:34 +0300 Subject: [PATCH 62/70] Code cleanup --- .../Processing/OverridableTxProcessingEnv.cs | 1 - src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs | 1 - src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs | 3 --- 3 files changed, 5 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs index bbd5bcef20f..da0f252c160 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingEnv.cs @@ -39,7 +39,6 @@ public OverridableTxProcessingEnv( _transactionProcessorLazy = new(CreateTransactionProcessor); } - protected virtual ITransactionProcessor CreateTransactionProcessor() => new TransactionProcessor(SpecProvider, StateProvider, Machine, CodeInfoRepository, LogManager); diff --git a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs index 177b272442c..e5e9697ba1a 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/OverlayTrieStore.cs @@ -31,6 +31,5 @@ protected override void VerifyNewCommitSet(long blockNumber) } #endif - // TODO clarify is ClearCache is reliable enough to use public void ResetOverrides() => ClearCache(); } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index cd4a4937e5c..05d43a25655 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -634,9 +634,6 @@ private void PruneCache(bool skipRecalculateMemory = false) if (_logger.IsDebug) _logger.Debug($"Finished pruning nodes in {(long)Stopwatch.GetElapsedTime(start).TotalMilliseconds}ms {MemoryUsedByDirtyCache / 1.MB()} MB, last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); } - /// - /// This method is here to support testing. - /// public void ClearCache() { foreach (TrieStoreDirtyNodesCache dirtyNode in _dirtyNodes) From 086e5b54e40da7ff8179f98adfee22c87b159d05 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 19:55:39 +0300 Subject: [PATCH 63/70] Use `TraceModuleFactory` to create module for `TraceRpcModuleTests` --- .../Modules/TraceRpcModuleTests.cs | 58 ++++++------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 7393869f7d1..b165bfb0336 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -6,8 +6,6 @@ using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; -using Nethermind.Blockchain; -using Nethermind.Blockchain.Receipts; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; @@ -17,21 +15,16 @@ using Nethermind.JsonRpc.Modules.Trace; using NUnit.Framework; using Nethermind.Blockchain.Find; -using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; -using Nethermind.Consensus.Tracing; -using Nethermind.Consensus.Validators; using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Evm.Tracing.ParityStyle; -using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Serialization.Json; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; using Nethermind.JsonRpc.Data; -using Nethermind.JsonRpc.Modules; using Nethermind.Serialization.Rlp; namespace Nethermind.JsonRpc.Test.Modules; @@ -44,42 +37,10 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) { JsonRpcConfig = new JsonRpcConfig(); Blockchain = await TestRpcBlockchain.ForTest(isAura ? SealEngineType.AuRa : SealEngineType.NethDev).Build(specProvider); + await Blockchain.AddFunds(TestItem.AddressA, 1000.Ether()); await Blockchain.AddFunds(TestItem.AddressB, 1000.Ether()); await Blockchain.AddFunds(TestItem.AddressC, 1000.Ether()); - ReceiptsRecovery receiptsRecovery = - new(Blockchain.EthereumEcdsa, Blockchain.SpecProvider); - IReceiptFinder receiptFinder = new FullInfoReceiptFinder(Blockchain.ReceiptStorage, receiptsRecovery, Blockchain.BlockFinder); - OverridableTxProcessingEnv txProcessingEnv = - new(Blockchain.OverridableWorldStateManager, Blockchain.BlockTree.AsReadOnly(), Blockchain.SpecProvider, Blockchain.LogManager); - IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(Keccak.EmptyTreeHash); - - RewardCalculator rewardCalculatorSource = new(Blockchain.SpecProvider); - - IRewardCalculator rewardCalculator = rewardCalculatorSource.Get(scope.TransactionProcessor); - - RpcBlockTransactionsExecutor rpcBlockTransactionsExecutor = new(scope.TransactionProcessor, scope.WorldState); - BlockProcessor.BlockValidationTransactionsExecutor executeBlockTransactionsExecutor = new(scope.TransactionProcessor, - scope.WorldState); - - ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor) => new( - scope, - Always.Valid, - Blockchain.BlockPreprocessorStep, - rewardCalculator, - Blockchain.ReceiptStorage, - Blockchain.SpecProvider, - Blockchain.BlockTree, - Blockchain.StateReader, - Blockchain.LogManager, - transactionsExecutor); - - ReadOnlyChainProcessingEnv traceProcessingEnv = CreateChainProcessingEnv(rpcBlockTransactionsExecutor); - ReadOnlyChainProcessingEnv executeProcessingEnv = CreateChainProcessingEnv(executeBlockTransactionsExecutor); - - Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, - traceOptions: ProcessingOptions.TraceTransactions); - TraceRpcModule = new TraceRpcModule(receiptFinder, tracer, Blockchain.BlockFinder, JsonRpcConfig, txProcessingEnv); for (int i = 1; i < 10; i++) { @@ -93,13 +54,30 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) } await Blockchain.AddBlock(transactions.ToArray()); } + + Factory = new( + Blockchain.OverridableWorldStateManager, + Blockchain.DbProvider, + Blockchain.BlockTree, + JsonRpcConfig, + Blockchain.BlockPreprocessorStep, + new RewardCalculator(Blockchain.SpecProvider), + Blockchain.ReceiptStorage, + Blockchain.SpecProvider, + Blockchain.PoSSwitcher, + Blockchain.LogManager + ); + + TraceRpcModule = Factory.Create(); } public ITraceRpcModule TraceRpcModule { get; private set; } = null!; + public TraceModuleFactory Factory { get; private set; } = null!; public IJsonRpcConfig JsonRpcConfig { get; private set; } = null!; public TestRpcBlockchain Blockchain { get; set; } = null!; } + [Test] public async Task Tx_positions_are_fine() { From 54b3e89af89c68b60b61f281ec7ab81b99f1a6cf Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 19:56:08 +0300 Subject: [PATCH 64/70] Add state override storage test for trace_call --- .../Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index b165bfb0336..e75839a6c66 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -946,6 +946,13 @@ public async Task Trace_replayBlockTransactions_stateDiff() """{"0xc200000000000000000000000000000000000000":{"code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""", """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"\u002B":"0x0"},"code":"=","nonce":{"\u002B":"0x1"},"storage":{}},"0xc200000000000000000000000000000000000000":{"balance":"=","code":"=","nonce":"=","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":{"*":{"from":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0x1122334455667788990011223344556677889900112233445566778899001122"}}}}},"trace":[],"vmTrace":null},"id":67}""" )] + [TestCase( + "Uses storage from state override", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0x60fe47b1112233445566778899001122334455667788990011223344556677889900112233445566778899001122"}""", + "stateDiff", + """{"0xc200000000000000000000000000000000000000":{"state": {"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000123456"}, "code":"0x6080604052348015600e575f80fd5b50600436106030575f3560e01c80632a1afcd914603457806360fe47b114604d575b5f80fd5b603b5f5481565b60405190815260200160405180910390f35b605c6058366004605e565b5f55565b005b5f60208284031215606d575f80fd5b503591905056fea2646970667358221220fd4e5f3894be8e57fc7460afebb5c90d96c3486d79bf47b00c2ed666ab2f82b364736f6c634300081a0033"}}""", + """{"jsonrpc":"2.0","result":{"output":null,"stateDiff":{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":{"\u002B":"0x0"},"code":"=","nonce":{"\u002B":"0x1"},"storage":{}},"0xc200000000000000000000000000000000000000":{"balance":"=","code":"=","nonce":"=","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":{"*":{"from":"0x0000000000000000000000000000000000000000000000000000000000123456","to":"0x1122334455667788990011223344556677889900112233445566778899001122"}}}}},"trace":[],"vmTrace":null},"id":67}""" + )] [TestCase( "Executes precompile using overriden address", """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0x0000000000000000000000000000000000123456","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", From bdf2c84c90da29eb78c55e9190926442529f6889 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Tue, 22 Oct 2024 19:59:54 +0300 Subject: [PATCH 65/70] Naming cleanup --- .../Modules/DebugModuleMockedTests.cs | 585 --------------- .../Modules/DebugModuleTests.cs | 681 ++++++++++++++---- .../Modules/DebugRpcModuleTests.cs | 210 ++++++ 3 files changed, 738 insertions(+), 738 deletions(-) delete mode 100644 src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs create mode 100644 src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs deleted file mode 100644 index e60238e5d5b..00000000000 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleMockedTests.cs +++ /dev/null @@ -1,585 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using FluentAssertions; -using Nethermind.Blockchain; -using Nethermind.Blockchain.Blocks; -using Nethermind.Blockchain.Find; -using Nethermind.Config; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; -using Nethermind.Core.Specs; -using Nethermind.Core.Test.Builders; -using Nethermind.Db; -using Nethermind.Evm.Tracing.GethStyle; -using Nethermind.Evm.Tracing.GethStyle.Custom; -using Nethermind.Facade.Eth.RpcTransaction; -using Nethermind.Int256; -using Nethermind.JsonRpc.Modules.DebugModule; -using Nethermind.JsonRpc.Modules.Eth; -using Nethermind.Logging; -using Nethermind.Serialization.Rlp; -using NSubstitute; -using NSubstitute.ReturnsExtensions; -using NUnit.Framework; - -namespace Nethermind.JsonRpc.Test.Modules; - -// Tests with mocked IDebugBridge -[Parallelizable(ParallelScope.Self)] -public class DebugModuleMockedTests -{ - private readonly IJsonRpcConfig jsonRpcConfig = new JsonRpcConfig(); - private readonly ISpecProvider specProvider = Substitute.For(); - private readonly IDebugBridge debugBridge = Substitute.For(); - private readonly MemDb _blocksDb = new(); - - [Test] - public async Task Get_from_db() - { - byte[] key = new byte[] { 1, 2, 3 }; - byte[] value = new byte[] { 4, 5, 6 }; - debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns(value); - - - IConfigProvider configProvider = Substitute.For(); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = - await RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key) as JsonRpcSuccessResponse; - - byte[]? result = response?.Result as byte[]; - } - - [Test] - public async Task Get_from_db_null_value() - { - debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns((byte[])null!); - - IConfigProvider configProvider = Substitute.For(); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - byte[] key = new byte[] { 1, 2, 3 }; - using var response = - await RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key) as - JsonRpcSuccessResponse; - - Assert.That(response, Is.Not.Null); - } - - [TestCase(1)] - [TestCase(0x1)] - public async Task Get_chain_level(object parameter) - { - debugBridge.GetLevelInfo(1).Returns( - new ChainLevelInfo( - true, - new[] - { - new BlockInfo(TestItem.KeccakA, 1000), - new BlockInfo(TestItem.KeccakB, 1001), - })); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getChainLevel", parameter) as JsonRpcSuccessResponse; - var chainLevel = response?.Result as ChainLevelForRpc; - Assert.That(chainLevel, Is.Not.Null); - Assert.That(chainLevel?.HasBlockOnMainChain, Is.EqualTo(true)); - Assert.That(chainLevel?.BlockInfos.Length, Is.EqualTo(2)); - } - - [Test] - public async Task Get_block_rlp_by_hash() - { - BlockDecoder decoder = new(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - debugBridge.GetBlockRlp(new BlockParameter(Keccak.Zero)).Returns(rlp.Bytes); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", Keccak.Zero) as JsonRpcSuccessResponse; - Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); - } - - [Test] - public async Task Get_raw_Header() - { - HeaderDecoder decoder = new(); - Block blk = Build.A.Block.WithNumber(0).TestObject; - Rlp rlp = decoder.Encode(blk.Header); - debugBridge.GetBlock(new BlockParameter((long)0)).Returns(blk); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getRawHeader", 0) as JsonRpcSuccessResponse; - Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); - } - - [Test] - public async Task Get_block_rlp() - { - BlockDecoder decoder = new(); - IDebugBridge localDebugBridge = Substitute.For(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - localDebugBridge.GetBlockRlp(new BlockParameter(1)).Returns(rlp.Bytes); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, localDebugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", 1) as JsonRpcSuccessResponse; - - Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); - } - - [Test] - public async Task Get_rawblock() - { - BlockDecoder decoder = new(); - IDebugBridge localDebugBridge = Substitute.For(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - localDebugBridge.GetBlockRlp(new BlockParameter(1)).Returns(rlp.Bytes); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, localDebugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getRawBlock", 1) as JsonRpcSuccessResponse; - - Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); - } - - [Test] - public async Task Get_block_rlp_when_missing() - { - debugBridge.GetBlockRlp(new BlockParameter(1)).ReturnsNull(); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", 1) as JsonRpcErrorResponse; - - Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); - } - - [Test] - public async Task Get_rawblock_when_missing() - { - debugBridge.GetBlockRlp(new BlockParameter(1)).ReturnsNull(); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getRawBlock", 1) as JsonRpcErrorResponse; - - Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); - } - - [Test] - public async Task Get_block_rlp_by_hash_when_missing() - { - BlockDecoder decoder = new(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - debugBridge.GetBlockRlp(new BlockParameter(Keccak.Zero)).ReturnsNull(); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", Keccak.Zero) as JsonRpcErrorResponse; - - Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); - } - - [Test] - public async Task Get_trace() - { - GethTxTraceEntry entry = new() - { - Storage = new Dictionary - { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - }, - Memory = new string[] - { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }, - Stack = new string[] - { - "7".PadLeft(64, '0'), - "8".PadLeft(64, '0') - }, - Opcode = "STOP", - Gas = 22000, - GasCost = 1, - Depth = 1 - }; - - var trace = new GethLikeTxTrace(); - trace.ReturnValue = Bytes.FromHexString("a2"); - trace.Entries.Add(entry); - - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new object()); - - Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[\"0000000000000000000000000000000000000000000000000000000000000007\",\"0000000000000000000000000000000000000000000000000000000000000008\"],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); - } - - [Test] - public async Task Get_js_trace() - { - GethLikeTxTrace trace = new() { CustomTracerResult = new GethLikeCustomTrace() { Value = new { CustomProperty = 1 } } }; - - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new object()); - - Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"customProperty\":1},\"id\":67}")); - } - - [Test] - public async Task Get_trace_with_options() - { - GethTxTraceEntry entry = new() - { - Storage = new Dictionary - { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - }, - Memory = new string[] - { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }, - Stack = new string[] - { - }, - Opcode = "STOP", - Gas = 22000, - GasCost = 1, - Depth = 1 - }; - - - GethLikeTxTrace trace = new() { ReturnValue = Bytes.FromHexString("a2") }; - trace.Entries.Add(entry); - - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new { disableStack = true }); - - Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); - } - - private BlockTree BuildBlockTree(Func? builderOptions = null) - { - BlockTreeBuilder builder = Build.A.BlockTree().WithBlocksDb(_blocksDb).WithBlockStore(new BlockStore(_blocksDb)); - builder = builderOptions?.Invoke(builder) ?? builder; - return builder.TestObject; - } - - [Test] - public void Debug_getBadBlocks_test() - { - IBlockStore badBlocksStore = null!; - BlockTree blockTree = BuildBlockTree(b => b.WithBadBlockStore(badBlocksStore = new BlockStore(b.BadBlocksDb))); - - Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; - Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; - Block block2 = Build.A.Block.WithNumber(2).WithDifficulty(3).WithParent(block1).TestObject; - Block block3 = Build.A.Block.WithNumber(2).WithDifficulty(4).WithParent(block2).TestObject; - - blockTree.SuggestBlock(block0); - blockTree.SuggestBlock(block1); - blockTree.SuggestBlock(block2); - blockTree.SuggestBlock(block3); - - blockTree.DeleteInvalidBlock(block1); - - BlockDecoder decoder = new(); - _blocksDb.Set(block1.Hash ?? new Hash256("0x0"), decoder.Encode(block1).Bytes); - - debugBridge.GetBadBlocks().Returns(badBlocksStore.GetAll()); - - AddBlockResult result = blockTree.SuggestBlock(block1); - Assert.That(result, Is.EqualTo(AddBlockResult.InvalidBlock)); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - ResultWrapper> blocks = rpcModule.debug_getBadBlocks(); - Assert.That(blocks.Data.Count, Is.EqualTo(1)); - Assert.That(blocks.Data.ElementAt(0).Hash, Is.EqualTo(block1.Hash)); - Assert.That(blocks.Data.ElementAt(0).Block.Difficulty, Is.EqualTo(new UInt256(2))); - } - - [Test] - public async Task Get_trace_with_javascript_setup() - { - GethTraceOptions passedOption = null!; - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Do(arg => passedOption = arg)) - .Returns(new GethLikeTxTrace()); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new { disableStack = true, tracerConfig = new { a = true } }); - passedOption.TracerConfig!.ToString().Should().Be("{\"a\":true}"); - } - - [Test] - public void Debug_traceCall_test() - { - GethTxTraceEntry entry = new(); - - entry.Storage = new Dictionary - { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - }; - - entry.Memory = new string[] - { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }; - - entry.Stack = new string[] { }; - entry.Opcode = "STOP"; - entry.Gas = 22000; - entry.GasCost = 1; - entry.Depth = 1; - - var trace = new GethLikeTxTrace(); - trace.ReturnValue = Bytes.FromHexString("a2"); - trace.Entries.Add(entry); - - GethTraceOptions gtOptions = new(); - - Transaction transaction = Build.A.Transaction.WithTo(TestItem.AddressA).WithHash(TestItem.KeccakA).TestObject; - TransactionForRpc txForRpc = TransactionForRpc.FromTransaction(transaction); - - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - ResultWrapper debugTraceCall = rpcModule.debug_traceCall(txForRpc, null, gtOptions); - var expected = ResultWrapper.Success( - new GethLikeTxTrace() - { - Failed = false, - Entries = new List() - { - new GethTxTraceEntry() - { - Gas = 22000, - GasCost = 1, - Depth = 1, - Memory = new string[] - { - "0000000000000000000000000000000000000000000000000000000000000005", - "0000000000000000000000000000000000000000000000000000000000000006" - }, - Opcode = "STOP", - ProgramCounter = 0, - Stack = Array.Empty(), - Storage = new Dictionary() - { - { - "0000000000000000000000000000000000000000000000000000000000000001", - "0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "0000000000000000000000000000000000000000000000000000000000000003", - "0000000000000000000000000000000000000000000000000000000000000004" - }, - } - } - }, - Gas = 0, - ReturnValue = new byte[] { 162 } - } - ); - - debugTraceCall.Should().BeEquivalentTo(expected); - } - - [Test] - public async Task Migrate_receipts() - { - debugBridge.MigrateReceipts(Arg.Any()).Returns(true); - IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_migrateReceipts", 100); - Assert.That(response, Is.Not.Null); - } - - [Test] - public async Task Update_head_block() - { - debugBridge.UpdateHeadBlock(Arg.Any()); - IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - await RpcTest.TestSerializedRequest(rpcModule, "debug_resetHead", TestItem.KeccakA); - debugBridge.Received().UpdateHeadBlock(TestItem.KeccakA); - } - - [Test] - public void TraceBlock_Success() - { - var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); - var tracesClone = TestItem.CloneObject(traces); - var blockRlp = new Rlp(TestItem.RandomDataA); - - debugBridge - .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) - .Returns(traces); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); - var expected = ResultWrapper.Success(tracesClone); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void TraceBlock_Fail() - { - var blockRlp = new Rlp(TestItem.RandomDataA); - - debugBridge - .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) - .Returns(default(GethLikeTxTrace[])); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); - var expected = ResultWrapper.Fail($"Trace is null for RLP {blockRlp.Bytes.ToHexString()}", ErrorCodes.ResourceNotFound); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void StandardTraceBlockToFile() - { - var blockHash = Keccak.EmptyTreeHash; - - static IEnumerable GetFileNames(Hash256 hash) => - new[] { $"block_{hash.ToShortString()}-0", $"block_{hash.ToShortString()}-1" }; - - debugBridge - .TraceBlockToFile(Arg.Is(blockHash), Arg.Any(), Arg.Any()) - .Returns(c => GetFileNames(c.ArgAt(0))); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_standardTraceBlockToFile(blockHash); - var expected = ResultWrapper>.Success(GetFileNames(blockHash)); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void StandardTraceBadBlockToFile() - { - var blockHash = Keccak.EmptyTreeHash; - - static IEnumerable GetFileNames(Hash256 hash) => - new[] { $"block_{hash.ToShortString()}-0", $"block_{hash.ToShortString()}-1" }; - - debugBridge - .TraceBadBlockToFile(Arg.Is(blockHash), Arg.Any(), Arg.Any()) - .Returns(c => GetFileNames(c.ArgAt(0))); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_standardTraceBadBlockToFile(blockHash); - var expected = ResultWrapper>.Success(GetFileNames(blockHash)); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void TraceBlockByHash_Success() - { - var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); - var tracesClone = TestItem.CloneObject(traces); - var blockHash = TestItem.KeccakA; - - debugBridge - .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) - .Returns(traces); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_traceBlockByHash(blockHash); - var expected = ResultWrapper.Success(tracesClone); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void TraceBlockByHash_Fail() - { - var blockHash = TestItem.KeccakA; - - debugBridge - .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) - .Returns(default(GethLikeTxTrace[])); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_traceBlockByHash(blockHash); - var expected = ResultWrapper.Fail($"Trace is null for block {blockHash}", ErrorCodes.ResourceNotFound); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void TraceBlockByNumber_Success() - { - var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); - var tracesClone = TestItem.CloneObject(traces); - var blockNumber = BlockParameter.Latest; - - debugBridge - .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) - .Returns(traces); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_traceBlockByNumber(blockNumber); - var expected = ResultWrapper.Success(tracesClone); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void TraceBlockByNumber_Fail() - { - var blockNumber = BlockParameter.Latest; - - debugBridge - .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) - .Returns(default(GethLikeTxTrace[])); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); - var actual = rpcModule.debug_traceBlockByNumber(blockNumber); - var expected = ResultWrapper.Fail($"Trace is null for block {blockNumber}", ErrorCodes.ResourceNotFound); - - actual.Should().BeEquivalentTo(expected); - } - - private static GethLikeTxTrace MockGethLikeTrace() - { - var trace = new GethLikeTxTrace { ReturnValue = new byte[] { 0xA2 } }; - - trace.Entries.Add(new GethTxTraceEntry - { - Depth = 1, - Gas = 22000, - GasCost = 1, - Memory = new string[] - { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }, - Opcode = "STOP", - ProgramCounter = 32, - Stack = new string[] - { - "7".PadLeft(64, '0'), - "8".PadLeft(64, '0') - }, - Storage = new Dictionary - { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - } - }); - - return trace; - } -} diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs index 775ba7f3868..a54d705a3d3 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs @@ -2,209 +2,584 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.IO.Abstractions; -using System.Text.Json; +using System.Collections.Generic; +using System.Linq; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using Nethermind.Blockchain; using Nethermind.Blockchain.Blocks; -using Nethermind.Blockchain.Receipts; +using Nethermind.Blockchain.Find; using Nethermind.Config; -using Nethermind.Consensus.Rewards; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; +using Nethermind.Db; using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.Evm.Tracing.GethStyle.Custom; +using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Int256; using Nethermind.JsonRpc.Modules.DebugModule; -using Nethermind.Synchronization.ParallelSync; +using Nethermind.JsonRpc.Modules.Eth; +using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using NSubstitute; +using NSubstitute.ReturnsExtensions; using NUnit.Framework; namespace Nethermind.JsonRpc.Test.Modules; +// Tests with mocked IDebugBridge [Parallelizable(ParallelScope.Self)] public class DebugModuleTests { - private class Context : IDisposable + private readonly IJsonRpcConfig jsonRpcConfig = new JsonRpcConfig(); + private readonly ISpecProvider specProvider = Substitute.For(); + private readonly IDebugBridge debugBridge = Substitute.For(); + private readonly MemDb _blocksDb = new(); + + [Test] + public async Task Get_from_db() { - public IDebugRpcModule DebugRpcModule { get; } - public TestRpcBlockchain Blockchain { get; } + byte[] key = new byte[] { 1, 2, 3 }; + byte[] value = new byte[] { 4, 5, 6 }; + debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns(value); - private Context(TestRpcBlockchain blockchain, IDebugRpcModule debugRpcModule) - { - DebugRpcModule = debugRpcModule; - Blockchain = blockchain; - } - public static async Task Create(ISpecProvider? specProvider = null, bool isAura = false) - { - TestRpcBlockchain blockchain = await TestRpcBlockchain.ForTest(isAura ? SealEngineType.AuRa : SealEngineType.NethDev).Build(specProvider); + IConfigProvider configProvider = Substitute.For(); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = + await RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key) as JsonRpcSuccessResponse; - IConfigProvider configProvider = Substitute.For(); - IReceiptsMigration receiptsMigration = Substitute.For(); - ISyncModeSelector syncModeSelector = Substitute.For(); - var factory = new DebugModuleFactory( - blockchain.WorldStateManager, - blockchain.DbProvider, - blockchain.BlockTree, - blockchain.RpcConfig, - blockchain.BlockValidator, - blockchain.BlockPreprocessorStep, - NoBlockRewards.Instance, - blockchain.ReceiptStorage, - receiptsMigration, - configProvider, - blockchain.SpecProvider, - syncModeSelector, - new BlockStore(blockchain.BlocksDb), - new FileSystem(), - blockchain.LogManager - ); + byte[]? result = response?.Result as byte[]; + } - IDebugRpcModule debugRpcModule = factory.Create(); + [Test] + public async Task Get_from_db_null_value() + { + debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns((byte[])null!); + + IConfigProvider configProvider = Substitute.For(); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + byte[] key = new byte[] { 1, 2, 3 }; + using var response = + await RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key) as + JsonRpcSuccessResponse; - return new(blockchain, debugRpcModule); - } + Assert.That(response, Is.Not.Null); + } + + [TestCase(1)] + [TestCase(0x1)] + public async Task Get_chain_level(object parameter) + { + debugBridge.GetLevelInfo(1).Returns( + new ChainLevelInfo( + true, + new[] + { + new BlockInfo(TestItem.KeccakA, 1000), + new BlockInfo(TestItem.KeccakB, 1001), + })); - public void Dispose() => Blockchain.Dispose(); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getChainLevel", parameter) as JsonRpcSuccessResponse; + var chainLevel = response?.Result as ChainLevelForRpc; + Assert.That(chainLevel, Is.Not.Null); + Assert.That(chainLevel?.HasBlockOnMainChain, Is.EqualTo(true)); + Assert.That(chainLevel?.BlockInfos.Length, Is.EqualTo(2)); } [Test] - public async Task Debug_traceCall_fails_when_not_enough_balance() + public async Task Get_block_rlp_by_hash() { - using Context ctx = await Context.Create(); + BlockDecoder decoder = new(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + debugBridge.GetBlockRlp(new BlockParameter(Keccak.Zero)).Returns(rlp.Bytes); - Address address = Build.An.Address.TestObject; - UInt256 balance = 100.Ether(), send = balance / 2; + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", Keccak.Zero) as JsonRpcSuccessResponse; + Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); + } - JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", - new { from = $"{address}", to = $"{TestItem.AddressC}", value = send.ToString("X") } - ); + [Test] + public async Task Get_raw_Header() + { + HeaderDecoder decoder = new(); + Block blk = Build.A.Block.WithNumber(0).TestObject; + Rlp rlp = decoder.Encode(blk.Header); + debugBridge.GetBlock(new BlockParameter((long)0)).Returns(blk); - response.Should().BeOfType() - .Which.Error?.Message?.Should().Contain("insufficient funds"); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getRawHeader", 0) as JsonRpcSuccessResponse; + Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); } [Test] - public async Task Debug_traceCall_runs_on_top_of_specified_block() + public async Task Get_block_rlp() { - using Context ctx = await Context.Create(); - TestRpcBlockchain blockchain = ctx.Blockchain; + BlockDecoder decoder = new(); + IDebugBridge localDebugBridge = Substitute.For(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + localDebugBridge.GetBlockRlp(new BlockParameter(1)).Returns(rlp.Bytes); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, localDebugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", 1) as JsonRpcSuccessResponse; - Address address = Build.An.Address.TestObject; - UInt256 balance = 100.Ether(); + Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); + } - await blockchain.AddFunds(address, balance / 2); - await blockchain.AddFunds(address, balance / 2); - Hash256 lastBlockHash = blockchain.BlockTree.Head!.Hash!; + [Test] + public async Task Get_rawblock() + { + BlockDecoder decoder = new(); + IDebugBridge localDebugBridge = Substitute.For(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + localDebugBridge.GetBlockRlp(new BlockParameter(1)).Returns(rlp.Bytes); - JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", - new { from = $"{address}", to = $"{TestItem.AddressC}", value = balance.ToString("X") }, - $"{lastBlockHash}" - ); + DebugRpcModule rpcModule = new(LimboLogs.Instance, localDebugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getRawBlock", 1) as JsonRpcSuccessResponse; - response.Should().BeOfType(); - } - - [TestCase( - "Nonce override doesn't cause failure", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", - """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""" - )] - [TestCase( - "Uses account balance from state override", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x100"}""", - """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" - )] - [TestCase( - "Executes code from state override", - """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", - """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", - "00000000000000000000000000000000000000000000003635c9adc5de9f09e5" - )] - [TestCase( - "Executes precompile using overriden address", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", - """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", - "000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099" - )] - public async Task Debug_traceCall_with_state_override(string name, string transactionJson, string stateOverrideJson, string? expectedValue = null) - { - var transaction = JsonSerializer.Deserialize(transactionJson); - var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); - - using Context ctx = await Context.Create(); - - JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", - transaction, null, new { stateOverrides = stateOverride } - ); + Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); + } + + [Test] + public async Task Get_block_rlp_when_missing() + { + debugBridge.GetBlockRlp(new BlockParameter(1)).ReturnsNull(); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", 1) as JsonRpcErrorResponse; + + Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); + } + + [Test] + public async Task Get_rawblock_when_missing() + { + debugBridge.GetBlockRlp(new BlockParameter(1)).ReturnsNull(); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getRawBlock", 1) as JsonRpcErrorResponse; - GethLikeTxTrace trace = response.Should().BeOfType() - .Which.Result.Should().BeOfType() - .Subject; - - if (expectedValue != null) - Convert.ToHexString(trace.ReturnValue).Should().BeEquivalentTo(expectedValue); - } - - [TestCase( - "When balance is overriden", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", - """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" - )] - [TestCase( - "When address code is overriden", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", - """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" - )] - [TestCase( - "When precompile address is changed", - """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", - """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" - )] - public async Task debug_traceCall_with_state_override_does_not_affect_other_calls(string name, string transactionJson, string stateOverrideJson) - { - var transaction = JsonSerializer.Deserialize(transactionJson); - var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); - - using Context ctx = await Context.Create(); - - var resultOverrideBefore = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); + } + + [Test] + public async Task Get_block_rlp_by_hash_when_missing() + { + BlockDecoder decoder = new(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + debugBridge.GetBlockRlp(new BlockParameter(Keccak.Zero)).ReturnsNull(); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + using var response = await RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", Keccak.Zero) as JsonRpcErrorResponse; + + Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); + } + + [Test] + public async Task Get_trace() + { + GethTxTraceEntry entry = new() { - stateOverrides = stateOverride, - enableMemory = false, - disableStorage = true, - disableStack = true, - tracer = "callTracer", - tracerConfig = new { withLog = false } - }); + Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + }, + Memory = new string[] + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }, + Stack = new string[] + { + "7".PadLeft(64, '0'), + "8".PadLeft(64, '0') + }, + Opcode = "STOP", + Gas = 22000, + GasCost = 1, + Depth = 1 + }; + + var trace = new GethLikeTxTrace(); + trace.ReturnValue = Bytes.FromHexString("a2"); + trace.Entries.Add(entry); + + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new object()); + + Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[\"0000000000000000000000000000000000000000000000000000000000000007\",\"0000000000000000000000000000000000000000000000000000000000000008\"],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); + } + + [Test] + public async Task Get_js_trace() + { + GethLikeTxTrace trace = new() { CustomTracerResult = new GethLikeCustomTrace() { Value = new { CustomProperty = 1 } } }; + + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new object()); - var resultNoOverride = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"customProperty\":1},\"id\":67}")); + } + + [Test] + public async Task Get_trace_with_options() + { + GethTxTraceEntry entry = new() { - // configuration to minimize number of fields being compared - enableMemory = false, - disableStorage = true, - disableStack = true, - tracer = "callTracer", - tracerConfig = new { withLog = false } - }); + Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + }, + Memory = new string[] + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }, + Stack = new string[] + { + }, + Opcode = "STOP", + Gas = 22000, + GasCost = 1, + Depth = 1 + }; + + + GethLikeTxTrace trace = new() { ReturnValue = Bytes.FromHexString("a2") }; + trace.Entries.Add(entry); + + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new { disableStack = true }); + + Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); + } + + private BlockTree BuildBlockTree(Func? builderOptions = null) + { + BlockTreeBuilder builder = Build.A.BlockTree().WithBlocksDb(_blocksDb).WithBlockStore(new BlockStore(_blocksDb)); + builder = builderOptions?.Invoke(builder) ?? builder; + return builder.TestObject; + } + + [Test] + public void Debug_getBadBlocks_test() + { + IBlockStore badBlocksStore = null!; + BlockTree blockTree = BuildBlockTree(b => b.WithBadBlockStore(badBlocksStore = new BlockStore(b.BadBlocksDb))); + + Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; + Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; + Block block2 = Build.A.Block.WithNumber(2).WithDifficulty(3).WithParent(block1).TestObject; + Block block3 = Build.A.Block.WithNumber(2).WithDifficulty(4).WithParent(block2).TestObject; + + blockTree.SuggestBlock(block0); + blockTree.SuggestBlock(block1); + blockTree.SuggestBlock(block2); + blockTree.SuggestBlock(block3); + + blockTree.DeleteInvalidBlock(block1); + + BlockDecoder decoder = new(); + _blocksDb.Set(block1.Hash ?? new Hash256("0x0"), decoder.Encode(block1).Bytes); + + debugBridge.GetBadBlocks().Returns(badBlocksStore.GetAll()); + + AddBlockResult result = blockTree.SuggestBlock(block1); + Assert.That(result, Is.EqualTo(AddBlockResult.InvalidBlock)); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + ResultWrapper> blocks = rpcModule.debug_getBadBlocks(); + Assert.That(blocks.Data.Count, Is.EqualTo(1)); + Assert.That(blocks.Data.ElementAt(0).Hash, Is.EqualTo(block1.Hash)); + Assert.That(blocks.Data.ElementAt(0).Block.Difficulty, Is.EqualTo(new UInt256(2))); + } + + [Test] + public async Task Get_trace_with_javascript_setup() + { + GethTraceOptions passedOption = null!; + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Do(arg => passedOption = arg)) + .Returns(new GethLikeTxTrace()); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + await RpcTest.TestSerializedRequest(rpcModule, "debug_traceTransaction", TestItem.KeccakA, new { disableStack = true, tracerConfig = new { a = true } }); + passedOption.TracerConfig!.ToString().Should().Be("{\"a\":true}"); + } + + [Test] + public void Debug_traceCall_test() + { + GethTxTraceEntry entry = new(); - var resultOverrideAfter = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + entry.Storage = new Dictionary { - stateOverrides = stateOverride, - enableMemory = false, - disableStorage = true, - disableStack = true, - tracer = "callTracer", - tracerConfig = new { withLog = false } - }); + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + }; - Assert.Multiple(() => + entry.Memory = new string[] { - Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); - Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }; + + entry.Stack = new string[] { }; + entry.Opcode = "STOP"; + entry.Gas = 22000; + entry.GasCost = 1; + entry.Depth = 1; + + var trace = new GethLikeTxTrace(); + trace.ReturnValue = Bytes.FromHexString("a2"); + trace.Entries.Add(entry); + + GethTraceOptions gtOptions = new(); + + Transaction transaction = Build.A.Transaction.WithTo(TestItem.AddressA).WithHash(TestItem.KeccakA).TestObject; + TransactionForRpc txForRpc = TransactionForRpc.FromTransaction(transaction); + + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + ResultWrapper debugTraceCall = rpcModule.debug_traceCall(txForRpc, null, gtOptions); + var expected = ResultWrapper.Success( + new GethLikeTxTrace() + { + Failed = false, + Entries = new List() + { + new GethTxTraceEntry() + { + Gas = 22000, + GasCost = 1, + Depth = 1, + Memory = new string[] + { + "0000000000000000000000000000000000000000000000000000000000000005", + "0000000000000000000000000000000000000000000000000000000000000006" + }, + Opcode = "STOP", + ProgramCounter = 0, + Stack = Array.Empty(), + Storage = new Dictionary() + { + { + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + }, + } + } + }, + Gas = 0, + ReturnValue = new byte[] { 162 } + } + ); + + debugTraceCall.Should().BeEquivalentTo(expected); + } + + [Test] + public async Task Migrate_receipts() + { + debugBridge.MigrateReceipts(Arg.Any()).Returns(true); + IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_migrateReceipts", 100); + Assert.That(response, Is.Not.Null); + } + + [Test] + public async Task Update_head_block() + { + debugBridge.UpdateHeadBlock(Arg.Any()); + IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + await RpcTest.TestSerializedRequest(rpcModule, "debug_resetHead", TestItem.KeccakA); + debugBridge.Received().UpdateHeadBlock(TestItem.KeccakA); + } + + [Test] + public void TraceBlock_Success() + { + var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); + var tracesClone = TestItem.CloneObject(traces); + var blockRlp = new Rlp(TestItem.RandomDataA); + + debugBridge + .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) + .Returns(traces); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); + var expected = ResultWrapper.Success(tracesClone); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void TraceBlock_Fail() + { + var blockRlp = new Rlp(TestItem.RandomDataA); + + debugBridge + .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) + .Returns(default(GethLikeTxTrace[])); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); + var expected = ResultWrapper.Fail($"Trace is null for RLP {blockRlp.Bytes.ToHexString()}", ErrorCodes.ResourceNotFound); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void StandardTraceBlockToFile() + { + var blockHash = Keccak.EmptyTreeHash; + + static IEnumerable GetFileNames(Hash256 hash) => + new[] { $"block_{hash.ToShortString()}-0", $"block_{hash.ToShortString()}-1" }; + + debugBridge + .TraceBlockToFile(Arg.Is(blockHash), Arg.Any(), Arg.Any()) + .Returns(c => GetFileNames(c.ArgAt(0))); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_standardTraceBlockToFile(blockHash); + var expected = ResultWrapper>.Success(GetFileNames(blockHash)); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void StandardTraceBadBlockToFile() + { + var blockHash = Keccak.EmptyTreeHash; + + static IEnumerable GetFileNames(Hash256 hash) => + new[] { $"block_{hash.ToShortString()}-0", $"block_{hash.ToShortString()}-1" }; + + debugBridge + .TraceBadBlockToFile(Arg.Is(blockHash), Arg.Any(), Arg.Any()) + .Returns(c => GetFileNames(c.ArgAt(0))); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_standardTraceBadBlockToFile(blockHash); + var expected = ResultWrapper>.Success(GetFileNames(blockHash)); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void TraceBlockByHash_Success() + { + var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); + var tracesClone = TestItem.CloneObject(traces); + var blockHash = TestItem.KeccakA; + + debugBridge + .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) + .Returns(traces); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_traceBlockByHash(blockHash); + var expected = ResultWrapper.Success(tracesClone); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void TraceBlockByHash_Fail() + { + var blockHash = TestItem.KeccakA; + + debugBridge + .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) + .Returns(default(GethLikeTxTrace[])); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_traceBlockByHash(blockHash); + var expected = ResultWrapper.Fail($"Trace is null for block {blockHash}", ErrorCodes.ResourceNotFound); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void TraceBlockByNumber_Success() + { + var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); + var tracesClone = TestItem.CloneObject(traces); + var blockNumber = BlockParameter.Latest; + + debugBridge + .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) + .Returns(traces); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_traceBlockByNumber(blockNumber); + var expected = ResultWrapper.Success(tracesClone); + + actual.Should().BeEquivalentTo(expected); + } + + [Test] + public void TraceBlockByNumber_Fail() + { + var blockNumber = BlockParameter.Latest; + + debugBridge + .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) + .Returns(default(GethLikeTxTrace[])); + + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider); + var actual = rpcModule.debug_traceBlockByNumber(blockNumber); + var expected = ResultWrapper.Fail($"Trace is null for block {blockNumber}", ErrorCodes.ResourceNotFound); + + actual.Should().BeEquivalentTo(expected); + } + + private static GethLikeTxTrace MockGethLikeTrace() + { + var trace = new GethLikeTxTrace { ReturnValue = new byte[] { 0xA2 } }; + + trace.Entries.Add(new GethTxTraceEntry + { + Depth = 1, + Gas = 22000, + GasCost = 1, + Memory = new string[] + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }, + Opcode = "STOP", + ProgramCounter = 32, + Stack = new string[] + { + "7".PadLeft(64, '0'), + "8".PadLeft(64, '0') + }, + Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + } }); + + return trace; } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs new file mode 100644 index 00000000000..2356623f860 --- /dev/null +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs @@ -0,0 +1,210 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO.Abstractions; +using System.Text.Json; +using System.Threading.Tasks; +using FluentAssertions; +using Nethermind.Blockchain.Blocks; +using Nethermind.Blockchain.Receipts; +using Nethermind.Config; +using Nethermind.Consensus.Rewards; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; +using Nethermind.Core.Test.Builders; +using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.Int256; +using Nethermind.JsonRpc.Modules.DebugModule; +using Nethermind.Synchronization.ParallelSync; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.JsonRpc.Test.Modules; + +[Parallelizable(ParallelScope.Self)] +public class DebugRpcModuleTests +{ + private class Context : IDisposable + { + public IDebugRpcModule DebugRpcModule { get; } + public TestRpcBlockchain Blockchain { get; } + + private Context(TestRpcBlockchain blockchain, IDebugRpcModule debugRpcModule) + { + DebugRpcModule = debugRpcModule; + Blockchain = blockchain; + } + + public static async Task Create(ISpecProvider? specProvider = null, bool isAura = false) + { + TestRpcBlockchain blockchain = await TestRpcBlockchain.ForTest(isAura ? SealEngineType.AuRa : SealEngineType.NethDev).Build(specProvider); + + IConfigProvider configProvider = Substitute.For(); + IReceiptsMigration receiptsMigration = Substitute.For(); + ISyncModeSelector syncModeSelector = Substitute.For(); + var factory = new DebugModuleFactory( + blockchain.WorldStateManager, + blockchain.DbProvider, + blockchain.BlockTree, + blockchain.RpcConfig, + blockchain.BlockValidator, + blockchain.BlockPreprocessorStep, + NoBlockRewards.Instance, + blockchain.ReceiptStorage, + receiptsMigration, + configProvider, + blockchain.SpecProvider, + syncModeSelector, + new BlockStore(blockchain.BlocksDb), + new FileSystem(), + blockchain.LogManager + ); + + IDebugRpcModule debugRpcModule = factory.Create(); + + return new(blockchain, debugRpcModule); + } + + public void Dispose() => Blockchain.Dispose(); + } + + [Test] + public async Task Debug_traceCall_fails_when_not_enough_balance() + { + using Context ctx = await Context.Create(); + + Address address = Build.An.Address.TestObject; + UInt256 balance = 100.Ether(), send = balance / 2; + + JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", + new { from = $"{address}", to = $"{TestItem.AddressC}", value = send.ToString("X") } + ); + + response.Should().BeOfType() + .Which.Error?.Message?.Should().Contain("insufficient funds"); + } + + [Test] + public async Task Debug_traceCall_runs_on_top_of_specified_block() + { + using Context ctx = await Context.Create(); + TestRpcBlockchain blockchain = ctx.Blockchain; + + Address address = Build.An.Address.TestObject; + UInt256 balance = 100.Ether(); + + await blockchain.AddFunds(address, balance / 2); + await blockchain.AddFunds(address, balance / 2); + Hash256 lastBlockHash = blockchain.BlockTree.Head!.Hash!; + + JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", + new { from = $"{address}", to = $"{TestItem.AddressC}", value = balance.ToString("X") }, + $"{lastBlockHash}" + ); + + response.Should().BeOfType(); + } + + [TestCase( + "Nonce override doesn't cause failure", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"nonce":"0x123"}}""" + )] + [TestCase( + "Uses account balance from state override", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","value":"0x100"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" + )] + [TestCase( + "Executes code from state override", + """{"from":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""", + "00000000000000000000000000000000000000000000003635c9adc5de9f09e5" + )] + [TestCase( + "Executes precompile using overriden address", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""", + "000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099" + )] + public async Task Debug_traceCall_with_state_override(string name, string transactionJson, string stateOverrideJson, string? expectedValue = null) + { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + + using Context ctx = await Context.Create(); + + JsonRpcResponse response = await RpcTest.TestRequest(ctx.DebugRpcModule, "debug_traceCall", + transaction, null, new { stateOverrides = stateOverride } + ); + + GethLikeTxTrace trace = response.Should().BeOfType() + .Which.Result.Should().BeOfType() + .Subject; + + if (expectedValue != null) + Convert.ToHexString(trace.ReturnValue).Should().BeEquivalentTo(expectedValue); + } + + [TestCase( + "When balance is overriden", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xbe5c953dd0ddb0ce033a98f36c981f1b74d3b33f","value":"0x100"}""", + """{"0x7f554713be84160fdf0178cc8df86f5aabd33397":{"balance":"0x100"}}""" + )] + [TestCase( + "When address code is overriden", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xf8b2cb4f000000000000000000000000b7705ae4c6f81b66cdb323c65f4e8133690fc099"}""", + """{"0xc200000000000000000000000000000000000000":{"code":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8b2cb4f14610030575b600080fd5b61004a600480360381019061004591906100e4565b610060565b604051610057919061012a565b60405180910390f35b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100b182610086565b9050919050565b6100c1816100a6565b81146100cc57600080fd5b50565b6000813590506100de816100b8565b92915050565b6000602082840312156100fa576100f9610081565b5b6000610108848285016100cf565b91505092915050565b6000819050919050565b61012481610111565b82525050565b600060208201905061013f600083018461011b565b9291505056fea2646970667358221220172c443a163d8a43e018c339d1b749c312c94b6de22835953d960985daf228c764736f6c63430008120033"}}""" + )] + [TestCase( + "When precompile address is changed", + """{"from":"0x7f554713be84160fdf0178cc8df86f5aabd33397","to":"0xc200000000000000000000000000000000000000","input":"0xB6E16D27AC5AB427A7F68900AC5559CE272DC6C37C82B3E052246C82244C50E4000000000000000000000000000000000000000000000000000000000000001C7B8B1991EB44757BC688016D27940DF8FB971D7C87F77A6BC4E938E3202C44037E9267B0AEAA82FA765361918F2D8ABD9CDD86E64AA6F2B81D3C4E0B69A7B055"}""", + """{"0x0000000000000000000000000000000000000001":{"movePrecompileToAddress":"0xc200000000000000000000000000000000000000", "code": "0x"}}""" + )] + public async Task debug_traceCall_with_state_override_does_not_affect_other_calls(string name, string transactionJson, string stateOverrideJson) + { + var transaction = JsonSerializer.Deserialize(transactionJson); + var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); + + using Context ctx = await Context.Create(); + + var resultOverrideBefore = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + { + stateOverrides = stateOverride, + enableMemory = false, + disableStorage = true, + disableStack = true, + tracer = "callTracer", + tracerConfig = new { withLog = false } + }); + + var resultNoOverride = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + { + // configuration to minimize number of fields being compared + enableMemory = false, + disableStorage = true, + disableStack = true, + tracer = "callTracer", + tracerConfig = new { withLog = false } + }); + + var resultOverrideAfter = await RpcTest.TestSerializedRequest(ctx.DebugRpcModule, "debug_traceCall", transaction, null, new + { + stateOverrides = stateOverride, + enableMemory = false, + disableStorage = true, + disableStack = true, + tracer = "callTracer", + tracerConfig = new { withLog = false } + }); + + Assert.Multiple(() => + { + Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); + Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); + }); + } +} From b6b656ad6b1d850375a644559a14c61eabb98aa0 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 23 Oct 2024 20:11:36 +0300 Subject: [PATCH 66/70] Fix DB cleanup --- .../Nethermind.State/OverridableWorldState.cs | 24 +++++++------------ .../OverridableWorldStateManager.cs | 7 +++--- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/Nethermind/Nethermind.State/OverridableWorldState.cs b/src/Nethermind/Nethermind.State/OverridableWorldState.cs index c5dbeaadc0a..70a1bfc0afb 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldState.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldState.cs @@ -1,33 +1,27 @@ // SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core; using Nethermind.Db; using Nethermind.Logging; using Nethermind.Trie.Pruning; namespace Nethermind.State; -public class OverridableWorldState : WorldState +public class OverridableWorldState( + OverlayTrieStore trieStore, + IReadOnlyDbProvider dbProvider, + ILogManager? logManager, + PreBlockCaches? preBlockCaches = null, + bool populatePreBlockCache = true) + : WorldState(trieStore, dbProvider.GetDb(DbNames.Code), logManager, preBlockCaches, populatePreBlockCache) { - private readonly OverlayTrieStore _trieStore; - private readonly IReadOnlyDb _codeDb; - - public OverridableWorldState( - OverlayTrieStore trieStore, IReadOnlyDb codeDb, ILogManager? logManager, - PreBlockCaches? preBlockCaches = null, bool populatePreBlockCache = true - ) : base(trieStore, codeDb, logManager, preBlockCaches, populatePreBlockCache) - { - _trieStore = trieStore; - _codeDb = codeDb; - } /// /// Resets changes applied via /// public void ResetOverrides() { - _trieStore.ResetOverrides(); - _codeDb.ClearTempChanges(); + trieStore.ResetOverrides(); + dbProvider.ClearTempChanges(); } } diff --git a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs index 5445ee22090..82eb253ae56 100644 --- a/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs +++ b/src/Nethermind/Nethermind.State/OverridableWorldStateManager.cs @@ -10,7 +10,7 @@ namespace Nethermind.State; public class OverridableWorldStateManager : IWorldStateManager { - private readonly IReadOnlyDb _codeDb; + private readonly ReadOnlyDbProvider _readOnlyDbProvider; private readonly StateReader _reader; private readonly WorldState _state; @@ -19,11 +19,10 @@ public class OverridableWorldStateManager : IWorldStateManager public OverridableWorldStateManager(IDbProvider dbProvider, IReadOnlyTrieStore trieStore, ILogManager? logManager) { - dbProvider = new ReadOnlyDbProvider(dbProvider, true); + dbProvider = _readOnlyDbProvider = new(dbProvider, true); OverlayTrieStore overlayTrieStore = new(dbProvider.StateDb, trieStore, logManager); _logManager = logManager; - _codeDb = (IReadOnlyDb)dbProvider.GetDb(DbNames.Code); _reader = new(overlayTrieStore, dbProvider.GetDb(DbNames.Code), logManager); _state = new(overlayTrieStore, dbProvider.GetDb(DbNames.Code), logManager); _overlayTrieStore = overlayTrieStore; @@ -38,7 +37,7 @@ public IWorldState CreateResettableWorldState(IWorldState? forWarmup = null) if (forWarmup is not null) throw new NotSupportedException("Overridable world state with warm up is not supported."); - return new OverridableWorldState(_overlayTrieStore, _codeDb, _logManager); + return new OverridableWorldState(_overlayTrieStore, _readOnlyDbProvider, _logManager); } public event EventHandler? ReorgBoundaryReached From e872c4ed2a1fb754ddd0f6dc8fff471114366028 Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 24 Oct 2024 10:00:13 +0300 Subject: [PATCH 67/70] Create separate `OverridableWorldStateManager` per module --- .../Steps/RegisterRpcModules.cs | 4 ++-- .../Modules/DebugRpcModuleTests.cs | 2 +- .../Modules/TraceRpcModuleTests.cs | 2 +- .../Modules/DebugModule/DebugModuleFactory.cs | 18 ++++++------------ .../Modules/Trace/TraceModuleFactory.cs | 18 ++++++++++-------- .../Rpc/OptimismTraceModuleFactory.cs | 13 +++++++------ .../Rpc/RegisterOptimismRpcModules.cs | 2 +- 7 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index 28fca655ffc..5bc4f2ffc9a 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -99,7 +99,7 @@ public virtual async Task Execute(CancellationToken cancellationToken) rpcModuleProvider.RegisterBounded(proofModuleFactory, 2, _jsonRpcConfig.Timeout); DebugModuleFactory debugModuleFactory = new( - _api.WorldStateManager, + _api.WorldStateManager.TrieStore, _api.DbProvider, _api.BlockTree, _jsonRpcConfig, @@ -257,7 +257,7 @@ protected ModuleFactoryBase CreateTraceModuleFactory() StepDependencyException.ThrowIfNull(_api.SpecProvider); return new TraceModuleFactory( - _api.WorldStateManager, + _api.WorldStateManager.TrieStore, _api.DbProvider, _api.BlockTree, _jsonRpcConfig, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs index 2356623f860..b0719d15396 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs @@ -46,7 +46,7 @@ public static async Task Create(ISpecProvider? specProvider = null, boo IReceiptsMigration receiptsMigration = Substitute.For(); ISyncModeSelector syncModeSelector = Substitute.For(); var factory = new DebugModuleFactory( - blockchain.WorldStateManager, + blockchain.WorldStateManager.TrieStore, blockchain.DbProvider, blockchain.BlockTree, blockchain.RpcConfig, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index e75839a6c66..ad9cc4db9aa 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -56,7 +56,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) } Factory = new( - Blockchain.OverridableWorldStateManager, + Blockchain.OverridableWorldStateManager.TrieStore, Blockchain.DbProvider, Blockchain.BlockTree, JsonRpcConfig, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index e3720545237..ccab397b14a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.IO.Abstractions; using Nethermind.Blockchain; using Nethermind.Blockchain.Blocks; @@ -25,7 +24,7 @@ namespace Nethermind.JsonRpc.Modules.DebugModule; public class DebugModuleFactory : ModuleFactoryBase { - private readonly OverridableWorldStateManager _worldStateManager; + private readonly IReadOnlyTrieStore _trieStore; private readonly IJsonRpcConfig _jsonRpcConfig; private readonly IBlockValidator _blockValidator; private readonly IRewardCalculatorSource _rewardCalculatorSource; @@ -40,10 +39,9 @@ public class DebugModuleFactory : ModuleFactoryBase private readonly ISyncModeSelector _syncModeSelector; private readonly IBlockStore _badBlockStore; private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; public DebugModuleFactory( - IWorldStateManager worldStateManager, + IReadOnlyTrieStore trieStore, IDbProvider dbProvider, IBlockTree blockTree, IJsonRpcConfig jsonRpcConfig, @@ -59,6 +57,7 @@ public DebugModuleFactory( IFileSystem fileSystem, ILogManager logManager) { + _trieStore = trieStore; _dbProvider = dbProvider.AsReadOnly(false); _blockTree = blockTree.AsReadOnly(); _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); @@ -73,17 +72,12 @@ public DebugModuleFactory( _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); _badBlockStore = badBlockStore; _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); - _logger = logManager.GetClassLogger(); - _worldStateManager = new(dbProvider, worldStateManager.TrieStore, logManager); } public override IDebugRpcModule Create() { - OverridableTxProcessingEnv txEnv = new( - _worldStateManager, - _blockTree, - _specProvider, - _logManager); + OverridableWorldStateManager worldStateManager = new(_dbProvider, _trieStore, _logManager); + OverridableTxProcessingEnv txEnv = new(worldStateManager, _blockTree, _specProvider, _logManager); IReadOnlyTxProcessingScope scope = txEnv.Build(Keccak.EmptyTreeHash); @@ -97,7 +91,7 @@ public override IDebugRpcModule Create() _receiptStorage, _specProvider, _blockTree, - _worldStateManager.GlobalStateReader, + worldStateManager.GlobalStateReader, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index c67f301f839..11a2ce1ba68 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -15,11 +15,12 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.State; +using Nethermind.Trie.Pruning; namespace Nethermind.JsonRpc.Modules.Trace; public class TraceModuleFactory( - IWorldStateManager worldStateManager, + IReadOnlyTrieStore trieStore, IDbProvider dbProvider, IBlockTree blockTree, IJsonRpcConfig jsonRpcConfig, @@ -30,7 +31,7 @@ public class TraceModuleFactory( IPoSSwitcher poSSwitcher, ILogManager logManager) : ModuleFactoryBase { - protected readonly OverridableWorldStateManager _worldStateManager = new(dbProvider, worldStateManager.TrieStore, logManager); + protected readonly IReadOnlyTrieStore _trieStore = trieStore; protected readonly IReadOnlyBlockTree _blockTree = blockTree.AsReadOnly(); protected readonly IJsonRpcConfig _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); protected readonly IReceiptStorage _receiptStorage = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); @@ -40,9 +41,9 @@ public class TraceModuleFactory( protected readonly IRewardCalculatorSource _rewardCalculatorSource = rewardCalculatorSource ?? throw new ArgumentNullException(nameof(rewardCalculatorSource)); protected readonly IPoSSwitcher _poSSwitcher = poSSwitcher ?? throw new ArgumentNullException(nameof(poSSwitcher)); - protected virtual OverridableTxProcessingEnv CreateTxProcessingEnv() => new(_worldStateManager, _blockTree, _specProvider, _logManager); + protected virtual OverridableTxProcessingEnv CreateTxProcessingEnv(OverridableWorldStateManager worldStateManager) => new(worldStateManager, _blockTree, _specProvider, _logManager); - protected virtual ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new( + protected virtual ReadOnlyChainProcessingEnv CreateChainProcessingEnv(OverridableWorldStateManager worldStateManager, IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new( scope, Always.Valid, _recoveryStep, @@ -50,13 +51,14 @@ public class TraceModuleFactory( _receiptStorage, _specProvider, _blockTree, - _worldStateManager.GlobalStateReader, + worldStateManager.GlobalStateReader, _logManager, transactionsExecutor); public override ITraceRpcModule Create() { - OverridableTxProcessingEnv txProcessingEnv = CreateTxProcessingEnv(); + OverridableWorldStateManager worldStateManager = new(dbProvider, _trieStore, logManager); + OverridableTxProcessingEnv txProcessingEnv = CreateTxProcessingEnv(worldStateManager); IReadOnlyTxProcessingScope scope = txProcessingEnv.Build(Keccak.EmptyTreeHash); IRewardCalculator rewardCalculator = @@ -66,8 +68,8 @@ public override ITraceRpcModule Create() RpcBlockTransactionsExecutor rpcBlockTransactionsExecutor = new(scope.TransactionProcessor, scope.WorldState); BlockProcessor.BlockValidationTransactionsExecutor executeBlockTransactionsExecutor = new(scope.TransactionProcessor, scope.WorldState); - ReadOnlyChainProcessingEnv traceProcessingEnv = CreateChainProcessingEnv(rpcBlockTransactionsExecutor, scope, rewardCalculator); - ReadOnlyChainProcessingEnv executeProcessingEnv = CreateChainProcessingEnv(executeBlockTransactionsExecutor, scope, rewardCalculator); + ReadOnlyChainProcessingEnv traceProcessingEnv = CreateChainProcessingEnv(worldStateManager, rpcBlockTransactionsExecutor, scope, rewardCalculator); + ReadOnlyChainProcessingEnv executeProcessingEnv = CreateChainProcessingEnv(worldStateManager, executeBlockTransactionsExecutor, scope, rewardCalculator); Tracer tracer = new(scope.WorldState, traceProcessingEnv.ChainProcessor, executeProcessingEnv.ChainProcessor, traceOptions: ProcessingOptions.TraceTransactions); diff --git a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs index 4f023c25ac6..bf5b837c883 100644 --- a/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/Rpc/OptimismTraceModuleFactory.cs @@ -15,11 +15,12 @@ using Nethermind.JsonRpc.Modules.Trace; using Nethermind.Logging; using Nethermind.State; +using Nethermind.Trie.Pruning; namespace Nethermind.Optimism.Rpc; public class OptimismTraceModuleFactory( - IWorldStateManager worldStateManager, + IReadOnlyTrieStore trieStore, IDbProvider dbProvider, IBlockTree blockTree, IJsonRpcConfig jsonRpcConfig, @@ -33,7 +34,7 @@ public class OptimismTraceModuleFactory( IOptimismSpecHelper opSpecHelper, Create2DeployerContractRewriter contractRewriter, IWithdrawalProcessor withdrawalProcessor) : TraceModuleFactory( - worldStateManager, + trieStore, dbProvider, blockTree, jsonRpcConfig, @@ -44,10 +45,10 @@ public class OptimismTraceModuleFactory( poSSwitcher, logManager) { - protected override OverridableTxProcessingEnv CreateTxProcessingEnv() => - new OptimismOverridableTxProcessingEnv(_worldStateManager, _blockTree, _specProvider, _logManager, l1CostHelper, opSpecHelper); + protected override OverridableTxProcessingEnv CreateTxProcessingEnv(OverridableWorldStateManager worldStateManager) => + new OptimismOverridableTxProcessingEnv(worldStateManager, _blockTree, _specProvider, _logManager, l1CostHelper, opSpecHelper); - protected override ReadOnlyChainProcessingEnv CreateChainProcessingEnv(IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new OptimismReadOnlyChainProcessingEnv( + protected override ReadOnlyChainProcessingEnv CreateChainProcessingEnv(OverridableWorldStateManager worldStateManager, IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor, IReadOnlyTxProcessingScope scope, IRewardCalculator rewardCalculator) => new OptimismReadOnlyChainProcessingEnv( scope, Always.Valid, _recoveryStep, @@ -55,7 +56,7 @@ protected override OverridableTxProcessingEnv CreateTxProcessingEnv() => _receiptStorage, _specProvider, _blockTree, - _worldStateManager.GlobalStateReader, + worldStateManager.GlobalStateReader, _logManager, opSpecHelper, contractRewriter, diff --git a/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs b/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs index 93aefa7dabe..3f3072485f4 100644 --- a/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs +++ b/src/Nethermind/Nethermind.Optimism/Rpc/RegisterOptimismRpcModules.cs @@ -103,7 +103,7 @@ protected override void RegisterTraceRpcModule(IRpcModuleProvider rpcModuleProvi StepDependencyException.ThrowIfNull(_api.SpecHelper); OptimismTraceModuleFactory traceModuleFactory = new( - _api.WorldStateManager, + _api.WorldStateManager.TrieStore, _api.DbProvider, _api.BlockTree, _jsonRpcConfig, From 4d8294291ca4f844d9ffa510d6d979b2f42e198a Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Thu, 24 Oct 2024 10:57:03 +0300 Subject: [PATCH 68/70] Code cleanup --- .../Processing/OverridableTxProcessingScope.cs | 8 ++++---- .../Nethermind.Consensus/Processing/ProcessingOptions.cs | 2 +- .../Simulate/EthSimulateTestsBlocksAndTransactions.cs | 1 - .../OptimismOverridableTxProcessingEnv.cs | 9 ++------- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs index 692cad747ee..b168b1c1e93 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OverridableTxProcessingScope.cs @@ -15,6 +15,10 @@ public class OverridableTxProcessingScope( Hash256 originalStateRoot ) : IOverridableTxProcessingScope { + public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; + public ITransactionProcessor TransactionProcessor => transactionProcessor; + public IWorldState WorldState => worldState; + public void Dispose() { worldState.StateRoot = originalStateRoot; @@ -22,8 +26,4 @@ public void Dispose() worldState.ResetOverrides(); codeInfoRepository.ResetOverrides(); } - - public IOverridableCodeInfoRepository CodeInfoRepository => codeInfoRepository; - public ITransactionProcessor TransactionProcessor => transactionProcessor; - public IWorldState WorldState => worldState; } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs index 2f6b76bb48d..82799e5578d 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingOptions.cs @@ -52,7 +52,7 @@ public enum ProcessingOptions MarkAsProcessed = 128, /// - /// Forces to run on top of specified block state, instead of reverting to the previous one. + /// Forces to run on top of the specified block state, instead of reverting to the previous one. /// ForceSameBlock = 1 << 8, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs index c426b282f40..a7f8b54e2dc 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs @@ -14,7 +14,6 @@ using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.Facade.Eth.RpcTransaction; -using Nethermind.Facade.Proxy.Models; using Nethermind.Facade.Proxy.Models.Simulate; using Nethermind.Int256; using Nethermind.JsonRpc.Modules.Eth; diff --git a/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs b/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs index 573a07c3c5c..9e06be1ddcd 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismOverridableTxProcessingEnv.cs @@ -19,13 +19,8 @@ public class OptimismOverridableTxProcessingEnv( ILogManager logManager, IL1CostHelper l1CostHelper, IOptimismSpecHelper opSpecHelper, - IWorldState? worldStateToWarmUp = null) : OverridableTxProcessingEnv( - worldStateManager, - readOnlyBlockTree, - specProvider, - logManager, - worldStateToWarmUp -) + IWorldState? worldStateToWarmUp = null) + : OverridableTxProcessingEnv(worldStateManager, readOnlyBlockTree, specProvider, logManager, worldStateToWarmUp) { protected override ITransactionProcessor CreateTransactionProcessor() { From 2fa1c8e7d758372da4bb0ae0bc4d36223686225e Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 30 Oct 2024 23:42:58 +0200 Subject: [PATCH 69/70] Build fix --- .../Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs index b0719d15396..621d756b5cc 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugRpcModuleTests.cs @@ -58,7 +58,7 @@ public static async Task Create(ISpecProvider? specProvider = null, boo configProvider, blockchain.SpecProvider, syncModeSelector, - new BlockStore(blockchain.BlocksDb), + new BadBlockStore(blockchain.BlocksDb, 100), new FileSystem(), blockchain.LogManager ); From 92809ffa179185b3c62244261d76f1d724a3670a Mon Sep 17 00:00:00 2001 From: Alex Bespalov Date: Wed, 30 Oct 2024 23:52:23 +0200 Subject: [PATCH 70/70] PR fixes --- .../Nethermind.Facade/BlockchainBridge.cs | 26 ++++++++----------- .../Modules/DebugRpcModuleTests.cs | 13 ++++++---- .../Eth/EthRpcModuleTests.EstimateGas.cs | 12 +++++---- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 13 ++++++---- .../Modules/TraceRpcModuleTests.cs | 13 ++++++---- 5 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 537f4929570..42e3c884e2f 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -153,8 +153,9 @@ public CallOutput Call(BlockHeader header, Transaction tx, Dictionary(transactionJson); var stateOverride = JsonSerializer.Deserialize(stateOverrideJson); @@ -201,10 +204,10 @@ public async Task debug_traceCall_with_state_override_does_not_affect_other_call tracerConfig = new { withLog = false } }); - Assert.Multiple(() => + using (new AssertionScope()) { - Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); - Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); - }); + JToken.Parse(resultOverrideBefore).Should().BeEquivalentTo(resultOverrideAfter); + JToken.Parse(resultNoOverride).Should().NotBeEquivalentTo(resultOverrideAfter); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index fa07c897b72..26077b2de8b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -5,6 +5,8 @@ using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; +using FluentAssertions.Execution; +using FluentAssertions.Json; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -293,7 +295,7 @@ public async Task Estimate_gas_with_state_override(string name, string transacti string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); - Assert.That(serialized, Is.EqualTo(expectedResult)); + JToken.Parse(serialized).Should().BeEquivalentTo(expectedResult); } [TestCase( @@ -324,10 +326,10 @@ public async Task Estimate_gas_with_state_override_does_not_affect_other_calls(s var resultOverrideAfter = await ctx.Test.TestEthRpc("eth_estimateGas", transaction, "latest", stateOverride); - Assert.Multiple(() => + using (new AssertionScope()) { - Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); - Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); - }); + JToken.Parse(resultOverrideBefore).Should().BeEquivalentTo(resultOverrideAfter); + JToken.Parse(resultNoOverride).Should().NotBeEquivalentTo(resultOverrideAfter); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index d9ad794c148..caeb411c8d5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -4,6 +4,8 @@ using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; +using FluentAssertions.Execution; +using FluentAssertions.Json; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -14,6 +16,7 @@ using Nethermind.Specs.Forks; using Nethermind.Specs.Test; using Nethermind.State; +using Newtonsoft.Json.Linq; using NUnit.Framework; namespace Nethermind.JsonRpc.Test.Modules.Eth; @@ -329,7 +332,7 @@ public async Task Eth_call_with_state_override(string name, string transactionJs string serialized = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); - Assert.That(serialized, Is.EqualTo(expectedResult)); + JToken.Parse(serialized).Should().BeEquivalentTo(expectedResult); } [TestCase( @@ -360,10 +363,10 @@ public async Task Eth_call_with_state_override_does_not_affect_other_calls(strin var resultOverrideAfter = await ctx.Test.TestEthRpc("eth_call", transaction, "latest", stateOverride); - Assert.Multiple(() => + using (new AssertionScope()) { - Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); - Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); - }); + JToken.Parse(resultOverrideBefore).Should().BeEquivalentTo(resultOverrideAfter); + JToken.Parse(resultNoOverride).Should().NotBeEquivalentTo(resultOverrideAfter); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index ad9cc4db9aa..20c674df14a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -6,6 +6,8 @@ using System.Text.Json; using System.Threading.Tasks; using FluentAssertions; +using FluentAssertions.Execution; +using FluentAssertions.Json; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; @@ -26,6 +28,7 @@ using Nethermind.Specs.Test; using Nethermind.JsonRpc.Data; using Nethermind.Serialization.Rlp; +using Newtonsoft.Json.Linq; namespace Nethermind.JsonRpc.Test.Modules; @@ -971,7 +974,7 @@ public async Task Trace_call_with_state_override(string name, string transaction context.TraceRpcModule, "trace_call", transaction, new[] { traceType }, "latest", stateOverride); - Assert.That(serialized, Is.EqualTo(expectedResult), serialized.Replace("\"", "\\\"")); + JToken.Parse(serialized).Should().BeEquivalentTo(expectedResult); } [TestCase( @@ -1003,10 +1006,10 @@ public async Task Trace_call_with_state_override_does_not_affect_other_calls(str var resultOverrideAfter = await RpcTest.TestSerializedRequest(context.TraceRpcModule, "trace_call", transaction, traceTypes, null, stateOverride); - Assert.Multiple(() => + using (new AssertionScope()) { - Assert.That(resultOverrideBefore, Is.EqualTo(resultOverrideAfter), resultOverrideBefore.Replace("\"", "\\\"")); - Assert.That(resultNoOverride, Is.Not.EqualTo(resultOverrideAfter), resultNoOverride.Replace("\"", "\\\"")); - }); + JToken.Parse(resultOverrideBefore).Should().BeEquivalentTo(resultOverrideAfter); + JToken.Parse(resultNoOverride).Should().NotBeEquivalentTo(resultOverrideAfter); + } } }