From cb4e20aa2a07e355935306a962b562ad83d79fde Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 18 Jul 2019 23:12:29 +0100 Subject: [PATCH] Introduce particle gas costs for Istanbul --- lib/evmone/analysis.cpp | 15 +++++++++++++-- lib/evmone/analysis.hpp | 2 ++ lib/evmone/execution.cpp | 6 ++++++ lib/evmone/instructions.cpp | 8 ++++++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/evmone/analysis.cpp b/lib/evmone/analysis.cpp index 3089cf6890..54c4555cf8 100644 --- a/lib/evmone/analysis.cpp +++ b/lib/evmone/analysis.cpp @@ -50,6 +50,15 @@ evmc_call_kind op2call_kind(uint8_t opcode) noexcept code_analysis analyze( const exec_fn_table& fns, evmc_revision rev, const uint8_t* code, size_t code_size) noexcept { + // FIXME: change to an if outside + static auto to_gas_cost = [&](int64_t gas_cost) + { + if (rev >= EVMC_ISTANBUL) + return static_cast(gas_cost / particles_per_gas); + else + return static_cast(gas_cost); + }; + code_analysis analysis; // TODO: Check if final result exceeds the reservation. analysis.instrs.reserve(code_size + 1); @@ -113,11 +122,13 @@ code_analysis analyze( else if (c >= OP_SWAP1 && c <= OP_SWAP16) instr.arg.p.number = c - OP_SWAP1 + 1; else if (c == OP_GAS) - instr.arg.p.number = static_cast(block->gas_cost); + { + instr.arg.p.number = to_gas_cost(block->gas_cost); + } else if (c == OP_DELEGATECALL || c == OP_CALL || c == OP_CALLCODE || c == OP_STATICCALL || c == OP_CREATE || c == OP_CREATE2) { - instr.arg.p.number = static_cast(block->gas_cost); + instr.arg.p.number = to_gas_cost(block->gas_cost); instr.arg.p.call_kind = op2call_kind(c == OP_STATICCALL ? uint8_t{OP_CALL} : c); } else if (c == OP_PC) diff --git a/lib/evmone/analysis.hpp b/lib/evmone/analysis.hpp index 037ae013b1..a328422a90 100644 --- a/lib/evmone/analysis.hpp +++ b/lib/evmone/analysis.hpp @@ -32,6 +32,8 @@ static_assert(continue_status == 0, "The 'continue' status is not 0"); /// The EVMC_INTERNAL_ERROR MUST NOT be used in evmone for any other case. constexpr auto stop_status = EVMC_INTERNAL_ERROR; +constexpr unsigned particles_per_gas = 1000; + /// The stack for 256-bit EVM words. /// /// This implementation reserves memory inplace for all possible stack items (1024), diff --git a/lib/evmone/execution.cpp b/lib/evmone/execution.cpp index af5169a460..c46b3b7a17 100644 --- a/lib/evmone/execution.cpp +++ b/lib/evmone/execution.cpp @@ -28,6 +28,8 @@ evmc_result execute(evmc_instance*, evmc_context* ctx, evmc_revision rev, const state->host = evmc::HostContext{ctx}; state->gas_left = msg->gas; state->rev = rev; + if (rev >= EVMC_ISTANBUL) + state->gas_left *= particles_per_gas; while (state->status == continue_status) { auto& instr = analysis.instrs[state->pc]; @@ -44,7 +46,11 @@ evmc_result execute(evmc_instance*, evmc_context* ctx, evmc_revision rev, const result.status_code = state->status != stop_status ? state->status : continue_status; if (result.status_code == EVMC_SUCCESS || result.status_code == EVMC_REVERT) + { result.gas_left = state->gas_left; + if (rev >= EVMC_ISTANBUL) + result.gas_left /= particles_per_gas; + } if (state->output_size > 0) { diff --git a/lib/evmone/instructions.cpp b/lib/evmone/instructions.cpp index f12390c1b6..271b712baf 100644 --- a/lib/evmone/instructions.cpp +++ b/lib/evmone/instructions.cpp @@ -37,8 +37,9 @@ bool check_memory(execution_state& state, const uint256& offset, const uint256& const auto new_size = o + s; if (m < new_size) { + auto cost_per_word = (state.rev >= EVMC_ISTANBUL) ? 3 : 3 * particles_per_gas; auto w = (new_size + 31) / 32; - auto new_cost = 3 * w + w * w / 512; + auto new_cost = cost_per_word * w + w * w / 512; auto cost = new_cost - state.memory_prev_cost; state.memory_prev_cost = new_cost; @@ -514,7 +515,10 @@ void op_gas(execution_state& state, instr_argument arg) noexcept { const auto correction = state.current_block_cost - arg.p.number; const auto gas = static_cast(state.gas_left + correction); - state.stack.push(gas); + if (state.rev >= EVMC_ISTANBUL) + state.stack.push(gas / particles_per_gas); + else + state.stack.push(gas); } void op_gasprice(execution_state& state, instr_argument) noexcept