Skip to content

Commit

Permalink
Use refund value returned from EVMC instead of calculating in Host
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed Sep 5, 2022
1 parent ed5484e commit 3c70fa4
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 71 deletions.
79 changes: 29 additions & 50 deletions core/silkworm/execution/evm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ CallResult EVM::execute(const Transaction& txn, uint64_t gas) noexcept {

evmc::Result res{contract_creation ? create(message) : call(message)};

return {res.status_code, static_cast<uint64_t>(res.gas_left), {res.output_data, res.output_size}};
const auto gas_left = static_cast<uint64_t>(res.gas_left);
const auto gas_refund = static_cast<uint64_t>(res.gas_refund);
return {res.status_code, gas_left, gas_refund, {res.output_data, res.output_size}};
}

evmc::Result EVM::create(const evmc_message& message) noexcept {
Expand Down Expand Up @@ -248,6 +250,7 @@ evmc::Result EVM::call(const evmc_message& message) noexcept {
state_.revert_to_snapshot(snapshot);
if (res.status_code != EVMC_REVERT) {
res.gas_left = 0;
res.gas_refund = 0;
}
}

Expand Down Expand Up @@ -403,69 +406,45 @@ evmc_storage_status EvmHost::set_storage(const evmc::address& address, const evm

evm_.state().set_storage(address, key, new_val);

const evmc_revision rev{evm_.revision()};
const bool eip1283{rev >= EVMC_ISTANBUL || rev == EVMC_CONSTANTINOPLE};

if (!eip1283) {
if (is_zero(current_val)) {
return EVMC_STORAGE_ADDED;
}

if (is_zero(new_val)) {
evm_.state().add_refund(fee::kRSClear);
return EVMC_STORAGE_DELETED;
}

return EVMC_STORAGE_MODIFIED;
}

const uint64_t sload_cost{[rev]() {
if (rev >= EVMC_BERLIN) {
return fee::kWarmStorageReadCost;
} else if (rev >= EVMC_ISTANBUL) {
return fee::kGSLoadIstanbul;
} else {
return fee::kGSLoadTangerineWhistle;
}
}()};

uint64_t sstore_reset_gas{fee::kGSReset};
if (rev >= EVMC_BERLIN) {
sstore_reset_gas -= fee::kColdSloadCost;
}

// https://eips.ethereum.org/EIPS/eip-1283
const evmc::bytes32 original_val{evm_.state().get_original_storage(address, key)};

// https://eips.ethereum.org/EIPS/eip-3529
const uint64_t sstore_clears_refund{rev >= EVMC_LONDON ? sstore_reset_gas + fee::kAccessListStorageKeyCost
: fee::kRSClear};

if (original_val == current_val) {
if (is_zero(original_val)) {
return EVMC_STORAGE_ADDED;
} else {
if (is_zero(new_val)) {
return EVMC_STORAGE_DELETED;
} else {
return EVMC_STORAGE_MODIFIED;
}
}
if (is_zero(new_val)) {
evm_.state().add_refund(sstore_clears_refund);
}
return EVMC_STORAGE_MODIFIED;
} else {
} else { // original_val != current_val
if (!is_zero(original_val)) {
if (is_zero(current_val)) {
evm_.state().subtract_refund(sstore_clears_refund);
if (original_val == new_val) {
return EVMC_STORAGE_DELETED_RESTORED;
} else {
return EVMC_STORAGE_DELETED_ADDED;
}
}
// !is_zero(current_val)
if (is_zero(new_val)) {
evm_.state().add_refund(sstore_clears_refund);
return EVMC_STORAGE_MODIFIED_DELETED;
} else {
if (original_val == new_val) {
return EVMC_STORAGE_MODIFIED_RESTORED;
} else {
return EVMC_STORAGE_ASSIGNED;
}
}
}
// is_zero(original_val)
if (original_val == new_val) {
if (is_zero(original_val)) {
evm_.state().add_refund(fee::kGSSet - sload_cost);
} else {
evm_.state().add_refund(sstore_reset_gas - sload_cost);
}
return EVMC_STORAGE_ADDED_DELETED;
} else {
return EVMC_STORAGE_ASSIGNED;
}
return EVMC_STORAGE_ASSIGNED;
}
}

Expand Down Expand Up @@ -515,7 +494,7 @@ evmc::Result EvmHost::call(const evmc_message& message) noexcept {
// geth returns CREATE output only in case of REVERT
return res;
} else {
evmc::Result res_with_no_output{res.status_code, res.gas_left};
evmc::Result res_with_no_output{res.status_code, res.gas_left, res.gas_refund};
res_with_no_output.create_address = res.create_address;
return res_with_no_output;
}
Expand Down
1 change: 1 addition & 0 deletions core/silkworm/execution/evm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace silkworm {
struct CallResult {
evmc_status_code status{EVMC_SUCCESS};
uint64_t gas_left{0};
uint64_t gas_refund{0};
Bytes data;
};

Expand Down
4 changes: 3 additions & 1 deletion core/silkworm/execution/evm_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,9 @@ class TestTracer : public EvmTracer {
}
void on_execution_end(const evmc_result& res, const IntraBlockState& intra_block_state) noexcept override {
execution_end_called_ = true;
result_ = {res.status_code, static_cast<uint64_t>(res.gas_left), {res.output_data, res.output_size}};
const auto gas_left = static_cast<uint64_t>(res.gas_left);
const auto gas_refund = static_cast<uint64_t>(res.gas_refund);
result_ = {res.status_code, gas_left, gas_refund, {res.output_data, res.output_size}};
if (contract_address_ && pc_stack_.size() > 0) {
const auto pc = pc_stack_.back();
storage_stack_[pc] =
Expand Down
10 changes: 4 additions & 6 deletions core/silkworm/execution/processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void ExecutionProcessor::execute_transaction(const Transaction& txn, Receipt& re

const CallResult vm_res{evm_.execute(txn, txn.gas_limit - static_cast<uint64_t>(g0))};

const uint64_t gas_used{txn.gas_limit - refund_gas(txn, vm_res.gas_left)};
const uint64_t gas_used{txn.gas_limit - refund_gas(txn, vm_res.gas_left, vm_res.gas_refund)};

// award the fee recipient
const intx::uint256 priority_fee_per_gas{txn.priority_fee_per_gas(base_fee_per_gas)};
Expand All @@ -127,12 +127,10 @@ uint64_t ExecutionProcessor::available_gas() const noexcept {
return evm_.block().header.gas_limit - cumulative_gas_used_;
}

uint64_t ExecutionProcessor::refund_gas(const Transaction& txn, uint64_t gas_left) noexcept {
uint64_t ExecutionProcessor::refund_gas(const Transaction& txn, uint64_t gas_left, uint64_t gas_refund) noexcept {
const evmc_revision rev{evm_.revision()};
uint64_t refund{state_.get_refund()};
if (rev < EVMC_LONDON) {
refund += fee::kRSelfDestruct * state_.number_of_self_destructs();
}
uint64_t refund{gas_refund};

const uint64_t max_refund_quotient{rev >= EVMC_LONDON ? param::kMaxRefundQuotientLondon
: param::kMaxRefundQuotientFrontier};
const uint64_t max_refund{(txn.gas_limit - gas_left) / max_refund_quotient};
Expand Down
2 changes: 1 addition & 1 deletion core/silkworm/execution/processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ExecutionProcessor {
[[nodiscard]] ValidationResult execute_block_no_post_validation(std::vector<Receipt>& receipts) noexcept;

uint64_t available_gas() const noexcept;
uint64_t refund_gas(const Transaction& txn, uint64_t gas_left) noexcept;
uint64_t refund_gas(const Transaction& txn, uint64_t gas_left, uint64_t refund_gas) noexcept;

uint64_t cumulative_gas_used_{0};
IntraBlockState state_;
Expand Down
7 changes: 0 additions & 7 deletions core/silkworm/state/intra_block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,6 @@ IntraBlockState::Snapshot IntraBlockState::take_snapshot() const noexcept {
IntraBlockState::Snapshot snapshot;
snapshot.journal_size_ = journal_.size();
snapshot.log_size_ = logs_.size();
snapshot.refund_ = refund_;
return snapshot;
}

Expand All @@ -348,7 +347,6 @@ void IntraBlockState::revert_to_snapshot(const IntraBlockState::Snapshot& snapsh
}
journal_.resize(snapshot.journal_size_);
logs_.resize(snapshot.log_size_);
refund_ = snapshot.refund_;
}

void IntraBlockState::finalize_transaction() {
Expand All @@ -368,16 +366,11 @@ void IntraBlockState::clear_journal_and_substate() {
self_destructs_.clear();
logs_.clear();
touched_.clear();
refund_ = 0;
// EIP-2929
accessed_addresses_.clear();
accessed_storage_keys_.clear();
}

void IntraBlockState::add_log(const Log& log) noexcept { logs_.push_back(log); }

void IntraBlockState::add_refund(uint64_t addend) noexcept { refund_ += addend; }

void IntraBlockState::subtract_refund(uint64_t subtrahend) noexcept { refund_ -= subtrahend; }

} // namespace silkworm
6 changes: 0 additions & 6 deletions core/silkworm/state/intra_block_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class IntraBlockState {

size_t journal_size_{0};
size_t log_size_{0};
uint64_t refund_{0};
};

IntraBlockState(const IntraBlockState&) = delete;
Expand Down Expand Up @@ -109,11 +108,6 @@ class IntraBlockState {
std::vector<Log>& logs() noexcept { return logs_; }
const std::vector<Log>& logs() const noexcept { return logs_; }

void add_refund(uint64_t addend) noexcept;
void subtract_refund(uint64_t subtrahend) noexcept;

uint64_t get_refund() const noexcept { return refund_; }

const FlatHashSet<evmc::address>& touched() const noexcept { return touched_; }

private:
Expand Down

0 comments on commit 3c70fa4

Please sign in to comment.