Skip to content

Commit

Permalink
Merge pull request #492 from ethereum/instructions_storage
Browse files Browse the repository at this point in the history
Move storage instructions implementations to .cpp
  • Loading branch information
chfast authored Aug 18, 2022
2 parents cc6b692 + 5350ed2 commit 08c97c8
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 90 deletions.
1 change: 1 addition & 0 deletions lib/evmone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_library(evmone
eof.hpp
instructions.hpp
instructions_calls.cpp
instructions_storage.cpp
instructions_traits.hpp
instructions_xmacro.hpp
opcodes_helpers.h
Expand Down
92 changes: 2 additions & 90 deletions lib/evmone/instructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,97 +670,9 @@ inline evmc_status_code mstore8(StackTop stack, ExecutionState& state) noexcept
return EVMC_SUCCESS;
}

inline evmc_status_code sload(StackTop stack, ExecutionState& state) noexcept
{
auto& x = stack.top();
const auto key = intx::be::store<evmc::bytes32>(x);

if (state.rev >= EVMC_BERLIN &&
state.host.access_storage(state.msg->recipient, key) == EVMC_ACCESS_COLD)
{
// The warm storage access cost is already applied (from the cost table).
// Here we need to apply additional cold storage access cost.
constexpr auto additional_cold_sload_cost =
instr::cold_sload_cost - instr::warm_storage_read_cost;
if ((state.gas_left -= additional_cold_sload_cost) < 0)
return EVMC_OUT_OF_GAS;
}

x = intx::be::load<uint256>(state.host.get_storage(state.msg->recipient, key));

return EVMC_SUCCESS;
}

inline evmc_status_code sstore(StackTop stack, ExecutionState& state) noexcept
{
if (state.in_static_mode())
return EVMC_STATIC_MODE_VIOLATION;

if (state.rev >= EVMC_ISTANBUL && state.gas_left <= 2300)
return EVMC_OUT_OF_GAS;
evmc_status_code sload(StackTop stack, ExecutionState& state) noexcept;

const auto key = intx::be::store<evmc::bytes32>(stack.pop());
const auto value = intx::be::store<evmc::bytes32>(stack.pop());

int cost = 0;
if (state.rev >= EVMC_BERLIN &&
state.host.access_storage(state.msg->recipient, key) == EVMC_ACCESS_COLD)
cost = instr::cold_sload_cost;

const auto status = state.host.set_storage(state.msg->recipient, key, value);

if (state.rev <= EVMC_BYZANTIUM || state.rev == EVMC_PETERSBURG) // legacy
{
switch (status)
{
case EVMC_STORAGE_ASSIGNED:
case EVMC_STORAGE_MODIFIED_DELETED:
case EVMC_STORAGE_ADDED_DELETED:
case EVMC_STORAGE_MODIFIED_RESTORED:
case EVMC_STORAGE_MODIFIED:
case EVMC_STORAGE_DELETED:
cost = 5000;
break;
case EVMC_STORAGE_ADDED:
case EVMC_STORAGE_DELETED_ADDED:
case EVMC_STORAGE_DELETED_RESTORED:
cost = 20000;
break;
}
}
else // net gas cost metering
{
switch (status)
{
case EVMC_STORAGE_ASSIGNED:
case EVMC_STORAGE_DELETED_ADDED:
case EVMC_STORAGE_DELETED_RESTORED:
case EVMC_STORAGE_MODIFIED_DELETED:
case EVMC_STORAGE_ADDED_DELETED:
case EVMC_STORAGE_MODIFIED_RESTORED:
if (state.rev >= EVMC_BERLIN)
cost += instr::warm_storage_read_cost;
else if (state.rev == EVMC_ISTANBUL)
cost = 800;
else
cost = 200; // Constantinople
break;
case EVMC_STORAGE_MODIFIED:
case EVMC_STORAGE_DELETED:
if (state.rev >= EVMC_BERLIN)
cost += 5000 - instr::cold_sload_cost;
else
cost = 5000;
break;
case EVMC_STORAGE_ADDED:
cost += 20000;
break;
}
}
if ((state.gas_left -= cost) < 0)
return EVMC_OUT_OF_GAS;
return EVMC_SUCCESS;
}
evmc_status_code sstore(StackTop stack, ExecutionState& state) noexcept;

/// Internal jump implementation for JUMP/JUMPI instructions.
inline code_iterator jump_impl(ExecutionState& state, const uint256& dst) noexcept
Expand Down
100 changes: 100 additions & 0 deletions lib/evmone/instructions_storage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2019 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include "instructions.hpp"

namespace evmone::instr::core
{
evmc_status_code sload(StackTop stack, ExecutionState& state) noexcept
{
auto& x = stack.top();
const auto key = intx::be::store<evmc::bytes32>(x);

if (state.rev >= EVMC_BERLIN &&
state.host.access_storage(state.msg->recipient, key) == EVMC_ACCESS_COLD)
{
// The warm storage access cost is already applied (from the cost table).
// Here we need to apply additional cold storage access cost.
constexpr auto additional_cold_sload_cost =
instr::cold_sload_cost - instr::warm_storage_read_cost;
if ((state.gas_left -= additional_cold_sload_cost) < 0)
return EVMC_OUT_OF_GAS;
}

x = intx::be::load<uint256>(state.host.get_storage(state.msg->recipient, key));

return EVMC_SUCCESS;
}

evmc_status_code sstore(StackTop stack, ExecutionState& state) noexcept
{
if (state.in_static_mode())
return EVMC_STATIC_MODE_VIOLATION;

if (state.rev >= EVMC_ISTANBUL && state.gas_left <= 2300)
return EVMC_OUT_OF_GAS;

const auto key = intx::be::store<evmc::bytes32>(stack.pop());
const auto value = intx::be::store<evmc::bytes32>(stack.pop());

int cost = 0;
if (state.rev >= EVMC_BERLIN &&
state.host.access_storage(state.msg->recipient, key) == EVMC_ACCESS_COLD)
cost = instr::cold_sload_cost;

const auto status = state.host.set_storage(state.msg->recipient, key, value);

if (state.rev <= EVMC_BYZANTIUM || state.rev == EVMC_PETERSBURG) // legacy
{
switch (status)
{
case EVMC_STORAGE_ASSIGNED:
case EVMC_STORAGE_MODIFIED_DELETED:
case EVMC_STORAGE_ADDED_DELETED:
case EVMC_STORAGE_MODIFIED_RESTORED:
case EVMC_STORAGE_MODIFIED:
case EVMC_STORAGE_DELETED:
cost = 5000;
break;
case EVMC_STORAGE_ADDED:
case EVMC_STORAGE_DELETED_ADDED:
case EVMC_STORAGE_DELETED_RESTORED:
cost = 20000;
break;
}
}
else // net gas cost metering
{
switch (status)
{
case EVMC_STORAGE_ASSIGNED:
case EVMC_STORAGE_DELETED_ADDED:
case EVMC_STORAGE_DELETED_RESTORED:
case EVMC_STORAGE_MODIFIED_DELETED:
case EVMC_STORAGE_ADDED_DELETED:
case EVMC_STORAGE_MODIFIED_RESTORED:
if (state.rev >= EVMC_BERLIN)
cost += instr::warm_storage_read_cost;
else if (state.rev == EVMC_ISTANBUL)
cost = 800;
else
cost = 200; // Constantinople
break;
case EVMC_STORAGE_MODIFIED:
case EVMC_STORAGE_DELETED:
if (state.rev >= EVMC_BERLIN)
cost += 5000 - instr::cold_sload_cost;
else
cost = 5000;
break;
case EVMC_STORAGE_ADDED:
cost += 20000;
break;
}
}
if ((state.gas_left -= cost) < 0)
return EVMC_OUT_OF_GAS;
return EVMC_SUCCESS;
}
} // namespace evmone::instr::core

0 comments on commit 08c97c8

Please sign in to comment.