Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add final refund in processor #215

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/dev/check_changes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ int main(int argc, char* argv[]) {
processor.evm().analysis_cache = &analysis_cache;
processor.evm().state_pool = &state_pool;

if (const auto res{processor.execute_and_write_block(receipts)}; res != ValidationResult::kOk) {
if (const auto res{processor.execute_and_write_block(receipts, {})}; res != ValidationResult::kOk) {
log::Error() << "Failed to execute block " << block_num;
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/dev/scan_txs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ int main(int argc, char* argv[]) {
processor.evm().state_pool = &state_pool;

// Execute the block and retrieve the receipts
if (const auto res{processor.execute_and_write_block(receipts)}; res != ValidationResult::kOk) {
if (const auto res{processor.execute_and_write_block(receipts, {})}; res != ValidationResult::kOk) {
std::cerr << "Validation error " << static_cast<int>(res) << " at block " << block_num << "\n";
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/state-transition/state_transition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ void StateTransition::run() {
block_validation == ValidationResult::kOk &&
pre_txn_validation == ValidationResult::kOk &&
txn_validation == ValidationResult::kOk) {
processor.execute_transaction(txn, receipt);
processor.execute_transaction(txn, receipt, {});
processor.evm().state().write_to_db(block.header.number);
} else {
cleanup_error_block(block, processor, rev);
Expand Down
2 changes: 1 addition & 1 deletion cmd/test/ethereum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions eosevm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ set(EOS_EVM_PUBLIC_LIBS
evmc
tl::expected
nlohmann_json::nlohmann_json
evmone
Microsoft.GSL::GSL
)

target_link_libraries(
Expand Down
64 changes: 64 additions & 0 deletions eosevm/refund_v3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "refund_v3.hpp"

namespace eosevm {

std::tuple<silkworm::ExecutionResult, intx::uint256, uint64_t, uint64_t> gas_refund_v3(uint64_t eos_evm_version, const silkworm::CallResult& vm_res, const silkworm::Transaction& txn,
const evmone::gas_parameters scaled_gas_params, const intx::uint256& price, const silkworm::gas_prices_t& gas_prices, const intx::uint256& inclusion_price) {

uint64_t storage_gas_consumed{vm_res.storage_gas_consumed};
const bool contract_creation{!txn.to};
auto gas_left = vm_res.gas_left;
if(contract_creation) {
if( vm_res.status == EVMC_SUCCESS ) {
storage_gas_consumed += scaled_gas_params.G_txcreate; //correct storage gas consumed to account for initial G_txcreate storage gas
} else {
gas_left += scaled_gas_params.G_txcreate;
}
}

evmone::gas_state_t vm_res_gas_state(eos_evm_version, static_cast<int64_t>(vm_res.gas_refund),
static_cast<int64_t>(storage_gas_consumed), static_cast<int64_t>(vm_res.storage_gas_refund), static_cast<int64_t>(vm_res.speculative_cpu_gas_consumed));

gas_left += static_cast<uint64_t>(vm_res_gas_state.collapse());
auto gas_used = txn.gas_limit - gas_left;
assert(vm_res_gas_state.cpu_gas_refund() == 0);
const auto total_storage_gas_consumed = static_cast<uint64_t>(vm_res_gas_state.storage_gas_consumed());
assert(gas_used > total_storage_gas_consumed);
const auto total_cpu_gas_consumed = gas_used - total_storage_gas_consumed;

silkworm::ExecutionResult res;
res.cpu_gas_consumed = total_cpu_gas_consumed;
res.discounted_storage_gas_consumed = static_cast<uint64_t>(total_storage_gas_consumed);
res.inclusion_fee = intx::uint256(total_cpu_gas_consumed)*inclusion_price;
res.storage_fee = intx::uint256(total_storage_gas_consumed)*price;

auto final_fee = price * gas_used;
if(gas_prices.storage_price >= gas_prices.overhead_price) {
intx::uint256 gas_refund = intx::uint256(total_cpu_gas_consumed);
gas_refund *= intx::uint256(gas_prices.storage_price-gas_prices.overhead_price);
gas_refund /= price;

SILKWORM_ASSERT(gas_refund <= gas_used);
gas_left += static_cast<uint64_t>(gas_refund);
assert(txn.gas_limit >= gas_left);
gas_used = txn.gas_limit - gas_left;
SILKWORM_ASSERT(gas_used >= total_storage_gas_consumed);
final_fee = price * gas_used;

assert(final_fee >= res.storage_fee);
const auto overhead_and_inclusion_fee = final_fee - res.storage_fee;
if( overhead_and_inclusion_fee >= res.inclusion_fee ) {
res.overhead_fee = overhead_and_inclusion_fee - res.inclusion_fee;
} else {
res.inclusion_fee = overhead_and_inclusion_fee;
res.overhead_fee = 0;
}
} else {
res.overhead_fee = final_fee - res.inclusion_fee - res.storage_fee;
}

assert(final_fee == res.inclusion_fee + res.storage_fee + res.overhead_fee);
return std::make_tuple(res, final_fee, gas_used, gas_left);
}

} // namespace eosevm
11 changes: 11 additions & 0 deletions eosevm/refund_v3.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <silkworm/core/execution/evm.hpp>
#include <silkworm/core/types/gas_prices.hpp>

namespace eosevm {

std::tuple<silkworm::ExecutionResult, intx::uint256, uint64_t, uint64_t> gas_refund_v3(uint64_t eos_evm_version, const silkworm::CallResult& vm_res, const silkworm::Transaction& txn,
const evmone::gas_parameters scaled_gas_params, const intx::uint256& price, const silkworm::gas_prices_t& gas_prices, const intx::uint256& inclusion_price);

} // namespace eosevm
1 change: 1 addition & 0 deletions silkworm/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set(SILKWORM_CORE_PUBLIC_LIBS
nlohmann_json::nlohmann_json
secp256k1
tl::expected
eos_evm
)
set(SILKWORM_CORE_PRIVATE_LIBS ff blst)

Expand Down
6 changes: 3 additions & 3 deletions silkworm/core/execution/evm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,19 @@ class DelegatingTracer : public evmone::Tracer {
IntraBlockState& intra_block_state_;
};

EVM::EVM(const Block& block, IntraBlockState& state, const ChainConfig& config, const evmone::gas_parameters& gas_params) noexcept
EVM::EVM(const Block& block, IntraBlockState& state, const ChainConfig& config) noexcept
: beneficiary{block.header.beneficiary},
block_{block},
state_{state},
config_{config},
evm1_{evmc_create_evmone()},
gas_params_{gas_params},
eos_evm_version_{config.eos_evm_version(block.header)} { }

EVM::~EVM() { evm1_->destroy(evm1_); }

CallResult EVM::execute(const Transaction& txn, uint64_t gas) noexcept {
CallResult EVM::execute(const Transaction& txn, uint64_t gas, const evmone::gas_parameters& gas_params) noexcept {
assert(txn.from.has_value()); // sender must be recovered
gas_params_ = gas_params;

txn_ = &txn;

Expand Down
20 changes: 10 additions & 10 deletions silkworm/core/execution/evm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
#include <silkworm/core/types/block.hpp>

namespace silkworm {
struct ExecutionResult {
// inclusion_fee+overhead_fee+storage_fee == receipt.cumulative_gas_used*effective_price
uint64_t discounted_storage_gas_consumed{0};
uint64_t cpu_gas_consumed{0};
intx::uint256 overhead_fee; //approx. => cpu_gas_consumed * overhead_price
intx::uint256 inclusion_fee; //approx. => cpu_gas_consumed * inclusion_price
intx::uint256 storage_fee; //exactly => discounted_storage_gas_consumed * effective_price
};

struct CallResult {
evmc_status_code status{EVMC_SUCCESS};
Expand Down Expand Up @@ -75,7 +83,7 @@ class EVM {
EVM(const EVM&) = delete;
EVM& operator=(const EVM&) = delete;

EVM(const Block& block, IntraBlockState& state, const ChainConfig& config, const evmone::gas_parameters& gas_params)
EVM(const Block& block, IntraBlockState& state, const ChainConfig& config)
noexcept;

~EVM();
Expand All @@ -88,7 +96,7 @@ class EVM {
[[nodiscard]] const IntraBlockState& state() const noexcept { return state_; }

// Precondition: txn.from must be recovered
CallResult execute(const Transaction& txn, uint64_t gas) noexcept;
CallResult execute(const Transaction& txn, uint64_t gas, const evmone::gas_parameters& gas_params) noexcept;

[[nodiscard]] evmc_revision revision() const noexcept;

Expand All @@ -108,14 +116,6 @@ class EVM {
message_filter_ = message_filter;
}

void update_gas_params(const evmone::gas_parameters& gas_params) {
gas_params_ = gas_params;
}

const evmone::gas_parameters& get_gas_params() {
return gas_params_;
}

uint64_t get_eos_evm_version()const {
return eos_evm_version_;
}
Expand Down
Loading
Loading