Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
70 changes: 49 additions & 21 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,18 @@ const vector<digest_type>& block_header_state::get_new_protocol_feature_activati

#warning Add last_proposed_finalizer_policy_generation to snapshot_block_header_state_v3, see header file TODO

// -------------------------------------------------------------------------------------------------
// `finish_next` updates the next `block_header_state` according to the contents of the
// header extensions (either new protocol_features or instant_finality_extension) applicable to this
// next block .
//
// These extensions either result from the execution of the previous block (in case this node
// was the block producer) or were received from the network in a `signed_block`.
// -------------------------------------------------------------------------------------------------
Copy link
Contributor

Choose a reason for hiding this comment

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

Like those descriptions!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

void finish_next(const block_header_state& prev,
block_header_state& next_header_state,
vector<digest_type> new_protocol_feature_activations,
std::shared_ptr<proposer_policy> new_proposer_policy,
std::optional<finalizer_policy> new_finalizer_policy,
qc_claim_t qc_claim) {

instant_finality_extension if_ext) {
// activated protocol features
// ---------------------------
if (!new_protocol_feature_activations.empty()) {
Expand All @@ -98,7 +103,7 @@ void finish_next(const block_header_state& prev,
// ---------------
next_header_state.active_proposer_policy = prev.active_proposer_policy;

if(!prev.proposer_policies.empty()) {
if (!prev.proposer_policies.empty()) {
auto it = prev.proposer_policies.begin();
// +1 since this is called after the block is built, this will be the active schedule for the next block
if (it->first.slot <= next_header_state.header.timestamp.slot + 1) {
Expand All @@ -109,9 +114,10 @@ void finish_next(const block_header_state& prev,
}
}

if (new_proposer_policy) {
if (if_ext.new_proposer_policy) {
// called when assembling the block
next_header_state.proposer_policies[new_proposer_policy->active_time] = std::move(new_proposer_policy);
next_header_state.proposer_policies[if_ext.new_proposer_policy->active_time] =
std::move(if_ext.new_proposer_policy);
}

// finality_core
Expand All @@ -120,54 +126,77 @@ void finish_next(const block_header_state& prev,
.block_id = prev.block_id,
.timestamp = prev.timestamp()
};
next_header_state.core = prev.core.next(parent_block, qc_claim);
next_header_state.core = prev.core.next(parent_block, if_ext.qc_claim);

// finalizer policy
// ----------------
next_header_state.active_finalizer_policy = prev.active_finalizer_policy;

if(!prev.finalizer_policies.empty()) {
if (!prev.finalizer_policies.empty()) {
auto lib = next_header_state.core.last_final_block_num();
auto it = prev.finalizer_policies.begin();
if (it->first > lib) {
// we have at least one `finalizer_policy` in our map, but none of these is
// due to become active of this block because lib has not advanced enough, so
// we just copy the multimap and keep using the same `active_finalizer_policy`
// ---------------------------------------------------------------------------
next_header_state.finalizer_policies = prev.finalizer_policies;
} else {
while (it != prev.finalizer_policies.end() && it->first <= lib) {
const finalizer_policy_tracker& tracker = it->second;
if (tracker.state == finalizer_policy_tracker::state_t::pending) {
// new finalizer_policy becones active
// -----------------------------------
next_header_state.active_finalizer_policy.reset(new finalizer_policy(*tracker.policy));
next_header_state.active_finalizer_policy->generation = prev.active_finalizer_policy->generation + 1;
} else {
assert(tracker.state == finalizer_policy_tracker::state_t::proposed);
// block where finalizer_policy was proposed became final. The finalizer policy will
// become active when next block becomes final.
// ---------------------------------------------------------------------------------
finalizer_policy_tracker t { finalizer_policy_tracker::state_t::pending, tracker.policy };
next_header_state.finalizer_policies.emplace(next_header_state.block_num(), std::move(t));
}
++it;
}
if (it != prev.finalizer_policies.end()) {
// copy remainder of pending finalizer_policy changes
// --------------------------------------------------
next_header_state.finalizer_policies.insert(boost::container::ordered_unique_range_t(),
it, prev.finalizer_policies.end());
}
}
}

if (new_finalizer_policy) {
if (if_ext.new_finalizer_policy) {
// a new `finalizer_policy` was proposed in the previous block, and is present in the previous
// block's header extensions.
// Add this new proposal to the `finalizer_policies` multimap which tracks the in-flight proposals,
// increment the generation number, and log that proposal (debug level).
// ------------------------------------------------------------------------------------------------
dlog("New finalizer policy proposed in block ${id}: ${pol}",
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we log block number instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue specifies that ids should be logged, which makes sense as these blocks are not final, so we may have the same block number in different forks.

("id", prev.block_id)("pol", *if_ext.new_finalizer_policy));
next_header_state.finalizer_policy_generation = if_ext.new_finalizer_policy->generation;
next_header_state.finalizer_policies.emplace(
next_header_state.block_num(),
finalizer_policy_tracker{finalizer_policy_tracker::state_t::proposed,
std::make_shared<finalizer_policy>(std::move(*new_finalizer_policy))});
std::make_shared<finalizer_policy>(std::move(*if_ext.new_finalizer_policy))});

} else {
next_header_state.finalizer_policy_generation = prev.finalizer_policy_generation;
}

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

// Now that we have the block id of the new block, log what changed.
// -----------------------------------------------------------------
if (next_header_state.active_finalizer_policy != prev.active_finalizer_policy) {
const auto& act = next_header_state.active_finalizer_policy;
ilog("Finalizer policy generation change: ${old_gen} -> ${new_gen}",
("old_gen", prev.active_finalizer_policy->generation)("new_gen",act->generation));
ilog("New finalizer policy becoming active in block ${id}: ${pol}",("id", next_header_state.block_id)("pol", *act));
}
}

block_header_state block_header_state::next(block_header_state_input& input) const {
Expand All @@ -187,13 +216,13 @@ block_header_state block_header_state::next(block_header_state_input& input) con

// finality extension
// ------------------
instant_finality_extension new_if_ext {input.most_recent_ancestor_with_qc,
input.new_finalizer_policy,
input.new_proposer_policy};
instant_finality_extension new_if_ext { input.most_recent_ancestor_with_qc,
std::move(input.new_finalizer_policy),
std::move(input.new_proposer_policy) };

uint16_t if_ext_id = instant_finality_extension::extension_id();
emplace_extension(next_header_state.header.header_extensions, if_ext_id, fc::raw::pack(new_if_ext));
next_header_state.header_exts.emplace(if_ext_id, std::move(new_if_ext));
next_header_state.header_exts.emplace(if_ext_id, new_if_ext);

// add protocol_feature_activation extension
// -----------------------------------------
Expand All @@ -205,9 +234,7 @@ block_header_state block_header_state::next(block_header_state_input& input) con
next_header_state.header_exts.emplace(ext_id, std::move(pfa_ext));
}

finish_next(*this, next_header_state, std::move(input.new_protocol_feature_activations),
std::move(input.new_proposer_policy), std::move(input.new_finalizer_policy),
input.most_recent_ancestor_with_qc);
finish_next(*this, next_header_state, std::move(input.new_protocol_feature_activations), std::move(new_if_ext));

return next_header_state;
}
Expand All @@ -230,6 +257,8 @@ block_header_state block_header_state::next(const signed_block_header& h, valida
block_header_state next_header_state;
next_header_state.header = static_cast<const block_header&>(h);
next_header_state.header_exts = h.validate_and_extract_header_extensions();
next_header_state.finalizer_policy_generation = finalizer_policy_generation;

const auto& exts = next_header_state.header_exts;

// retrieve protocol_feature_activation from incoming block header extension
Expand Down Expand Up @@ -262,8 +291,7 @@ block_header_state block_header_state::next(const signed_block_header& h, valida
("f", next_core_metadata.final_on_strong_qc_block_num));
};

finish_next(*this, next_header_state, std::move(new_protocol_feature_activations), if_ext.new_proposer_policy,
if_ext.new_finalizer_policy, if_ext.qc_claim);
finish_next(*this, next_header_state, std::move(new_protocol_feature_activations), if_ext);

return next_header_state;
}
Expand Down
7 changes: 4 additions & 3 deletions libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ block_state_ptr block_state::create_if_genesis_block(const block_state_legacy& b
result.active_proposer_policy->proposer_schedule = bsp.active_schedule;
result.proposer_policies = {}; // none pending at IF genesis block
result.finalizer_policies = {}; // none pending at IF genesis block
result.finalizer_policy_generation = 1;
result.header_exts = bsp.header_exts;

// set block_state data ----
result.block = bsp.block;
result.strong_digest = result.compute_finality_digest(); // all block_header_state data populated in result at this point
result.weak_digest = create_weak_digest(result.strong_digest);

// TODO: https://github.com/AntelopeIO/leap/issues/2057
// TODO: Do not aggregate votes on blocks created from block_state_legacy. This can be removed when #2057 complete.
// pending_qc will not be used in the genesis block as finalizers will not vote on it, but still create it for consistency.
result.pending_qc = pending_quorum_certificate{result.active_finalizer_policy->finalizers.size(),
result.active_finalizer_policy->threshold,
result.active_finalizer_policy->max_weak_sum_before_weak_final()};
Expand Down Expand Up @@ -143,7 +143,8 @@ block_state::block_state(snapshot_detail::snapshot_block_state_v7&& sbs)
.active_finalizer_policy = std::move(sbs.active_finalizer_policy),
.active_proposer_policy = std::move(sbs.active_proposer_policy),
.proposer_policies = std::move(sbs.proposer_policies),
.finalizer_policies = std::move(sbs.finalizer_policies)
.finalizer_policies = std::move(sbs.finalizer_policies),
.finalizer_policy_generation = sbs.finalizer_policy_generation
}
, strong_digest(compute_finality_digest())
, weak_digest(create_weak_digest(strong_digest))
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,8 @@ struct building_block {
}
},
[&](building_block_if& bb) {
fin_pol.generation = bb.parent.finalizer_policy_generation + 1;
bb.new_finalizer_policy = std::move(fin_pol);
// generation will be updated when activated
} },
v);
}
Expand Down
6 changes: 5 additions & 1 deletion libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ struct block_header_state {
// `pending` becomes active, and the `proposed` becomes `pending` (for a different block number).
flat_multimap<block_num_type, finalizer_policy_tracker> finalizer_policies;

// generation increases by one each time a new finalizer_policy is proposed in a block
// It matches the finalizer policy generation most recently included in this block's `if_extension` or its ancestors
uint32_t finalizer_policy_generation{1};

// ------ data members caching information available elsewhere ----------------------
header_extension_multimap header_exts; // redundant with the data stored in header
Expand Down Expand Up @@ -123,4 +126,5 @@ FC_REFLECT( eosio::chain::finalizer_policy_tracker, (state)(policy))

FC_REFLECT( eosio::chain::block_header_state, (block_id)(header)
(activated_protocol_features)(core)(active_finalizer_policy)
(active_proposer_policy)(proposer_policies)(finalizer_policies)(header_exts))
(active_proposer_policy)(proposer_policies)(finalizer_policies)
(finalizer_policy_generation)(header_exts))
3 changes: 3 additions & 0 deletions libraries/chain/include/eosio/chain/snapshot_detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ namespace eosio::chain::snapshot_detail {
proposer_policy_ptr active_proposer_policy;
flat_map<block_timestamp_type, proposer_policy_ptr> proposer_policies;
flat_multimap<block_num_type, finalizer_policy_tracker> finalizer_policies;
uint32_t finalizer_policy_generation;

// from block_state
std::optional<valid_t> valid;
Expand All @@ -133,6 +134,7 @@ namespace eosio::chain::snapshot_detail {
, active_proposer_policy(bs.active_proposer_policy)
, proposer_policies(bs.proposer_policies)
, finalizer_policies(bs.finalizer_policies)
, finalizer_policy_generation(bs.finalizer_policy_generation)
, valid(bs.valid)
{}
};
Expand Down Expand Up @@ -212,6 +214,7 @@ FC_REFLECT( eosio::chain::snapshot_detail::snapshot_block_state_v7,
(active_proposer_policy)
(proposer_policies)
(finalizer_policies)
(finalizer_policy_generation)
(valid)
)

Expand Down