Skip to content

Commit

Permalink
rpcdaemon: EVMExecutor remove constructor with RemoteState (#1293)
Browse files Browse the repository at this point in the history
  • Loading branch information
lupin012 authored Jun 26, 2023
1 parent be0de77 commit 3710a17
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 161 deletions.
4 changes: 2 additions & 2 deletions silkworm/silkrpc/core/call_many.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ CallManyResult CallExecutor::executes_all_bundles(const silkworm::ChainConfig* c
txn.recover_sender();
}

auto exec_result = executor.call_sync(block, txn);
auto exec_result = executor.call(block, txn);

if ((clock_time::since(start_time) / 1000000) > timeout) {
std::ostringstream oss;
Expand Down Expand Up @@ -110,7 +110,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_sync(blockContext.block, txn);
auto call_execution_result = executor.call(blockContext.block, txn);

if (call_execution_result.pre_check_error) {
result.error = call_execution_result.pre_check_error;
Expand Down
2 changes: 1 addition & 1 deletion silkworm/silkrpc/core/estimate_gas_oracle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ boost::asio::awaitable<intx::uint256> EstimateGasOracle::estimate_gas(const Call
}

ExecutionResult EstimateGasOracle::try_execution(EVMExecutor& executor, const silkworm::Block& block, const silkworm::Transaction& transaction) {
return executor.call_sync(block, transaction);
return executor.call(block, transaction);
}

void EstimateGasOracle::throw_exception(ExecutionResult& result, uint64_t cap) {
Expand Down
10 changes: 5 additions & 5 deletions silkworm/silkrpc/core/evm_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ awaitable<void> DebugExecutor::execute(json::Stream& stream, const silkworm::Blo
stream.open_array();

Tracers tracers{debug_tracer};
const auto execution_result = executor.call_sync(block, txn, tracers, /* refund */ false, /* gasBailout */ false);
const auto execution_result = executor.call(block, txn, tracers, /* refund */ false, /* gasBailout */ false);

debug_tracer->flush_logs();
stream.close_array();
Expand Down Expand Up @@ -428,7 +428,7 @@ awaitable<void> DebugExecutor::execute(json::Stream& stream, uint64_t block_numb
if (!txn.from) {
txn.recover_sender();
}
executor.call_sync(block, txn);
executor.call(block, txn);
}
executor.reset();

Expand All @@ -438,7 +438,7 @@ awaitable<void> DebugExecutor::execute(json::Stream& stream, uint64_t block_numb
stream.open_array();

Tracers tracers{debug_tracer};
const auto execution_result = executor.call_sync(block, transaction, tracers);
const auto execution_result = executor.call(block, transaction, tracers);

debug_tracer->flush_logs();
stream.close_array();
Expand Down Expand Up @@ -492,7 +492,7 @@ awaitable<void> DebugExecutor::execute(json::Stream& stream,
txn.recover_sender();
}

executor.call_sync(block, txn);
executor.call(block, txn);
}
executor.reset();

Expand Down Expand Up @@ -531,7 +531,7 @@ awaitable<void> DebugExecutor::execute(json::Stream& stream,
auto debug_tracer = std::make_shared<debug::DebugTracer>(stream, config_);
Tracers tracers{debug_tracer};

const auto execution_result = executor.call_sync(blockContext.block, txn, tracers, /* refund */ false, /* gasBailout */ false);
const auto execution_result = executor.call(blockContext.block, txn, tracers, /* refund */ false, /* gasBailout */ false);

debug_tracer->flush_logs();
stream.close_array();
Expand Down
117 changes: 2 additions & 115 deletions silkworm/silkrpc/core/evm_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,120 +201,7 @@ std::optional<std::string> EVMExecutor::pre_check(const EVM& evm, const silkworm
return std::nullopt;
}

boost::asio::awaitable<ExecutionResult> EVMExecutor::call(
const silkworm::Block& block,
const silkworm::Transaction& txn,
Tracers tracers,
bool refund,
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;

const auto this_executor = co_await boost::asio::this_coro::executor;

const auto call_result = co_await boost::asio::async_compose<decltype(boost::asio::use_awaitable), void(ExecutionResult)>(
[this, this_executor, &block, &txn, &tracers, &refund, &gas_bailout](auto&& self) {
SILK_TRACE << "EVMExecutor::call post block: " << block.header.number << " txn: " << &txn;
boost::asio::post(workers_, [this, this_executor, &block, &txn, &tracers, &refund, &gas_bailout, self = std::move(self)]() mutable {
auto& svc = use_service<AnalysisCacheService>(workers_);
EVM evm{block, ibs_state_, config_};
evm.analysis_cache = svc.get_analysis_cache();
evm.state_pool = svc.get_object_pool();
evm.beneficiary = rule_set_->get_beneficiary(block.header);

for (auto& tracer : tracers) {
evm.add_tracer(*tracer);
}

SILKWORM_ASSERT(txn.from.has_value());
ibs_state_.access_account(*txn.from);

const evmc_revision rev{evm.revision()};
const intx::uint256 base_fee_per_gas{evm.block().header.base_fee_per_gas.value_or(0)};
const intx::uint128 g0{protocol::intrinsic_gas(txn, rev)};
SILKWORM_ASSERT(g0 <= UINT64_MAX); // true due to the precondition (transaction must be valid)

const auto error = pre_check(evm, txn, base_fee_per_gas, g0);
if (error) {
Bytes data{};
ExecutionResult exec_result{1000, txn.gas_limit, data, *error};
boost::asio::post(this_executor, [exec_result, self = std::move(self)]() mutable {
self.complete(exec_result);
});
return;
}

intx::uint256 want;
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;
}
const auto have = ibs_state_.get_balance(*txn.from);
if (have < want + txn.value) {
if (!gas_bailout) {
Bytes data{};
std::string from = to_hex(*txn.from);
std::string msg = "insufficient funds for gas * price + value: address 0x" + from + " have " + intx::to_string(have) + " want " + intx::to_string(want + txn.value);
ExecutionResult exec_result{1000, txn.gas_limit, data, msg};
boost::asio::post(this_executor, [exec_result, self = std::move(self)]() mutable {
self.complete(exec_result);
});
return;
}
} else {
ibs_state_.subtract_from_balance(*txn.from, want);
}

if (txn.to.has_value()) {
ibs_state_.access_account(*txn.to);
// EVM itself increments the nonce for contract creation
ibs_state_.set_nonce(*txn.from, ibs_state_.get_nonce(*txn.from) + 1);
}
for (const AccessListEntry& ae : txn.access_list) {
ibs_state_.access_account(ae.account);
for (const evmc::bytes32& key : ae.storage_keys) {
ibs_state_.access_storage(ae.account, key);
}
}

SILK_DEBUG << "EVMExecutor::call execute on EVM txn: " << &txn << " g0: " << static_cast<uint64_t>(g0) << " start";
const auto result{evm.execute(txn, txn.gas_limit - static_cast<uint64_t>(g0))};
SILK_DEBUG << "EVMExecutor::call execute on EVM txn: " << &txn << " gas_left: " << result.gas_left << " end";

uint64_t gas_left = result.gas_left;
const uint64_t gas_used{txn.gas_limit - refund_gas(evm, txn, result.gas_left, result.gas_refund)};
if (refund) {
gas_left = txn.gas_limit - gas_used;
}

// 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);

for (auto tracer : evm.tracers()) {
tracer.get().on_reward_granted(result, evm.state());
}
ibs_state_.finalize_transaction();

ExecutionResult exec_result{result.status, gas_left, result.data};
boost::asio::post(this_executor, [exec_result, self = std::move(self)]() mutable {
self.complete(exec_result);
});
});
},
boost::asio::use_awaitable);

SILK_DEBUG << "EVMExecutor::call call_result: " << call_result.error_code << " #data: " << call_result.data.size() << " end";

co_return call_result;
}

ExecutionResult EVMExecutor::call_sync(
ExecutionResult EVMExecutor::call(
const silkworm::Block& block,
const silkworm::Transaction& txn,
Tracers tracers,
Expand Down Expand Up @@ -421,7 +308,7 @@ awaitable<ExecutionResult> EVMExecutor::call(const silkworm::ChainConfig& config
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_sync(block, txn, tracers, refund, gas_bailout);
auto exec_result = executor.call(block, txn, tracers, refund, gas_bailout);
boost::asio::post(this_executor, [exec_result, self = std::move(self)]() mutable {
self.complete(exec_result);
});
Expand Down
21 changes: 2 additions & 19 deletions silkworm/silkrpc/core/evm_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#include <silkworm/core/types/block.hpp>
#include <silkworm/core/types/transaction.hpp>
#include <silkworm/silkrpc/core/rawdb/accessors.hpp>
#include <silkworm/silkrpc/core/remote_state.hpp> // to be removed
#include <silkworm/silkrpc/core/state_reader.hpp>

namespace silkworm::rpc {

Expand Down Expand Up @@ -83,24 +83,10 @@ class EVMExecutor {
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, silkworm::State& remote_state)
: config_(config),
workers_{workers},
state_{nullptr},
state1_{remote_state},
ibs_state_{state1_},
rule_set_(protocol::rule_set_factory(config)) {
SILKWORM_ASSERT(rule_set_);
if (!has_service<AnalysisCacheService>(workers_)) {
make_service<AnalysisCacheService>(workers_);
}
}

EVMExecutor(const silkworm::ChainConfig& config, boost::asio::thread_pool& workers, std::shared_ptr<silkworm::State>& state)
: config_(config),
workers_{workers},
state_{state},
state1_{*state_},
ibs_state_{*state_},
rule_set_(protocol::rule_set_factory(config)) {
SILKWORM_ASSERT(rule_set_);
Expand All @@ -113,9 +99,7 @@ class EVMExecutor {
EVMExecutor(const EVMExecutor&) = delete;
EVMExecutor& operator=(const EVMExecutor&) = delete;

boost::asio::awaitable<ExecutionResult> call(const silkworm::Block& block, const silkworm::Transaction& txn, Tracers tracers = {},
bool refund = true, bool gas_bailout = false);
ExecutionResult call_sync(const silkworm::Block& block, const silkworm::Transaction& txn, Tracers tracers = {}, bool refund = true, bool gas_bailout = false);
ExecutionResult call(const silkworm::Block& block, const silkworm::Transaction& txn, Tracers tracers = {}, bool refund = true, bool gas_bailout = false);
void reset();

private:
Expand All @@ -126,7 +110,6 @@ class EVMExecutor {
const silkworm::ChainConfig& config_;
boost::asio::thread_pool& workers_;
std::shared_ptr<silkworm::State> state_;
silkworm::State& state1_;
IntraBlockState ibs_state_;
protocol::RuleSetPtr rule_set_;
};
Expand Down
18 changes: 6 additions & 12 deletions silkworm/silkrpc/core/evm_executor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +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 execution_result = boost::asio::co_spawn(my_pool.next_io_context().get_executor(), executor.call(block, txn, {}), boost::asio::use_future);
auto result = execution_result.get();
auto result = executor.call(block, txn, {});
my_pool.stop();
my_pool.join();
CHECK(result.error_code == 1000);
Expand Down Expand Up @@ -111,8 +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 execution_result = boost::asio::co_spawn(my_pool.next_io_context().get_executor(), executor.call(block, txn, {}), boost::asio::use_future);
auto result = execution_result.get();
auto result = executor.call(block, txn, {});
my_pool.stop();
my_pool.join();
CHECK(result.error_code == 1000);
Expand Down Expand Up @@ -142,8 +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 execution_result = boost::asio::co_spawn(my_pool.next_io_context().get_executor(), executor.call(block, txn, {}), boost::asio::use_future);
auto result = execution_result.get();
auto result = executor.call(block, txn, {});
my_pool.stop();
my_pool.join();
CHECK(result.error_code == 1000);
Expand Down Expand Up @@ -173,8 +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 execution_result = boost::asio::co_spawn(my_pool.next_io_context().get_executor(), executor.call(block, txn, {}), boost::asio::use_future);
auto result = execution_result.get();
auto result = executor.call(block, txn, {});
my_pool.stop();
my_pool.join();
CHECK(result.error_code == 1000);
Expand Down Expand Up @@ -204,8 +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 execution_result = boost::asio::co_spawn(my_pool.next_io_context().get_executor(), executor.call(block, txn, {}, false, /* gasBailout */ true), boost::asio::use_future);
auto result = execution_result.get();
auto result = executor.call(block, txn, {}, false, /* gasBailout */ true);
executor.reset();
my_pool.stop();
my_pool.join();
Expand Down Expand Up @@ -243,8 +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 execution_result = boost::asio::co_spawn(my_pool.next_io_context().get_executor(), executor.call(block, txn, {}, true, true), boost::asio::use_future);
auto result = execution_result.get();
auto result = executor.call(block, txn, {}, true, /* gasBailout */ true);
my_pool.stop();
my_pool.join();
CHECK(result.error_code == 0);
Expand Down
Loading

0 comments on commit 3710a17

Please sign in to comment.