Skip to content

Commit

Permalink
gas param update
Browse files Browse the repository at this point in the history
  • Loading branch information
taokayan committed Jan 31, 2024
1 parent 7e1fb46 commit 4e71139
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/evm_runtime/config_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ 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();

private:
bool is_dirty()const;
void set_dirty();
Expand Down
11 changes: 11 additions & 0 deletions include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,22 @@ class [[eosio::contract]] evm_contract : public contract

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

[[eosio::action]] void updtgasparam(double kb_ram_price);

// 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::check(get_sender() == get_self(), "forbidden to call");
};

#ifdef WITH_ADMIN_ACTIONS
[[eosio::action]] void rmgcstore(uint64_t id);
[[eosio::action]] void setkvstore(uint64_t account_id, const bytes& key, const std::optional<bytes>& value);
Expand Down
38 changes: 37 additions & 1 deletion include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,41 @@ struct evm_version_type {
uint64_t cached_version=0;
};

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;
time_point pending_time;

bool is_active(time_point_sec genesis_time, time_point current_time)const {
eosevm::block_mapping bm(genesis_time.sec_since_epoch());
auto current_block_num = bm.timestamp_to_evm_block_num(current_time.time_since_epoch().count());
auto pending_block_num = bm.timestamp_to_evm_block_num(pending_time.time_since_epoch().count());
return current_block_num > pending_block_num;
}

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)) {
current = *pending;
pending.reset();
pending_time = time_point();
// don't use make_pair as it create ref to temp objects
return std::pair<const gas_parameter_data_type &, bool>(current, true);
}
return std::pair<const gas_parameter_data_type &, bool>(current, false);
}
};

struct [[eosio::table]] [[eosio::contract("evm_contract")]] config
{
unsigned_int version; // placeholder for future variant index
Expand All @@ -283,8 +318,9 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] config
uint32_t miner_cut = 0;
uint32_t status = 0; // <- bit mask values from status_flags
binary_extension<evm_version_type> evm_version;
binary_extension<gas_parameter_type> gas_parameter;

EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version));
EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version)(gas_parameter));
};

} //namespace evm_runtime
23 changes: 23 additions & 0 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ 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();
if (gas_param_pair.second) {
eosio::check(current_version >= 1, "gas parameter change not allowed if evm_version is 0");
}

std::optional<std::pair<const std::string, const ChainConfig*>> found_chain_config = lookup_known_chain(_config->get_chainid());
check( found_chain_config.has_value(), "failed to find expected chain config" );

Expand Down Expand Up @@ -452,6 +457,19 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const

engine.finalize(ep.state(), ep.evm().block());
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();
}

if (current_version >= 1) {
auto event = evmtx_type{evmtx_v0{current_version, txn.get_rlptx()}};
action(std::vector<permission_level>{}, get_self(), "evmtx"_n, event)
Expand Down Expand Up @@ -783,4 +801,9 @@ void evm_contract::setversion(uint64_t version) {
_config->set_evm_version(version);
}

void evm_contract::updtgasparam(double kb_ram_price) {
require_auth(get_self());
_config->update_gas_params(kb_ram_price);
}

} //evm_runtime
52 changes: 52 additions & 0 deletions src/config_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,58 @@ 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");

if (!_cached_config.gas_parameter.has_value()) {
_cached_config.gas_parameter = gas_parameter_type();
}
gas_parameter_type &param = *(_cached_config.gas_parameter);

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

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

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");

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();

set_dirty();
}

std::pair<const gas_parameter_type::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);
}

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

if (pair.second) {
set_dirty();
}

return pair;
}

bool config_wrapper::is_dirty()const {
return _dirty;
}
Expand Down

0 comments on commit 4e71139

Please sign in to comment.