Skip to content

Commit

Permalink
GH-6 Update logic to increment version on every new proposal schedule…
Browse files Browse the repository at this point in the history
… placed in a block header extension
  • Loading branch information
heifner committed May 1, 2024
1 parent 51d4488 commit 7e10458
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 33 deletions.
15 changes: 10 additions & 5 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,23 @@ void finish_next(const block_header_state& prev,
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) {
while (it != prev.proposer_policies.end() && it->first.slot <= next_header_state.header.timestamp.slot + 1) {
next_header_state.active_proposer_policy = it->second;
next_header_state.proposer_policies = { ++it, prev.proposer_policies.end() };
} else {
++it;
}
if (it == prev.proposer_policies.begin()) { // none made active
next_header_state.proposer_policies = prev.proposer_policies;
} else if (it != prev.proposer_policies.end()) { // some made active
next_header_state.proposer_policies = { it, prev.proposer_policies.end() };
} else { // all made active
// next_header_state.proposer_policies will be emtpy
}
}

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

// finality_core
Expand Down
25 changes: 6 additions & 19 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,24 +496,11 @@ struct building_block {
std::tuple<uint32_t, bool> get_next_proposer_schedule_version(const vector<producer_authority>& producers) const {
assert(active_proposer_policy);

bool should_propose = false;
auto get_next_sched = [&]() -> const producer_authority_schedule& {
// if there are any policies already proposed but not active yet then they are what needs to be compared
if (!parent.proposer_policies.empty()) {
block_timestamp_type active_time = detail::get_next_next_round_block_time(timestamp);
if (auto itr = parent.proposer_policies.find(active_time); itr != parent.proposer_policies.cend()) {
// Same active time, a new proposer schedule will replace this entry, `next` therefore is the previous
should_propose = true;
if (itr != parent.proposer_policies.begin()) {
return (--itr)->second->proposer_schedule;
}
// no previous to what will be replaced, use active
return active_proposer_policy->proposer_schedule;
}
// will not replace any proposed policies, use next to become active
return parent.proposer_policies.begin()->second->proposer_schedule;
return (--parent.proposer_policies.end())->second->proposer_schedule;
}

// none currently in-flight, use active
return active_proposer_policy->proposer_schedule;
};
Expand All @@ -524,10 +511,10 @@ struct building_block {

if (!std::ranges::equal(lhs.producers, producers)) {
++v;
should_propose = true;
return {v, true};
}

return {v, should_propose};
return {v, false};
}

};
Expand Down Expand Up @@ -5226,7 +5213,7 @@ int64_t controller_impl::set_proposed_producers( vector<producer_authority> prod
if (gpo.proposed_schedule_block_num) {
if (std::equal(producers.begin(), producers.end(),
gpo.proposed_schedule.producers.begin(), gpo.proposed_schedule.producers.end())) {
return gpo.proposed_schedule.version; // the proposed producer schedule does not change
return std::numeric_limits<uint32_t>::max(); // the proposed producer schedule does not change
}
// clear gpo proposed_schedule as we may determine no diff between proposed producers and next proposer schedule
db.modify( gpo, [&]( auto& gp ) {
Expand All @@ -5238,7 +5225,7 @@ int64_t controller_impl::set_proposed_producers( vector<producer_authority> prod

auto [version, should_propose] = pending->get_next_proposer_schedule_version(producers);
if (!should_propose)
return version;
return std::numeric_limits<uint32_t>::max();

producer_authority_schedule sch;
sch.version = version;
Expand All @@ -5253,7 +5240,7 @@ int64_t controller_impl::set_proposed_producers( vector<producer_authority> prod
gp.proposed_schedule = sch;
});

return sch.version;
return std::numeric_limits<uint32_t>::max();
}

int64_t controller_impl::set_proposed_producers_legacy( vector<producer_authority> producers ) {
Expand Down
17 changes: 11 additions & 6 deletions libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,18 @@ struct block_header_state {
finalizer_policy_ptr active_finalizer_policy; // finalizer set + threshold + generation, supports `digest()`
proposer_policy_ptr active_proposer_policy; // producer authority schedule, supports `digest()`

// block time when proposer_policy will become active
// <block time when proposer_policy will become active, proposer policy>
// The active time is the next,next producer round. For example,
// round A [1,2,..12], next_round B [1,2,..12], next_next_round C [1,2,..12], D [1,2,..12]
// If proposed in A1, A2, .. A12 becomes active in C1
// If proposed in B1, B2, .. B12 becomes active in D1
// If proposed in A2 and another proposed in B3 then there can be 2 in the map
flat_map<block_timestamp_type, proposer_policy_ptr> proposer_policies;
// round A [1,2,..12], next_round B [1,2,..12], next_next_round C [1,2,..12], D [1,2,..12]
// If proposed in A1, A2, .. A12 becomes active in C1
// If proposed in B1, B2, .. B12 becomes active in D1
// This is a `deque` because the same active block time can contain up to 12 entries (one per block)
// for the entry proposed in a block:
// For example, proposer policy proposed: P1 in A1, P2 in A7, P3 in A12, P4 in B2, P5 in B12 then the map contains:
// [C1 -> P1],[C1 -> P2],[C1 -> P3],[D1 -> P4],[D1 -> P5]
// At C1 P1,P2,P3 are applied causing an active policy of P3
// At D1 P4,P5 are appliced causing an acive policy of P5
std::deque<std::pair<block_timestamp_type, proposer_policy_ptr>> proposer_policies;

// track in-flight finalizer policies. This is a `multimap` because the same block number
// can hold a `proposed` and a `pending` finalizer_policy. When that block becomes final, the
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 @@ -116,7 +116,7 @@ namespace eosio::chain::snapshot_detail {
finality_core core;
finalizer_policy_ptr active_finalizer_policy;
proposer_policy_ptr active_proposer_policy;
flat_map<block_timestamp_type, proposer_policy_ptr> proposer_policies;
std::deque<std::pair<block_timestamp_type, proposer_policy_ptr>> proposer_policies;
flat_multimap<block_num_type, finalizer_policy_tracker> finalizer_policies;
uint32_t finalizer_policy_generation;

Expand Down
6 changes: 4 additions & 2 deletions libraries/chain/include/eosio/chain/webassembly/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ namespace webassembly {
*
* @param packed_producer_schedule - vector of producer keys
*
* @return -1 if proposing a new producer schedule was unsuccessful, otherwise returns the version of the new proposed schedule.
* @return pre-savanna: -1 if proposing a new producer schedule was unsuccessful, otherwise returns the version of the new proposed schedule.
* post-savanna: -1 if proposing a new producer schedule was unsuccessful, otherwise returns max uint32_t
*/
int64_t set_proposed_producers(legacy_span<const char> packed_producer_schedule);

Expand All @@ -169,7 +170,8 @@ namespace webassembly {
* @param packed_producer_format - format of the producer data blob.
* @param packed_producer_schedule - packed data of representing the producer schedule in the format indicated.
*
* @return -1 if proposing a new producer schedule was unsuccessful, otherwise returns the version of the new proposed schedule.
* @return pre-savanna: -1 if proposing a new producer schedule was unsuccessful, otherwise returns the version of the new proposed schedule.
* post-savanna: -1 if proposing a new producer schedule was unsuccessful, otherwise returns max uint32_t
*/
int64_t set_proposed_producers_ex(uint64_t packed_producer_format, legacy_span<const char> packed_producer_schedule);

Expand Down

0 comments on commit 7e10458

Please sign in to comment.