Skip to content

Commit 29396aa

Browse files
authored
Merge pull request #68 from AntelopeIO/GH-6-proposer-policy
IF: Do not set new proposer policy unless different
2 parents dcda785 + 9df701c commit 29396aa

File tree

2 files changed

+72
-20
lines changed

2 files changed

+72
-20
lines changed

libraries/chain/controller.cpp

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -491,16 +491,38 @@ struct building_block {
491491

492492
uint32_t get_block_num() const { return block_num; }
493493

494-
uint32_t get_next_proposer_schedule_version() const {
495-
if (!parent.proposer_policies.empty()) {
496-
block_timestamp_type active_time = detail::get_next_next_round_block_time(timestamp);
497-
if (auto itr = parent.proposer_policies.find(active_time); itr != parent.proposer_policies.cend()) {
498-
return itr->second->proposer_schedule.version; // will replace so return same version
494+
// returns the next proposer schedule version and true if different
495+
// if producers is not different then returns the current schedule version (or next schedule version)
496+
std::tuple<uint32_t, bool> get_next_proposer_schedule_version(const vector<producer_authority>& producers) const {
497+
assert(active_proposer_policy);
498+
499+
auto get_next_sched = [&]() -> const producer_authority_schedule& {
500+
// if there are any policies already proposed but not active yet then they are what needs to be compared
501+
if (!parent.proposer_policies.empty()) {
502+
block_timestamp_type active_time = detail::get_next_next_round_block_time(timestamp);
503+
if (auto itr = parent.proposer_policies.find(active_time); itr != parent.proposer_policies.cend()) {
504+
// Same active time, a new proposer schedule will replace this entry, `next` therefore is the previous
505+
if (itr != parent.proposer_policies.begin()) {
506+
return (--itr)->second->proposer_schedule;
507+
}
508+
// no previous to what will be replaced, use active
509+
return active_proposer_policy->proposer_schedule;
510+
}
511+
// will not replace any proposed policies, use next to become active
512+
return parent.proposer_policies.begin()->second->proposer_schedule;
499513
}
500-
return (--parent.proposer_policies.end())->second->proposer_schedule.version + 1;
514+
515+
// none currently in-flight, use active
516+
return active_proposer_policy->proposer_schedule;
517+
};
518+
519+
const producer_authority_schedule& lhs = get_next_sched();
520+
521+
if (std::ranges::equal(lhs.producers, producers)) {
522+
return {lhs.version, false};
501523
}
502-
assert(active_proposer_policy);
503-
return active_proposer_policy->proposer_schedule.version + 1;
524+
525+
return {lhs.version + 1, true};
504526
}
505527

506528
};
@@ -591,11 +613,13 @@ struct building_block {
591613
v);
592614
}
593615

594-
int64_t get_next_proposer_schedule_version() const {
616+
std::tuple<uint32_t, bool> get_next_proposer_schedule_version(const vector<producer_authority>& producers) const {
595617
return std::visit(
596-
overloaded{[](const building_block_legacy&) -> int64_t { return -1; },
597-
[&](const building_block_if& bb) -> int64_t { return bb.get_next_proposer_schedule_version(); }
598-
},
618+
overloaded{[](const building_block_legacy&) -> std::tuple<uint32_t, bool> { return {-1, false}; },
619+
[&](const building_block_if& bb) -> std::tuple<uint32_t, bool> {
620+
return bb.get_next_proposer_schedule_version(producers);
621+
}
622+
},
599623
v);
600624
}
601625

@@ -887,11 +911,13 @@ struct pending_state {
887911
_block_stage);
888912
}
889913

890-
int64_t get_next_proposer_schedule_version() const {
914+
std::tuple<uint32_t, bool> get_next_proposer_schedule_version(const vector<producer_authority>& producers) const {
891915
return std::visit(overloaded{
892-
[](const building_block& stage) -> int64_t { return stage.get_next_proposer_schedule_version(); },
893-
[](const assembled_block&) -> int64_t { assert(false); return -1; },
894-
[](const completed_block&) -> int64_t { assert(false); return -1; }
916+
[&](const building_block& stage) -> std::tuple<uint32_t, bool> {
917+
return stage.get_next_proposer_schedule_version(producers);
918+
},
919+
[](const assembled_block&) -> std::tuple<uint32_t, bool> { assert(false); return {-1, false}; },
920+
[](const completed_block&) -> std::tuple<uint32_t, bool> { assert(false); return {-1, false}; }
895921
},
896922
_block_stage);
897923
}
@@ -5189,17 +5215,20 @@ int64_t controller_impl::set_proposed_producers( vector<producer_authority> prod
51895215
return -1; // INSTANT_FINALITY depends on DISALLOW_EMPTY_PRODUCER_SCHEDULE
51905216

51915217
assert(pending);
5192-
const auto& gpo = db.get<global_property_object>();
5193-
auto cur_block_num = chain_head.block_num() + 1;
51945218

5195-
producer_authority_schedule sch;
5219+
auto [version, diff] = pending->get_next_proposer_schedule_version(producers);
5220+
if (!diff)
5221+
return version;
51965222

5197-
sch.version = pending->get_next_proposer_schedule_version();
5223+
producer_authority_schedule sch;
5224+
sch.version = version;
51985225
sch.producers = std::move(producers);
51995226

52005227
ilog( "proposed producer schedule with version ${v}", ("v", sch.version) );
52015228

52025229
// overwrite any existing proposed_schedule set earlier in this block
5230+
auto cur_block_num = chain_head.block_num() + 1;
5231+
auto& gpo = db.get<global_property_object>();
52035232
db.modify( gpo, [&]( auto& gp ) {
52045233
gp.proposed_schedule_block_num = cur_block_num;
52055234
gp.proposed_schedule = sch;

unittests/producer_schedule_if_tests.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,29 @@ BOOST_FIXTURE_TEST_CASE( proposer_policy_progression_test, validating_tester ) t
170170
// sch3 becomes active
171171
BOOST_CHECK_EQUAL( 2u, control->active_producers().version ); // should be 2 as sch2 was replaced by sch3
172172
BOOST_CHECK_EQUAL( true, compare_schedules( sch3, control->active_producers() ) );
173+
174+
// get to next producer round
175+
auto prod = produce_block()->producer;
176+
for (auto b = produce_block(); b->producer == prod; b = produce_block());
177+
178+
// test no change to active schedule
179+
set_producers( {"bob"_n,"alice"_n} ); // same as before, so no change
180+
produce_blocks(config::producer_repetitions);
181+
produce_blocks(config::producer_repetitions);
182+
BOOST_CHECK_EQUAL( 2u, control->active_producers().version ); // should be 2 as not different so no change
183+
BOOST_CHECK_EQUAL( true, compare_schedules( sch3, control->active_producers() ) );
184+
185+
// test no change to proposed schedule, only the first one will take affect
186+
for (size_t i = 0; i < config::producer_repetitions*2-1; ++i) {
187+
BOOST_CHECK_EQUAL( 2u, control->active_producers().version ); // should be 2 as not taken affect yet
188+
BOOST_CHECK_EQUAL( true, compare_schedules( sch3, control->active_producers() ) );
189+
set_producers( {"bob"_n,"carol"_n} );
190+
produce_block();
191+
}
192+
produce_block();
193+
BOOST_CHECK_EQUAL( 3u, control->active_producers().version ); // should be 3 now as bob,carol now active
194+
BOOST_CHECK_EQUAL( true, compare_schedules( sch2, control->active_producers() ) );
195+
173196
} FC_LOG_AND_RETHROW()
174197

175198

0 commit comments

Comments
 (0)