Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bdfeb08
Introduce chain_config_v2 for max_sync_call_depth and max_sync_call_d…
linh2931 Mar 14, 2025
ea867bf
Update test-data/consensus_blockchain/snapshot for new chain_config
linh2931 Mar 14, 2025
35cee9e
Implement Snapshot V9 to support new chain_config_v2
linh2931 Mar 16, 2025
77fcfbb
Update snapshot compatible test for snapshot V9
linh2931 Mar 16, 2025
176cedb
Update test snapshot for savanna_misc_tests/verify_block_compatibitity
linh2931 Mar 16, 2025
c77065a
Correct syntax error in assert text (from no allowed to not allowed)
linh2931 Mar 16, 2025
318d440
Print out the value of MAX_SIZE_OF_BYTE_ARRAYS for EOS_ASSERT of max_…
linh2931 Mar 16, 2025
2ffd898
Update SHiP ABI file for chain_config_v2
linh2931 Mar 16, 2025
93f0295
Remove unnecessary == and != operators
linh2931 Mar 19, 2025
1890e98
Replace a unsafe assignment operator (v1&v2 fields left out) with an …
linh2931 Mar 19, 2025
7a19b34
Do not reset v1 and v2 fields to default and replace manual assignmen…
linh2931 Mar 19, 2025
806fd71
Add chain_config_v2 fields to SHiP packing operator
linh2931 Mar 20, 2025
fee79f7
add default == operator
linh2931 Mar 20, 2025
0296069
point to abieos sync_call branch which has new chain_config_v2 for SH…
linh2931 Mar 20, 2025
4799bfe
Update test_deltas_global_property_history to use ship_protocol::chai…
linh2931 Mar 20, 2025
ebd7f51
Update the variant index of chain_config for SHiP serialization
linh2931 Mar 20, 2025
ddf7fdf
Update to point to latest abieos which fixes missing chain_config_v1 …
linh2931 Mar 20, 2025
e3e4305
Merge branch 'call_implementation' into sync_call_limits
linh2931 Mar 20, 2025
466c6c2
Merge branch 'sync_call' into sync_call_limits
linh2931 Mar 28, 2025
30d934c
Correct a typo in a comment
linh2931 Mar 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion libraries/chain/chain_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,17 @@ namespace eosio { namespace chain {
void chain_config_v1::validate() const {
chain_config_v0::validate();
EOS_ASSERT( max_action_return_value_size <= MAX_SIZE_OF_BYTE_ARRAYS, action_validate_exception,
"max action return value size should be less than MAX_SIZE_OF_BYTE_ARRAYS" );
"max action return value size should be less than ${max} (MAX_SIZE_OF_BYTE_ARRAYS)",
("max", MAX_SIZE_OF_BYTE_ARRAYS));
}

void chain_config_v2::validate() const {
chain_config_v1::validate();
EOS_ASSERT( 1 <= max_sync_call_depth, action_validate_exception,
"max sync call depth should be at least 1" );
EOS_ASSERT( max_sync_call_data_size <= MAX_SIZE_OF_BYTE_ARRAYS, action_validate_exception,
"max sync call data size should be less than ${max} (MAX_SIZE_OF_BYTE_ARRAYS)",
("max", MAX_SIZE_OF_BYTE_ARRAYS));
}

bool config_entry_validator::operator()(uint32_t id) const {
Expand All @@ -56,6 +66,16 @@ bool config_entry_validator::operator()(uint32_t id) const {
}
}
break;

case chain_config_v2::max_sync_call_depth_id:
case chain_config_v2::max_sync_call_data_size_id:
{
allowed = control.is_builtin_activated(builtin_protocol_feature_t::sync_call);
if (!allowed){
wlog("sync_call protocol feature is not active, max_sync_call_depth and max_sync_call_data_size configs are not allowed");
}
}
break;
}

return allowed;
Expand Down
23 changes: 22 additions & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2388,6 +2388,7 @@ struct controller_impl {
using v3 = legacy::snapshot_global_property_object_v3;
using v4 = legacy::snapshot_global_property_object_v4;
using v5 = legacy::snapshot_global_property_object_v5;
using v6 = legacy::snapshot_global_property_object_v6;

if (std::clamp(header.version, v2::minimum_version, v2::maximum_version) == header.version ) {
std::optional<genesis_state> genesis = extract_legacy_genesis_state(*snapshot, header.version);
Expand Down Expand Up @@ -2440,6 +2441,18 @@ struct controller_impl {
});
return; // early out to avoid default processing
}

if (std::clamp(header.version, v6::minimum_version, v6::maximum_version) == header.version) {
snapshot->read_section<global_property_object>([&db = this->db](auto& section) {
v6 legacy_global_properties;
section.read_row(legacy_global_properties, db);

db.create<global_property_object>([&legacy_global_properties](auto& gpo) {
gpo.initialize_from(legacy_global_properties);
});
});
return; // early out to avoid default processing
}
}

snapshot->read_section<value_t>([this,&rows_loaded]( auto& section ) {
Expand Down Expand Up @@ -2559,7 +2572,7 @@ struct controller_impl {

genesis.initial_configuration.validate();
db.create<global_property_object>([&genesis,&chain_id=this->chain_id](auto& gpo ){
gpo.configuration = genesis.initial_configuration;
gpo.configuration.copy_from_v0(genesis.initial_configuration);
// TODO: Update this when genesis protocol features are enabled.
gpo.wasm_configuration = genesis_state::default_initial_wasm_configuration;
gpo.chain_id = chain_id;
Expand Down Expand Up @@ -6035,6 +6048,7 @@ chain_id_type controller::extract_chain_id(snapshot_reader& snapshot) {

using v4 = legacy::snapshot_global_property_object_v4;
using v5 = legacy::snapshot_global_property_object_v5;
using v6 = legacy::snapshot_global_property_object_v6;
if (header.version <= v4::maximum_version) {
snapshot.read_section<global_property_object>([&chain_id]( auto &section ){
v4 global_properties;
Expand All @@ -6049,6 +6063,13 @@ chain_id_type controller::extract_chain_id(snapshot_reader& snapshot) {
chain_id = global_properties.chain_id;
});
}
else if (header.version <= v6::maximum_version) {
snapshot.read_section<global_property_object>([&chain_id]( auto &section ){
v6 global_properties;
section.read_row(global_properties);
chain_id = global_properties.chain_id;
});
}
else {
snapshot.read_section<global_property_object>([&chain_id]( auto &section ){
snapshot_global_property_object global_properties;
Expand Down
130 changes: 123 additions & 7 deletions libraries/chain/include/eosio/chain/chain_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,55 @@ struct chain_config_v1 : chain_config_v0 {
}
};

/**
* @brief v2 Producer-voted blockchain configuration parameters
*
* If Adding new parameters create chain_config_v[n] class instead of adding
* new parameters to v2, v1 or v0. This is needed for snapshots backward compatibility
*/
struct chain_config_v2 : chain_config_v1 {
using Base = chain_config_v1;

uint32_t max_sync_call_depth = config::default_max_sync_call_depth; ///< size limit for sync call depth
uint32_t max_sync_call_data_size = config::default_max_sync_call_data_size; ///< size limit for sync call data: input and return value respectively

//order must match parameters as ids are used in serialization
enum {
max_sync_call_depth_id = Base::PARAMS_COUNT,
max_sync_call_data_size_id,
PARAMS_COUNT
};

inline const Base& base() const {
return static_cast<const Base&>(*this);
}

void validate() const;

template<typename Stream>
friend Stream& operator << ( Stream& out, const chain_config_v2& c ) {
return c.log(out) << "\n";
}

// no need to define !=
bool operator == (const chain_config_v2&) const = default;

inline void copy_from_v0(const chain_config_v0& b) {
// copy v0 fields
chain_config_v0::operator= (b);

// leave v1 and v2 fields alone as changing them might break consensus
// if the intention is to only set v0 fields.
}

protected:
template<typename Stream>
Stream& log(Stream& out) const{
return base().log(out) << ", Max Sync Call Depth: " << max_sync_call_depth
<< ", Max Sync Call Data Size: " << max_sync_call_data_size;
}
};

class controller;

struct config_entry_validator{
Expand All @@ -192,8 +241,8 @@ struct config_entry_validator{
bool operator()(uint32_t id) const;
};

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

} } // namespace eosio::chain
Expand All @@ -215,6 +264,10 @@ FC_REFLECT_DERIVED(eosio::chain::chain_config_v1, (eosio::chain::chain_config_v0
(max_action_return_value_size)
)

FC_REFLECT_DERIVED(eosio::chain::chain_config_v2, (eosio::chain::chain_config_v1),
(max_sync_call_depth)(max_sync_call_data_size)
)

namespace fc {

/**
Expand All @@ -230,7 +283,7 @@ inline DataStream &operator<<(DataStream &s, const eosio::chain::data_entry<eosi

//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));
EOS_ASSERT(entry.is_allowed(), unsupported_feature, "config id ${id} is not allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v0::max_block_net_usage_id:
Expand Down Expand Up @@ -308,7 +361,7 @@ inline DataStream &operator<<(DataStream &s, const eosio::chain::data_entry<eosi
//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));
EOS_ASSERT(entry.is_allowed(), unsupported_feature, "config id ${id} is not allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v1::max_action_return_value_size_id:
Expand All @@ -322,6 +375,41 @@ inline DataStream &operator<<(DataStream &s, const eosio::chain::data_entry<eosi
return s;
}

/**
* @brief This is for packing data_entry<chain_config_v2, ...>
* that is used as part of packing data_range<chain_config_v2, ...>
* @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_v2, 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 not allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v2::max_sync_call_depth_id:
fc::raw::pack(s, entry.config.max_sync_call_depth);
break;
case chain_config_v2::max_sync_call_data_size_id:
fc::raw::pack(s, entry.config.max_sync_call_data_size);
break;
default:
data_entry<chain_config_v1, 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, ...>
Expand All @@ -333,7 +421,7 @@ 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));
EOS_ASSERT(entry.is_allowed(), eosio::chain::unsupported_feature, "config id ${id} is not allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v0::max_block_net_usage_id:
Expand Down Expand Up @@ -405,7 +493,7 @@ 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));
EOS_ASSERT(entry.is_allowed(), unsupported_feature, "config id ${id} is not allowed", ("id", entry.id));

switch (entry.id){
case chain_config_v1::max_action_return_value_size_id:
Expand All @@ -419,6 +507,34 @@ inline DataStream &operator>>(DataStream &s, eosio::chain::data_entry<eosio::cha
return s;
}

/**
* @brief This is for unpacking data_entry<chain_config_v2, ...>
* that is used as part of unpacking data_range<chain_config_v2, ...>
* @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_v2, eosio::chain::config_entry_validator> &entry){
using namespace eosio::chain;

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

switch (entry.id){
case chain_config_v2::max_sync_call_depth_id:
fc::raw::unpack(s, entry.config.max_sync_call_depth);
break;
case chain_config_v2::max_sync_call_data_size_id:
fc::raw::unpack(s, entry.config.max_sync_call_data_size);
break;
default:
eosio::chain::data_entry<chain_config_v1, 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 | ...
Expand Down Expand Up @@ -478,4 +594,4 @@ inline DataStream& operator>>( DataStream& s, eosio::chain::data_range<T, eosio:
return s;
}

} //namespace fc
} //namespace fc
2 changes: 2 additions & 0 deletions libraries/chain/include/eosio/chain/chain_id_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace chain {
struct snapshot_global_property_object_v3;
struct snapshot_global_property_object_v4;
struct snapshot_global_property_object_v5;
struct snapshot_global_property_object_v6;
}

struct chain_id_type : public fc::sha256 {
Expand Down Expand Up @@ -62,6 +63,7 @@ namespace chain {
friend struct legacy::snapshot_global_property_object_v3;
friend struct legacy::snapshot_global_property_object_v4;
friend struct legacy::snapshot_global_property_object_v5;
friend struct legacy::snapshot_global_property_object_v6;
};

} } // namespace eosio::chain
Expand Down
4 changes: 3 additions & 1 deletion libraries/chain/include/eosio/chain/chain_snapshot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ struct chain_snapshot_header {
* - new member `latest_qc_claim_block_active_finalizer_policy` in `block_header_state`
* - 2 new members (`pending` and `active` policy generations in every `block_ref` of the `finality_core`)
* - Spring v1.0.1 is incompatible with v7 format, but can read previous formats
* 9: Updated for Spring v2.0.0 release:
* - chain_config_v2 update for new members `max_sync_call_depth` and `max_sync_call_data_size`
*/

static constexpr uint32_t minimum_compatible_version = 2;
static constexpr uint32_t current_version = 8;
static constexpr uint32_t current_version = 9;

static constexpr uint32_t first_version_with_split_table_sections = 7;

Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/include/eosio/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ const static uint32_t default_max_variable_signature_length = 16384u;
const static uint32_t default_max_action_return_value_size = 256;
const static uint32_t default_max_reversible_blocks = 3600u;

const static uint32_t default_max_sync_call_depth = 16u;
const static uint32_t default_max_sync_call_data_size = 512 * 1024; // for input and output each

const static uint32_t default_max_transaction_finality_status_success_duration_sec = 180;
const static uint32_t default_max_transaction_finality_status_failure_duration_sec = 180;

Expand Down
24 changes: 21 additions & 3 deletions libraries/chain/include/eosio/chain/global_property_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,25 @@ namespace eosio::chain {

std::optional<block_num_type> proposed_schedule_block_num;
producer_authority_schedule proposed_schedule;
chain_config configuration;
chain_config_v1 configuration;
chain_id_type chain_id;
kv_database_config kv_configuration;
wasm_config wasm_configuration;
};
struct snapshot_global_property_object_v6 {
// minimum_version and maximum_version refer to chain_snapshot_header
// version. snapshot_global_property_object_v6 applies to version 7 & 8
static constexpr uint32_t minimum_version = 7;
static constexpr uint32_t maximum_version = 8;
static_assert(chain_snapshot_header::minimum_compatible_version <= maximum_version,
"snapshot_global_property_object_v6 is no longer needed");

std::optional<block_num_type> proposed_schedule_block_num;
producer_authority_schedule proposed_schedule;
chain_config_v1 configuration;
chain_id_type chain_id;
wasm_config wasm_configuration;
};
}

/**
Expand Down Expand Up @@ -102,7 +116,7 @@ namespace eosio::chain {
proposed_schedule = legacy.proposed_schedule;
}

configuration = legacy.configuration;
configuration.copy_from_v0(legacy.configuration);
chain_id = chain_id_val;

if constexpr (std::is_same_v<T, legacy::snapshot_global_property_object_v2> ||
Expand All @@ -113,7 +127,7 @@ namespace eosio::chain {
}
}

// For snapshot_global_property_object v3, v4, and v5
// For snapshot_global_property_object v3, v4, v5, and v6
template<typename T>
void initialize_from( const T& legacy ) {
initialize_from(legacy, legacy.chain_id);
Expand Down Expand Up @@ -207,6 +221,10 @@ FC_REFLECT(eosio::chain::legacy::snapshot_global_property_object_v5,
(proposed_schedule_block_num)(proposed_schedule)(configuration)(chain_id)(kv_configuration)(wasm_configuration)
)

FC_REFLECT(eosio::chain::legacy::snapshot_global_property_object_v6,
(proposed_schedule_block_num)(proposed_schedule)(configuration)(chain_id)(wasm_configuration)
)

FC_REFLECT(eosio::chain::snapshot_global_property_object,
(proposed_schedule_block_num)(proposed_schedule)(configuration)(chain_id)(wasm_configuration)
)
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/eosio/chain/snapshot_detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ namespace eosio::chain::snapshot_detail {

struct snapshot_block_state_data_v8 {
static constexpr uint32_t minimum_version = 8;
static constexpr uint32_t maximum_version = 8;
static constexpr uint32_t maximum_version = 9;

std::optional<snapshot_block_header_state_legacy_v3> bs_l;
std::optional<snapshot_block_state_v8> bs;
Expand Down
Loading