Skip to content

Commit

Permalink
Use gas_parameters inside EVMExecutor
Browse files Browse the repository at this point in the history
  • Loading branch information
elmato committed Mar 13, 2024
1 parent 4dca8ec commit 8738e98
Show file tree
Hide file tree
Showing 28 changed files with 263 additions and 31 deletions.
26 changes: 26 additions & 0 deletions silkworm/silkrpc/commands/debug_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,32 @@ class DummyCursor : public ethdb::CursorDupSort {
co_return kv;
}

awaitable<KeyValue> prev() override {
KeyValue out;

if (itr_ != table_.begin() && table_.begin() != table_.end()) {
--itr_;
auto key{*silkworm::from_hex(itr_.key())};
auto value{*silkworm::from_hex(itr_.value().get<std::string>())};
out = KeyValue{key, value};
}

co_return out;
}

awaitable<KeyValue> last() override {
KeyValue out;

if (table_.begin() != table_.end()) {
itr_ = --table_.end();
auto key{*silkworm::from_hex(itr_.key())};
auto value{*silkworm::from_hex(itr_.value().get<std::string>())};
out = KeyValue{key, value};
}

co_return out;
}

awaitable<KeyValue> next() override {
KeyValue out;

Expand Down
14 changes: 10 additions & 4 deletions silkworm/silkrpc/commands/eth_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
#include <silkworm/silkrpc/types/syncing_data.hpp>
#include <silkworm/silkrpc/types/transaction.hpp>

#include <silkworm/silkrpc/core/gas_parameters.hpp>

namespace silkworm::rpc::commands {

awaitable<std::pair<uint64_t, uint64_t>> get_block_numbers(const Filter& filter, const core::rawdb::DatabaseReader& reader) {
Expand Down Expand Up @@ -1137,12 +1139,14 @@ awaitable<void> EthereumRpcApi::handle_eth_call(const nlohmann::json& request, s
silkworm::Transaction txn{call.to_transaction()};
if(!txn.from.has_value()) txn.from = evmc::address{0};

const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(tx_database, chain_config_ptr, block_with_hash->block.header);

const core::rawdb::DatabaseReader& db_reader =
is_latest_block ? static_cast<core::rawdb::DatabaseReader&>(cached_database) : static_cast<core::rawdb::DatabaseReader&>(tx_database);
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);

if (execution_result.success()) {
make_glaze_json_content(reply, request["id"], execution_result.data);
Expand Down Expand Up @@ -1284,6 +1288,7 @@ awaitable<void> EthereumRpcApi::handle_eth_create_access_list(const nlohmann::js
const auto block_with_hash = co_await core::read_block_by_number_or_hash(*block_cache_, tx_database, block_number_or_hash);
const auto chain_id = co_await core::rawdb::read_chain_id(tx_database);
const auto chain_config_ptr = lookup_chain_config(chain_id);
const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(tx_database, chain_config_ptr, block_with_hash->block.header);

const bool is_latest_block = co_await core::get_latest_executed_block_number(tx_database) == block_with_hash->block.header.number;
const core::rawdb::DatabaseReader& db_reader =
Expand Down Expand Up @@ -1325,7 +1330,7 @@ awaitable<void> EthereumRpcApi::handle_eth_create_access_list(const nlohmann::js
*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);
std::move(tracers), /* refund */ true, /* gasBailout */ false, eos_evm_version, gas_params);

if (execution_result.pre_check_error) {
reply = make_json_error(request["id"], -32000, execution_result.pre_check_error.value());
Expand Down Expand Up @@ -1383,12 +1388,13 @@ awaitable<void> EthereumRpcApi::handle_eth_call_bundle(const nlohmann::json& req
auto tx = co_await database_->begin();

try {
ethdb::kv::CachedDatabase tx_database{block_number_or_hash, *tx, *state_cache_};
ethdb::TransactionDatabase tx_database{*tx};
ethdb::kv::CachedDatabase cached_database{block_number_or_hash, *tx, *state_cache_};

const auto block_with_hash = co_await core::read_block_by_number_or_hash(*block_cache_, tx_database, block_number_or_hash);
const auto chain_id = co_await core::rawdb::read_chain_id(tx_database);
const auto chain_config_ptr = lookup_chain_config(chain_id);
const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(tx_database, chain_config_ptr, block_with_hash->block.header);

const bool is_latest_block = co_await core::get_latest_executed_block_number(tx_database) == block_with_hash->block.header.number;
const core::rawdb::DatabaseReader& db_reader =
Expand All @@ -1414,7 +1420,7 @@ awaitable<void> 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);
if (execution_result.pre_check_error) {
reply = make_json_error(request["id"], -32000, execution_result.pre_check_error.value());
error = true;
Expand Down
1 change: 1 addition & 0 deletions silkworm/silkrpc/commands/eth_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <boost/asio/awaitable.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/thread_pool.hpp>
#include <evmone/execution_state.hpp>
#include <evmc/evmc.hpp>
#include <nlohmann/json.hpp>

Expand Down
26 changes: 26 additions & 0 deletions silkworm/silkrpc/core/account_dumper_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,32 @@ class DummyCursor : public ethdb::CursorDupSort {
co_return kv;
}

boost::asio::awaitable<KeyValue> prev() override {
KeyValue out;

if (itr_ != table_.begin() && table_.begin() != table_.end()) {
--itr_;
auto key{*silkworm::from_hex(itr_.key())};
auto value{*silkworm::from_hex(itr_.value().get<std::string>())};
out = KeyValue{key, value};
}

co_return out;
}

boost::asio::awaitable<KeyValue> last() override {
KeyValue out;

if (table_.begin() != table_.end()) {
itr_ = --table_.end();
auto key{*silkworm::from_hex(itr_.key())};
auto value{*silkworm::from_hex(itr_.value().get<std::string>())};
out = KeyValue{key, value};
}

co_return out;
}

boost::asio::awaitable<KeyValue> next() override {
KeyValue out;

Expand Down
26 changes: 26 additions & 0 deletions silkworm/silkrpc/core/account_walker_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,32 @@ class DummyCursor : public ethdb::CursorDupSort {
co_return kv;
}

boost::asio::awaitable<KeyValue> prev() override {
KeyValue out;

if (itr_ != table_.begin() && table_.begin() != table_.end()) {
--itr_;
auto key{*silkworm::from_hex(itr_.key())};
auto value{*silkworm::from_hex(itr_.value().get<std::string>())};
out = KeyValue{key, value};
}

co_return out;
}

boost::asio::awaitable<KeyValue> last() override {
KeyValue out;

if (table_.begin() != table_.end()) {
itr_ = --table_.end();
auto key{*silkworm::from_hex(itr_.key())};
auto value{*silkworm::from_hex(itr_.value().get<std::string>())};
out = KeyValue{key, value};
}

co_return out;
}

boost::asio::awaitable<KeyValue> next() override {
KeyValue out;

Expand Down
11 changes: 7 additions & 4 deletions silkworm/silkrpc/core/estimate_gas_oracle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "estimate_gas_oracle.hpp"
#include <silkworm/silkrpc/core/gas_parameters.hpp>

#include <string>

Expand Down Expand Up @@ -77,6 +78,8 @@ boost::asio::awaitable<intx::uint256> EstimateGasOracle::estimate_gas(const Call

SILK_DEBUG << "hi: " << hi << ", lo: " << lo << ", cap: " << cap;

const auto [eos_evm_version, gas_params] = co_await load_gas_parameters(tx_database_, &config_, block.header);

auto this_executor = co_await boost::asio::this_coro::executor;
auto exec_result = co_await boost::asio::async_compose<decltype(boost::asio::use_awaitable), void(ExecutionResult)>(
[&](auto&& self) {
Expand All @@ -91,7 +94,7 @@ boost::asio::awaitable<intx::uint256> EstimateGasOracle::estimate_gas(const Call
auto mid = (hi + lo) / 2;
transaction.gas_limit = mid;

result = try_execution(executor, block, transaction);
result = try_execution(executor, block, transaction, eos_evm_version, gas_params);

if(result.pre_check_error && !result.pre_check_error.value().starts_with("intrinsic gas too low")) {
boost::asio::post(this_executor, [result, self = std::move(self)]() mutable {
Expand All @@ -109,7 +112,7 @@ boost::asio::awaitable<intx::uint256> EstimateGasOracle::estimate_gas(const Call

if (hi == cap) {
transaction.gas_limit = hi;
result = try_execution(executor, block, transaction);
result = try_execution(executor, block, transaction, eos_evm_version, gas_params);
SILK_DEBUG << "HI == cap tested again with " << (result.success() ? "succeed" : "failed");
} else {
result.pre_check_error = std::nullopt;
Expand All @@ -131,9 +134,9 @@ boost::asio::awaitable<intx::uint256> EstimateGasOracle::estimate_gas(const Call
co_return hi;
}

ExecutionResult EstimateGasOracle::try_execution(EVMExecutor& executor, const silkworm::Block& block, const silkworm::Transaction& transaction) {
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);
return executor.call(block, transaction, {}, true, false, eos_evm_version, gas_params);
}

void EstimateGasOracle::throw_exception(ExecutionResult& result, uint64_t cap) {
Expand Down
2 changes: 1 addition & 1 deletion silkworm/silkrpc/core/estimate_gas_oracle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class EstimateGasOracle {
boost::asio::awaitable<intx::uint256> estimate_gas(const Call& call, const silkworm::Block& latest_block);

protected:
virtual ExecutionResult try_execution(EVMExecutor& executor, const silkworm::Block& _block, const silkworm::Transaction& transaction);
virtual ExecutionResult try_execution(EVMExecutor& executor, const silkworm::Block& _block, const silkworm::Transaction& transaction, uint64_t eos_evm_version, const evmone::gas_parameters& gas_params);

private:
void throw_exception(ExecutionResult& result, uint64_t cap);
Expand Down
30 changes: 15 additions & 15 deletions silkworm/silkrpc/core/estimate_gas_oracle_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ TEST_CASE("estimate gas") {
SECTION("Call empty, always fails but success in last step") {
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
ExecutionResult expect_result_fail{.pre_check_error = "intrinsic gas too low"};
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(16)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_fail))
Expand All @@ -129,7 +129,7 @@ TEST_CASE("estimate gas") {

SECTION("Call empty, always succeeds") {
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _)).Times(14).WillRepeatedly(Return(expect_result_ok));
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _)).Times(14).WillRepeatedly(Return(expect_result_ok));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
const intx::uint256& estimate_gas = result.get();
CHECK(estimate_gas == kTxGas);
Expand All @@ -138,7 +138,7 @@ TEST_CASE("estimate gas") {
SECTION("Call empty, alternatively fails and succeeds") {
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
ExecutionResult expect_result_fail{.pre_check_error = "intrinsic gas too low"};
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(14)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_ok))
Expand All @@ -163,7 +163,7 @@ TEST_CASE("estimate gas") {
SECTION("Call empty, alternatively succeeds and fails") {
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
ExecutionResult expect_result_fail{.pre_check_error = "intrinsic gas too low"};
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(14)
.WillOnce(Return(expect_result_ok))
.WillOnce(Return(expect_result_fail))
Expand All @@ -189,7 +189,7 @@ TEST_CASE("estimate gas") {
call.gas = kTxGas * 4;
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
ExecutionResult expect_result_fail{.pre_check_error = "intrinsic gas too low"};
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(17)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_fail))
Expand Down Expand Up @@ -217,7 +217,7 @@ TEST_CASE("estimate gas") {
SECTION("Call with gas, always succeeds") {
call.gas = kTxGas * 4;
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(15)
.WillRepeatedly(Return(expect_result_ok));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
Expand All @@ -232,7 +232,7 @@ TEST_CASE("estimate gas") {
call.gas = kTxGas * 2;
call.gas_price = intx::uint256{10'000};

EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(16)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_fail))
Expand Down Expand Up @@ -262,7 +262,7 @@ TEST_CASE("estimate gas") {
call.gas = kTxGas * 2;
call.gas_price = intx::uint256{40'000};

EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(13)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_fail))
Expand Down Expand Up @@ -290,7 +290,7 @@ TEST_CASE("estimate gas") {
call.gas_price = intx::uint256{10'000};
call.value = intx::uint256{500'000'000};

EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(16)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_fail))
Expand Down Expand Up @@ -321,7 +321,7 @@ TEST_CASE("estimate gas") {
call.gas_price = intx::uint256{20'000};
call.value = intx::uint256{500'000'000};

EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(13)
.WillOnce(Return(expect_result_fail))
.WillOnce(Return(expect_result_fail))
Expand All @@ -345,7 +345,7 @@ TEST_CASE("estimate gas") {
SECTION("Call gas above allowance, always succeeds, gas capped") {
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
call.gas = kGasCap * 2;
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _)).Times(24).WillRepeatedly(Return(expect_result_ok));
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _)).Times(24).WillRepeatedly(Return(expect_result_ok));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
const intx::uint256& estimate_gas = result.get();

Expand All @@ -356,7 +356,7 @@ TEST_CASE("estimate gas") {
ExecutionResult expect_result_ok{.error_code = evmc_status_code::EVMC_SUCCESS};
call.gas = kTxGas / 2;

EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _)).Times(14).WillRepeatedly(Return(expect_result_ok));
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _)).Times(14).WillRepeatedly(Return(expect_result_ok));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
const intx::uint256& estimate_gas = result.get();

Expand All @@ -368,7 +368,7 @@ TEST_CASE("estimate gas") {
call.value = intx::uint256{2'000'000'000};

try {
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _)).Times(16).WillRepeatedly(Return(expect_result_fail));
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _)).Times(16).WillRepeatedly(Return(expect_result_fail));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
result.get();
CHECK(false);
Expand All @@ -389,7 +389,7 @@ TEST_CASE("estimate gas") {
call.value = intx::uint256{500'000'000};

try {
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(1)
.WillOnce(Return(expect_result_fail_pre_check));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
Expand All @@ -413,7 +413,7 @@ TEST_CASE("estimate gas") {
call.value = intx::uint256{500'000'000};

try {
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _))
EXPECT_CALL(estimate_gas_oracle, try_execution(_, _, _, _, _))
.Times(1)
.WillOnce(Return(expect_result_fail_pre_check));
auto result = boost::asio::co_spawn(pool, estimate_gas_oracle.estimate_gas(call, block), boost::asio::use_future);
Expand Down
Loading

0 comments on commit 8738e98

Please sign in to comment.