Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #11 from eosnetworkfoundation/backport-params
Browse files Browse the repository at this point in the history
Backport BLOCKCHAIN_PARAMETERS from 2.1
  • Loading branch information
swatanabe authored Jan 18, 2022
2 parents 8748f59 + ee592ad commit 3dbbf95
Show file tree
Hide file tree
Showing 21 changed files with 1,016 additions and 3 deletions.
9 changes: 9 additions & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ struct controller_impl {
set_activation_handler<builtin_protocol_feature_t::wtmsig_block_signatures>();
set_activation_handler<builtin_protocol_feature_t::action_return_value>();
set_activation_handler<builtin_protocol_feature_t::configurable_wasm_limits>();
set_activation_handler<builtin_protocol_feature_t::blockchain_parameters>();

self.irreversible_block.connect([this](const block_state_ptr& bsp) {
wasmif.current_lib(bsp->block_num);
Expand Down Expand Up @@ -3419,6 +3420,14 @@ void controller_impl::on_activation<builtin_protocol_feature_t::configurable_was
} );
}

template<>
void controller_impl::on_activation<builtin_protocol_feature_t::blockchain_parameters>() {
db.modify( db.get<protocol_state_object>(), [&]( auto& ps ) {
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "get_parameters_packed" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "set_parameters_packed" );
} );
}

/// End of protocol feature activation handlers

} } /// eosio::chain
267 changes: 267 additions & 0 deletions libraries/chain/include/eosio/chain/chain_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <eosio/chain/types.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/chain_config_helper.hpp>

namespace eosio { namespace chain {

Expand Down Expand Up @@ -193,6 +194,7 @@ struct config_entry_validator{

//after adding 1st value to chain_config_v1 change this using to point to v1
using chain_config = chain_config_v1;
using config_range = data_range<chain_config, config_entry_validator>;

} } // namespace eosio::chain

Expand All @@ -212,3 +214,268 @@ FC_REFLECT(eosio::chain::chain_config_v0,
FC_REFLECT_DERIVED(eosio::chain::chain_config_v1, (eosio::chain::chain_config_v0),
(max_action_return_value_size)
)

namespace fc {

/**
* @brief This is for packing data_entry<chain_config_v0, ...>
* that is used as part of packing data_range<chain_config_v0, ...>
* @param s datastream
* @param entry contains config reference and particular id
* @throws config_parse_error if id is unknown
*/
template <typename DataStream>
inline DataStream &operator<<(DataStream &s, const eosio::chain::data_entry<eosio::chain::chain_config_v0, eosio::chain::config_entry_validator> &entry){
using namespace eosio::chain;

//initial requirements were to skip packing field if it is not activated.
//this approach allows to spam this function with big buffer so changing this behavior
EOS_ASSERT(entry.is_allowed(), unsupported_feature, "config id ${id} is no allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v0::max_block_net_usage_id:
fc::raw::pack(s, entry.config.max_block_net_usage);
break;
case chain_config_v0::target_block_net_usage_pct_id:
fc::raw::pack(s, entry.config.target_block_net_usage_pct);
break;
case chain_config_v0::max_transaction_net_usage_id:
fc::raw::pack(s, entry.config.max_transaction_net_usage);
break;
case chain_config_v0::base_per_transaction_net_usage_id:
fc::raw::pack(s, entry.config.base_per_transaction_net_usage);
break;
case chain_config_v0::net_usage_leeway_id:
fc::raw::pack(s, entry.config.net_usage_leeway);
break;
case chain_config_v0::context_free_discount_net_usage_num_id:
fc::raw::pack(s, entry.config.context_free_discount_net_usage_num);
break;
case chain_config_v0::context_free_discount_net_usage_den_id:
fc::raw::pack(s, entry.config.context_free_discount_net_usage_den);
break;
case chain_config_v0::max_block_cpu_usage_id:
fc::raw::pack(s, entry.config.max_block_cpu_usage);
break;
case chain_config_v0::target_block_cpu_usage_pct_id:
fc::raw::pack(s, entry.config.target_block_cpu_usage_pct);
break;
case chain_config_v0::max_transaction_cpu_usage_id:
fc::raw::pack(s, entry.config.max_transaction_cpu_usage);
break;
case chain_config_v0::min_transaction_cpu_usage_id:
fc::raw::pack(s, entry.config.min_transaction_cpu_usage);
break;
case chain_config_v0::max_transaction_lifetime_id:
fc::raw::pack(s, entry.config.max_transaction_lifetime);
break;
case chain_config_v0::deferred_trx_expiration_window_id:
fc::raw::pack(s, entry.config.deferred_trx_expiration_window);
break;
case chain_config_v0::max_transaction_delay_id:
fc::raw::pack(s, entry.config.max_transaction_delay);
break;
case chain_config_v0::max_inline_action_size_id:
fc::raw::pack(s, entry.config.max_inline_action_size);
break;
case chain_config_v0::max_inline_action_depth_id:
fc::raw::pack(s, entry.config.max_inline_action_depth);
break;
case chain_config_v0::max_authority_depth_id:
fc::raw::pack(s, entry.config.max_authority_depth);
break;
default:
FC_THROW_EXCEPTION(config_parse_error, "DataStream& operator<<: no such id: ${id}", ("id", entry.id));
}
return s;
}

/**
* @brief This is for packing data_entry<chain_config_v1, ...>
* that is used as part of packing data_range<chain_config_v1, ...>
* @param s datastream
* @param entry contains config reference and particular id
* @throws unsupported_feature if protocol feature for particular id is not activated
*/
template <typename DataStream>
inline DataStream &operator<<(DataStream &s, const eosio::chain::data_entry<eosio::chain::chain_config_v1, eosio::chain::config_entry_validator> &entry){
using namespace eosio::chain;

//initial requirements were to skip packing field if it is not activated.
//this approach allows to spam this function with big buffer so changing this behavior
//moreover:
//The contract has no way to know that the value was skipped and is likely to behave incorrectly.
//When the protocol feature is not activated, the old version of nodeos that doesn't know about
//the entry MUST behave the same as the new version of nodeos that does.
//Skipping known but unactivated entries violates this.
EOS_ASSERT(entry.is_allowed(), unsupported_feature, "config id ${id} is no allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v1::max_action_return_value_size_id:
fc::raw::pack(s, entry.config.max_action_return_value_size);
break;
default:
data_entry<chain_config_v0, config_entry_validator> base_entry(entry);
fc::raw::pack(s, base_entry);
}

return s;
}

/**
* @brief This is for unpacking data_entry<chain_config_v0, ...>
* that is used as part of unpacking data_range<chain_config_v0, ...>
* @param s datastream
* @param entry contains config reference and particular id
* @throws unsupported_feature if protocol feature for particular id is not activated
*/
template <typename DataStream>
inline DataStream &operator>>(DataStream &s, eosio::chain::data_entry<eosio::chain::chain_config_v0, eosio::chain::config_entry_validator> &entry){
using namespace eosio::chain;

EOS_ASSERT(entry.is_allowed(), eosio::chain::unsupported_feature, "config id ${id} is no allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v0::max_block_net_usage_id:
fc::raw::unpack(s, entry.config.max_block_net_usage);
break;
case chain_config_v0::target_block_net_usage_pct_id:
fc::raw::unpack(s, entry.config.target_block_net_usage_pct);
break;
case chain_config_v0::max_transaction_net_usage_id:
fc::raw::unpack(s, entry.config.max_transaction_net_usage);
break;
case chain_config_v0::base_per_transaction_net_usage_id:
fc::raw::unpack(s, entry.config.base_per_transaction_net_usage);
break;
case chain_config_v0::net_usage_leeway_id:
fc::raw::unpack(s, entry.config.net_usage_leeway);
break;
case chain_config_v0::context_free_discount_net_usage_num_id:
fc::raw::unpack(s, entry.config.context_free_discount_net_usage_num);
break;
case chain_config_v0::context_free_discount_net_usage_den_id:
fc::raw::unpack(s, entry.config.context_free_discount_net_usage_den);
break;
case chain_config_v0::max_block_cpu_usage_id:
fc::raw::unpack(s, entry.config.max_block_cpu_usage);
break;
case chain_config_v0::target_block_cpu_usage_pct_id:
fc::raw::unpack(s, entry.config.target_block_cpu_usage_pct);
break;
case chain_config_v0::max_transaction_cpu_usage_id:
fc::raw::unpack(s, entry.config.max_transaction_cpu_usage);
break;
case chain_config_v0::min_transaction_cpu_usage_id:
fc::raw::unpack(s, entry.config.min_transaction_cpu_usage);
break;
case chain_config_v0::max_transaction_lifetime_id:
fc::raw::unpack(s, entry.config.max_transaction_lifetime);
break;
case chain_config_v0::deferred_trx_expiration_window_id:
fc::raw::unpack(s, entry.config.deferred_trx_expiration_window);
break;
case chain_config_v0::max_transaction_delay_id:
fc::raw::unpack(s, entry.config.max_transaction_delay);
break;
case chain_config_v0::max_inline_action_size_id:
fc::raw::unpack(s, entry.config.max_inline_action_size);
break;
case chain_config_v0::max_inline_action_depth_id:
fc::raw::unpack(s, entry.config.max_inline_action_depth);
break;
case chain_config_v0::max_authority_depth_id:
fc::raw::unpack(s, entry.config.max_authority_depth);
break;
default:
FC_THROW_EXCEPTION(eosio::chain::config_parse_error, "DataStream& operator<<: no such id: ${id}", ("id", entry.id));
}

return s;
}

/**
* @brief This is for unpacking data_entry<chain_config_v1, ...>
* that is used as part of unpacking data_range<chain_config_v1, ...>
* @param s datastream
* @param entry contains config reference and particular id
* @throws unsupported_feature if protocol feature for particular id is not activated
*/
template <typename DataStream>
inline DataStream &operator>>(DataStream &s, eosio::chain::data_entry<eosio::chain::chain_config_v1, eosio::chain::config_entry_validator> &entry){
using namespace eosio::chain;

EOS_ASSERT(entry.is_allowed(), unsupported_feature, "config id ${id} is no allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v1::max_action_return_value_size_id:
fc::raw::unpack(s, entry.config.max_action_return_value_size);
break;
default:
eosio::chain::data_entry<chain_config_v0, config_entry_validator> base_entry(entry);
fc::raw::unpack(s, base_entry);
}

return s;
}

/**
* @brief Packs config stream in the following format:
* |uint32_t:sequence_length | uint32_t:parameter_id | <various>:parameter_value | ...
* @param s datastream
* @param selection contains ids range to pack
* @throws config_parse_error on duplicate or unknown id in selection
*/
template<typename DataStream, typename T>
inline DataStream& operator<<( DataStream& s, const eosio::chain::data_range<T, eosio::chain::config_entry_validator>& selection ) {
using namespace eosio::chain;

fc::unsigned_int size = selection.ids.size();
fc::raw::pack(s, size);

//vector here serves as hash map where key is always an index
std::vector<bool> visited(T::PARAMS_COUNT, false);
for (auto uid : selection.ids){
uint32_t id = uid;
EOS_ASSERT(id < visited.size(), config_parse_error, "provided id ${id} should be less than ${size}", ("id", id)("size", visited.size()));
EOS_ASSERT(!visited[id], config_parse_error, "duplicate id provided: ${id}", ("id", id));
visited[id] = true;

fc::raw::pack(s, fc::unsigned_int(id));
fc::raw::pack(s, data_entry(selection.config, id, selection.validator));
}

return s;
}

/**
* @brief Unpacks config stream in the following format:
* |uint32_t:sequence_length | uint32_t:parameter_id | <various>:parameter_value | ...
* @param s datastream
* @param selection contains config reference where values will be unpacked
* @throws config_parse_error on duplicate or unknown id in stream
*/
template<typename DataStream, typename T>
inline DataStream& operator>>( DataStream& s, eosio::chain::data_range<T, eosio::chain::config_entry_validator>& selection ) {
using namespace eosio::chain;

fc::unsigned_int length;
fc::raw::unpack(s, length);

//vector here serves as hash map where key is always an index
std::vector<bool> visited(T::PARAMS_COUNT, false);
for (uint32_t i = 0; i < length; ++i) {
fc::unsigned_int id;
fc::raw::unpack(s, id);

EOS_ASSERT(id.value < visited.size(), config_parse_error, "provided id ${id} should be less than ${size}", ("id", id)("size", visited.size()));
EOS_ASSERT(!visited[id], config_parse_error, "duplicate id provided: ${id}", ("id", id));
visited[id] = true;

data_entry<T, config_entry_validator> cfg_entry(selection.config, id, selection.validator);
fc::raw::unpack(s, cfg_entry);
}
return s;
}

} //namespace fc
51 changes: 51 additions & 0 deletions libraries/chain/include/eosio/chain/chain_config_helper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <eosio/chain/types.hpp> /* vector */

namespace eosio { namespace chain {

/**
* helper class to serialize only selected ids of the class
*/
template<typename T, typename Validator>
struct data_range {

T& config;
vector<fc::unsigned_int> ids;
Validator validator;

data_range(T& c, Validator val) : config(c), validator(val){}
data_range(T& c, vector<fc::unsigned_int>&& id_list, const Validator& val)
: data_range(c, val){
ids = std::move(id_list);
}
};

/**
* helper class to serialize specific class entry
*/
template<typename T, typename Validator>
struct data_entry {
private:
struct _dummy{};
public:

T& config;
uint32_t id;
Validator validator;
data_entry(T& c, uint32_t entry_id, Validator validate)
: config(c),
id(entry_id),
validator(validate) {}
template <typename Y>
explicit data_entry(const data_entry<Y, Validator>& another,
typename std::enable_if_t<std::is_base_of_v<T, Y>, _dummy> = _dummy{})
: data_entry(another.config, another.id, another.validator)
{}

bool is_allowed() const{
return validator(id);
}
};

}} // namespace eosio::chain
2 changes: 2 additions & 0 deletions libraries/chain/include/eosio/chain/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ namespace eosio { namespace chain {
3160010, "No abi file found" )
FC_DECLARE_DERIVED_EXCEPTION( wasm_config_unknown_version, contract_exception,
3160015, "Unknown wasm_config version" )
FC_DECLARE_DERIVED_EXCEPTION( config_parse_error, contract_exception,
3160016, "Parsing config error" )

FC_DECLARE_DERIVED_EXCEPTION( producer_exception, chain_exception,
3170000, "Producer exception" )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ enum class builtin_protocol_feature_t : uint32_t {
wtmsig_block_signatures,
action_return_value,
configurable_wasm_limits,
blockchain_parameters
};

struct protocol_feature_subjective_restrictions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,9 @@ inline constexpr auto get_intrinsic_table() {
"eosio_injection._eosio_ui64_to_f64",
"env.set_action_return_value",
"env.get_wasm_parameters_packed",
"env.set_wasm_parameters_packed"
"env.set_wasm_parameters_packed",
"env.get_parameters_packed",
"env.set_parameters_packed"
);
}
inline constexpr std::size_t find_intrinsic_index(std::string_view hf) {
Expand Down
Loading

0 comments on commit 3dbbf95

Please sign in to comment.