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: Update new proposer policy algorithm #74

Merged
merged 12 commits into from
May 2, 2024
Merged

Conversation

heifner
Copy link
Member

@heifner heifner commented Apr 26, 2024

set_proposed_producers[_ex] host functions after Savanna activation check to see if the policy to be proposed is different than the last proposal policy in the queue (not the currently active one). If it is the same, it avoids adding the policy to the queue (it acts like a no-op).

The host functions now return uint32_t max as the version number if the proposed policy is valid. If it is invalid (e.g. empty producers in the policy) it returns -1; this is the only time is returns -1. This means that if the caller of the host function proposes a policy that is identical to the one it last proposed, the host function will still return successfully (not with a -1 return value, but with a uint32_t max).

The diff in the block extension is relative to the previous policy proposed and represented in a block extension (as a diff) in the history of the chain. (diff is begin worked under #5).

Resolves #6

@heifner heifner linked an issue Apr 26, 2024 that may be closed by this pull request
@heifner heifner requested review from linh2931 and greg7mdp April 26, 2024 11:37
@heifner heifner added the OCI Work exclusive to OCI team label Apr 26, 2024
linh2931
linh2931 previously approved these changes Apr 26, 2024
Base automatically changed from savanna to main April 29, 2024 18:39
@greg7mdp

This comment was marked as resolved.

@greg7mdp

This comment was marked as resolved.

@greg7mdp

This comment was marked as resolved.

@heifner
Copy link
Member Author

heifner commented Apr 29, 2024

It seems inconsistent. I'm not quite understanding why we used proposer_policies.end()) before?

That was an error, corrected in this PR.

@heifner
Copy link
Member Author

heifner commented Apr 29, 2024

Are we returning a policy which will become active later? If that's the case, even if the one proposed in the current block is identical, shouldn't we take that one into account rather than making it a no-op?

The same block is handled in the set_proposed_producers method.

@heifner
Copy link
Member Author

heifner commented Apr 29, 2024

Will if (itr != parent.proposer_policies.begin()) { ever be true? What are the cases where we have more than one entry in this map?

round A [1,2,..12], next_round B [1,2,..12], next_next_round C [1,2,..12], D [1,2,..12]

If set in A1, A2, .. A12 becomes active in C1
If set in B1, B2, .. B12 becomes active in D1

e.g. If one is set in A2 and another in B2 then there can be 2 in the map at B3.

@greg7mdp

This comment was marked as resolved.

@greg7mdp

This comment was marked as duplicate.

@greg7mdp

This comment was marked as resolved.

@greg7mdp

This comment was marked as resolved.

@heifner

This comment was marked as resolved.

@greg7mdp

This comment was marked as resolved.

@greg7mdp

This comment was marked as resolved.

@heifner
Copy link
Member Author

heifner commented Apr 30, 2024

Added additional test cases and added a fix. Ultimately, it is rather complicated to calculate what the version will be ahead of time. If you can think of additional test cases please let me know.

@greg7mdp

This comment was marked as resolved.

@heifner heifner changed the title IF: Fix setting proposer schedule more than once per block IF: Update new proposer policy algorithm May 1, 2024
@heifner heifner added the consensus-protocol Change to the consensus protocol. Impacts light client validation. label May 1, 2024
@heifner heifner requested review from linh2931 and greg7mdp May 1, 2024 12:21
@heifner heifner dismissed linh2931’s stale review May 1, 2024 12:21

Change to algorithm.

libraries/chain/block_header_state.cpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
libraries/chain/include/eosio/chain/block_header_state.hpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
libraries/chain/controller.cpp Outdated Show resolved Hide resolved
libraries/chain/include/eosio/chain/block_header_state.hpp Outdated Show resolved Hide resolved
Comment on lines 3138 to 3147

auto [version, should_propose] = pending->get_next_proposer_schedule_version(gpo.proposed_schedule.producers);
if (should_propose) {
new_proposer_policy = std::make_unique<proposer_policy>();
new_proposer_policy->active_time = detail::get_next_next_round_block_time(bb.timestamp());
new_proposer_policy->proposer_schedule = producer_authority_schedule::from_shared(gpo.proposed_schedule);
new_proposer_policy->proposer_schedule.version = version;
ilog("Scheduling proposer schedule change at ${t}: ${s}",
("t", new_proposer_policy->active_time)("s", new_proposer_policy->proposer_schedule));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to change if you don't want to, but I kinda like this more functional style where the lambda returns the new proposer_policy (if any) , and we use the return value directly without an intermediate variable.

         // Any proposer policy?
         auto process_new_proposer_policy = [&](auto&) -> std::unique_ptr<proposer_policy> {
            std::unique_ptr<proposer_policy> new_proposer_policy;
            const auto& gpo = db.get<global_property_object>();
            if (gpo.proposed_schedule_block_num) {

               auto [version, should_propose] = pending->get_next_proposer_schedule_version(gpo.proposed_schedule.producers);
               if (should_propose) {
                  new_proposer_policy                    = std::make_unique<proposer_policy>();
                  new_proposer_policy->active_time       = detail::get_next_next_round_block_time(bb.timestamp());
                  new_proposer_policy->proposer_schedule = producer_authority_schedule::from_shared(gpo.proposed_schedule);
                  new_proposer_policy->proposer_schedule.version = version;
                  ilog("Scheduling proposer schedule change at ${t}: ${s}",
                       ("t", new_proposer_policy->active_time)("s", new_proposer_policy->proposer_schedule));
               }

               db.modify( gpo, [&]( auto& gp ) {
                  gp.proposed_schedule_block_num = std::optional<block_num_type>();
                  gp.proposed_schedule.version = 0;
                  gp.proposed_schedule.producers.clear();
               });
            }
            return new_proposer_policy;
         };

         auto assembled_block =
            bb.assemble_block(thread_pool.get_executor(), protocol_features.get_protocol_feature_set(), fork_db,
                              apply_s<std::unique_ptr<proposer_policy>>(chain_head, process_new_proposer_policy),
                              validating, std::move(validating_qc_data), validating_bsp);

libraries/chain/controller.cpp Show resolved Hide resolved
// if producers is not different then returns the current schedule version (or next schedule version)
std::tuple<uint32_t, bool> get_next_proposer_schedule_version(const vector<producer_authority>& producers) const {
std::tuple<uint32_t, bool> get_next_proposer_schedule_version(const shared_vector<shared_producer_authority>& producers) const {
Copy link
Contributor

Choose a reason for hiding this comment

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

This could return std::optional<uint32_t>, i.e. return a new version if one is needed.

@heifner heifner merged commit e1a3381 into main May 2, 2024
36 checks passed
@heifner heifner deleted the GH-6-proposer-policy-2 branch May 2, 2024 20:01
@ericpassmore
Copy link
Contributor

Note:start
group: IF
category: INTERNALS
summary: Avoid adding new proposer policy if there is no change.
Note:end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
consensus-protocol Change to the consensus protocol. Impacts light client validation. OCI Work exclusive to OCI team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Avoid adding new proposer policy if there is no change
4 participants