Skip to content

Commit

Permalink
fixes gas parameter logics
Browse files Browse the repository at this point in the history
  • Loading branch information
taokayan committed Feb 6, 2024
1 parent 4e71139 commit c72fd66
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 68 deletions.
7 changes: 4 additions & 3 deletions include/evm_runtime/config_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ struct config_wrapper {
void set_ingress_bridge_fee(const eosio::asset& ingress_bridge_fee);

uint64_t get_gas_price()const;
void set_gas_price(uint64_t gas_price);

uint32_t get_miner_cut()const;
void set_miner_cut(uint32_t miner_cut);
Expand All @@ -43,8 +42,10 @@ struct config_wrapper {
void set_fee_parameters(const fee_parameters& fee_params,
bool allow_any_to_be_unspecified);

void update_gas_params(double kb_price);
std::pair<const gas_parameter_type::gas_parameter_data_type &, bool> get_gas_param_maybe_update();
void update_gas_params(eosio::asset ram_price_mb, std::optional<uint64_t> minimum_gas_price);
void update_gas_params2(std::optional<uint64_t> gas_txnewaccount, std::optional<uint64_t> gas_newaccount, std::optional<uint64_t> gas_txcreate, std::optional<uint64_t> gas_codedeposit, std::optional<uint64_t> gas_sset, std::optional<uint64_t> minimum_gas_price);

std::pair<const gas_parameter_data_type &, bool> get_gas_param_maybe_update();

private:
bool is_dirty()const;
Expand Down
9 changes: 3 additions & 6 deletions include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,16 @@ class [[eosio::contract]] evm_contract : public contract

[[eosio::action]] void setversion(uint64_t version);

[[eosio::action]] void updtgasparam(double kb_ram_price);
[[eosio::action]] void updtgasparam(eosio::asset ram_price_mb, std::optional<uint64_t> minimum_gas_price);
[[eosio::action]] void updtgaspara2(uint64_t gas_txnewaccount, uint64_t gas_newaccount, uint64_t gas_txcreate, uint64_t gas_codedeposit, uint64_t gas_sset);

// Events
[[eosio::action]] void evmtx(eosio::ignore<evm_runtime::evmtx_type> event){
eosio::check(get_sender() == get_self(), "forbidden to call");
};

// Events
[[eosio::action]] void configchgdv1(eosio::ignore<uint64_t> gas_txnnewaccount,
eosio::ignore<uint64_t> gas_newaccount,
eosio::ignore<uint64_t> gas_txcreate,
eosio::ignore<uint64_t> gas_codedeposit,
eosio::ignore<uint64_t> gas_sset) {
[[eosio::action]] void configchange(gas_parameter_data_type gas_parameter_data) {
eosio::check(get_sender() == get_self(), "forbidden to call");
};

Expand Down
13 changes: 11 additions & 2 deletions include/evm_runtime/runtime_config.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
#pragma once

#include <variant>
namespace evm_runtime {

struct runtime_config {
bool allow_special_signature = false;
bool abort_on_failure = false;
bool enforce_chain_id = true;
bool allow_non_self_miner = true;
};

struct gas_parameter_data_v1 {
uint64_t minimum_gas_price = 0;
uint64_t gas_txnewaccount = 0;
uint64_t gas_newaccount = 25000;
uint64_t gas_txcreate = 32000;
uint64_t gas_codedeposit = 200;
uint64_t gas_sset = 20000;
};
using gas_parameter_data_type = std::variant<gas_parameter_data_v1>;

} //namespace evm_runtime
16 changes: 6 additions & 10 deletions include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <eosio/binary_extension.hpp>

#include <evm_runtime/types.hpp>
#include <evm_runtime/runtime_config.hpp>
#include <eosevm/block_mapping.hpp>

#include <silkworm/core/common/base.hpp>
Expand Down Expand Up @@ -274,15 +275,6 @@ struct evm_version_type {
};

struct gas_parameter_type {
struct gas_parameter_data_v1 {
uint64_t gas_txnewaccount = 0;
uint64_t gas_newaccount = 0;
uint64_t gas_txcreate = 0;
uint64_t gas_codedeposit = 0;
uint64_t gas_sset = 0;
};

using gas_parameter_data_type = std::variant<gas_parameter_data_v1>;

gas_parameter_data_type current;
std::optional<gas_parameter_data_type> pending;
Expand All @@ -295,9 +287,13 @@ struct gas_parameter_type {
return current_block_num > pending_block_num;
}

bool will_update(time_point_sec genesis_time, time_point current_time) const {
return (pending.has_value() && is_active(genesis_time, current_time));
}

std::pair<const gas_parameter_data_type &, bool> get_gas_param_maybe_update(
time_point_sec genesis_time, time_point current_time) {
if (pending.has_value() && is_active(genesis_time, current_time)) {
if (will_update(genesis_time, current_time)) {
current = *pending;
pending.reset();
pending_time = time_point();
Expand Down
34 changes: 21 additions & 13 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,10 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const

auto current_version = _config->get_evm_version_and_maybe_promote();

std::pair<const gas_parameter_type::gas_parameter_data_type &, bool> gas_param_pair = _config->get_gas_param_maybe_update();
std::pair<const gas_parameter_data_type &, bool> gas_param_pair = _config->get_gas_param_maybe_update();
if (gas_param_pair.second) {
eosio::check(current_version >= 1, "gas parameter change not allowed if evm_version is 0");
// should not happen
eosio::check(current_version >= 1, "gas param change requires evm_version >= 1");
}

std::optional<std::pair<const std::string, const ChainConfig*>> found_chain_config = lookup_known_chain(_config->get_chainid());
Expand Down Expand Up @@ -459,15 +460,8 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const
ep.state().write_to_db(ep.evm().block().header.number);

if (gas_param_pair.second) {
const auto& gas_param_v1 = std::get<gas_parameter_type::gas_parameter_data_v1>(gas_param_pair.first);
action(std::vector<permission_level>{}, get_self(), "configchgdv1"_n,
std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>(
gas_param_v1.gas_txnewaccount,
gas_param_v1.gas_newaccount,
gas_param_v1.gas_txcreate,
gas_param_v1.gas_codedeposit,
gas_param_v1.gas_sset
)).send();
action(std::vector<permission_level>{}, get_self(),
"configchange"_n, gas_param_pair.first).send();
}

if (current_version >= 1) {
Expand Down Expand Up @@ -801,9 +795,23 @@ void evm_contract::setversion(uint64_t version) {
_config->set_evm_version(version);
}

void evm_contract::updtgasparam(double kb_ram_price) {
void evm_contract::updtgasparam(eosio::asset ram_price_mb, std::optional<uint64_t> minimum_gas_price) {
require_auth(get_self());
_config->update_gas_params(kb_ram_price);
_config->update_gas_params(ram_price_mb, minimum_gas_price);
}

void evm_contract::updtgaspara2(uint64_t gas_txnewaccount,
uint64_t gas_newaccount,
uint64_t gas_txcreate,
uint64_t gas_codedeposit,
uint64_t gas_sset) {
require_auth(get_self());
_config->update_gas_params2(gas_txnewaccount,
gas_newaccount,
gas_txcreate,
gas_codedeposit,
gas_sset,
std::optional<uint64_t>() /* min_gas_price*/);
}

} //evm_runtime
109 changes: 75 additions & 34 deletions src/config_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ void config_wrapper::set_ingress_bridge_fee(const eosio::asset& ingress_bridge_f
}

uint64_t config_wrapper::get_gas_price()const {
return _cached_config.gas_price;
}

void config_wrapper::set_gas_price(uint64_t gas_price) {
_cached_config.gas_price = gas_price;
set_dirty();
uint64_t gas_price = _cached_config.gas_price;
if (_cached_config.gas_parameter.has_value() &&
_cached_config.gas_parameter->will_update(_cached_config.genesis_time, get_current_time())) {
std::visit([&](const auto &v) {
if (v.minimum_gas_price) gas_price = v.minimum_gas_price;
}, *(_cached_config.gas_parameter->pending));
}
return gas_price;
}

uint32_t config_wrapper::get_miner_cut()const {
Expand Down Expand Up @@ -121,7 +123,18 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params,
bool allow_any_to_be_unspecified)
{
if (fee_params.gas_price.has_value()) {
_cached_config.gas_price = *fee_params.gas_price;
if (_cached_config.evm_version.has_value() && _cached_config.evm_version->cached_version >= 1) {
// activate in the next evm block
this->update_gas_params2(std::optional<uint64_t>(), /* gas_txnewaccount */
std::optional<uint64_t>(), /* gas_newaccount */
std::optional<uint64_t>(), /* gas_txcreate */
std::optional<uint64_t>(), /* gas_codedeposit */
std::optional<uint64_t>(), /* gas_sset */
*fee_params.gas_price /* minimum_gas_price */
);
} else {
_cached_config.gas_price = *fee_params.gas_price;
}
} else {
eosio::check(allow_any_to_be_unspecified, "All required fee parameters not specified: missing gas_price");
}
Expand All @@ -144,52 +157,80 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params,
set_dirty();
}

void config_wrapper::update_gas_params(double kb_ram_price) {

// for simplicity, just ensure last (cached) evm_version >= 1, not touching promote logic
eosio::check(_cached_config.evm_version.has_value() && _cached_config.evm_version->cached_version >= 1,
"required evm_version at least 1");
void config_wrapper::update_gas_params(eosio::asset ram_price_mb, std::optional<uint64_t> minimum_gas_price) {

if (!_cached_config.gas_parameter.has_value()) {
_cached_config.gas_parameter = gas_parameter_type();
}
gas_parameter_type &param = *(_cached_config.gas_parameter);
uint64_t gas_price = (minimum_gas_price.has_value() && *minimum_gas_price) > 0 ?
*minimum_gas_price : _cached_config.gas_price;
eosio::check(ram_price_mb.symbol == token_symbol, "invalid price symbol");

double gas_per_byte_f =
(kb_ram_price * 1e18 / (1024.0)) / (_cached_config.gas_price * (100000 - _cached_config.miner_cut) / 100000);
double gas_per_byte_f = (ram_price_mb.amount / 10000.0 * 1e18 / (1024.0 * 1024.0)) /
(gas_price * (double)(100000 - _cached_config.miner_cut) / 100000.0);

// round up to multiple of 8 bytes
constexpr uint64_t account_bytes = 352;
constexpr uint64_t account_bytes = 347;
constexpr uint64_t contract_fixed_bytes = 606;
constexpr uint64_t storage_slot_bytes = 352;
constexpr uint64_t storage_slot_bytes = 346;

eosio::check(gas_per_byte_f >= 0.0, "gas per byte can not be negative");
eosio::check(gas_per_byte_f * contract_fixed_bytes < (double)(0x7ffffffffffull), "gas per byte excceed limit");
eosio::check(gas_per_byte_f >= 0.0, "gas_per_byte must >= 0");
eosio::check(gas_per_byte_f * contract_fixed_bytes < (double)(0x7ffffffffffull), "gas_per_byte too big");

uint64_t gas_per_byte = (uint64_t)(gas_per_byte_f + 1.0);

param.pending = gas_parameter_type::gas_parameter_data_v1 {
.gas_txnewaccount = account_bytes * gas_per_byte,
.gas_newaccount = account_bytes * gas_per_byte,
.gas_txcreate = contract_fixed_bytes * gas_per_byte,
.gas_codedeposit = gas_per_byte,
.gas_sset = 100 + storage_slot_bytes * gas_per_byte
};
param.pending_time = get_current_time();
this->update_gas_params2(account_bytes * gas_per_byte, /* gas_txnewaccount */
account_bytes * gas_per_byte, /* gas_newaccount */
contract_fixed_bytes * gas_per_byte, /*gas_txcreate*/
gas_per_byte,/*gas_codedeposit*/
100 + storage_slot_bytes * gas_per_byte,/*gas_sset*/
minimum_gas_price /*minimum_gas_price*/
);
}

void config_wrapper::update_gas_params2(std::optional<uint64_t> gas_txnewaccount, std::optional<uint64_t> gas_newaccount, std::optional<uint64_t> gas_txcreate, std::optional<uint64_t> gas_codedeposit, std::optional<uint64_t> gas_sset, std::optional<uint64_t> minimum_gas_price)
{
// for simplicity, ensure last (cached) evm_version >= 1, not touching promote logic
eosio::check(_cached_config.evm_version.has_value() && _cached_config.evm_version->cached_version >= 1,
"evm_version must >= 1");

// for simplcity, wait for at least 1 trx to trigger the creation of _cached_config.gas_parameter
eosio::check(_cached_config.gas_parameter.has_value(), "current gas_parameter must exist");

gas_parameter_type &param = *(_cached_config.gas_parameter);

gas_parameter_data_type new_pending = (param.pending.has_value() ? *(param.pending) : param.current);

std::visit([&](auto & v) {
if (gas_txnewaccount.has_value()) v.gas_txnewaccount = *gas_txnewaccount;
if (gas_newaccount.has_value()) v.gas_newaccount = *gas_newaccount;
if (gas_txcreate.has_value()) v.gas_txcreate = *gas_txcreate;
if (gas_codedeposit.has_value()) v.gas_codedeposit = *gas_codedeposit;
if (gas_sset.has_value()) v.gas_sset = *gas_sset;
if (minimum_gas_price.has_value()) {
v.minimum_gas_price = *minimum_gas_price;
} else if (v.minimum_gas_price == 0) {
v.minimum_gas_price = _cached_config.gas_price;
}
}, new_pending);

param.pending = new_pending;
param.pending_time = get_current_time();
set_dirty();
}

std::pair<const gas_parameter_type::gas_parameter_data_type &, bool> config_wrapper::get_gas_param_maybe_update() {
std::pair<const gas_parameter_data_type &, bool> config_wrapper::get_gas_param_maybe_update() {
if (!_cached_config.gas_parameter.has_value()) {
_cached_config.gas_parameter = gas_parameter_type();
set_dirty();
return std::pair<const gas_parameter_type::gas_parameter_data_type &, bool>(_cached_config.gas_parameter->current, false);
return std::pair<const gas_parameter_data_type &, bool>(_cached_config.gas_parameter->current, false);
}

auto pair = _cached_config.gas_parameter->get_gas_param_maybe_update(_cached_config.genesis_time, get_current_time());

if (pair.second) {
if (pair.second) { // update
// populate minimum_gas_price to config only if minimum_gas_price > 0
uint64_t minimum_gas_price = 0;
std::visit([&](const auto &v) {
minimum_gas_price = v.minimum_gas_price;
}, pair.first);
if (minimum_gas_price) _cached_config.gas_price = minimum_gas_price;
set_dirty();
}

Expand Down

0 comments on commit c72fd66

Please sign in to comment.