From 1295861256b3bdc2d51ee302ed5ab0f6b1f44f46 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Wed, 4 Sep 2024 02:03:50 -0300 Subject: [PATCH 1/5] Refactor EVMExecutor::call --- silkworm/silkrpc/commands/eth_api.cpp | 8 +++---- silkworm/silkrpc/commands/trace_api.cpp | 3 ++- silkworm/silkrpc/core/call_many.cpp | 13 ++++++---- silkworm/silkrpc/core/call_many.hpp | 5 +++- silkworm/silkrpc/core/estimate_gas_oracle.cpp | 2 +- silkworm/silkrpc/core/evm_debug.cpp | 15 +++++++----- silkworm/silkrpc/core/evm_executor.cpp | 14 +++++------ silkworm/silkrpc/core/evm_executor.hpp | 8 +++---- silkworm/silkrpc/core/evm_trace.cpp | 24 ++++++++++++------- silkworm/silkrpc/core/evm_trace.hpp | 1 + silkworm/silkrpc/core/gas_parameters.cpp | 2 +- silkworm/silkrpc/core/gas_parameters.hpp | 6 ++--- 12 files changed, 60 insertions(+), 41 deletions(-) diff --git a/silkworm/silkrpc/commands/eth_api.cpp b/silkworm/silkrpc/commands/eth_api.cpp index fad37c6e..00b32b05 100644 --- a/silkworm/silkrpc/commands/eth_api.cpp +++ b/silkworm/silkrpc/commands/eth_api.cpp @@ -1155,7 +1155,7 @@ awaitable EthereumRpcApi::handle_eth_call(const nlohmann::json& request, s const auto execution_result = co_await EVMExecutor::call( *chain_config_ptr, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num) { return tx->create_state(io_executor, db_reader, block_num); - }, {}, true, false, eos_evm_version, gas_params); + }, gas_params, eos_evm_version, {}, true, false); if (execution_result.success()) { make_glaze_json_content(reply, request["id"], execution_result.data); @@ -1338,8 +1338,8 @@ awaitable EthereumRpcApi::handle_eth_create_access_list(const nlohmann::js const auto execution_result = co_await EVMExecutor::call( *chain_config_ptr, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num) { return tx->create_state(io_executor, db_reader, block_num); - }, - std::move(tracers), /* refund */ true, /* gasBailout */ false, eos_evm_version, gas_params); + }, gas_params, eos_evm_version, + std::move(tracers), /* refund */ true, /* gasBailout */ false); if (execution_result.pre_check_error) { reply = make_json_error(request["id"], -32000, execution_result.pre_check_error.value()); @@ -1429,7 +1429,7 @@ awaitable EthereumRpcApi::handle_eth_call_bundle(const nlohmann::json& req const auto execution_result = co_await EVMExecutor::call( *chain_config_ptr, workers_, block_with_hash->block, tx_with_block->transaction, [&](auto& io_executor, auto block_num) { return tx->create_state(io_executor, db_reader, block_num); - }, {}, true, false, eos_evm_version, gas_params); + }, gas_params, eos_evm_version, {}, true, false); if (execution_result.pre_check_error) { reply = make_json_error(request["id"], -32000, execution_result.pre_check_error.value()); error = true; diff --git a/silkworm/silkrpc/commands/trace_api.cpp b/silkworm/silkrpc/commands/trace_api.cpp index 3fda999e..3db64f49 100644 --- a/silkworm/silkrpc/commands/trace_api.cpp +++ b/silkworm/silkrpc/commands/trace_api.cpp @@ -32,7 +32,8 @@ #include #include #include - +#include +#include namespace silkworm::rpc::commands { // https://eth.wiki/json-rpc/API#trace_call diff --git a/silkworm/silkrpc/core/call_many.cpp b/silkworm/silkrpc/core/call_many.cpp index 8ff69787..f2299fbc 100644 --- a/silkworm/silkrpc/core/call_many.cpp +++ b/silkworm/silkrpc/core/call_many.cpp @@ -41,7 +41,7 @@ #include #include #include - +#include namespace silkworm::rpc::call { using boost::asio::awaitable; @@ -53,7 +53,9 @@ CallManyResult CallExecutor::executes_all_bundles(const silkworm::ChainConfig* c std::optional opt_timeout, const AccountsOverrides& accounts_overrides, int32_t transaction_index, - boost::asio::any_io_executor& this_executor) { + boost::asio::any_io_executor& this_executor, + const evmone::gas_parameters& gas_params, + uint64_t eos_evm_version) { CallManyResult result; const auto& block = block_with_hash.block; const auto& block_transactions = block.transactions; @@ -70,7 +72,7 @@ CallManyResult CallExecutor::executes_all_bundles(const silkworm::ChainConfig* c txn.recover_sender(); } - auto exec_result = executor.call(block, txn); + auto exec_result = executor.call(block, txn, gas_params, eos_evm_version); if ((clock_time::since(start_time) / 1000000) > timeout) { std::ostringstream oss; @@ -110,7 +112,7 @@ CallManyResult CallExecutor::executes_all_bundles(const silkworm::ChainConfig* c for (const auto& call : bundle.transactions) { silkworm::Transaction txn{call.to_transaction()}; - auto call_execution_result = executor.call(blockContext.block, txn); + auto call_execution_result = executor.call(blockContext.block, txn, gas_params, eos_evm_version); if (call_execution_result.pre_check_error) { result.error = call_execution_result.pre_check_error; @@ -171,12 +173,13 @@ boost::asio::awaitable CallExecutor::execute(const Bundles& bund if (transaction_index == -1) { transaction_index = static_cast(block_with_hash->block.transactions.size()); } + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(tx_database, chain_config_ptr, block_with_hash->block); auto this_executor = co_await boost::asio::this_coro::executor; result = co_await boost::asio::async_compose( [&](auto&& self) { boost::asio::post(workers_, [&, self = std::move(self)]() mutable { - result = executes_all_bundles(chain_config_ptr, *block_with_hash, tx_database, bundles, opt_timeout, accounts_overrides, transaction_index, this_executor); + result = executes_all_bundles(chain_config_ptr, *block_with_hash, tx_database, bundles, opt_timeout, accounts_overrides, transaction_index, this_executor, gas_params, eos_evm_version); boost::asio::post(this_executor, [result, self = std::move(self)]() mutable { self.complete(result); }); diff --git a/silkworm/silkrpc/core/call_many.hpp b/silkworm/silkrpc/core/call_many.hpp index e152cbdd..da581d98 100644 --- a/silkworm/silkrpc/core/call_many.hpp +++ b/silkworm/silkrpc/core/call_many.hpp @@ -39,6 +39,7 @@ #include #include #include +#include namespace silkworm::rpc::call { @@ -68,7 +69,9 @@ class CallExecutor { std::optional opt_timeout, const AccountsOverrides& accounts_overrides, int32_t transaction_index, - boost::asio::any_io_executor& executor); + boost::asio::any_io_executor& executor, + const evmone::gas_parameters& gas_params, + uint64_t eos_evm_version); private: ethdb::Transaction& transaction_; diff --git a/silkworm/silkrpc/core/estimate_gas_oracle.cpp b/silkworm/silkrpc/core/estimate_gas_oracle.cpp index 7e549117..28d5fec3 100644 --- a/silkworm/silkrpc/core/estimate_gas_oracle.cpp +++ b/silkworm/silkrpc/core/estimate_gas_oracle.cpp @@ -136,7 +136,7 @@ boost::asio::awaitable EstimateGasOracle::estimate_gas(const Call ExecutionResult EstimateGasOracle::try_execution(EVMExecutor& executor, const silkworm::Block& block, const silkworm::Transaction& transaction, uint64_t eos_evm_version, const evmone::gas_parameters& gas_params) { executor.reset_all(); - return executor.call(block, transaction, {}, true, false, eos_evm_version, gas_params); + return executor.call(block, transaction, gas_params, eos_evm_version, {}, true, false); } void EstimateGasOracle::throw_exception(ExecutionResult& result, uint64_t cap) { diff --git a/silkworm/silkrpc/core/evm_debug.cpp b/silkworm/silkrpc/core/evm_debug.cpp index 35796d89..7a423bc9 100644 --- a/silkworm/silkrpc/core/evm_debug.cpp +++ b/silkworm/silkrpc/core/evm_debug.cpp @@ -35,7 +35,7 @@ #include #include #include - +#include namespace silkworm::rpc::debug { using boost::asio::awaitable; @@ -347,6 +347,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, const silkworm::Blo const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; co_await boost::asio::async_compose( @@ -371,7 +372,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, const silkworm::Blo stream.open_array(); Tracers tracers{debug_tracer}; - const auto execution_result = executor.call(block, txn, std::move(tracers), /* refund */ false, /* gasBailout */ false); + const auto execution_result = executor.call(block, txn, gas_params, eos_evm_version, std::move(tracers), /* refund */ false, /* gasBailout */ false); debug_tracer->flush_logs(); stream.close_array(); @@ -411,6 +412,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, uint64_t block_numb const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; co_await boost::asio::async_compose( @@ -425,7 +427,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, uint64_t block_numb if (!txn.from) { txn.recover_sender(); } - executor.call(block, txn); + executor.call(block, txn, gas_params, eos_evm_version); } executor.reset(); @@ -435,7 +437,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, uint64_t block_numb stream.open_array(); Tracers tracers{debug_tracer}; - const auto execution_result = executor.call(block, transaction, std::move(tracers)); + const auto execution_result = executor.call(block, transaction, gas_params, eos_evm_version, std::move(tracers)); debug_tracer->flush_logs(); stream.close_array(); @@ -473,6 +475,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; co_await boost::asio::async_compose( @@ -488,7 +491,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, txn.recover_sender(); } - executor.call(block, txn); + executor.call(block, txn, gas_params, eos_evm_version); } executor.reset(); @@ -527,7 +530,7 @@ awaitable DebugExecutor::execute(json::Stream& stream, auto debug_tracer = std::make_shared(stream, config_); Tracers tracers{debug_tracer}; - const auto execution_result = executor.call(blockContext.block, txn, std::move(tracers), /* refund */ false, /* gasBailout */ false); + const auto execution_result = executor.call(blockContext.block, txn, gas_params, eos_evm_version, std::move(tracers), /* refund */ false, /* gasBailout */ false); debug_tracer->flush_logs(); stream.close_array(); diff --git a/silkworm/silkrpc/core/evm_executor.cpp b/silkworm/silkrpc/core/evm_executor.cpp index 6bb3d4df..116c8949 100644 --- a/silkworm/silkrpc/core/evm_executor.cpp +++ b/silkworm/silkrpc/core/evm_executor.cpp @@ -220,11 +220,11 @@ std::optional EVMExecutor::pre_check(const EVM& evm, const silkworm ExecutionResult EVMExecutor::call( const silkworm::Block& block, const silkworm::Transaction& txn, + const evmone::gas_parameters& gas_params, + uint64_t eos_evm_version, Tracers tracers, bool refund, - bool gas_bailout, - uint64_t eos_evm_version, - const evmone::gas_parameters& gas_params) { + bool gas_bailout) { SILK_DEBUG << "EVMExecutor::call: " << block.header.number << " gasLimit: " << txn.gas_limit << " refund: " << refund << " gasBailout: " << gas_bailout; SILK_DEBUG << "EVMExecutor::call: transaction: " << &txn; @@ -334,18 +334,18 @@ awaitable EVMExecutor::call(const silkworm::ChainConfig& config const silkworm::Block& block, const silkworm::Transaction& txn, StateFactory state_factory, + const evmone::gas_parameters& gas_params, + uint64_t eos_evm_version, Tracers tracers, bool refund, - bool gas_bailout, - uint64_t eos_evm_version, - const evmone::gas_parameters& gas_params) { + bool gas_bailout) { auto this_executor = co_await boost::asio::this_coro::executor; const auto execution_result = co_await boost::asio::async_compose( [&](auto&& self) { boost::asio::post(workers, [&, self = std::move(self)]() mutable { auto state = state_factory(this_executor, block.header.number); EVMExecutor executor{config, workers, state}; - auto exec_result = executor.call(block, txn, tracers, refund, gas_bailout, eos_evm_version, gas_params); + auto exec_result = executor.call(block, txn, gas_params, eos_evm_version, tracers, refund, gas_bailout); boost::asio::post(this_executor, [exec_result, self = std::move(self)]() mutable { self.complete(exec_result); }); diff --git a/silkworm/silkrpc/core/evm_executor.hpp b/silkworm/silkrpc/core/evm_executor.hpp index 6a088fba..ae1e16bf 100644 --- a/silkworm/silkrpc/core/evm_executor.hpp +++ b/silkworm/silkrpc/core/evm_executor.hpp @@ -84,11 +84,11 @@ class EVMExecutor { const silkworm::Block& block, const silkworm::Transaction& txn, StateFactory state_factory, + const evmone::gas_parameters& gas_params, + uint64_t eos_evm_version, Tracers tracers = {}, bool refund = true, - bool gas_bailout = false, - uint64_t eos_evm_version = 0, - const evmone::gas_parameters& gas_params = {}); + bool gas_bailout = false); static std::string get_error_message(int64_t error_code, const Bytes& error_data, bool full_error = true); EVMExecutor(const silkworm::ChainConfig& config, boost::asio::thread_pool& workers, std::shared_ptr& state) @@ -107,7 +107,7 @@ class EVMExecutor { EVMExecutor(const EVMExecutor&) = delete; EVMExecutor& operator=(const EVMExecutor&) = delete; - ExecutionResult call(const silkworm::Block& block, const silkworm::Transaction& txn, Tracers tracers = {}, bool refund = true, bool gas_bailout = false, uint64_t eos_evm_version = 0, const evmone::gas_parameters& gas_params={}); + ExecutionResult call(const silkworm::Block& block, const silkworm::Transaction& txn, const evmone::gas_parameters& gas_params, uint64_t eos_evm_version, Tracers tracers = {}, bool refund = true, bool gas_bailout = false); void reset(); void reset_all(); diff --git a/silkworm/silkrpc/core/evm_trace.cpp b/silkworm/silkrpc/core/evm_trace.cpp index c4e6e06c..38fc5ba6 100644 --- a/silkworm/silkrpc/core/evm_trace.cpp +++ b/silkworm/silkrpc/core/evm_trace.cpp @@ -40,6 +40,7 @@ #include #include #include +#include namespace silkworm::rpc::trace { @@ -1237,6 +1238,7 @@ awaitable> TraceCallExecutor::trace_block_transacti const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; @@ -1283,7 +1285,7 @@ awaitable> TraceCallExecutor::trace_block_transacti tracers.push_back(ibs_tracer); - auto execution_result = executor.call(block, transaction, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); + auto execution_result = executor.call(block, transaction, gas_params, eos_evm_version, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); if (execution_result.pre_check_error) { result.pre_check_error = execution_result.pre_check_error.value(); } else { @@ -1315,6 +1317,7 @@ awaitable TraceCallExecutor::trace_calls(const silkworm::Bl const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; const auto ret_result = co_await boost::asio::async_compose( @@ -1354,7 +1357,7 @@ awaitable TraceCallExecutor::trace_calls(const silkworm::Bl } tracers.push_back(ibs_tracer); - auto execution_result = executor.call(block, transaction, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); + auto execution_result = executor.call(block, transaction, gas_params, eos_evm_version, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); if (execution_result.pre_check_error) { result.pre_check_error = "first run for txIndex " + std::to_string(index) + " error: " + execution_result.pre_check_error.value(); @@ -1384,6 +1387,7 @@ boost::asio::awaitable TraceCallExecutor::trace_deploy_transa const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; @@ -1408,7 +1412,7 @@ boost::asio::awaitable TraceCallExecutor::trace_deploy_transa transaction.recover_sender(); } - executor.call(block, transaction, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); + executor.call(block, transaction, gas_params, eos_evm_version, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); executor.reset(); if (create_tracer->found()) { @@ -1457,6 +1461,7 @@ boost::asio::awaitable TraceCallExecutor::trace_transaction_ const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, transaction_with_block.block_with_hash.block); auto current_executor = co_await boost::asio::this_coro::executor; @@ -1473,7 +1478,7 @@ boost::asio::awaitable TraceCallExecutor::trace_transaction_ Tracers tracers{entry_tracer}; - executor.call(transaction_with_block.block_with_hash.block, transaction_with_block.transaction, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); + executor.call(transaction_with_block.block_with_hash.block, transaction_with_block.transaction, gas_params, eos_evm_version, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); boost::asio::post(current_executor, [entry_tracer, self = std::move(self)]() mutable { self.complete(entry_tracer); @@ -1490,6 +1495,7 @@ boost::asio::awaitable TraceCallExecutor::trace_transaction_error(c const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, transaction_with_block.block_with_hash.block); auto current_executor = co_await boost::asio::this_coro::executor; @@ -1503,7 +1509,7 @@ boost::asio::awaitable TraceCallExecutor::trace_transaction_error(c EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; Tracers tracers{}; - auto execution_result = executor.call(transaction_with_block.block_with_hash.block, transaction_with_block.transaction, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); + auto execution_result = executor.call(transaction_with_block.block_with_hash.block, transaction_with_block.transaction, gas_params, eos_evm_version, std::move(tracers), /*refund=*/true, /*gas_bailout=*/true); std::string result = "0x"; if (execution_result.error_code != evmc_status_code::EVMC_SUCCESS) { @@ -1524,6 +1530,7 @@ boost::asio::awaitable TraceCallExecutor::trace_operation const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, transaction_with_block.block_with_hash.block); auto current_executor = co_await boost::asio::this_coro::executor; auto state = tx_.create_state(current_executor, database_reader_, block_number - 1); @@ -1534,7 +1541,7 @@ boost::asio::awaitable TraceCallExecutor::trace_operation auto tracer = std::make_shared(initial_ibs); Tracers tracers{tracer}; - auto execution_result = executor.call(transaction_with_block.block_with_hash.block, transaction_with_block.transaction, tracers, /*refund=*/true, /*gas_bailout=*/true); + auto execution_result = executor.call(transaction_with_block.block_with_hash.block, transaction_with_block.transaction, gas_params, eos_evm_version, tracers, /*refund=*/true, /*gas_bailout=*/true); co_return tracer->result(); } @@ -1598,6 +1605,7 @@ awaitable TraceCallExecutor::execute(std::uint64_t block_number const auto chain_id = co_await core::rawdb::read_chain_id(database_reader_); const auto chain_config_ptr = lookup_chain_config(chain_id); + const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(database_reader_, chain_config_ptr, block); auto current_executor = co_await boost::asio::this_coro::executor; @@ -1620,7 +1628,7 @@ awaitable TraceCallExecutor::execute(std::uint64_t block_number if (!txn.from) { txn.recover_sender(); } - const auto execution_result = executor.call(block, txn, tracers, /*refund=*/true, /*gas_bailout=*/true); + const auto execution_result = executor.call(block, txn, gas_params, eos_evm_version, tracers, /*refund=*/true, /*gas_bailout=*/true); if (execution_result.pre_check_error) { SILK_ERROR << "execution failed for tx " << idx << " due to pre-check error: " << *execution_result.pre_check_error; } @@ -1642,7 +1650,7 @@ awaitable TraceCallExecutor::execute(std::uint64_t block_number tracers.push_back(std::make_shared(traces.state_diff.value(), state_addresses)); } - const auto execution_result = executor.call(block, transaction, tracers, /*refund=*/true, /*gas_bailout=*/true); + const auto execution_result = executor.call(block, transaction, gas_params, eos_evm_version, tracers, /*refund=*/true, /*gas_bailout=*/true); if (execution_result.pre_check_error) { result.pre_check_error = execution_result.pre_check_error.value(); diff --git a/silkworm/silkrpc/core/evm_trace.hpp b/silkworm/silkrpc/core/evm_trace.hpp index 7e1cf4ce..cad17153 100644 --- a/silkworm/silkrpc/core/evm_trace.hpp +++ b/silkworm/silkrpc/core/evm_trace.hpp @@ -45,6 +45,7 @@ #include #include #include +#include namespace silkworm::rpc::trace { diff --git a/silkworm/silkrpc/core/gas_parameters.cpp b/silkworm/silkrpc/core/gas_parameters.cpp index 628763e7..73b72dea 100644 --- a/silkworm/silkrpc/core/gas_parameters.cpp +++ b/silkworm/silkrpc/core/gas_parameters.cpp @@ -3,7 +3,7 @@ namespace silkworm { -awaitable> load_gas_parameters(TransactionDatabase& tx_database, const silkworm::ChainConfig* chain_config_ptr, const silkworm::Block& block) { +awaitable> load_gas_parameters(const DatabaseReader& tx_database, const silkworm::ChainConfig* chain_config_ptr, const silkworm::Block& block) { auto eos_evm_version = chain_config_ptr->eos_evm_version(block.header); evmone::gas_parameters gas_params; diff --git a/silkworm/silkrpc/core/gas_parameters.hpp b/silkworm/silkrpc/core/gas_parameters.hpp index a6f7fbba..729f7227 100644 --- a/silkworm/silkrpc/core/gas_parameters.hpp +++ b/silkworm/silkrpc/core/gas_parameters.hpp @@ -6,13 +6,13 @@ #include #include #include -#include +#include -using silkworm::rpc::ethdb::TransactionDatabase; +using silkworm::rpc::core::rawdb::DatabaseReader; using boost::asio::awaitable; namespace silkworm { - awaitable> load_gas_parameters(TransactionDatabase& tx_database, const silkworm::ChainConfig* chain_config_ptr, const silkworm::Block& header); + awaitable> load_gas_parameters(const DatabaseReader& tx_database, const silkworm::ChainConfig* chain_config_ptr, const silkworm::Block& header); } From 1144f5c76101298dfda98bebbe5ed1165ab5c3b4 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Thu, 5 Sep 2024 14:04:09 -0300 Subject: [PATCH 2/5] Fix evm_executor tests --- silkworm/silkrpc/core/evm_executor_test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/silkworm/silkrpc/core/evm_executor_test.cpp b/silkworm/silkrpc/core/evm_executor_test.cpp index daaaeaa0..8015c2fb 100644 --- a/silkworm/silkrpc/core/evm_executor_test.cpp +++ b/silkworm/silkrpc/core/evm_executor_test.cpp @@ -81,7 +81,7 @@ TEST_CASE("EVMExecutor") { test::DummyTransaction tx{0, mock_cursor}; auto state = tx.create_state(current_executor, tx_database, block_number); EVMExecutor executor{*chain_config_ptr, workers, state}; - auto result = executor.call(block, txn, {}); + auto result = executor.call(block, txn, {}, 0, {}); my_pool.stop(); my_pool.join(); CHECK(result.error_code == std::nullopt); @@ -110,7 +110,7 @@ TEST_CASE("EVMExecutor") { test::DummyTransaction tx{0, mock_cursor}; auto state = tx.create_state(current_executor, tx_database, block_number); EVMExecutor executor{*chain_config_ptr, workers, state}; - auto result = executor.call(block, txn, {}); + auto result = executor.call(block, txn, {}, 0, {}); my_pool.stop(); my_pool.join(); CHECK(result.error_code == std::nullopt); @@ -140,7 +140,7 @@ TEST_CASE("EVMExecutor") { test::DummyTransaction tx{0, mock_cursor}; auto state = tx.create_state(current_executor, tx_database, block_number); EVMExecutor executor{*chain_config_ptr, workers, state}; - auto result = executor.call(block, txn, {}); + auto result = executor.call(block, txn, {}, 0, {}); my_pool.stop(); my_pool.join(); CHECK(result.error_code == std::nullopt); @@ -170,7 +170,7 @@ TEST_CASE("EVMExecutor") { test::DummyTransaction tx{0, mock_cursor}; auto state = tx.create_state(current_executor, tx_database, block_number); EVMExecutor executor{*chain_config_ptr, workers, state}; - auto result = executor.call(block, txn, {}); + auto result = executor.call(block, txn, {}, 0, {}); my_pool.stop(); my_pool.join(); CHECK(result.error_code == std::nullopt); @@ -200,7 +200,7 @@ TEST_CASE("EVMExecutor") { test::DummyTransaction tx{0, mock_cursor}; auto state = tx.create_state(current_executor, tx_database, block_number); EVMExecutor executor{*chain_config_ptr, workers, state}; - auto result = executor.call(block, txn, {}, false, /* gasBailout */ true); + auto result = executor.call(block, txn, {}, 0, {}, false, /* gasBailout */ true); executor.reset(); my_pool.stop(); my_pool.join(); @@ -238,7 +238,7 @@ TEST_CASE("EVMExecutor") { test::DummyTransaction tx{0, mock_cursor}; auto state = tx.create_state(current_executor, tx_database, block_number); EVMExecutor executor{*chain_config_ptr, workers, state}; - auto result = executor.call(block, txn, {}, true, /* gasBailout */ true); + auto result = executor.call(block, txn, {}, 0, {}, true, /* gasBailout */ true); my_pool.stop(); my_pool.join(); CHECK(result.error_code == 0); From abdbd056f99b635c87c353e0ede739c06b4447d6 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Tue, 10 Sep 2024 16:01:33 -0300 Subject: [PATCH 3/5] EVMExecutor handle gas usage and refunds in the same way as the processor --- silkworm/silkrpc/core/evm_executor.cpp | 43 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/silkworm/silkrpc/core/evm_executor.cpp b/silkworm/silkrpc/core/evm_executor.cpp index 116c8949..51f1bc0a 100644 --- a/silkworm/silkrpc/core/evm_executor.cpp +++ b/silkworm/silkrpc/core/evm_executor.cpp @@ -166,17 +166,22 @@ std::string EVMExecutor::get_error_message(int64_t error_code, const Bytes& erro uint64_t EVMExecutor::refund_gas(const EVM& evm, const silkworm::Transaction& txn, uint64_t gas_left, uint64_t gas_refund) { const evmc_revision rev{evm.revision()}; - const uint64_t max_refund_quotient{rev >= EVMC_LONDON ? protocol::kMaxRefundQuotientLondon - : protocol::kMaxRefundQuotientFrontier}; - const uint64_t max_refund{(txn.gas_limit - gas_left) / max_refund_quotient}; - uint64_t refund = gas_refund < max_refund ? gas_refund : max_refund; // min - gas_left += refund; + if( evm.get_eos_evm_version() < 2 ) { + const uint64_t max_refund_quotient{rev >= EVMC_LONDON ? protocol::kMaxRefundQuotientLondon + : protocol::kMaxRefundQuotientFrontier}; + const uint64_t max_refund{(txn.gas_limit - gas_left) / max_refund_quotient}; + uint64_t refund = gas_refund < max_refund ? gas_refund : max_refund; // min + gas_left += refund; + } else { + gas_left += gas_refund; + if( gas_left > txn.gas_limit - silkworm::protocol::fee::kGTransaction ) { + gas_left = txn.gas_limit - silkworm::protocol::fee::kGTransaction; + } + } const intx::uint256 base_fee_per_gas{evm.block().header.base_fee_per_gas.value_or(0)}; - SILK_DEBUG << "EVMExecutor::refund_gas txn.max_fee_per_gas: " << txn.max_fee_per_gas << " base_fee_per_gas: " << base_fee_per_gas; - const intx::uint256 effective_gas_price{txn.max_fee_per_gas >= base_fee_per_gas ? txn.effective_gas_price(base_fee_per_gas) - : txn.max_priority_fee_per_gas}; - SILK_DEBUG << "EVMExecutor::refund_gas effective_gas_price: " << effective_gas_price; + const intx::uint256 effective_gas_price{txn.effective_gas_price(base_fee_per_gas)}; + SILK_DEBUG << "EVMExecutor::refund_gas effective_gas_price: " << effective_gas_price << ", txn.max_fee_per_gas: " << txn.max_fee_per_gas << ", base_fee_per_gas: " << base_fee_per_gas; ibs_state_.add_to_balance(*txn.from, gas_left * effective_gas_price); return gas_left; } @@ -260,13 +265,18 @@ ExecutionResult EVMExecutor::call( } intx::uint256 want; + const intx::uint256 effective_gas_price{txn.effective_gas_price(base_fee_per_gas)}; if (txn.max_fee_per_gas > 0 || txn.max_priority_fee_per_gas > 0) { // This method should be called after check (max_fee and base_fee) present in pre_check() method - const intx::uint256 effective_gas_price{txn.effective_gas_price(base_fee_per_gas)}; want = txn.gas_limit * effective_gas_price; } else { want = 0; } + + // EIP-4844 data gas cost (calc_data_fee) + const intx::uint256 data_gas_price{evm.block().header.data_gas_price().value_or(0)}; + want += txn.total_data_gas() * data_gas_price; + const auto have = ibs_state_.get_balance(*txn.from); if (have < want + txn.value) { if (!gas_bailout) { @@ -290,6 +300,12 @@ ExecutionResult EVMExecutor::call( ibs_state_.access_storage(ae.account, key); } } + + if (rev >= EVMC_SHANGHAI) { + // EIP-3651: Warm COINBASE + ibs_state_.access_account(evm.beneficiary); + } + silkworm::CallResult result; try { SILK_DEBUG << "EVMExecutor::call execute on EVM txn: " << &txn << " g0: " << static_cast(g0) << " start"; @@ -312,10 +328,9 @@ ExecutionResult EVMExecutor::call( } // Reward the fee recipient - const intx::uint256 priority_fee_per_gas{txn.max_fee_per_gas >= base_fee_per_gas ? txn.priority_fee_per_gas(base_fee_per_gas) - : txn.max_priority_fee_per_gas}; - SILK_DEBUG << "EVMExecutor::call evm.beneficiary: " << evm.beneficiary << " balance: " << priority_fee_per_gas * gas_used; - ibs_state_.add_to_balance(evm.beneficiary, priority_fee_per_gas * gas_used); + const intx::uint256 price{evm.config().protocol_rule_set == protocol::RuleSetType::kTrust ? effective_gas_price : txn.priority_fee_per_gas(base_fee_per_gas)}; + ibs_state_.add_to_balance(evm.beneficiary, price * gas_used); + SILK_DEBUG << "EVMExecutor::call evm.beneficiary: " << evm.beneficiary << " balance: " << price * gas_used; for (auto tracer : evm.tracers()) { tracer.get().on_reward_granted(result, evm.state()); From 497daf5e3acbdcab43f47d3a66fbad9392e0c1e6 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Tue, 10 Sep 2024 16:02:09 -0300 Subject: [PATCH 4/5] eth_call: perfom gas bailout in case from field is not specified --- silkworm/silkrpc/commands/eth_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/silkworm/silkrpc/commands/eth_api.cpp b/silkworm/silkrpc/commands/eth_api.cpp index 00b32b05..07947c73 100644 --- a/silkworm/silkrpc/commands/eth_api.cpp +++ b/silkworm/silkrpc/commands/eth_api.cpp @@ -1155,7 +1155,7 @@ awaitable EthereumRpcApi::handle_eth_call(const nlohmann::json& request, s const auto execution_result = co_await EVMExecutor::call( *chain_config_ptr, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num) { return tx->create_state(io_executor, db_reader, block_num); - }, gas_params, eos_evm_version, {}, true, false); + }, gas_params, eos_evm_version, {}, true, txn.from == evmc::address{0}); if (execution_result.success()) { make_glaze_json_content(reply, request["id"], execution_result.data); From aeaac3762cd09f8ee71f8c80b3392adb2c165232 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Wed, 11 Sep 2024 21:33:25 -0300 Subject: [PATCH 5/5] Fix calculation of effective_gas_price --- silkworm/silkrpc/core/evm_executor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/silkworm/silkrpc/core/evm_executor.cpp b/silkworm/silkrpc/core/evm_executor.cpp index 51f1bc0a..d0a3ba45 100644 --- a/silkworm/silkrpc/core/evm_executor.cpp +++ b/silkworm/silkrpc/core/evm_executor.cpp @@ -180,7 +180,8 @@ uint64_t EVMExecutor::refund_gas(const EVM& evm, const silkworm::Transaction& tx } const intx::uint256 base_fee_per_gas{evm.block().header.base_fee_per_gas.value_or(0)}; - const intx::uint256 effective_gas_price{txn.effective_gas_price(base_fee_per_gas)}; + const intx::uint256 effective_gas_price{txn.max_fee_per_gas >= base_fee_per_gas ? txn.effective_gas_price(base_fee_per_gas) + : txn.max_priority_fee_per_gas}; SILK_DEBUG << "EVMExecutor::refund_gas effective_gas_price: " << effective_gas_price << ", txn.max_fee_per_gas: " << txn.max_fee_per_gas << ", base_fee_per_gas: " << base_fee_per_gas; ibs_state_.add_to_balance(*txn.from, gas_left * effective_gas_price); return gas_left; @@ -265,7 +266,8 @@ ExecutionResult EVMExecutor::call( } intx::uint256 want; - const intx::uint256 effective_gas_price{txn.effective_gas_price(base_fee_per_gas)}; + const intx::uint256 effective_gas_price{txn.max_fee_per_gas >= base_fee_per_gas ? txn.effective_gas_price(base_fee_per_gas) + : txn.max_priority_fee_per_gas}; if (txn.max_fee_per_gas > 0 || txn.max_priority_fee_per_gas > 0) { // This method should be called after check (max_fee and base_fee) present in pre_check() method want = txn.gas_limit * effective_gas_price;