diff --git a/cmd/dev/check_changes.cpp b/cmd/dev/check_changes.cpp index 6a55fb96..37d86cf9 100644 --- a/cmd/dev/check_changes.cpp +++ b/cmd/dev/check_changes.cpp @@ -94,7 +94,7 @@ int main(int argc, char* argv[]) { db::Buffer buffer{txn, /*prune_history_threshold=*/0, /*historical_block=*/block_num}; - ExecutionProcessor processor{block, *rule_set, buffer, *chain_config}; + ExecutionProcessor processor{block, *rule_set, buffer, *chain_config, {}}; processor.evm().analysis_cache = &analysis_cache; processor.evm().state_pool = &state_pool; diff --git a/cmd/dev/scan_txs.cpp b/cmd/dev/scan_txs.cpp index a0f5536f..f3945902 100644 --- a/cmd/dev/scan_txs.cpp +++ b/cmd/dev/scan_txs.cpp @@ -91,7 +91,7 @@ int main(int argc, char* argv[]) { db::Buffer buffer{txn, /*prune_history_threshold=*/0, /*historical_block=*/block_num}; - ExecutionProcessor processor{block, *rule_set, buffer, *chain_config}; + ExecutionProcessor processor{block, *rule_set, buffer, *chain_config, {}}; processor.evm().analysis_cache = &analysis_cache; processor.evm().state_pool = &state_pool; diff --git a/cmd/state-transition/state_transition.cpp b/cmd/state-transition/state_transition.cpp index bcee7c5d..ed2a609d 100644 --- a/cmd/state-transition/state_transition.cpp +++ b/cmd/state-transition/state_transition.cpp @@ -327,7 +327,7 @@ void StateTransition::run() { auto block = get_block(*state, config); auto txn = get_transaction(expectedSubState); - ExecutionProcessor processor{block, *ruleSet, *state, config}; + ExecutionProcessor processor{block, *ruleSet, *state, config, {}}; Receipt receipt; const evmc_revision rev{config.revision(block.header)}; diff --git a/cmd/test/ethereum.cpp b/cmd/test/ethereum.cpp index 42aa1e43..5b1e608e 100644 --- a/cmd/test/ethereum.cpp +++ b/cmd/test/ethereum.cpp @@ -254,7 +254,7 @@ RunResults blockchain_test(const nlohmann::json& json_test) { InMemoryState state; init_pre_state(json_test["pre"], state); - Blockchain blockchain{state, config, genesis_block}; + Blockchain blockchain{state, config, genesis_block, {}}; blockchain.state_pool = &execution_state_pool; blockchain.exo_evm = exo_evm; diff --git a/silkworm/core/chain/config.cpp b/silkworm/core/chain/config.cpp index d3cb53c9..d82fbb2d 100644 --- a/silkworm/core/chain/config.cpp +++ b/silkworm/core/chain/config.cpp @@ -196,13 +196,20 @@ evmc_revision ChainConfig::revision(const BlockHeader& header) const noexcept { if(protocol_rule_set != protocol::RuleSetType::kTrust) { return determine_revision_by_block(header.number, header.timestamp); } + auto evm_version = eos_evm_version(header); + return eosevm::version_to_evmc_revision(evm_version); +} + +uint64_t ChainConfig::eos_evm_version(const BlockHeader& header) const noexcept { uint64_t evm_version = 0; - if(header.number == 0) { - evm_version = _version.has_value() ? *_version : 0; - } else { - evm_version = eosevm::nonce_to_version(header.nonce); + if(protocol_rule_set == protocol::RuleSetType::kTrust) { + if(header.number == 0) { + evm_version = _version.has_value() ? *_version : 0; + } else { + evm_version = eosevm::nonce_to_version(header.nonce); + } } - return eosevm::version_to_evmc_revision(evm_version); + return evm_version; } std::vector ChainConfig::distinct_fork_numbers() const { diff --git a/silkworm/core/chain/config.hpp b/silkworm/core/chain/config.hpp index f6575ac7..1a0f3f60 100644 --- a/silkworm/core/chain/config.hpp +++ b/silkworm/core/chain/config.hpp @@ -176,6 +176,7 @@ struct ChainConfig { [[nodiscard]] evmc_revision determine_revision_by_block(uint64_t block_number, uint64_t block_time) const noexcept; [[nodiscard]] evmc_revision revision(const BlockHeader& header) const noexcept; + [[nodiscard]] uint64_t eos_evm_version(const BlockHeader& header) const noexcept; [[nodiscard]] std::vector distinct_fork_numbers() const; [[nodiscard]] std::vector distinct_fork_times() const; diff --git a/silkworm/core/common/test_util.hpp b/silkworm/core/common/test_util.hpp index ffd43cc1..f76ba8d7 100644 --- a/silkworm/core/common/test_util.hpp +++ b/silkworm/core/common/test_util.hpp @@ -61,6 +61,12 @@ inline constexpr ChainConfig kShanghaiConfig{ ._shanghai_time = 0, }; +inline constexpr ChainConfig kIstanbulTrustConfig{ + .chain_id = 15555, + .protocol_rule_set = protocol::RuleSetType::kTrust, + ._version = 1 +}; + static const std::map kNetworkConfig{ {"Frontier", test::kFrontierConfig}, {"Homestead", diff --git a/silkworm/core/execution/evm.cpp b/silkworm/core/execution/evm.cpp index ea8d7bcf..4834a6e0 100644 --- a/silkworm/core/execution/evm.cpp +++ b/silkworm/core/execution/evm.cpp @@ -61,12 +61,14 @@ class DelegatingTracer : public evmone::Tracer { IntraBlockState& intra_block_state_; }; -EVM::EVM(const Block& block, IntraBlockState& state, const ChainConfig& config) noexcept +EVM::EVM(const Block& block, IntraBlockState& state, const ChainConfig& config, const evmone::gas_parameters& gas_params) noexcept : beneficiary{block.header.beneficiary}, block_{block}, state_{state}, config_{config}, - evm1_{evmc_create_evmone()} {} + evm1_{evmc_create_evmone()}, + gas_params_{gas_params}, + eos_evm_version_{config.eos_evm_version(block.header)} { } EVM::~EVM() { evm1_->destroy(evm1_); } @@ -80,6 +82,7 @@ CallResult EVM::execute(const Transaction& txn, uint64_t gas) noexcept { const evmc_message message{ .kind = contract_creation ? EVMC_CREATE : EVMC_CALL, + .depth = 0, .gas = static_cast(gas), .recipient = destination, .sender = *txn.from, @@ -157,7 +160,7 @@ evmc::Result EVM::create(const evmc_message& message) noexcept { if (evm_res.status_code == EVMC_SUCCESS) { const size_t code_len{evm_res.output_size}; - const uint64_t code_deploy_gas{code_len * protocol::fee::kGCodeDeposit}; + const uint64_t code_deploy_gas{code_len * (eos_evm_version_ > 0 ? gas_params_.G_codedeposit : protocol::fee::kGCodeDeposit)}; if (rev >= EVMC_SPURIOUS_DRAGON && code_len > protocol::kMaxCodeSize) { // EIP-170: Contract code size limit @@ -213,6 +216,11 @@ evmc::Result EVM::call(const evmc_message& message) noexcept { const auto snapshot{state_.take_snapshot()}; + const evmc_revision rev{revision()}; + bool recipient_is_dead = !is_reserved_address(message.recipient) && + !precompile::is_precompile(message.recipient, rev) && + state_.is_dead(message.recipient); + if (message.kind == EVMC_CALL) { if (message.flags & EVMC_STATIC) { // Match geth logic @@ -224,8 +232,6 @@ evmc::Result EVM::call(const evmc_message& message) noexcept { } } - const evmc_revision rev{revision()}; - if (precompile::is_precompile(message.code_address, rev)) { static_assert(std::size(precompile::kContracts) < 256); const uint8_t num{message.code_address.bytes[kAddressLength - 1]}; @@ -251,13 +257,31 @@ evmc::Result EVM::call(const evmc_message& message) noexcept { tracer.get().on_execution_end(res.raw(),state_); } } else { - const ByteView code{state_.get_code(message.code_address)}; + + evmc_message revisted_message{message}; + if(eos_evm_version_ > 0 && revisted_message.depth == 0 && recipient_is_dead) { + if ((res.gas_left -= static_cast(gas_params_.G_txnewaccount)) < 0) { + // If we run out of gas lets do everything here + state_.revert_to_snapshot(snapshot); + res.status_code = EVMC_OUT_OF_GAS; + res.gas_refund = 0; + res.gas_left = 0; + for (auto tracer : tracers_) { + tracer.get().on_execution_start(rev, revisted_message, {}); + tracer.get().on_execution_end(res.raw(), state_); + } + return res; + } + revisted_message.gas = res.gas_left; + } + + const ByteView code{state_.get_code(revisted_message.code_address)}; if (code.empty() && tracers_.empty()) { // Do not skip execution if there are any tracers return res; } - const evmc::bytes32 code_hash{state_.get_code_hash(message.code_address)}; - res = evmc::Result{execute(message, code, &code_hash)}; + const evmc::bytes32 code_hash{state_.get_code_hash(revisted_message.code_address)}; + res = evmc::Result{execute(revisted_message, code, &code_hash)}; } if (res.status_code != EVMC_SUCCESS) { @@ -320,7 +344,9 @@ evmc_result EVM::execute_with_baseline_interpreter(evmc_revision rev, const evmc EvmHost host{*this}; gsl::owner state{acquire_state()}; - state->reset(msg, rev, host.get_interface(), host.to_context(), code); + + state->reset(msg, rev, host.get_interface(), host.to_context(), code, gas_params_); + state->eos_evm_version = eos_evm_version_; const auto vm{static_cast(evm1_)}; evmc_result res{evmone::baseline::execute(*vm, msg.gas, *state, *analysis)}; diff --git a/silkworm/core/execution/evm.hpp b/silkworm/core/execution/evm.hpp index 6b39decd..11caef15 100644 --- a/silkworm/core/execution/evm.hpp +++ b/silkworm/core/execution/evm.hpp @@ -72,7 +72,7 @@ class EVM { EVM(const EVM&) = delete; EVM& operator=(const EVM&) = delete; - EVM(const Block& block, IntraBlockState& state, const ChainConfig& config) + EVM(const Block& block, IntraBlockState& state, const ChainConfig& config, const evmone::gas_parameters& gas_params) noexcept; ~EVM(); @@ -103,6 +103,10 @@ class EVM { message_filter_ = message_filter; } + void update_gas_params(const evmone::gas_parameters& gas_params) { + gas_params_ = gas_params; + } + private: friend class EvmHost; @@ -127,6 +131,9 @@ class EVM { evmc_vm* evm1_{nullptr}; std::optional message_filter_; + + evmone::gas_parameters gas_params_; + uint64_t eos_evm_version_=0; }; class EvmHost : public evmc::Host { diff --git a/silkworm/core/execution/evm_test.cpp b/silkworm/core/execution/evm_test.cpp index 941bf09c..037801f6 100644 --- a/silkworm/core/execution/evm_test.cpp +++ b/silkworm/core/execution/evm_test.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "address.hpp" @@ -40,7 +41,7 @@ TEST_CASE("Value transfer") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; CHECK(state.get_balance(from) == 0); CHECK(state.get_balance(to) == 0); @@ -96,7 +97,7 @@ TEST_CASE("Smart contract with storage") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, test::kShanghaiConfig}; + EVM evm{block, state, test::kShanghaiConfig, {}}; Transaction txn{}; txn.from = caller; @@ -168,7 +169,7 @@ TEST_CASE("Maximum call depth") { IntraBlockState state{db}; state.set_code(contract, code); - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; AnalysisCache analysis_cache{/*maxSize=*/16}; evm.analysis_cache = &analysis_cache; @@ -227,7 +228,7 @@ TEST_CASE("DELEGATECALL") { state.set_code(caller_address, caller_code); state.set_code(callee_address, callee_code); - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; Transaction txn{}; txn.from = caller_address; @@ -288,7 +289,7 @@ TEST_CASE("CREATE should only return on failure") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; Transaction txn{}; txn.from = caller; @@ -320,7 +321,7 @@ TEST_CASE("Contract overwrite") { IntraBlockState state{db}; state.set_code(contract_address, old_code); - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; Transaction txn{}; txn.from = caller; @@ -343,7 +344,7 @@ TEST_CASE("EIP-3541: Reject new contracts starting with the 0xEF byte") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, config}; + EVM evm{block, state, config, {}}; Transaction txn; txn.from = 0x1000000000000000000000000000000000000000_address; @@ -465,7 +466,7 @@ TEST_CASE("Tracing smart contract with storage") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; Transaction txn{}; txn.from = caller; @@ -595,7 +596,7 @@ TEST_CASE("Tracing creation smart contract with CREATE2") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; Transaction txn{}; txn.from = caller; @@ -621,7 +622,7 @@ TEST_CASE("Tracing smart contract w/o code") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; CHECK(evm.tracers().empty()); TestTracer tracer1; @@ -682,7 +683,7 @@ TEST_CASE("Tracing precompiled contract failure") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, kMainnetConfig}; + EVM evm{block, state, kMainnetConfig, {}}; CHECK(evm.tracers().empty()); TestTracer tracer1; @@ -712,7 +713,7 @@ TEST_CASE("Smart contract creation w/ insufficient balance") { InMemoryState db; IntraBlockState state{db}; - EVM evm{block, state, test::kShanghaiConfig}; + EVM evm{block, state, test::kShanghaiConfig, {}}; Transaction txn{}; txn.from = caller; @@ -724,4 +725,68 @@ TEST_CASE("Smart contract creation w/ insufficient balance") { CHECK(res.status == EVMC_INSUFFICIENT_BALANCE); } +TEST_CASE("EOS EVM codedeposit test") { + Block block{}; + block.header.number = 1; + block.header.nonce = eosevm::version_to_nonce(1); + + evmc::address caller{0x0a6bb546b9208cfab9e8fa2b9b2c042b18df7030_address}; + Bytes code{*from_hex("608060405234801561001057600080fd5b50610173806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806313bdfacd14610030575b600080fd5b61003861004e565b604051610045919061011b565b60405180910390f35b60606040518060400160405280600c81526020017f48656c6c6f20576f726c64210000000000000000000000000000000000000000815250905090565b600081519050919050565b600082825260208201905092915050565b60005b838110156100c55780820151818401526020810190506100aa565b60008484015250505050565b6000601f19601f8301169050919050565b60006100ed8261008b565b6100f78185610096565b93506101078185602086016100a7565b610110816100d1565b840191505092915050565b6000602082019050818103600083015261013581846100e2565b90509291505056fea264697066735822122046344ce4c7e7c91dba98aef897cc7773af40fbff6b6da10885c36037b9d37a3764736f6c63430008110033")}; + + evmone::gas_parameters gas_params; + gas_params.G_codedeposit = 500; + + InMemoryState db; + IntraBlockState state{db}; + state.set_balance(caller, intx::uint256{1e18}); + EVM evm{block, state, test::kIstanbulTrustConfig, gas_params}; + + Transaction txn{}; + txn.from = caller; + txn.data = code; + + uint64_t gas = 1'500'000; + CallResult res = evm.execute(txn, 1'500'000); + CHECK(res.status == EVMC_SUCCESS); + CHECK(gas-res.gas_left == 123 + 500*371); //G_codedeposit=500, codelen=371 +} + +TEST_CASE("EOS EVM G_txnewaccount") { + Block block{}; + block.header.number = 1; + block.header.nonce = eosevm::version_to_nonce(1); + + evmc::address sender{0x0a6bb546b9208cfab9e8fa2b9b2c042b18df7030_address}; + evmc::address receiver{0x1a6bb546b9208cfab9e8fa2b9b2c042b18df7030_address}; + + evmone::gas_parameters gas_params; + gas_params.G_txnewaccount = 0; + + InMemoryState db; + IntraBlockState state{db}; + state.set_balance(sender, intx::uint256{1e18}); + EVM evm{block, state, test::kIstanbulTrustConfig, gas_params}; + + Transaction txn{}; + txn.from = sender; + txn.to = receiver; + txn.value = intx::uint256{0}; + + CallResult res = evm.execute(txn, 0); + CHECK(res.status == EVMC_SUCCESS); + CHECK(res.gas_left == 0); + CHECK(res.gas_refund == 0); + + gas_params.G_txnewaccount = 1; + evm.update_gas_params(gas_params); + + res = evm.execute(txn, 0); + CHECK(res.status == EVMC_OUT_OF_GAS); + CHECK(res.gas_refund == 0); + CHECK(res.gas_left == 0); + +} + + + } // namespace silkworm diff --git a/silkworm/core/execution/execution.hpp b/silkworm/core/execution/execution.hpp index a292915f..667844bb 100644 --- a/silkworm/core/execution/execution.hpp +++ b/silkworm/core/execution/execution.hpp @@ -41,12 +41,12 @@ namespace silkworm { * @param state The Ethereum state at the beginning of the block. */ [[nodiscard]] inline ValidationResult execute_block(const Block& block, State& state, - const ChainConfig& chain_config) noexcept { + const ChainConfig& chain_config, const evmone::gas_parameters& gas_params) noexcept { auto rule_set{protocol::rule_set_factory(chain_config)}; if (!rule_set) { return ValidationResult::kUnknownProtocolRuleSet; } - ExecutionProcessor processor{block, *rule_set, state, chain_config}; + ExecutionProcessor processor{block, *rule_set, state, chain_config, gas_params}; std::vector receipts; return processor.execute_and_write_block(receipts); } diff --git a/silkworm/core/execution/execution_test.cpp b/silkworm/core/execution/execution_test.cpp index b0aedc56..05f4514e 100644 --- a/silkworm/core/execution/execution_test.cpp +++ b/silkworm/core/execution/execution_test.cpp @@ -76,7 +76,7 @@ TEST_CASE("Execute two blocks") { // Execute first block // --------------------------------------- - REQUIRE(execute_block(block, state, test::kLondonConfig) == ValidationResult::kOk); + REQUIRE(execute_block(block, state, test::kLondonConfig, {}) == ValidationResult::kOk); auto contract_address{create_address(sender, /*nonce=*/0)}; std::optional contract_account{state.read_account(contract_address)}; @@ -114,7 +114,7 @@ TEST_CASE("Execute two blocks") { block.transactions[0].data = *from_hex(new_val); block.transactions[0].max_priority_fee_per_gas = 20 * kGiga; - REQUIRE(execute_block(block, state, test::kLondonConfig) == ValidationResult::kOk); + REQUIRE(execute_block(block, state, test::kLondonConfig, {}) == ValidationResult::kOk); storage0 = state.read_storage(contract_address, kDefaultIncarnation, storage_key0); CHECK(to_hex(storage0) == new_val); diff --git a/silkworm/core/execution/processor.cpp b/silkworm/core/execution/processor.cpp index 14858322..64b97de2 100644 --- a/silkworm/core/execution/processor.cpp +++ b/silkworm/core/execution/processor.cpp @@ -26,8 +26,8 @@ namespace silkworm { ExecutionProcessor::ExecutionProcessor(const Block& block, protocol::IRuleSet& rule_set, State& state, - const ChainConfig& config) - : state_{state}, rule_set_{rule_set}, evm_{block, state_, config} { + const ChainConfig& config, const evmone::gas_parameters& gas_params) + : state_{state}, rule_set_{rule_set}, evm_{block, state_, config, gas_params} { evm_.beneficiary = rule_set.get_beneficiary(block.header); } diff --git a/silkworm/core/execution/processor.hpp b/silkworm/core/execution/processor.hpp index b6c24a59..071dcbfc 100644 --- a/silkworm/core/execution/processor.hpp +++ b/silkworm/core/execution/processor.hpp @@ -33,7 +33,7 @@ class ExecutionProcessor { ExecutionProcessor(const ExecutionProcessor&) = delete; ExecutionProcessor& operator=(const ExecutionProcessor&) = delete; - ExecutionProcessor(const Block& block, protocol::IRuleSet& rule_set, State& state, const ChainConfig& config); + ExecutionProcessor(const Block& block, protocol::IRuleSet& rule_set, State& state, const ChainConfig& config, const evmone::gas_parameters& gas_params); /** * Execute a transaction, but do not write to the DB yet. diff --git a/silkworm/core/execution/processor_test.cpp b/silkworm/core/execution/processor_test.cpp index 36811271..7432ca38 100644 --- a/silkworm/core/execution/processor_test.cpp +++ b/silkworm/core/execution/processor_test.cpp @@ -46,7 +46,7 @@ TEST_CASE("Zero gas price") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, {}}; Receipt receipt; processor.execute_transaction(txn, receipt); @@ -86,7 +86,7 @@ TEST_CASE("No refund on error") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, {}}; Transaction txn{ {.nonce = nonce, @@ -181,7 +181,7 @@ TEST_CASE("Self-destruct") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, {}}; processor.evm().state().add_to_balance(originator, kEther); processor.evm().state().set_code(caller_address, caller_code); @@ -331,7 +331,7 @@ TEST_CASE("Out of Gas during account re-creation") { }; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, {}}; processor.evm().state().add_to_balance(caller, kEther); Receipt receipt; @@ -374,7 +374,7 @@ TEST_CASE("Empty suicide beneficiary") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, {}}; processor.evm().state().add_to_balance(caller, kEther); Receipt receipt; @@ -431,7 +431,7 @@ TEST_CASE("EVM message filter") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kEOSEVMMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kEOSEVMMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kEOSEVMMainnetConfig, {}}; Transaction txn{ {.nonce = nonce, @@ -535,7 +535,7 @@ TEST_CASE("EVM message filter revert") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kEOSEVMMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kEOSEVMMainnetConfig}; + ExecutionProcessor processor{block, *rule_set, state, kEOSEVMMainnetConfig, {}}; Transaction txn{ {.nonce = nonce, diff --git a/silkworm/core/protocol/blockchain.cpp b/silkworm/core/protocol/blockchain.cpp index fa400167..6f45edca 100644 --- a/silkworm/core/protocol/blockchain.cpp +++ b/silkworm/core/protocol/blockchain.cpp @@ -21,8 +21,8 @@ namespace silkworm::protocol { -Blockchain::Blockchain(State& state, const ChainConfig& config, const Block& genesis_block) - : state_{state}, config_{config}, rule_set_{rule_set_factory(config)} { +Blockchain::Blockchain(State& state, const ChainConfig& config, const Block& genesis_block, const evmone::gas_parameters& gas_params) + : state_{state}, config_{config}, rule_set_{rule_set_factory(config)}, gas_params_{gas_params} { prime_state_with_genesis(genesis_block); } @@ -91,7 +91,7 @@ ValidationResult Blockchain::insert_block(Block& block, bool check_state_root) { } ValidationResult Blockchain::execute_block(const Block& block, bool check_state_root) { - ExecutionProcessor processor{block, *rule_set_, state_, config_}; + ExecutionProcessor processor{block, *rule_set_, state_, config_, gas_params_}; processor.evm().state_pool = state_pool; processor.evm().exo_evm = exo_evm; diff --git a/silkworm/core/protocol/blockchain.hpp b/silkworm/core/protocol/blockchain.hpp index 3c86c998..27e3a4dc 100644 --- a/silkworm/core/protocol/blockchain.hpp +++ b/silkworm/core/protocol/blockchain.hpp @@ -40,7 +40,7 @@ class Blockchain { * In the beginning the state must have the genesis allocation. * Later on the state may only be modified by the created instance of Blockchain. */ - explicit Blockchain(State& state, const ChainConfig& config, const Block& genesis_block); + explicit Blockchain(State& state, const ChainConfig& config, const Block& genesis_block, const evmone::gas_parameters& gas_params); // Not copyable nor movable Blockchain(const Blockchain&) = delete; @@ -71,6 +71,7 @@ class Blockchain { RuleSetPtr rule_set_; std::unordered_map bad_blocks_; std::vector receipts_; + evmone::gas_parameters gas_params_; }; } // namespace silkworm::protocol diff --git a/silkworm/node/db/access_layer_test.cpp b/silkworm/node/db/access_layer_test.cpp index c67c76c7..2365bf91 100644 --- a/silkworm/node/db/access_layer_test.cpp +++ b/silkworm/node/db/access_layer_test.cpp @@ -585,19 +585,19 @@ TEST_CASE("Account") { block1.header.number = 1; block1.header.beneficiary = miner_a; // miner_a gets one block reward - REQUIRE(execute_block(block1, buffer, test::kFrontierConfig) == ValidationResult::kOk); + REQUIRE(execute_block(block1, buffer, test::kFrontierConfig, {}) == ValidationResult::kOk); Block block2; block2.header.number = 2; block2.header.beneficiary = miner_b; // miner_a gets nothing - REQUIRE(execute_block(block2, buffer, test::kFrontierConfig) == ValidationResult::kOk); + REQUIRE(execute_block(block2, buffer, test::kFrontierConfig, {}) == ValidationResult::kOk); Block block3; block3.header.number = 3; block3.header.beneficiary = miner_a; // miner_a gets another block reward - REQUIRE(execute_block(block3, buffer, test::kFrontierConfig) == ValidationResult::kOk); + REQUIRE(execute_block(block3, buffer, test::kFrontierConfig, {}) == ValidationResult::kOk); buffer.write_to_db(); db::stages::write_stage_progress(txn, db::stages::kExecutionKey, 3); diff --git a/silkworm/node/stagedsync/stages/_test.cpp b/silkworm/node/stagedsync/stages/_test.cpp index 1d070e30..b7bac313 100644 --- a/silkworm/node/stagedsync/stages/_test.cpp +++ b/silkworm/node/stagedsync/stages/_test.cpp @@ -304,7 +304,7 @@ TEST_CASE("Sync Stages") { // --------------------------------------- auto expected_validation_result{magic_enum::enum_name(ValidationResult::kOk)}; auto actual_validation_result{ - magic_enum::enum_name(execute_block(block, buffer, node_settings.chain_config.value()))}; + magic_enum::enum_name(execute_block(block, buffer, node_settings.chain_config.value(), {}))}; REQUIRE(expected_validation_result == actual_validation_result); auto contract_address{create_address(sender, /*nonce=*/0)}; @@ -325,7 +325,7 @@ TEST_CASE("Sync Stages") { block.transactions[0].data = ByteView(new_val); actual_validation_result = - magic_enum::enum_name(execute_block(block, buffer, node_settings.chain_config.value())); + magic_enum::enum_name(execute_block(block, buffer, node_settings.chain_config.value(), {})); REQUIRE(expected_validation_result == actual_validation_result); // --------------------------------------- @@ -342,7 +342,7 @@ TEST_CASE("Sync Stages") { block.transactions[0].data = ByteView{new_val}; actual_validation_result = - magic_enum::enum_name(execute_block(block, buffer, node_settings.chain_config.value())); + magic_enum::enum_name(execute_block(block, buffer, node_settings.chain_config.value(), {})); REQUIRE(expected_validation_result == actual_validation_result); REQUIRE_NOTHROW(buffer.write_to_db()); REQUIRE_NOTHROW(db::stages::write_stage_progress(txn, db::stages::kExecutionKey, 3)); diff --git a/silkworm/node/stagedsync/stages/stage_execution.cpp b/silkworm/node/stagedsync/stages/stage_execution.cpp index 70a3c617..c96449e4 100644 --- a/silkworm/node/stagedsync/stages/stage_execution.cpp +++ b/silkworm/node/stagedsync/stages/stage_execution.cpp @@ -238,7 +238,7 @@ Stage::Result Execution::execute_batch(db::RWTxn& txn, BlockNum max_block_num, A log_time = now + 5s; } - ExecutionProcessor processor(block, *rule_set_, buffer, node_settings_->chain_config.value()); + ExecutionProcessor processor(block, *rule_set_, buffer, node_settings_->chain_config.value(), get_gas_params(block)); processor.evm().analysis_cache = &analysis_cache; processor.evm().state_pool = &state_pool; @@ -627,5 +627,13 @@ void Execution::unwind_state_from_changeset(db::ROCursor& source_changeset, db:: revert_state(new_key, new_value, plain_state_table, plain_code_table); src_data = source_changeset.to_previous(/*throw_notfound*/ false); } + +} + +evmone::gas_parameters Execution::get_gas_params(const Block& block) const{ + //TODO: get gas params from db + (void)block; + return {}; } + } // namespace silkworm::stagedsync diff --git a/silkworm/node/stagedsync/stages/stage_execution.hpp b/silkworm/node/stagedsync/stages/stage_execution.hpp index d8716d27..65223d77 100644 --- a/silkworm/node/stagedsync/stages/stage_execution.hpp +++ b/silkworm/node/stagedsync/stages/stage_execution.hpp @@ -65,6 +65,8 @@ class Execution final : public Stage { static void revert_state(ByteView key, ByteView value, db::RWCursorDupSort& plain_state_table, db::RWCursor& plain_code_table); + evmone::gas_parameters get_gas_params(const Block& block) const; + // Stats std::mutex progress_mtx_; // Synchronizes access to progress stats std::chrono::time_point lap_time_{std::chrono::steady_clock::now()}; diff --git a/silkworm/node/stagedsync/stages/stage_history_index_test.cpp b/silkworm/node/stagedsync/stages/stage_history_index_test.cpp index 809f7aab..a8cba21e 100644 --- a/silkworm/node/stagedsync/stages/stage_history_index_test.cpp +++ b/silkworm/node/stagedsync/stages/stage_history_index_test.cpp @@ -83,7 +83,7 @@ TEST_CASE("Stage History Index") { // --------------------------------------- // Execute first block // --------------------------------------- - CHECK(execute_block(block, buffer, kMainnetConfig) == ValidationResult::kOk); + CHECK(execute_block(block, buffer, kMainnetConfig, {}) == ValidationResult::kOk); auto contract_address{create_address(sender, /*nonce=*/0)}; // --------------------------------------- @@ -102,7 +102,7 @@ TEST_CASE("Stage History Index") { block.transactions[0].to = contract_address; block.transactions[0].data = *from_hex(new_val); - CHECK(execute_block(block, buffer, kMainnetConfig) == ValidationResult::kOk); + CHECK(execute_block(block, buffer, kMainnetConfig, {}) == ValidationResult::kOk); // --------------------------------------- // Execute third block @@ -120,7 +120,7 @@ TEST_CASE("Stage History Index") { block.transactions[0].to = contract_address; block.transactions[0].data = *from_hex(new_val); - CHECK(execute_block(block, buffer, kMainnetConfig) == ValidationResult::kOk); + CHECK(execute_block(block, buffer, kMainnetConfig, {}) == ValidationResult::kOk); buffer.write_to_db(); db::stages::write_stage_progress(txn, db::stages::kExecutionKey, 3); diff --git a/silkworm/silkrpc/core/evm_executor.cpp b/silkworm/silkrpc/core/evm_executor.cpp index 41a111b0..b6fd2667 100644 --- a/silkworm/silkrpc/core/evm_executor.cpp +++ b/silkworm/silkrpc/core/evm_executor.cpp @@ -227,7 +227,8 @@ ExecutionResult EVMExecutor::call( SILK_DEBUG << "EVMExecutor::call: transaction: " << &txn; auto& svc = use_service(workers_); - EVM evm{block, ibs_state_, config_}; + //TODO: get gas parameters + 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); diff --git a/third_party/evmone b/third_party/evmone index 159160b0..9b9d6529 160000 --- a/third_party/evmone +++ b/third_party/evmone @@ -1 +1 @@ -Subproject commit 159160b084af21de863c2889354e14be9d16ba72 +Subproject commit 9b9d6529289692288369cd1351d17832ee2dd047