Skip to content

Commit

Permalink
Use value_promoter to handle evm_version, consensus_parameter, overhe…
Browse files Browse the repository at this point in the history
…ad_price and storage_price
  • Loading branch information
elmato committed Jul 11, 2024
1 parent 48ad835 commit bd1b6a0
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 97 deletions.
99 changes: 31 additions & 68 deletions include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,10 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] config2
EOSLIB_SERIALIZE(config2, (next_account_id));
};

struct evm_version_type {
template <typename T>
struct value_promoter {
struct pending {
uint64_t version;
T value;
time_point time;

bool is_active(time_point_sec genesis_time, time_point current_time)const {
Expand All @@ -256,81 +257,43 @@ struct evm_version_type {
}
};

uint64_t get_version(time_point_sec genesis_time, time_point current_time)const {
uint64_t current_version = cached_version;
if(pending_version.has_value() && pending_version->is_active(genesis_time, current_time)) {
current_version = pending_version->version;
T get_value(time_point_sec genesis_time, time_point current_time)const {
T current_value = cached_value;
if(pending_value.has_value() && pending_value->is_active(genesis_time, current_time)) {
current_value = pending_value->value;
}
return current_version;
return current_value;
}

std::pair<uint64_t, bool> get_version_and_maybe_promote(time_point_sec genesis_time, time_point current_time) {
uint64_t current_version = cached_version;
std::pair<T, bool> get_value_and_maybe_promote(time_point_sec genesis_time, time_point current_time) {
T current_value = cached_value;
bool promoted = false;
if(pending_version.has_value() && pending_version->is_active(genesis_time, current_time)) {
current_version = pending_version->version;
if(pending_value.has_value() && pending_value->is_active(genesis_time, current_time)) {
current_value = pending_value->value;
promote_pending();
promoted = true;
}
return std::make_pair(current_version, promoted);
return std::make_pair(current_value, promoted);
}

void promote_pending() {
eosio::check(pending_version.has_value(), "no pending version");
cached_version = pending_version.value().version;
pending_version.reset();
}

std::optional<pending> pending_version;
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_consensus_parameter_data_type> 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->pending_time.time_since_epoch().count());
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;
template <typename Visitor>
void update(Visitor&& visitor_fn, time_point_sec genesis_time, time_point current_time) {
auto value = get_value_and_maybe_promote(genesis_time, current_time);
visitor_fn(value.first);
pending_value.emplace(pending{
.value = value.first,
.time = current_time
});
}

std::pair<const consensus_parameter_data_type &, bool> 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->data;
pending.reset();
// don't use make_pair as it create ref to temp objects
return std::pair<const consensus_parameter_data_type &, bool>(current, true);
}
return std::pair<const consensus_parameter_data_type &, bool>(current, false);
void promote_pending() {
eosio::check(pending_value.has_value(), "no pending value");
cached_value = pending_value.value().value;
pending_value.reset();
}

template <typename Visitor>
void update_consensus_param(Visitor visitor_fn, time_point 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
};
}
std::optional<pending> pending_value;
T cached_value=T{};
};

struct [[eosio::table]] [[eosio::contract("evm_contract")]] config
Expand All @@ -342,12 +305,12 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] config
uint64_t gas_price = 0;
uint32_t miner_cut = 0;
uint32_t status = 0; // <- bit mask values from status_flags
binary_extension<evm_version_type> evm_version;
binary_extension<consensus_parameter_type> consensus_parameter;
binary_extension<value_promoter<uint64_t>> evm_version;
binary_extension<value_promoter<consensus_parameter_data_type>> consensus_parameter;
binary_extension<eosio::name> token_contract; // <- default(unset) means eosio.token
binary_extension<uint32_t> queue_front_block;
binary_extension<uint64_t> overhead_price;
binary_extension<uint64_t> storage_price;
binary_extension<value_promoter<uint64_t>> overhead_price;
binary_extension<value_promoter<uint64_t>> storage_price;

EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version)(consensus_parameter)(token_contract)(queue_front_block)(overhead_price)(storage_price));
};
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ target_compile_options(evm_runtime PUBLIC --no-missing-ricardian-clause)
if (WITH_LARGE_STACK)
target_link_options(evm_runtime PUBLIC --stack-size=50000000)
else()
target_link_options(evm_runtime PUBLIC --stack-size=37328)
target_link_options(evm_runtime PUBLIC --stack-size=35504)
endif()
66 changes: 40 additions & 26 deletions src/config_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ config_wrapper::config_wrapper(eosio::name self) : _self(self), _config(self, se
if(_exists) {
_cached_config = _config.get();
}
if (!_cached_config.evm_version.has_value()) {
_cached_config.evm_version = value_promoter<uint64_t>{};
// Don't set dirty because action can be read-only.
}
if (!_cached_config.consensus_parameter.has_value()) {
_cached_config.consensus_parameter = consensus_parameter_type();
_cached_config.consensus_parameter = value_promoter<consensus_parameter_data_type>{};
// Don't set dirty because action can be read-only.
}
if (!_cached_config.token_contract.has_value()) {
Expand All @@ -21,10 +25,10 @@ config_wrapper::config_wrapper(eosio::name self) : _self(self), _config(self, se
_cached_config.queue_front_block = 0;
}
if (!_cached_config.overhead_price.has_value()) {
_cached_config.overhead_price = 0;
_cached_config.overhead_price = value_promoter<uint64_t>{};
}
if (!_cached_config.storage_price.has_value()) {
_cached_config.storage_price = 0;
_cached_config.storage_price = value_promoter<uint64_t>{};
}
}

Expand Down Expand Up @@ -92,20 +96,28 @@ void config_wrapper::set_gas_price(uint64_t gas_price) {
}

uint64_t config_wrapper::get_overhead_price()const {
return *_cached_config.overhead_price;
// should not happen
eosio::check(_cached_config.overhead_price.has_value(), "overhead_price not exist");
return _cached_config.overhead_price->get_value(_cached_config.genesis_time, get_current_time());
}

void config_wrapper::set_overhead_price(uint64_t price) {
_cached_config.overhead_price = price;
_cached_config.overhead_price->update([&](auto& v) {
v = price;
}, _cached_config.genesis_time, get_current_time());
set_dirty();
}

uint64_t config_wrapper::get_storage_price()const {
return *_cached_config.storage_price;
// should not happen
eosio::check(_cached_config.storage_price.has_value(), "storage_price not exist");
return _cached_config.storage_price->get_value(_cached_config.genesis_time, get_current_time());
}

void config_wrapper::set_storage_price(uint64_t price) {
_cached_config.storage_price = price;
_cached_config.storage_price->update([&](auto& v) {
v = price;
}, _cached_config.genesis_time, get_current_time());
set_dirty();
}

Expand Down Expand Up @@ -181,18 +193,16 @@ void config_wrapper::set_status(uint32_t status) {
}

uint64_t config_wrapper::get_evm_version()const {
uint64_t current_version = 0;
if(_cached_config.evm_version.has_value()) {
current_version = _cached_config.evm_version->get_version(_cached_config.genesis_time, get_current_time());
}
return current_version;
// should not happen
eosio::check(_cached_config.evm_version.has_value(), "evm_version not exist");
return _cached_config.evm_version->get_value(_cached_config.genesis_time, get_current_time());
}

uint64_t config_wrapper::get_evm_version_and_maybe_promote() {
uint64_t current_version = 0;
bool promoted = false;
if(_cached_config.evm_version.has_value()) {
std::tie(current_version, promoted) = _cached_config.evm_version->get_version_and_maybe_promote(_cached_config.genesis_time, get_current_time());
std::tie(current_version, promoted) = _cached_config.evm_version->get_value_and_maybe_promote(_cached_config.genesis_time, get_current_time());
}
if(promoted) {
if(current_version >=1 && _cached_config.miner_cut != 0) _cached_config.miner_cut = 0;
Expand All @@ -205,7 +215,9 @@ void config_wrapper::set_evm_version(uint64_t new_version) {
eosio::check(new_version <= eosevm::max_eos_evm_version, "Unsupported version");
auto current_version = get_evm_version_and_maybe_promote();
eosio::check(new_version > current_version, "new version must be greater than the active one");
_cached_config.evm_version.emplace(evm_version_type{evm_version_type::pending{new_version, get_current_time()}, current_version});
_cached_config.evm_version->update([&](auto& v) {
v = new_version;
}, _cached_config.genesis_time, get_current_time());
set_dirty();
}

Expand Down Expand Up @@ -285,32 +297,34 @@ void config_wrapper::update_consensus_parameters2(std::optional<uint64_t> gas_tx
// should not happen
eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist");

_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()) {
eosio::check(*gas_sset >= gas_sset_min, "gas_sset too small");
v.gas_parameter.gas_sset = *gas_sset;
}
}, get_current_time());
_cached_config.consensus_parameter->update([&](auto& p) {
std::visit([&](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()) {
eosio::check(*gas_sset >= gas_sset_min, "gas_sset too small");
v.gas_parameter.gas_sset = *gas_sset;
}
}, p);
}, _cached_config.genesis_time, get_current_time());

set_dirty();
}

const consensus_parameter_data_type& config_wrapper::get_consensus_param() {
// should not happen
eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist");
return _cached_config.consensus_parameter->get_consensus_param(_cached_config.genesis_time, get_current_time());
return _cached_config.consensus_parameter->get_value(_cached_config.genesis_time, get_current_time());
}

std::pair<const consensus_parameter_data_type &, bool> config_wrapper::get_consensus_param_and_maybe_promote() {

// should not happen
eosio::check(_cached_config.consensus_parameter.has_value(), "consensus_parameter not exist");

auto pair = _cached_config.consensus_parameter->get_consensus_param_and_maybe_promote(_cached_config.genesis_time, get_current_time());
auto pair = _cached_config.consensus_parameter->get_value_and_maybe_promote(_cached_config.genesis_time, get_current_time());
if (pair.second) {
set_dirty();
}
Expand Down
12 changes: 12 additions & 0 deletions tests/basic_evm_tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ namespace fc { namespace raw {
fc::raw::unpack(ds, queue_front_block);
tmp.queue_front_block.emplace(queue_front_block);
}
if(ds.remaining()) {
uint32_t overhead_price;
fc::raw::unpack(ds, overhead_price);
tmp.overhead_price.emplace(overhead_price);
}
if(ds.remaining()) {
uint32_t storage_price;
fc::raw::unpack(ds, storage_price);
tmp.storage_price.emplace(storage_price);
}

} FC_RETHROW_EXCEPTIONS(warn, "error unpacking partial_account_table_row") }
}}

Expand Down Expand Up @@ -317,6 +328,7 @@ config_table_row basic_evm_tester::get_config() const
static constexpr eosio::chain::name config_singleton_name = "config"_n;
const vector<char> d =
get_row_by_account(evm_account_name, evm_account_name, config_singleton_name, config_singleton_name);

return fc::raw::unpack<config_table_row>(d);
}

Expand Down
7 changes: 5 additions & 2 deletions tests/basic_evm_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ struct pending_consensus_parameter_data_type {
fc::time_point pending_time;
};
struct consensus_parameter_type {
consensus_parameter_data_type current;
std::optional<pending_consensus_parameter_data_type> pending;
consensus_parameter_data_type current;
};
struct config_table_row
{
Expand All @@ -109,6 +109,9 @@ struct config_table_row
std::optional<consensus_parameter_type> consensus_parameter;
std::optional<name> token_contract;
std::optional<uint32_t> queue_front_block;
std::optional<uint64_t> overhead_price;
std::optional<uint64_t> storage_price;

};

struct config2_table_row
Expand Down Expand Up @@ -235,7 +238,7 @@ FC_REFLECT(evm_test::account_code, (id)(ref_count)(code)(code_hash));
FC_REFLECT(evm_test::evmtx_v0, (eos_evm_version)(rlptx)(base_fee_per_gas));
FC_REFLECT_DERIVED(evm_test::evmtx_v1, (evm_test::evmtx_v0), (overhead_price)(storage_price));

FC_REFLECT(evm_test::consensus_parameter_type, (current)(pending));
FC_REFLECT(evm_test::consensus_parameter_type, (pending)(current));
FC_REFLECT(evm_test::pending_consensus_parameter_data_type, (data)(pending_time));
FC_REFLECT(evm_test::consensus_parameter_data_v0, (gas_parameter));
FC_REFLECT(evm_test::gas_parameter_type, (gas_txnewaccount)(gas_newaccount)(gas_txcreate)(gas_codedeposit)(gas_sset));
Expand Down

0 comments on commit bd1b6a0

Please sign in to comment.