Skip to content

Commit

Permalink
Merge branch 'main' into kayan_1.0_spring_main
Browse files Browse the repository at this point in the history
  • Loading branch information
taokayan committed Aug 8, 2024
2 parents 3a46f03 + df8db94 commit ee20087
Show file tree
Hide file tree
Showing 14 changed files with 447 additions and 150 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ jobs:
with:
owner: AntelopeIO
repo: cdt
target: 'v3.1.0'
target: 'v4.0.1'
prereleases: false
file: 'cdt_.*amd64.deb'

- name: Install CDT
run: sudo apt-get install -y ./cdt*.deb
run: |
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y ./cdt*.deb
- name: Build EOS EVM Contract
run: .github/workflows/build-contract.sh
Expand Down
13 changes: 11 additions & 2 deletions include/evm_runtime/config_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once
#include <eosio/eosio.hpp>

#include <evm_runtime/tables.hpp>
#include <eosio/asset.hpp>
#include <eosio/time.hpp>
#include <eosio/singleton.hpp>
#include <evm_runtime/tables.hpp>
namespace evm_runtime {

struct fee_parameters;
Expand All @@ -27,10 +27,19 @@ struct config_wrapper {
const eosio::asset& get_ingress_bridge_fee()const;
void set_ingress_bridge_fee(const eosio::asset& ingress_bridge_fee);

gas_prices_type get_gas_prices()const;
void set_gas_prices(const gas_prices_type& price);

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

template <typename Q, typename Func>
void enqueue(Func&& update_fnc);
void enqueue_gas_price(uint64_t gas_price);
void enqueue_gas_prices(const gas_prices_type& prices);

template <typename Q, typename Func>
void process_queue(Func&& update_func);
void process_price_queue();

uint32_t get_miner_cut()const;
Expand Down
5 changes: 4 additions & 1 deletion include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include <eosio/eosio.hpp>
#include <eosio/asset.hpp>
#include <eosio/binary_extension.hpp>
#include <eosio/singleton.hpp>
Expand All @@ -18,6 +17,8 @@ using namespace eosio;

namespace evm_runtime {

struct gas_prices_type;

class [[eosio::contract]] evm_contract : public contract
{
public:
Expand Down Expand Up @@ -88,6 +89,8 @@ class [[eosio::contract]] evm_contract : public contract
[[eosio::action]] void updtgasparam(eosio::asset ram_price_mb, uint64_t 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);

[[eosio::action]] void setgasprices(const gas_prices_type& prices);

// Events
[[eosio::action]] void evmtx(eosio::ignore<evm_runtime::evmtx_type> event){
eosio::check(get_sender() == get_self(), "forbidden to call");
Expand Down
114 changes: 24 additions & 90 deletions include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include <evm_runtime/value_promoter.hpp>

#include <eosio/eosio.hpp>
#include <eosio/fixed_bytes.hpp>
Expand All @@ -8,9 +9,11 @@

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

#include <eosevm/block_mapping.hpp>

#include <silkworm/core/common/base.hpp>

namespace evm_runtime {

using namespace eosio;
Expand Down Expand Up @@ -243,95 +246,15 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] config2
EOSLIB_SERIALIZE(config2, (next_account_id));
};

struct evm_version_type {
struct pending {
uint64_t version;
time_point 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(time.time_since_epoch().count());
return current_block_num > pending_block_num;
}
};

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;
}
return current_version;
}

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;
bool promoted = false;
if(pending_version.has_value() && pending_version->is_active(genesis_time, current_time)) {
current_version = pending_version->version;
promote_pending();
promoted = true;
}
return std::make_pair(current_version, 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 gas_prices_type {
uint64_t overhead_price{0};
uint64_t storage_price{0};
};
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;
}
using evm_version_type = uint64_t;

// 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<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);
}

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
};
}
};
VALUE_PROMOTER(evm_version_type);
VALUE_PROMOTER_REV(consensus_parameter_data_type);

struct [[eosio::table]] [[eosio::contract("evm_contract")]] config
{
Expand All @@ -342,12 +265,13 @@ 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_evm_version_type> 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<gas_prices_type> gas_prices;

EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version)(consensus_parameter)(token_contract)(queue_front_block));
EOSLIB_SERIALIZE(config, (version)(chainid)(genesis_time)(ingress_bridge_fee)(gas_price)(miner_cut)(status)(evm_version)(consensus_parameter)(token_contract)(queue_front_block)(gas_prices));
};

struct [[eosio::table]] [[eosio::contract("evm_contract")]] price_queue
Expand All @@ -359,7 +283,17 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] price_queue

EOSLIB_SERIALIZE(price_queue, (block)(price));
};

typedef eosio::multi_index<"pricequeue"_n, price_queue> price_queue_table;

struct [[eosio::table]] [[eosio::contract("evm_contract")]] prices_queue
{
uint64_t block;
gas_prices_type prices;

uint64_t primary_key()const { return block; }

EOSLIB_SERIALIZE(prices_queue, (block)(prices));
};
typedef eosio::multi_index<"pricesqueue"_n, prices_queue> prices_queue_table;

} //namespace evm_runtime
17 changes: 13 additions & 4 deletions include/evm_runtime/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,24 @@ namespace evm_runtime {

using bridge_message = std::variant<bridge_message_v0>;

struct evmtx_v0 {
struct evmtx_base {
uint64_t eos_evm_version;
bytes rlptx;
EOSLIB_SERIALIZE(evmtx_base, (eos_evm_version)(rlptx));
};

struct evmtx_v1 : evmtx_base {
uint64_t base_fee_per_gas;

EOSLIB_SERIALIZE(evmtx_v0, (eos_evm_version)(rlptx)(base_fee_per_gas));
EOSLIB_SERIALIZE_DERIVED(evmtx_v1, evmtx_base, (base_fee_per_gas));
};

struct evmtx_v3 : evmtx_base {
uint64_t overhead_price;
uint64_t storage_price;
EOSLIB_SERIALIZE_DERIVED(evmtx_v3, evmtx_base, (overhead_price)(storage_price));
};

using evmtx_type = std::variant<evmtx_v0>;
using evmtx_type = std::variant<evmtx_v1, evmtx_v3>;

struct fee_parameters
{
Expand Down
65 changes: 65 additions & 0 deletions include/evm_runtime/value_promoter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once
#include <eosio/time.hpp>
#include <eosio/print.hpp>
#include <eosevm/block_mapping.hpp>

#define VALUE_PROMOTER_PENDING(T)\
struct T##_pending {\
T value;\
time_point 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(time.time_since_epoch().count());\
return current_block_num > pending_block_num;\
}\
};

#define VALUE_PROMOTER_IMPL(T)\
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_value;\
}\
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_value.has_value() && pending_value->is_active(genesis_time, current_time)) {\
current_value = pending_value->value;\
promote_pending();\
promoted = true;\
}\
return std::pair<T, bool>(current_value, promoted);\
}\
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(T##_pending{\
.value = value.first,\
.time = current_time\
});\
}\
void promote_pending() {\
eosio::check(pending_value.has_value(), "no pending value");\
cached_value = pending_value.value().value;\
pending_value.reset();\
}

#define VALUE_PROMOTER(T)\
VALUE_PROMOTER_PENDING(T);\
struct value_promoter_##T {\
std::optional<T##_pending> pending_value;\
T cached_value = T{};\
VALUE_PROMOTER_IMPL(T)\
};

#define VALUE_PROMOTER_REV(T)\
VALUE_PROMOTER_PENDING(T);\
struct value_promoter_##T {\
T cached_value = T{};\
std::optional<T##_pending> pending_value;\
VALUE_PROMOTER_IMPL(T)\
};
2 changes: 1 addition & 1 deletion silkworm
Submodule silkworm updated 1 files
+2 −1 eosevm/version.hpp
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=35984)
endif()
31 changes: 24 additions & 7 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,13 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const
Block block;

std::optional<uint64_t> base_fee_per_gas;
auto gas_prices = _config->get_gas_prices();
if (current_version >= 1) {
base_fee_per_gas = _config->get_gas_price();
if( current_version >= 3) {
//base_fee_per_gas = f(gas_prices, min_inclusion_price)
} else {
base_fee_per_gas = _config->get_gas_price();
}
}

eosevm::prepare_block_header(block.header, bm, get_self().value,
Expand All @@ -493,8 +498,6 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const
);
}, gas_param_pair.first);

silkworm::ExecutionProcessor ep{block, engine, state, *found_chain_config->second, gas_params};

if (current_version >= 1) {
auto inclusion_price = std::min(tx.max_priority_fee_per_gas, tx.max_fee_per_gas - *base_fee_per_gas);
eosio::check(inclusion_price >= (min_inclusion_price.has_value() ? *min_inclusion_price : 0), "inclusion price must >= min_inclusion_price");
Expand All @@ -503,6 +506,8 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const
check(tx.max_fee_per_gas >= _config->get_gas_price(), "gas price is too low");
}

silkworm::ExecutionProcessor ep{block, engine, state, *found_chain_config->second, gas_params};

// Filter EVM messages (with data) that are sent to the reserved address
// corresponding to the EOS account holding the contract (self)
ep.set_evm_message_filter([&](const evmc_message& message) -> bool {
Expand All @@ -522,10 +527,12 @@ void evm_contract::process_tx(const runtime_config& rc, eosio::name miner, const
act.send(gas_param_pair.first);
}

if (current_version >= 1) {
auto event = evmtx_type{evmtx_v0{current_version, txn.get_rlptx(), *base_fee_per_gas}};
action(std::vector<permission_level>{}, get_self(), "evmtx"_n, event)
.send();
if(current_version >= 3) {
auto event = evmtx_type{evmtx_v3{current_version, txn.get_rlptx(), gas_prices.overhead_price, gas_prices.storage_price}};
action(std::vector<permission_level>{}, get_self(), "evmtx"_n, event).send();
} else if (current_version >= 1) {
auto event = evmtx_type{evmtx_v1{current_version, txn.get_rlptx(), *base_fee_per_gas}};
action(std::vector<permission_level>{}, get_self(), "evmtx"_n, event).send();
}
LOGTIME("EVM END");
}
Expand Down Expand Up @@ -899,4 +906,14 @@ void evm_contract::setgasparam(uint64_t gas_txnewaccount,
gas_sset);
}

void evm_contract::setgasprices(const gas_prices_type& prices) {
require_auth(get_self());
auto current_version = _config->get_evm_version_and_maybe_promote();
if(current_version >= 3) {
_config->enqueue_gas_prices(prices);
} else {
_config->set_gas_prices(prices);
}
}

} //evm_runtime
Loading

0 comments on commit ee20087

Please sign in to comment.