@@ -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;
0 commit comments