Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IF: Unification: Changes in controller to complete unification - Part 2 #2077

Merged
merged 25 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e2804da
Update `start_block` for IF.
greg7mdp Jan 9, 2024
610af7d
Mostly whitespace cleanup.
greg7mdp Jan 9, 2024
7d933af
Change `[greg todo]` to `#warning` for `producer_authority_schedule` …
greg7mdp Jan 9, 2024
1a3ded1
Resolve multiple `todo`s in controller and implement bew bhs::next() …
greg7mdp Jan 11, 2024
d2af863
GH-1980 Implement proposer policy change
heifner Jan 11, 2024
57ccf14
Update some todo comments.
greg7mdp Jan 11, 2024
be875ee
Merge branch 'hotstuff_integration' of github.com:AntelopeIO/leap int…
greg7mdp Jan 11, 2024
2c98018
Merge remote-tracking branch 'origin/gh_2034_part2' into GH-1980-prop…
heifner Jan 12, 2024
e896105
GH-1980 Fix merge issue
heifner Jan 12, 2024
a3c7628
Merge pull request #2078 from AntelopeIO/GH-1980-proposer
heifner Jan 12, 2024
0e72f5a
Move `header_exts` to block_header_state
greg7mdp Jan 12, 2024
53faa5b
Merge branch 'gh_2034_part2' of github.com:AntelopeIO/leap into gh_20…
greg7mdp Jan 12, 2024
8e3dca2
GH-1980 Copy over active policies
heifner Jan 12, 2024
cd3190d
cleanup `next(block_header_state_input& data)` function and update `h…
greg7mdp Jan 12, 2024
ab52975
Merge branch 'gh_2034_part2' of github.com:AntelopeIO/leap into gh_20…
greg7mdp Jan 12, 2024
d01debb
Cleanup `next(const signed_block_header& h, ...)`.
greg7mdp Jan 12, 2024
9499630
Add missing block id computation to `next()` function.
greg7mdp Jan 12, 2024
7253499
Simplify `block_header_state_core::next()` API.
greg7mdp Jan 12, 2024
fa2a60a
Remove unneeded template parameter for `block_data_gen_t`
greg7mdp Jan 12, 2024
1cc9fe3
Fix issue I introduced in commit 7253499
greg7mdp Jan 12, 2024
6473f31
Update `apply_block()` so that it works for the IF path.
greg7mdp Jan 12, 2024
854e9db
Fix todo for `report_block_header_diff`.
greg7mdp Jan 12, 2024
71cf33c
remove `block_state::cached_id` and update `id()` member function.
greg7mdp Jan 13, 2024
8934a42
Add `completed_block` construction for IF mode.
greg7mdp Jan 13, 2024
161d585
Remove unneeded include.
greg7mdp Jan 16, 2024
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
156 changes: 131 additions & 25 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
#include <eosio/chain/block_header_state.hpp>
#include <eosio/chain/block_header_state_utils.hpp>
#include <eosio/chain/hotstuff/instant_finality_extension.hpp>
#include <eosio/chain/hotstuff/proposer_policy.hpp>
#include <eosio/chain/exceptions.hpp>
#include <limits>

namespace eosio::chain {

producer_authority block_header_state::get_scheduled_producer(block_timestamp_type t) const {
return detail::get_scheduled_producer(proposer_policy->proposer_schedule.producers, t);
return detail::get_scheduled_producer(active_proposer_policy->proposer_schedule.producers, t);
}

const vector<digest_type>& block_header_state::get_new_protocol_feature_activations()const {
return detail::get_new_protocol_feature_activations(header_exts);
}

#warning Add last_proposed_finalizer_policy_generation to snapshot_block_header_state_v3, see header file TODO

block_header_state_core block_header_state_core::next(const uint32_t last_qc_block_num, bool is_last_qc_strong) const {
block_header_state_core block_header_state_core::next(qc_info_t incoming) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not const &?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passing by reference (indirection with a pointer) would actually be slower since the whole struct is 8 bytes.

// no state change if last_qc_block_num is the same
if (last_qc_block_num == this->last_qc_block_num) {
if (incoming.last_qc_block_num == this->last_qc_block_num) {
return {*this};
}

EOS_ASSERT(last_qc_block_num > this->last_qc_block_num, block_validate_exception,
EOS_ASSERT(incoming.last_qc_block_num > this->last_qc_block_num, block_validate_exception,
"new last_qc_block_num must be greater than old last_qc_block_num");

auto old_last_qc_block_num = this->last_qc_block_num;
auto old_final_on_strong_qc_block_num = this->final_on_strong_qc_block_num;

block_header_state_core result{*this};

if (is_last_qc_strong) {
if (incoming.is_last_qc_strong) {
// last QC is strong. We can progress forward.

// block with old final_on_strong_qc_block_num becomes irreversible
Expand All @@ -47,7 +52,7 @@ block_header_state_core block_header_state_core::next(const uint32_t last_qc_blo
}

// new last_qc_block_num is always the input last_qc_block_num.
result.last_qc_block_num = last_qc_block_num;
result.last_qc_block_num = incoming.last_qc_block_num;

return result;
}
Expand All @@ -61,37 +66,138 @@ block_header_state block_header_state::next(block_header_state_input& input) con
result.header = block_header {
.timestamp = input.timestamp, // [greg todo] do we have to do the slot++ stuff from the legacy version?
.producer = input.producer,
.confirmed = hs_block_confirmed, // todo: consider 0 instead
.previous = input.parent_id,
.transaction_mroot = input.transaction_mroot,
.action_mroot = input.action_mroot,
//.schedule_version = ?, [greg todo]
//.new_producers = ? [greg todo]
.schedule_version = header.schedule_version
};

// core
// ----
if (input.qc_info)
result.core = core.next(input.qc_info->last_qc_block_num, input.qc_info->is_last_qc_strong);
else
result.core = core;

// add block header extensions
// activated protocol features
// ---------------------------
if (!input.new_protocol_feature_activations.empty()) {
result.activated_protocol_features = std::make_shared<protocol_feature_activation_set>(
*activated_protocol_features, input.new_protocol_feature_activations);
} else {
result.activated_protocol_features = activated_protocol_features;
}

// block_header_state_core
// -----------------------
result.core = input.qc_info ? core.next(*input.qc_info) : core;

// proposal_mtree and finality_mtree
// ---------------------------------
// [greg todo] ??

// proposer policy
// ---------------
result.active_proposer_policy = active_proposer_policy;

if(!proposer_policies.empty()) {
auto it = proposer_policies.begin();
if (it->first <= input.timestamp) {
result.active_proposer_policy = it->second;
result.header.schedule_version = header.schedule_version + 1;
result.active_proposer_policy->proposer_schedule.version = result.header.schedule_version;
result.proposer_policies = { ++it, proposer_policies.end() };
} else {
result.proposer_policies = proposer_policies;
}
}

if (input.new_proposer_policy) {
// called when assembling the block
result.proposer_policies[result.header.timestamp] = input.new_proposer_policy;
}

// finalizer policy
// ----------------
result.active_finalizer_policy = active_finalizer_policy;

// [greg todo] correct support for new finalizer_policy activation using finalizer_policies map

if (input.new_finalizer_policy)
++input.new_finalizer_policy->generation;

std::optional<qc_info_t> qc_info = input.qc_info;
if (!qc_info) {
// [greg todo]: copy the one from the previous block (look in header.header_extensions)

// add IF block header extension
// -----------------------------
uint16_t if_ext_id = instant_finality_extension::extension_id();
auto if_entry = header_exts.lower_bound(if_ext_id);
auto& if_ext = std::get<instant_finality_extension>(if_entry->second);

instant_finality_extension new_if_ext {if_ext.qc_info,
std::move(input.new_finalizer_policy),
std::move(input.new_proposer_policy)};
if (input.qc_info)
new_if_ext.qc_info = *input.qc_info;

emplace_extension(result.header.header_extensions, if_ext_id, fc::raw::pack(new_if_ext));
result.header_exts.emplace(if_ext_id, std::move(new_if_ext));

// add protocol_feature_activation extension
// -----------------------------------------
if (!input.new_protocol_feature_activations.empty()) {
uint16_t ext_id = protocol_feature_activation::extension_id();
protocol_feature_activation pfa_ext{.protocol_features = std::move(input.new_protocol_feature_activations)};

emplace_extension(result.header.header_extensions, ext_id, fc::raw::pack(pfa_ext));
result.header_exts.emplace(ext_id, std::move(pfa_ext));
}

emplace_extension(result.header.header_extensions, instant_finality_extension::extension_id(),
fc::raw::pack(instant_finality_extension{qc_info,
std::move(input.new_finalizer_policy),
std::move(input.new_proposer_policy)}));


// Finally update block id from header
// -----------------------------------
result.id = result.header.calculate_id();

return result;
}

/**
* Transitions the current header state into the next header state given the supplied signed block header.
*
* Given a signed block header, generate the expected template based upon the header time,
* then validate that the provided header matches the template.
*
* If the header specifies new_producers then apply them accordingly.
*/
block_header_state block_header_state::next(const signed_block_header& h, const protocol_feature_set& pfs,
validator_t& validator) const {
auto producer = detail::get_scheduled_producer(active_proposer_policy->proposer_schedule.producers, h.timestamp).producer_name;

EOS_ASSERT( h.previous == id, unlinkable_block_exception, "previous mismatch" );
EOS_ASSERT( h.producer == producer, wrong_producer, "wrong producer specified" );

auto exts = h.validate_and_extract_header_extensions();

// retrieve protocol_feature_activation from incoming block header extension
// -------------------------------------------------------------------------
vector<digest_type> new_protocol_feature_activations;
if( exts.count(protocol_feature_activation::extension_id() > 0) ) {
auto pfa_entry = exts.lower_bound(protocol_feature_activation::extension_id());
auto& pfa_ext = std::get<protocol_feature_activation>(pfa_entry->second);
new_protocol_feature_activations = std::move(pfa_ext.protocol_features);
}

// retrieve instant_finality_extension data from block header extension
// --------------------------------------------------------------------
EOS_ASSERT(exts.count(instant_finality_extension::extension_id() > 0), misc_exception,
"Instant Finality Extension is expected to be present in all block headers after switch to IF");
auto if_entry = exts.lower_bound(instant_finality_extension::extension_id());
auto& if_ext = std::get<instant_finality_extension>(if_entry->second);

building_block_input bb_input{
.parent_id = id,
.timestamp = h.timestamp,
.producer = producer,
.new_protocol_feature_activations = std::move(new_protocol_feature_activations)
};

block_header_state_input bhs_input{
bb_input, h.transaction_mroot, h.action_mroot, if_ext.new_proposer_policy, if_ext.new_finalizer_policy,
if_ext.qc_info};

return next(bhs_input);
}

} // namespace eosio::chain
22 changes: 8 additions & 14 deletions libraries/chain/block_header_state_legacy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,15 @@ namespace eosio::chain {

if( maybe_new_producer_schedule ) {
result.pending_schedule.schedule = std::move(*maybe_new_producer_schedule);
result.pending_schedule.schedule_hash = std::move(*maybe_new_producer_schedule_hash);
result.pending_schedule.schedule_hash = *maybe_new_producer_schedule_hash;
result.pending_schedule.schedule_lib_num = block_number;
} else {
if( was_pending_promoted ) {
result.pending_schedule.schedule.version = prev_pending_schedule.schedule.version;
} else {
result.pending_schedule.schedule = std::move( prev_pending_schedule.schedule );
}
result.pending_schedule.schedule_hash = std::move( prev_pending_schedule.schedule_hash );
result.pending_schedule.schedule_hash = prev_pending_schedule.schedule_hash ;
result.pending_schedule.schedule_lib_num = prev_pending_schedule.schedule_lib_num;
}

Expand Down Expand Up @@ -369,13 +369,12 @@ namespace eosio::chain {
*/
block_header_state_legacy block_header_state_legacy::next(
const signed_block_header& h,
vector<signature_type>&& _additional_signatures,
vector<signature_type>&& additional_signatures,
const protocol_feature_set& pfs,
bool hotstuff_activated,
validator_t& validator,
bool skip_validate_signee )const
{
return next( h.timestamp, h.confirmed ).finish_next( h, std::move(_additional_signatures), pfs, validator, skip_validate_signee );
return next( h.timestamp, h.confirmed ).finish_next( h, std::move(additional_signatures), pfs, validator, skip_validate_signee );
}

digest_type block_header_state_legacy::sig_digest()const {
Expand Down Expand Up @@ -430,15 +429,10 @@ namespace eosio::chain {
}

/**
* Reference cannot outlive *this. Assumes header_exts is not mutated after instatiation.
* Reference cannot outlive *this. Assumes header_exts is not mutated after instantiation.
*/
const vector<digest_type>& block_header_state_legacy::get_new_protocol_feature_activations()const {
static const vector<digest_type> no_activations{};

if( header_exts.count(protocol_feature_activation::extension_id()) == 0 )
return no_activations;

return std::get<protocol_feature_activation>(header_exts.lower_bound(protocol_feature_activation::extension_id())->second).protocol_features;
return detail::get_new_protocol_feature_activations(header_exts);
}

block_header_state_legacy::block_header_state_legacy( legacy::snapshot_block_header_state_v2&& snapshot )
Expand All @@ -452,10 +446,10 @@ namespace eosio::chain {
producer_to_last_implied_irb = std::move(snapshot.producer_to_last_implied_irb);
valid_block_signing_authority = block_signing_authority_v0{ 1, {{std::move(snapshot.block_signing_key), 1}} };
confirm_count = std::move(snapshot.confirm_count);
id = std::move(snapshot.id);
id = snapshot.id;
header = std::move(snapshot.header);
pending_schedule.schedule_lib_num = snapshot.pending_schedule.schedule_lib_num;
pending_schedule.schedule_hash = std::move(snapshot.pending_schedule.schedule_hash);
pending_schedule.schedule_hash = snapshot.pending_schedule.schedule_hash;
pending_schedule.schedule = producer_authority_schedule( snapshot.pending_schedule.schedule );
activated_protocol_features = std::move(snapshot.activated_protocol_features);
}
Expand Down
Loading