From 4e7113941d6f3938545250feb253491f5ef7fb3d Mon Sep 17 00:00:00 2001 From: kayan Date: Wed, 31 Jan 2024 11:06:11 +0800 Subject: [PATCH 01/10] gas param update --- include/evm_runtime/config_wrapper.hpp | 3 ++ include/evm_runtime/evm_contract.hpp | 11 ++++++ include/evm_runtime/tables.hpp | 38 ++++++++++++++++++- src/actions.cpp | 23 ++++++++++++ src/config_wrapper.cpp | 52 ++++++++++++++++++++++++++ 5 files changed, 126 insertions(+), 1 deletion(-) diff --git a/include/evm_runtime/config_wrapper.hpp b/include/evm_runtime/config_wrapper.hpp index c109bafb..28622fc1 100644 --- a/include/evm_runtime/config_wrapper.hpp +++ b/include/evm_runtime/config_wrapper.hpp @@ -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 get_gas_param_maybe_update(); + private: bool is_dirty()const; void set_dirty(); diff --git a/include/evm_runtime/evm_contract.hpp b/include/evm_runtime/evm_contract.hpp index 6ef51f72..023b3dd9 100644 --- a/include/evm_runtime/evm_contract.hpp +++ b/include/evm_runtime/evm_contract.hpp @@ -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 event){ eosio::check(get_sender() == get_self(), "forbidden to call"); }; + // Events + [[eosio::action]] void configchgdv1(eosio::ignore gas_txnnewaccount, + eosio::ignore gas_newaccount, + eosio::ignore gas_txcreate, + eosio::ignore gas_codedeposit, + eosio::ignore 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& value); diff --git a/include/evm_runtime/tables.hpp b/include/evm_runtime/tables.hpp index 1be9088c..71476d68 100644 --- a/include/evm_runtime/tables.hpp +++ b/include/evm_runtime/tables.hpp @@ -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_type current; + std::optional 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 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(current, true); + } + return std::pair(current, false); + } +}; + struct [[eosio::table]] [[eosio::contract("evm_contract")]] config { unsigned_int version; // placeholder for future variant index @@ -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; + binary_extension 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 diff --git a/src/actions.cpp b/src/actions.cpp index 91872256..c2fe207b 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -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 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> found_chain_config = lookup_known_chain(_config->get_chainid()); check( found_chain_config.has_value(), "failed to find expected chain config" ); @@ -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_param_pair.first); + action(std::vector{}, get_self(), "configchgdv1"_n, + std::tuple( + 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{}, get_self(), "evmtx"_n, event) @@ -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 diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index c6656176..2866d0bb 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -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 ¶m = *(_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 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(_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; } From c72fd66c445264e2e2d7d2bc694d866bf6b40acd Mon Sep 17 00:00:00 2001 From: kayan Date: Tue, 6 Feb 2024 17:17:31 +0800 Subject: [PATCH 02/10] fixes gas parameter logics --- include/evm_runtime/config_wrapper.hpp | 7 +- include/evm_runtime/evm_contract.hpp | 9 +- include/evm_runtime/runtime_config.hpp | 13 ++- include/evm_runtime/tables.hpp | 16 ++-- src/actions.cpp | 34 +++++--- src/config_wrapper.cpp | 109 +++++++++++++++++-------- 6 files changed, 120 insertions(+), 68 deletions(-) diff --git a/include/evm_runtime/config_wrapper.hpp b/include/evm_runtime/config_wrapper.hpp index 28622fc1..65fb8f1b 100644 --- a/include/evm_runtime/config_wrapper.hpp +++ b/include/evm_runtime/config_wrapper.hpp @@ -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); @@ -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 get_gas_param_maybe_update(); + void update_gas_params(eosio::asset ram_price_mb, std::optional minimum_gas_price); + void update_gas_params2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional minimum_gas_price); + + std::pair get_gas_param_maybe_update(); private: bool is_dirty()const; diff --git a/include/evm_runtime/evm_contract.hpp b/include/evm_runtime/evm_contract.hpp index 023b3dd9..4f16173b 100644 --- a/include/evm_runtime/evm_contract.hpp +++ b/include/evm_runtime/evm_contract.hpp @@ -85,7 +85,8 @@ 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 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 event){ @@ -93,11 +94,7 @@ class [[eosio::contract]] evm_contract : public contract }; // Events - [[eosio::action]] void configchgdv1(eosio::ignore gas_txnnewaccount, - eosio::ignore gas_newaccount, - eosio::ignore gas_txcreate, - eosio::ignore gas_codedeposit, - eosio::ignore gas_sset) { + [[eosio::action]] void configchange(gas_parameter_data_type gas_parameter_data) { eosio::check(get_sender() == get_self(), "forbidden to call"); }; diff --git a/include/evm_runtime/runtime_config.hpp b/include/evm_runtime/runtime_config.hpp index 404fec59..ea752008 100644 --- a/include/evm_runtime/runtime_config.hpp +++ b/include/evm_runtime/runtime_config.hpp @@ -1,7 +1,6 @@ #pragma once - +#include namespace evm_runtime { - struct runtime_config { bool allow_special_signature = false; bool abort_on_failure = false; @@ -9,4 +8,14 @@ struct runtime_config { 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; + } //namespace evm_runtime \ No newline at end of file diff --git a/include/evm_runtime/tables.hpp b/include/evm_runtime/tables.hpp index 71476d68..a2511711 100644 --- a/include/evm_runtime/tables.hpp +++ b/include/evm_runtime/tables.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -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_type current; std::optional pending; @@ -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 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(); diff --git a/src/actions.cpp b/src/actions.cpp index c2fe207b..76433e46 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -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 gas_param_pair = _config->get_gas_param_maybe_update(); + std::pair 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> found_chain_config = lookup_known_chain(_config->get_chainid()); @@ -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_param_pair.first); - action(std::vector{}, get_self(), "configchgdv1"_n, - std::tuple( - 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{}, get_self(), + "configchange"_n, gas_param_pair.first).send(); } if (current_version >= 1) { @@ -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 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() /* min_gas_price*/); } } //evm_runtime diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index 2866d0bb..81725bee 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -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 { @@ -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(), /* gas_txnewaccount */ + std::optional(), /* gas_newaccount */ + std::optional(), /* gas_txcreate */ + std::optional(), /* gas_codedeposit */ + std::optional(), /* 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"); } @@ -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 minimum_gas_price) { - if (!_cached_config.gas_parameter.has_value()) { - _cached_config.gas_parameter = gas_parameter_type(); - } - gas_parameter_type ¶m = *(_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 gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional 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 ¶m = *(_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 config_wrapper::get_gas_param_maybe_update() { +std::pair 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(_cached_config.gas_parameter->current, false); + return std::pair(_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(); } From c04b278c8a6a895bcd56f2d14eebe131801ff13c Mon Sep 17 00:00:00 2001 From: kayan Date: Tue, 6 Feb 2024 21:18:16 +0800 Subject: [PATCH 03/10] fix gas param again --- include/evm_runtime/config_wrapper.hpp | 2 +- include/evm_runtime/tables.hpp | 19 ++++++++++++------- src/actions.cpp | 2 +- src/config_wrapper.cpp | 16 +++++----------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/evm_runtime/config_wrapper.hpp b/include/evm_runtime/config_wrapper.hpp index 65fb8f1b..2bf6c5ba 100644 --- a/include/evm_runtime/config_wrapper.hpp +++ b/include/evm_runtime/config_wrapper.hpp @@ -45,7 +45,7 @@ struct config_wrapper { void update_gas_params(eosio::asset ram_price_mb, std::optional minimum_gas_price); void update_gas_params2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional minimum_gas_price); - std::pair get_gas_param_maybe_update(); + std::pair get_gas_param_and_maybe_promote(); private: bool is_dirty()const; diff --git a/include/evm_runtime/tables.hpp b/include/evm_runtime/tables.hpp index a2511711..849dfb61 100644 --- a/include/evm_runtime/tables.hpp +++ b/include/evm_runtime/tables.hpp @@ -280,20 +280,17 @@ struct gas_parameter_type { std::optional pending; time_point pending_time; - bool is_active(time_point_sec genesis_time, time_point current_time)const { + bool is_pending_active(time_point_sec genesis_time, time_point current_time)const { + if (!pending.has_value()) return false; 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; } - 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 get_gas_param_maybe_update( + std::pair get_gas_param_and_maybe_promote( time_point_sec genesis_time, time_point current_time) { - if (will_update(genesis_time, current_time)) { + if (is_pending_active(genesis_time, current_time)) { current = *pending; pending.reset(); pending_time = time_point(); @@ -302,6 +299,14 @@ struct gas_parameter_type { } return std::pair(current, false); } + + template + void update_gas_param(Visitor visitor_fn, time_point current_time) { + gas_parameter_data_type new_pending = (pending.has_value() ? *pending : current); + std::visit(visitor_fn, new_pending); + pending = new_pending; + pending_time = current_time; + } }; struct [[eosio::table]] [[eosio::contract("evm_contract")]] config diff --git a/src/actions.cpp b/src/actions.cpp index 76433e46..a2ac022b 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -422,7 +422,7 @@ 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 gas_param_pair = _config->get_gas_param_maybe_update(); + std::pair gas_param_pair = _config->get_gas_param_and_maybe_promote(); if (gas_param_pair.second) { // should not happen eosio::check(current_version >= 1, "gas param change requires evm_version >= 1"); diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index 81725bee..5bbe7d76 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -67,7 +67,7 @@ void config_wrapper::set_ingress_bridge_fee(const eosio::asset& ingress_bridge_f uint64_t config_wrapper::get_gas_price()const { 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())) { + _cached_config.gas_parameter->is_pending_active(_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)); @@ -193,11 +193,7 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount // 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 ¶m = *(_cached_config.gas_parameter); - - gas_parameter_data_type new_pending = (param.pending.has_value() ? *(param.pending) : param.current); - - std::visit([&](auto & v) { + _cached_config.gas_parameter->update_gas_param([&](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; @@ -208,21 +204,19 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount } else if (v.minimum_gas_price == 0) { v.minimum_gas_price = _cached_config.gas_price; } - }, new_pending); + }, get_current_time()); - param.pending = new_pending; - param.pending_time = get_current_time(); set_dirty(); } -std::pair config_wrapper::get_gas_param_maybe_update() { +std::pair config_wrapper::get_gas_param_and_maybe_promote() { if (!_cached_config.gas_parameter.has_value()) { _cached_config.gas_parameter = gas_parameter_type(); set_dirty(); return std::pair(_cached_config.gas_parameter->current, false); } - auto pair = _cached_config.gas_parameter->get_gas_param_maybe_update(_cached_config.genesis_time, get_current_time()); + auto pair = _cached_config.gas_parameter->get_gas_param_and_maybe_promote(_cached_config.genesis_time, get_current_time()); if (pair.second) { // update // populate minimum_gas_price to config only if minimum_gas_price > 0 From 9a174ce339bfc8e04520f26b2925d742eb5b9be2 Mon Sep 17 00:00:00 2001 From: kayan Date: Thu, 8 Feb 2024 11:15:34 +0800 Subject: [PATCH 04/10] rename gas_parameter to consensus parameter, miner_cut and gas price range check --- include/evm_runtime/config_wrapper.hpp | 4 +-- include/evm_runtime/evm_contract.hpp | 6 ++-- include/evm_runtime/runtime_config.hpp | 9 +++-- include/evm_runtime/tables.hpp | 20 +++++------ include/evm_runtime/types.hpp | 1 + src/actions.cpp | 6 ++-- src/config_wrapper.cpp | 48 ++++++++++++++------------ 7 files changed, 51 insertions(+), 43 deletions(-) diff --git a/include/evm_runtime/config_wrapper.hpp b/include/evm_runtime/config_wrapper.hpp index 2bf6c5ba..70d3b90d 100644 --- a/include/evm_runtime/config_wrapper.hpp +++ b/include/evm_runtime/config_wrapper.hpp @@ -42,10 +42,10 @@ struct config_wrapper { void set_fee_parameters(const fee_parameters& fee_params, bool allow_any_to_be_unspecified); - void update_gas_params(eosio::asset ram_price_mb, std::optional minimum_gas_price); + void update_gas_params(eosio::asset ram_price_mb, uint64_t minimum_gas_price); void update_gas_params2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional minimum_gas_price); - std::pair get_gas_param_and_maybe_promote(); + std::pair get_consensus_param_and_maybe_promote(); private: bool is_dirty()const; diff --git a/include/evm_runtime/evm_contract.hpp b/include/evm_runtime/evm_contract.hpp index 4f16173b..745b55f1 100644 --- a/include/evm_runtime/evm_contract.hpp +++ b/include/evm_runtime/evm_contract.hpp @@ -85,8 +85,8 @@ class [[eosio::contract]] evm_contract : public contract [[eosio::action]] void setversion(uint64_t version); - [[eosio::action]] void updtgasparam(eosio::asset ram_price_mb, std::optional 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); + [[eosio::action]] void updtgasparam(eosio::asset ram_price_mb, uint64_t minimum_gas_price); + [[eosio::action]] void setgasparam(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 event){ @@ -94,7 +94,7 @@ class [[eosio::contract]] evm_contract : public contract }; // Events - [[eosio::action]] void configchange(gas_parameter_data_type gas_parameter_data) { + [[eosio::action]] void configchange(consensus_parameter_data_type consensus_parameter_data) { eosio::check(get_sender() == get_self(), "forbidden to call"); }; diff --git a/include/evm_runtime/runtime_config.hpp b/include/evm_runtime/runtime_config.hpp index ea752008..a0dd5e4a 100644 --- a/include/evm_runtime/runtime_config.hpp +++ b/include/evm_runtime/runtime_config.hpp @@ -8,14 +8,17 @@ struct runtime_config { bool allow_non_self_miner = true; }; -struct gas_parameter_data_v1 { - uint64_t minimum_gas_price = 0; +struct gas_parameter_type { 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; +struct consensus_parameter_data_v1 { + uint64_t minimum_gas_price = 0; + gas_parameter_type gas_parameter; +}; +using consensus_parameter_data_type = std::variant; } //namespace evm_runtime \ No newline at end of file diff --git a/include/evm_runtime/tables.hpp b/include/evm_runtime/tables.hpp index 849dfb61..baf582e2 100644 --- a/include/evm_runtime/tables.hpp +++ b/include/evm_runtime/tables.hpp @@ -274,10 +274,10 @@ struct evm_version_type { uint64_t cached_version=0; }; -struct gas_parameter_type { +struct consensus_parameter_type { - gas_parameter_data_type current; - std::optional pending; + consensus_parameter_data_type current; + std::optional pending; time_point pending_time; bool is_pending_active(time_point_sec genesis_time, time_point current_time)const { @@ -288,21 +288,21 @@ struct gas_parameter_type { return current_block_num > pending_block_num; } - std::pair get_gas_param_and_maybe_promote( + std::pair get_consensus_param_and_maybe_promote( time_point_sec genesis_time, time_point current_time) { if (is_pending_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(current, true); + return std::pair(current, true); } - return std::pair(current, false); + return std::pair(current, false); } template - void update_gas_param(Visitor visitor_fn, time_point current_time) { - gas_parameter_data_type new_pending = (pending.has_value() ? *pending : current); + void update_consensus_param(Visitor visitor_fn, time_point current_time) { + consensus_parameter_data_type new_pending = (pending.has_value() ? *pending : current); std::visit(visitor_fn, new_pending); pending = new_pending; pending_time = current_time; @@ -319,9 +319,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; - binary_extension gas_parameter; + binary_extension consensus_parameter; - EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version)(gas_parameter)); + EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version)(consensus_parameter)); }; } //namespace evm_runtime diff --git a/include/evm_runtime/types.hpp b/include/evm_runtime/types.hpp index cf52e68b..3207588a 100644 --- a/include/evm_runtime/types.hpp +++ b/include/evm_runtime/types.hpp @@ -12,6 +12,7 @@ namespace evm_runtime { using intx::operator""_u256; + static constexpr uint32_t ninety_percent = 90'000; static constexpr uint32_t hundred_percent = 100'000; constexpr unsigned evm_precision = 18; diff --git a/src/actions.cpp b/src/actions.cpp index a2ac022b..733bff53 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -422,7 +422,7 @@ 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 gas_param_pair = _config->get_gas_param_and_maybe_promote(); + std::pair gas_param_pair = _config->get_consensus_param_and_maybe_promote(); if (gas_param_pair.second) { // should not happen eosio::check(current_version >= 1, "gas param change requires evm_version >= 1"); @@ -795,12 +795,12 @@ void evm_contract::setversion(uint64_t version) { _config->set_evm_version(version); } -void evm_contract::updtgasparam(eosio::asset ram_price_mb, std::optional minimum_gas_price) { +void evm_contract::updtgasparam(eosio::asset ram_price_mb, uint64_t minimum_gas_price) { require_auth(get_self()); _config->update_gas_params(ram_price_mb, minimum_gas_price); } -void evm_contract::updtgaspara2(uint64_t gas_txnewaccount, +void evm_contract::setgasparam(uint64_t gas_txnewaccount, uint64_t gas_newaccount, uint64_t gas_txcreate, uint64_t gas_codedeposit, diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index 5bbe7d76..591951d6 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -66,11 +66,11 @@ void config_wrapper::set_ingress_bridge_fee(const eosio::asset& ingress_bridge_f uint64_t config_wrapper::get_gas_price()const { uint64_t gas_price = _cached_config.gas_price; - if (_cached_config.gas_parameter.has_value() && - _cached_config.gas_parameter->is_pending_active(_cached_config.genesis_time, get_current_time())) { + if (_cached_config.consensus_parameter.has_value() && + _cached_config.consensus_parameter->is_pending_active(_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)); + }, *(_cached_config.consensus_parameter->pending)); } return gas_price; } @@ -80,6 +80,7 @@ uint32_t config_wrapper::get_miner_cut()const { } void config_wrapper::set_miner_cut(uint32_t miner_cut) { + eosio::check(miner_cut <= ninety_percent, "miner_cut must <= 90%"); _cached_config.miner_cut = miner_cut; set_dirty(); } @@ -123,6 +124,7 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, bool allow_any_to_be_unspecified) { if (fee_params.gas_price.has_value()) { + eosio::check(*fee_params.gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); 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(), /* gas_txnewaccount */ @@ -140,8 +142,7 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, } if (fee_params.miner_cut.has_value()) { - eosio::check(*fee_params.miner_cut <= hundred_percent, "miner_cut cannot exceed 100,000 (100%)"); - + eosio::check(*fee_params.miner_cut <= ninety_percent, "miner_cut must <= 90%"); _cached_config.miner_cut = *fee_params.miner_cut; } else { eosio::check(allow_any_to_be_unspecified, "All required fee parameters not specified: missing miner_cut"); @@ -157,14 +158,13 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, set_dirty(); } -void config_wrapper::update_gas_params(eosio::asset ram_price_mb, std::optional minimum_gas_price) { +void config_wrapper::update_gas_params(eosio::asset ram_price_mb, uint64_t minimum_gas_price) { - 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"); + eosio::check(minimum_gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); 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); + (minimum_gas_price * (double)(100000 - _cached_config.miner_cut) / 100000.0); constexpr uint64_t account_bytes = 347; constexpr uint64_t contract_fixed_bytes = 606; @@ -190,15 +190,19 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount 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"); + // for simplcity, wait for at least 1 trx to trigger the creation of _cached_config.consensus_parameter + eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter must exist"); + + if (minimum_gas_price.has_value()) { + eosio::check(*minimum_gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); + } - _cached_config.gas_parameter->update_gas_param([&](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; + _cached_config.consensus_parameter->update_consensus_param([&](auto & v) { + if (gas_txnewaccount.has_value()) v.gas_parameter.gas_txnewaccount = *gas_txnewaccount; + if (gas_newaccount.has_value()) v.gas_parameter.gas_newaccount = *gas_newaccount; + if (gas_txcreate.has_value()) v.gas_parameter.gas_txcreate = *gas_txcreate; + if (gas_codedeposit.has_value()) v.gas_parameter.gas_codedeposit = *gas_codedeposit; + if (gas_sset.has_value()) v.gas_parameter.gas_sset = *gas_sset; if (minimum_gas_price.has_value()) { v.minimum_gas_price = *minimum_gas_price; } else if (v.minimum_gas_price == 0) { @@ -209,14 +213,14 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount set_dirty(); } -std::pair config_wrapper::get_gas_param_and_maybe_promote() { - if (!_cached_config.gas_parameter.has_value()) { - _cached_config.gas_parameter = gas_parameter_type(); +std::pair config_wrapper::get_consensus_param_and_maybe_promote() { + if (!_cached_config.consensus_parameter.has_value()) { + _cached_config.consensus_parameter = consensus_parameter_type(); set_dirty(); - return std::pair(_cached_config.gas_parameter->current, false); + return std::pair(_cached_config.consensus_parameter->current, false); } - auto pair = _cached_config.gas_parameter->get_gas_param_and_maybe_promote(_cached_config.genesis_time, get_current_time()); + auto pair = _cached_config.consensus_parameter->get_consensus_param_and_maybe_promote(_cached_config.genesis_time, get_current_time()); if (pair.second) { // update // populate minimum_gas_price to config only if minimum_gas_price > 0 From feb70dc52dcd257b6d3aa65ded3afee43f4041cd Mon Sep 17 00:00:00 2001 From: kayan Date: Thu, 8 Feb 2024 15:09:20 +0800 Subject: [PATCH 05/10] fix test case --- tests/gas_fee_tests.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/tests/gas_fee_tests.cpp b/tests/gas_fee_tests.cpp index bab9980e..03d779a3 100644 --- a/tests/gas_fee_tests.cpp +++ b/tests/gas_fee_tests.cpp @@ -84,26 +84,36 @@ try { BOOST_CHECK_EQUAL(conf1.miner_cut, starting_miner_cut); BOOST_CHECK_EQUAL(conf1.ingress_bridge_fee, make_asset(starting_ingress_bridge_fee_amount)); - // Cannot set miner_cut to above 100%. - BOOST_REQUIRE_EXCEPTION(setfeeparams({.miner_cut = 100'001}), + // Cannot set miner_cut to above 90%. + BOOST_REQUIRE_EXCEPTION(setfeeparams({.miner_cut = 90'001}), eosio_assert_message_exception, - eosio_assert_message_is("miner_cut cannot exceed 100,000 (100%)")); + eosio_assert_message_is("miner_cut must <= 90%")); - // Change only miner_cut to 100%. - setfeeparams({.miner_cut = 100'000}); + // Change only miner_cut to 90%. + setfeeparams({.miner_cut = 90'000}); const auto& conf2 = get_config(); BOOST_CHECK_EQUAL(conf2.gas_price, conf1.gas_price); - BOOST_CHECK_EQUAL(conf2.miner_cut, 100'000); + BOOST_CHECK_EQUAL(conf2.miner_cut, 90'000); BOOST_CHECK_EQUAL(conf2.ingress_bridge_fee, conf1.ingress_bridge_fee); - // Change only gas_price to 0 - setfeeparams({.gas_price = 0}); + + + BOOST_REQUIRE_EXCEPTION(setfeeparams({.gas_price = 0}), + eosio_assert_message_exception, + eosio_assert_message_is("gas_price must >= 1Gwei")); + + BOOST_REQUIRE_EXCEPTION(setfeeparams({.gas_price = 999'999'999}), + eosio_assert_message_exception, + eosio_assert_message_is("gas_price must >= 1Gwei")); + + // Change only gas_price to 1Gwei + setfeeparams({.gas_price = 1'000'000'000}); const auto& conf3 = get_config(); - BOOST_CHECK_EQUAL(conf3.gas_price, 0); + BOOST_CHECK_EQUAL(conf3.gas_price, 1'000'000'000); BOOST_CHECK_EQUAL(conf3.miner_cut, conf2.miner_cut); BOOST_CHECK_EQUAL(conf3.ingress_bridge_fee, conf2.ingress_bridge_fee); @@ -205,10 +215,10 @@ try { }; std::vector gas_fee_trials = { - {0, 50'000, 0, 0 }, + {1'000'000'000, 50'000, 10'500'000'000'000, 10'500'000'000'000}, {1'000'000'000, 0, 0, 21'000'000'000'000}, {1'000'000'000, 10'000, 2'100'000'000'000, 18'900'000'000'000}, - {1'000'000'000, 100'000, 21'000'000'000'000, 0 }, + {1'000'000'000, 90'000, 18'900'000'000'000, 2'100'000'000'000}, }; // EVM contract account acts as the miner From 992d8e16dcb04be28471663bb899725f77630e9a Mon Sep 17 00:00:00 2001 From: kayan Date: Fri, 9 Feb 2024 10:46:17 +0800 Subject: [PATCH 06/10] update g_sset formula --- src/config_wrapper.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index 591951d6..f05e4730 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -179,7 +179,7 @@ void config_wrapper::update_gas_params(eosio::asset ram_price_mb, uint64_t minim 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*/ + 2900 + storage_slot_bytes * gas_per_byte,/*gas_sset*/ minimum_gas_price /*minimum_gas_price*/ ); } @@ -202,7 +202,10 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount if (gas_newaccount.has_value()) v.gas_parameter.gas_newaccount = *gas_newaccount; if (gas_txcreate.has_value()) v.gas_parameter.gas_txcreate = *gas_txcreate; if (gas_codedeposit.has_value()) v.gas_parameter.gas_codedeposit = *gas_codedeposit; - if (gas_sset.has_value()) v.gas_parameter.gas_sset = *gas_sset; + if (gas_sset.has_value()) { + eosio::check(*gas_sset >= 2900, "G_sset must >= 2900"); + v.gas_parameter.gas_sset = *gas_sset; + } if (minimum_gas_price.has_value()) { v.minimum_gas_price = *minimum_gas_price; } else if (v.minimum_gas_price == 0) { From 17e0aa2bcf18d55826d4b3a907172c715d938e30 Mon Sep 17 00:00:00 2001 From: kayan Date: Thu, 15 Feb 2024 15:33:00 +0800 Subject: [PATCH 07/10] set minimum gas price in config wrapper's ctor, other fixes --- include/evm_runtime/runtime_config.hpp | 4 +-- include/evm_runtime/tables.hpp | 24 +++++++++------- include/evm_runtime/types.hpp | 1 + src/config_wrapper.cpp | 39 +++++++++++++------------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/include/evm_runtime/runtime_config.hpp b/include/evm_runtime/runtime_config.hpp index a0dd5e4a..7e12985c 100644 --- a/include/evm_runtime/runtime_config.hpp +++ b/include/evm_runtime/runtime_config.hpp @@ -15,10 +15,10 @@ struct gas_parameter_type { uint64_t gas_codedeposit = 200; uint64_t gas_sset = 20000; }; -struct consensus_parameter_data_v1 { +struct consensus_parameter_data_v0 { uint64_t minimum_gas_price = 0; gas_parameter_type gas_parameter; }; -using consensus_parameter_data_type = std::variant; +using consensus_parameter_data_type = std::variant; } //namespace evm_runtime \ No newline at end of file diff --git a/include/evm_runtime/tables.hpp b/include/evm_runtime/tables.hpp index baf582e2..4fa14b9b 100644 --- a/include/evm_runtime/tables.hpp +++ b/include/evm_runtime/tables.hpp @@ -274,26 +274,28 @@ struct evm_version_type { uint64_t cached_version=0; }; +struct pending_consensus_parameter_data_type { + consensus_parameter_data_type data; + time_point pending_time; +}; struct consensus_parameter_type { - consensus_parameter_data_type current; - std::optional pending; - time_point pending_time; + consensus_parameter_data_type current; + std::optional pending; bool is_pending_active(time_point_sec genesis_time, time_point current_time)const { if (!pending.has_value()) return false; 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()); + auto pending_block_num = bm.timestamp_to_evm_block_num(pending->pending_time.time_since_epoch().count()); return current_block_num > pending_block_num; } std::pair get_consensus_param_and_maybe_promote( time_point_sec genesis_time, time_point current_time) { if (is_pending_active(genesis_time, current_time)) { - current = *pending; + current = pending->data; pending.reset(); - pending_time = time_point(); // don't use make_pair as it create ref to temp objects return std::pair(current, true); } @@ -302,10 +304,12 @@ struct consensus_parameter_type { template void update_consensus_param(Visitor visitor_fn, time_point current_time) { - consensus_parameter_data_type new_pending = (pending.has_value() ? *pending : current); - std::visit(visitor_fn, new_pending); - pending = new_pending; - pending_time = current_time; + consensus_parameter_data_type new_pending = (pending.has_value() ? pending->data : current); + std::visit(visitor_fn, new_pending); + pending = pending_consensus_parameter_data_type{ + .data = new_pending, + .pending_time = current_time + }; } }; diff --git a/include/evm_runtime/types.hpp b/include/evm_runtime/types.hpp index 3207588a..1d859878 100644 --- a/include/evm_runtime/types.hpp +++ b/include/evm_runtime/types.hpp @@ -14,6 +14,7 @@ namespace evm_runtime { using intx::operator""_u256; static constexpr uint32_t ninety_percent = 90'000; static constexpr uint32_t hundred_percent = 100'000; + static constexpr uint64_t one_gwei = 1'000'000'000ull; constexpr unsigned evm_precision = 18; constexpr eosio::name token_account(eosio::name(TOKEN_ACCOUNT_NAME)); diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index f05e4730..ca4e4783 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -9,6 +9,15 @@ config_wrapper::config_wrapper(eosio::name self) : _self(self), _config(self, se if(_exists) { _cached_config = _config.get(); } + if (!_cached_config.consensus_parameter.has_value()){ + _cached_config.consensus_parameter = consensus_parameter_type(); + } + std::visit([&](auto &v) { + if (v.minimum_gas_price == 0) { + v.minimum_gas_price = _cached_config.gas_price; + // don't set dirty, as trxs can be read-only + } + }, _cached_config.consensus_parameter->current); } config_wrapper::~config_wrapper() { @@ -69,8 +78,8 @@ uint64_t config_wrapper::get_gas_price()const { if (_cached_config.consensus_parameter.has_value() && _cached_config.consensus_parameter->is_pending_active(_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.consensus_parameter->pending)); + gas_price = v.minimum_gas_price; + }, _cached_config.consensus_parameter->pending->data); } return gas_price; } @@ -190,8 +199,8 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount 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.consensus_parameter - eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter must exist"); + // should not happen + eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist"); if (minimum_gas_price.has_value()) { eosio::check(*minimum_gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); @@ -206,32 +215,22 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount eosio::check(*gas_sset >= 2900, "G_sset must >= 2900"); v.gas_parameter.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; - } + if (minimum_gas_price.has_value()) v.minimum_gas_price = *minimum_gas_price; }, get_current_time()); set_dirty(); } std::pair config_wrapper::get_consensus_param_and_maybe_promote() { - if (!_cached_config.consensus_parameter.has_value()) { - _cached_config.consensus_parameter = consensus_parameter_type(); - set_dirty(); - return std::pair(_cached_config.consensus_parameter->current, false); - } - auto pair = _cached_config.consensus_parameter->get_consensus_param_and_maybe_promote(_cached_config.genesis_time, get_current_time()); + // should not happen + eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist"); - if (pair.second) { // update - // populate minimum_gas_price to config only if minimum_gas_price > 0 - uint64_t minimum_gas_price = 0; + auto pair = _cached_config.consensus_parameter->get_consensus_param_and_maybe_promote(_cached_config.genesis_time, get_current_time()); + if (pair.second) { std::visit([&](const auto &v) { - minimum_gas_price = v.minimum_gas_price; + _cached_config.gas_price = v.minimum_gas_price; }, pair.first); - if (minimum_gas_price) _cached_config.gas_price = minimum_gas_price; set_dirty(); } From f5be16233612174b88a8bbcebe7b606d3a0c66df Mon Sep 17 00:00:00 2001 From: kayan Date: Tue, 20 Feb 2024 17:00:51 +0800 Subject: [PATCH 08/10] add unit test cases --- tests/CMakeLists.txt | 1 + tests/basic_evm_tester.cpp | 18 ++++ tests/basic_evm_tester.hpp | 6 ++ tests/gas_param_tests.cpp | 174 +++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 tests/gas_param_tests.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ddde4253..ecef07df 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -30,6 +30,7 @@ add_eosio_test_executable( unit_test ${CMAKE_SOURCE_DIR}/native_token_tests.cpp ${CMAKE_SOURCE_DIR}/mapping_tests.cpp ${CMAKE_SOURCE_DIR}/gas_fee_tests.cpp + ${CMAKE_SOURCE_DIR}/gas_param_tests.cpp ${CMAKE_SOURCE_DIR}/blockhash_tests.cpp ${CMAKE_SOURCE_DIR}/exec_tests.cpp ${CMAKE_SOURCE_DIR}/call_tests.cpp diff --git a/tests/basic_evm_tester.cpp b/tests/basic_evm_tester.cpp index 858b5115..037e81b1 100644 --- a/tests/basic_evm_tester.cpp +++ b/tests/basic_evm_tester.cpp @@ -419,6 +419,24 @@ transaction_trace_ptr basic_evm_tester::setversion(uint64_t version, name actor) mvo()("version", version)); } +transaction_trace_ptr basic_evm_tester::updtgasparam(asset ram_price_mb, uint64_t minimum_gas_price, name actor) { + return basic_evm_tester::push_action(evm_account_name, "updtgasparam"_n, actor, + mvo()("ram_price_mb", ram_price_mb)("minimum_gas_price", minimum_gas_price)); +} + +transaction_trace_ptr basic_evm_tester::setgasparam(uint64_t gas_txnewaccount, + uint64_t gas_newaccount, + uint64_t gas_txcreate, + uint64_t gas_codedeposit, + uint64_t gas_sset, name actor) { + return basic_evm_tester::push_action(evm_account_name, "setgasparam"_n, actor, + mvo()("gas_txnewaccount", gas_txnewaccount) + ("gas_newaccount", gas_newaccount) + ("gas_txcreate", gas_txcreate) + ("gas_codedeposit", gas_codedeposit) + ("gas_sset", gas_sset)); +} + transaction_trace_ptr basic_evm_tester::rmgcstore(uint64_t id, name actor) { return basic_evm_tester::push_action(evm_account_name, "rmgcstore"_n, actor, mvo()("id", id)); diff --git a/tests/basic_evm_tester.hpp b/tests/basic_evm_tester.hpp index 85afe70f..49f718eb 100644 --- a/tests/basic_evm_tester.hpp +++ b/tests/basic_evm_tester.hpp @@ -403,6 +403,12 @@ class basic_evm_tester : public evm_validating_tester transaction_trace_ptr call(name from, const evmc::bytes& to, const evmc::bytes& value, evmc::bytes& data, uint64_t gas_limit, name actor); transaction_trace_ptr admincall(const evmc::bytes& from, const evmc::bytes& to, const evmc::bytes& value, evmc::bytes& data, uint64_t gas_limit, name actor); evmc::address deploy_contract(evm_eoa& eoa, evmc::bytes bytecode); + transaction_trace_ptr updtgasparam(asset ram_price_mb, uint64_t minimum_gas_price, name actor); + transaction_trace_ptr setgasparam(uint64_t gas_txnewaccount, + uint64_t gas_newaccount, + uint64_t gas_txcreate, + uint64_t gas_codedeposit, + uint64_t gas_sset, name actor); void addegress(const std::vector& accounts); void removeegress(const std::vector& accounts); diff --git a/tests/gas_param_tests.cpp b/tests/gas_param_tests.cpp new file mode 100644 index 00000000..b4ee7ece --- /dev/null +++ b/tests/gas_param_tests.cpp @@ -0,0 +1,174 @@ +#include "basic_evm_tester.hpp" + +using namespace eosio::testing; +using namespace evm_test; + +BOOST_AUTO_TEST_SUITE(evm_gas_param_tests) + +struct gas_param_evm_tester : basic_evm_tester +{ + evm_eoa faucet_eoa; + + static constexpr name miner_account_name = "alice"_n; + + gas_param_evm_tester() : + faucet_eoa(evmc::from_hex("a3f1b69da92a0233ce29485d3049a4ace39e8d384bbc2557e3fc60940ce4e954").value()) + { + create_accounts({miner_account_name}); + transfer_token(faucet_account_name, miner_account_name, make_asset(100'0000)); + } + + void fund_evm_faucet() + { + transfer_token(faucet_account_name, evm_account_name, make_asset(100'0000), faucet_eoa.address_0x()); + } +}; + +BOOST_FIXTURE_TEST_CASE(basic, gas_param_evm_tester) try { + + uint64_t suggested_gas_price = 150'000'000'000ull; + init(15555, suggested_gas_price); + + produce_block(); + fund_evm_faucet(); + produce_block(); + + // wrong permission + BOOST_REQUIRE_EXCEPTION( + updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, "alice"_n), + missing_auth_exception, [](const missing_auth_exception & e){ return true;}); + + // wrong permission + BOOST_REQUIRE_EXCEPTION( + setgasparam(1,2,3,4,5, "alice"_n), + missing_auth_exception, [](const missing_auth_exception & e){ return true;}); + + // require promoted evm_version larger or equal to 1 + BOOST_REQUIRE_EXCEPTION( + updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("evm_version must >= 1")); + + // require promoted evm_version larger or equal to 1 + BOOST_REQUIRE_EXCEPTION( + setgasparam(1,2,3,4,5, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("evm_version must >= 1")); + + setversion(1, evm_account_name); + + produce_block(); + produce_block(); + + // require promoted evm_version larger or equal to 1 + BOOST_REQUIRE_EXCEPTION( + updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("evm_version must >= 1")); + + // kick of setverion, evmtx event generated + { + evm_eoa recipient; + silkworm::Transaction tx{ + .type = silkworm::Transaction::Type::kLegacy, + .max_priority_fee_per_gas = suggested_gas_price, + .max_fee_per_gas = suggested_gas_price, + .gas_limit = 21000, + .to = recipient.address, + .value = 1, + }; + faucet_eoa.sign(tx); + chain::transaction_trace_ptr trace = pushtx(tx); + BOOST_REQUIRE_EQUAL(trace->action_traces.size(), 2); + BOOST_ASSERT(trace->action_traces.size() >= 2 && trace->action_traces[0].act.name == "pushtx"_n); + BOOST_ASSERT(trace->action_traces.size() >= 2 && trace->action_traces[1].act.name == "evmtx"_n); + } + + // require miniumum gas at least 1 gwei + BOOST_REQUIRE_EXCEPTION( + updtgasparam(asset(10'0000, native_symbol), 999'999'999, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("gas_price must >= 1Gwei")); + + // invalid symbol in ram_price_mb paramerter + BOOST_REQUIRE_EXCEPTION( + updtgasparam(asset(10'0000, symbol::from_string("0,EOS")), 1'000'000'000, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("invalid price symbol")); + BOOST_REQUIRE_EXCEPTION( + updtgasparam(asset(10'0000, symbol::from_string("4,SYS")), 1'000'000'000, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("invalid price symbol")); + + // G_sset must >= 2900 + BOOST_REQUIRE_EXCEPTION( + setgasparam(21000,21000,21000,21000,2899, evm_account_name), + eosio_assert_message_exception, + eosio_assert_message_is("G_sset must >= 2900")); + + updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, evm_account_name); + + setgasparam(21000,21000,21000,21000,2900, evm_account_name); + + { + evm_eoa recipient; + silkworm::Transaction tx{ + .type = silkworm::Transaction::Type::kLegacy, + .max_priority_fee_per_gas = 1'000'000'000, + .max_fee_per_gas = 1'000'000'000, + .gas_limit = 21000, + .to = recipient.address, + .value = 1, + }; + uint64_t cur_nonce = faucet_eoa.next_nonce; + faucet_eoa.sign(tx); + BOOST_REQUIRE_EXCEPTION( + pushtx(tx), + eosio_assert_message_exception, + eosio_assert_message_is("gas price is too low")); + faucet_eoa.next_nonce = cur_nonce; + } + + produce_block(); + produce_block(); + + // new gas price take effect in the next evm block, configchange event before evmtx + { + evm_eoa recipient; + silkworm::Transaction tx{ + .type = silkworm::Transaction::Type::kLegacy, + .max_priority_fee_per_gas = 1'000'000'000, + .max_fee_per_gas = 1'000'000'000, + .gas_limit = 21000, + .to = recipient.address, + .value = 1, + }; + faucet_eoa.sign(tx); + chain::transaction_trace_ptr trace = pushtx(tx); + BOOST_REQUIRE_EQUAL(trace->action_traces.size(), 3); + BOOST_ASSERT(trace->action_traces.size() >= 3 && trace->action_traces[0].act.name == "pushtx"_n); + BOOST_ASSERT(trace->action_traces.size() >= 3 && trace->action_traces[1].act.name == "configchange"_n); + BOOST_ASSERT(trace->action_traces.size() >= 3 && trace->action_traces[2].act.name == "evmtx"_n); + } + + // subsequence trxs will have no more configchange event + { + evm_eoa recipient; + silkworm::Transaction tx{ + .type = silkworm::Transaction::Type::kLegacy, + .max_priority_fee_per_gas = 1'000'000'000, + .max_fee_per_gas = 1'000'000'000, + .gas_limit = 21000, + .to = recipient.address, + .value = 2, + }; + faucet_eoa.sign(tx); + chain::transaction_trace_ptr trace = pushtx(tx); + BOOST_REQUIRE_EQUAL(trace->action_traces.size(), 2); + BOOST_ASSERT(trace->action_traces.size() >= 2 && trace->action_traces[0].act.name == "pushtx"_n); + BOOST_ASSERT(trace->action_traces.size() >= 2 && trace->action_traces[1].act.name == "evmtx"_n); + } + +} FC_LOG_AND_RETHROW() + +BOOST_AUTO_TEST_SUITE_END() From d39abf677216c5e92bd44af646d1994880c174ef Mon Sep 17 00:00:00 2001 From: kayan Date: Thu, 22 Feb 2024 09:53:53 +0800 Subject: [PATCH 09/10] minor fixes --- include/evm_runtime/evm_contract.hpp | 1 + include/evm_runtime/tables.hpp | 9 +++++++ include/evm_runtime/types.hpp | 7 ++++++ src/actions.cpp | 4 ++-- src/config_wrapper.cpp | 36 +++++++++++++--------------- 5 files changed, 35 insertions(+), 22 deletions(-) diff --git a/include/evm_runtime/evm_contract.hpp b/include/evm_runtime/evm_contract.hpp index 745b55f1..78005139 100644 --- a/include/evm_runtime/evm_contract.hpp +++ b/include/evm_runtime/evm_contract.hpp @@ -97,6 +97,7 @@ class [[eosio::contract]] evm_contract : public contract [[eosio::action]] void configchange(consensus_parameter_data_type consensus_parameter_data) { eosio::check(get_sender() == get_self(), "forbidden to call"); }; + using configchange_action = eosio::action_wrapper<"configchange"_n, &evm_contract::configchange>; #ifdef WITH_ADMIN_ACTIONS [[eosio::action]] void rmgcstore(uint64_t id); diff --git a/include/evm_runtime/tables.hpp b/include/evm_runtime/tables.hpp index 4fa14b9b..2bb16407 100644 --- a/include/evm_runtime/tables.hpp +++ b/include/evm_runtime/tables.hpp @@ -291,6 +291,15 @@ struct consensus_parameter_type { return current_block_num > pending_block_num; } + // Reference invalidated by get_consensus_param_and_maybe_promote and update_consensus_param. + const consensus_parameter_data_type& get_consensus_param( + time_point_sec genesis_time, time_point current_time) const { + if (is_pending_active(genesis_time, current_time)) { + return pending->data; + } + return current; + } + std::pair get_consensus_param_and_maybe_promote( time_point_sec genesis_time, time_point current_time) { if (is_pending_active(genesis_time, current_time)) { diff --git a/include/evm_runtime/types.hpp b/include/evm_runtime/types.hpp index 1d859878..bb8cd964 100644 --- a/include/evm_runtime/types.hpp +++ b/include/evm_runtime/types.hpp @@ -22,6 +22,13 @@ namespace evm_runtime { constexpr intx::uint256 minimum_natively_representable = intx::exp(10_u256, intx::uint256(evm_precision - token_symbol.precision())); static_assert(evm_precision - token_symbol.precision() <= 14, "dust math may overflow a uint64_t"); + constexpr double pow10_const(int v) { + double r = 1.0; + while (v-- > 0) r *= 10.0; + return r; + } + constexpr double minimum_natively_representable_f = pow10_const(evm_precision - token_symbol.precision()); + typedef intx::uint<256> uint256; typedef intx::uint<512> uint512; typedef std::vector bytes; diff --git a/src/actions.cpp b/src/actions.cpp index 733bff53..d83a89fa 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -460,8 +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) { - action(std::vector{}, get_self(), - "configchange"_n, gas_param_pair.first).send(); + configchange_action act{get_self(), std::vector()}; + act.send(gas_param_pair.first); } if (current_version >= 1) { diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index ca4e4783..0aa0160d 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -9,15 +9,13 @@ config_wrapper::config_wrapper(eosio::name self) : _self(self), _config(self, se if(_exists) { _cached_config = _config.get(); } - if (!_cached_config.consensus_parameter.has_value()){ + if (!_cached_config.consensus_parameter.has_value()) { _cached_config.consensus_parameter = consensus_parameter_type(); - } - std::visit([&](auto &v) { - if (v.minimum_gas_price == 0) { + std::visit([&](auto &v) { v.minimum_gas_price = _cached_config.gas_price; - // don't set dirty, as trxs can be read-only - } - }, _cached_config.consensus_parameter->current); + }, _cached_config.consensus_parameter->current); + // Don't set dirty because action can be read-only. + } } config_wrapper::~config_wrapper() { @@ -74,14 +72,9 @@ void config_wrapper::set_ingress_bridge_fee(const eosio::asset& ingress_bridge_f } uint64_t config_wrapper::get_gas_price()const { - uint64_t gas_price = _cached_config.gas_price; - if (_cached_config.consensus_parameter.has_value() && - _cached_config.consensus_parameter->is_pending_active(_cached_config.genesis_time, get_current_time())) { - std::visit([&](const auto &v) { - gas_price = v.minimum_gas_price; - }, _cached_config.consensus_parameter->pending->data); - } - return gas_price; + return std::visit([&](const auto& v) { + return v.minimum_gas_price; + }, _cached_config.consensus_parameter->get_consensus_param(_cached_config.genesis_time, get_current_time())); } uint32_t config_wrapper::get_miner_cut()const { @@ -133,7 +126,7 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, bool allow_any_to_be_unspecified) { if (fee_params.gas_price.has_value()) { - eosio::check(*fee_params.gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); + eosio::check(*fee_params.gas_price >= one_gwei, "gas_price must >= 1Gwei"); 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(), /* gas_txnewaccount */ @@ -145,6 +138,10 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, ); } else { _cached_config.gas_price = *fee_params.gas_price; + std::visit([&](auto &v) { + v.minimum_gas_price = _cached_config.gas_price; + }, + _cached_config.consensus_parameter->current); } } else { eosio::check(allow_any_to_be_unspecified, "All required fee parameters not specified: missing gas_price"); @@ -170,10 +167,9 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, void config_wrapper::update_gas_params(eosio::asset ram_price_mb, uint64_t minimum_gas_price) { eosio::check(ram_price_mb.symbol == token_symbol, "invalid price symbol"); - eosio::check(minimum_gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); + eosio::check(minimum_gas_price >= one_gwei, "gas_price must >= 1Gwei"); - double gas_per_byte_f = (ram_price_mb.amount / 10000.0 * 1e18 / (1024.0 * 1024.0)) / - (minimum_gas_price * (double)(100000 - _cached_config.miner_cut) / 100000.0); + double gas_per_byte_f = (ram_price_mb.amount / (1024.0 * 1024.0) * minimum_natively_representable_f) / (minimum_gas_price * static_cast(hundred_percent - _cached_config.miner_cut) / hundred_percent); constexpr uint64_t account_bytes = 347; constexpr uint64_t contract_fixed_bytes = 606; @@ -203,7 +199,7 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist"); if (minimum_gas_price.has_value()) { - eosio::check(*minimum_gas_price >= 1000000000ull, "gas_price must >= 1Gwei"); + eosio::check(*minimum_gas_price >= one_gwei, "gas_price must >= 1Gwei"); } _cached_config.consensus_parameter->update_consensus_param([&](auto & v) { From 0953e8d4be33c50fa98ca05233faf505255509d9 Mon Sep 17 00:00:00 2001 From: kayan Date: Fri, 23 Feb 2024 17:24:37 +0800 Subject: [PATCH 10/10] other fixes --- include/evm_runtime/config_wrapper.hpp | 4 ++-- include/evm_runtime/types.hpp | 1 + src/actions.cpp | 4 ++-- src/config_wrapper.cpp | 22 +++++++++++----------- tests/gas_param_tests.cpp | 8 +------- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/evm_runtime/config_wrapper.hpp b/include/evm_runtime/config_wrapper.hpp index 70d3b90d..21cce268 100644 --- a/include/evm_runtime/config_wrapper.hpp +++ b/include/evm_runtime/config_wrapper.hpp @@ -42,8 +42,8 @@ struct config_wrapper { void set_fee_parameters(const fee_parameters& fee_params, bool allow_any_to_be_unspecified); - void update_gas_params(eosio::asset ram_price_mb, uint64_t minimum_gas_price); - void update_gas_params2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional minimum_gas_price); + void update_consensus_parameters(eosio::asset ram_price_mb, uint64_t minimum_gas_price); + void update_consensus_parameters2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional minimum_gas_price); std::pair get_consensus_param_and_maybe_promote(); diff --git a/include/evm_runtime/types.hpp b/include/evm_runtime/types.hpp index bb8cd964..67bac0e9 100644 --- a/include/evm_runtime/types.hpp +++ b/include/evm_runtime/types.hpp @@ -15,6 +15,7 @@ namespace evm_runtime { static constexpr uint32_t ninety_percent = 90'000; static constexpr uint32_t hundred_percent = 100'000; static constexpr uint64_t one_gwei = 1'000'000'000ull; + static constexpr uint64_t gas_sset_min = 2900; constexpr unsigned evm_precision = 18; constexpr eosio::name token_account(eosio::name(TOKEN_ACCOUNT_NAME)); diff --git a/src/actions.cpp b/src/actions.cpp index d83a89fa..3470fd02 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -797,7 +797,7 @@ void evm_contract::setversion(uint64_t version) { void evm_contract::updtgasparam(eosio::asset ram_price_mb, uint64_t minimum_gas_price) { require_auth(get_self()); - _config->update_gas_params(ram_price_mb, minimum_gas_price); + _config->update_consensus_parameters(ram_price_mb, minimum_gas_price); } void evm_contract::setgasparam(uint64_t gas_txnewaccount, @@ -806,7 +806,7 @@ void evm_contract::setgasparam(uint64_t gas_txnewaccount, uint64_t gas_codedeposit, uint64_t gas_sset) { require_auth(get_self()); - _config->update_gas_params2(gas_txnewaccount, + _config->update_consensus_parameters2(gas_txnewaccount, gas_newaccount, gas_txcreate, gas_codedeposit, diff --git a/src/config_wrapper.cpp b/src/config_wrapper.cpp index 0aa0160d..91401bf9 100644 --- a/src/config_wrapper.cpp +++ b/src/config_wrapper.cpp @@ -127,9 +127,9 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, { if (fee_params.gas_price.has_value()) { eosio::check(*fee_params.gas_price >= one_gwei, "gas_price must >= 1Gwei"); - if (_cached_config.evm_version.has_value() && _cached_config.evm_version->cached_version >= 1) { + if (get_evm_version() >= 1) { // activate in the next evm block - this->update_gas_params2(std::optional(), /* gas_txnewaccount */ + this->update_consensus_parameters2(std::optional(), /* gas_txnewaccount */ std::optional(), /* gas_newaccount */ std::optional(), /* gas_txcreate */ std::optional(), /* gas_codedeposit */ @@ -164,7 +164,7 @@ void config_wrapper::set_fee_parameters(const fee_parameters& fee_params, set_dirty(); } -void config_wrapper::update_gas_params(eosio::asset ram_price_mb, uint64_t minimum_gas_price) { +void config_wrapper::update_consensus_parameters(eosio::asset ram_price_mb, uint64_t minimum_gas_price) { eosio::check(ram_price_mb.symbol == token_symbol, "invalid price symbol"); eosio::check(minimum_gas_price >= one_gwei, "gas_price must >= 1Gwei"); @@ -175,25 +175,25 @@ void config_wrapper::update_gas_params(eosio::asset ram_price_mb, uint64_t minim constexpr uint64_t contract_fixed_bytes = 606; constexpr uint64_t storage_slot_bytes = 346; + constexpr uint64_t max_gas_per_byte = (1ull << 43) - 1; + 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"); + eosio::check(gas_per_byte_f * contract_fixed_bytes < (double)(max_gas_per_byte), "gas_per_byte too big"); uint64_t gas_per_byte = (uint64_t)(gas_per_byte_f + 1.0); - this->update_gas_params2(account_bytes * gas_per_byte, /* gas_txnewaccount */ + this->update_consensus_parameters2(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*/ - 2900 + storage_slot_bytes * gas_per_byte,/*gas_sset*/ + gas_sset_min + storage_slot_bytes * gas_per_byte,/*gas_sset*/ minimum_gas_price /*minimum_gas_price*/ ); } -void config_wrapper::update_gas_params2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional minimum_gas_price) +void config_wrapper::update_consensus_parameters2(std::optional gas_txnewaccount, std::optional gas_newaccount, std::optional gas_txcreate, std::optional gas_codedeposit, std::optional gas_sset, std::optional 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"); + eosio::check(get_evm_version() >= 1, "evm_version must >= 1"); // should not happen eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist"); @@ -208,7 +208,7 @@ void config_wrapper::update_gas_params2(std::optional gas_txnewaccount if (gas_txcreate.has_value()) v.gas_parameter.gas_txcreate = *gas_txcreate; if (gas_codedeposit.has_value()) v.gas_parameter.gas_codedeposit = *gas_codedeposit; if (gas_sset.has_value()) { - eosio::check(*gas_sset >= 2900, "G_sset must >= 2900"); + eosio::check(*gas_sset >= gas_sset_min, "gas_sset too small"); v.gas_parameter.gas_sset = *gas_sset; } if (minimum_gas_price.has_value()) v.minimum_gas_price = *minimum_gas_price; diff --git a/tests/gas_param_tests.cpp b/tests/gas_param_tests.cpp index b4ee7ece..590d3adf 100644 --- a/tests/gas_param_tests.cpp +++ b/tests/gas_param_tests.cpp @@ -60,12 +60,6 @@ BOOST_FIXTURE_TEST_CASE(basic, gas_param_evm_tester) try { produce_block(); produce_block(); - // require promoted evm_version larger or equal to 1 - BOOST_REQUIRE_EXCEPTION( - updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, evm_account_name), - eosio_assert_message_exception, - eosio_assert_message_is("evm_version must >= 1")); - // kick of setverion, evmtx event generated { evm_eoa recipient; @@ -104,7 +98,7 @@ BOOST_FIXTURE_TEST_CASE(basic, gas_param_evm_tester) try { BOOST_REQUIRE_EXCEPTION( setgasparam(21000,21000,21000,21000,2899, evm_account_name), eosio_assert_message_exception, - eosio_assert_message_is("G_sset must >= 2900")); + eosio_assert_message_is("gas_sset too small")); updtgasparam(asset(10'0000, native_symbol), 1'000'000'000, evm_account_name);