Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Add allow_commission_decrease_at_any_time feature which will allow #33847

Merged

Conversation

bji
Copy link
Contributor

@bji bji commented Oct 24, 2023

vote account commission to be lowered at any time during the epoch regardless of the commission_updates_only_allowed_in_first_half_of_epoch feature. Fixes #33843.

@bji bji requested a review from AshwinSekar October 24, 2023 20:37
@bji bji force-pushed the allow_commission_decrease_at_any_time branch from 92e8b80 to 166c6ad Compare October 24, 2023 20:45
@AshwinSekar AshwinSekar requested a review from joncinque October 24, 2023 21:20
@AshwinSekar
Copy link
Contributor

cc @joncinque the author of the original feature.

@codecov
Copy link

codecov bot commented Oct 24, 2023

Codecov Report

Merging #33847 (74a4a36) into master (79739e1) will increase coverage by 0.0%.
The diff coverage is 100.0%.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #33847   +/-   ##
=======================================
  Coverage    81.8%    81.8%           
=======================================
  Files         819      819           
  Lines      220915   220991   +76     
=======================================
+ Hits       180899   180964   +65     
- Misses      40016    40027   +11     

@CriesofCarrots
Copy link
Contributor

Not to delay progress, but we need to get in the habit of starting with a SIMD for feature-gated changes, like this.
Can you please make some version of #33843 into a SIMD? It would be helpful to suss out what parts of the process are significant impediments to smaller changes.

@bji
Copy link
Contributor Author

bji commented Oct 25, 2023

Not to delay progress, but we need to get in the habit of starting with a SIMD for feature-gated changes, like this. Can you please make some version of #33843 into a SIMD? It would be helpful to suss out what parts of the process are significant impediments to smaller changes.

Is a SIMD really needed for all features? This is a minor feature that really just "fixes" a shortcoming in an existing feature. Going through the SIMD process sure is painful ...

The only reason a feature gate is even added is because it's consensus breaking. I think of this more as any other "bug fix" change, it just happens to have a feature gate too for that reason.

@joncinque
Copy link
Contributor

While I can certainly appreciate the added hurdle of a SIMD, we need to get into the habit of "feature gates require SIMDs" in almost all cases. This should be an easy one to get approved, and I'll be happy to help out!

@bji bji force-pushed the allow_commission_decrease_at_any_time branch from 166c6ad to 9d30478 Compare October 26, 2023 16:37
@bji
Copy link
Contributor Author

bji commented Oct 26, 2023

SIMD 0079 has been added to propose this feature.

@bji
Copy link
Contributor Author

bji commented Nov 8, 2023

While I can certainly appreciate the added hurdle of a SIMD, we need to get into the habit of "feature gates require SIMDs" in almost all cases. This should be an easy one to get approved, and I'll be happy to help out!

The SIMD has been updated to respond to your comments, so it would be great to get that SIMD accepted now. Thanks.

@@ -724,6 +724,10 @@ pub mod update_hashes_per_tick6 {
solana_sdk::declare_id!("FKu1qYwLQSiehz644H6Si65U5ZQ2cp9GxsyFUfYcuADv");
}

pub mod allow_commission_decrease_at_any_time {
solana_sdk::declare_id!("9wWpKE7vL7EmZcDTPm8n9pPVGJLynedAdAxh3BzZnAoF");
Copy link
Contributor

Choose a reason for hiding this comment

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

@joncinque you want to hold the key for this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah no problem, I ground out decoMktMcnmiq6t3u7g5BfgcQu91nKZr6RvMYf9z1Jb

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

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

Looks great for the most part! Most of my comments are small, along with a way to avoid double deserialization in the function now

programs/vote/src/vote_state/mod.rs Outdated Show resolved Hide resolved
programs/vote/src/vote_state/mod.rs Outdated Show resolved Hide resolved
programs/vote/src/vote_state/mod.rs Outdated Show resolved Hide resolved
programs/vote/src/vote_state/mod.rs Outdated Show resolved Hide resolved
Comment on lines 884 to 907
let enforce_commission_update_rule =
if feature_set.is_active(&feature_set::allow_commission_decrease_at_any_time::id()) {
is_commission_increase(vote_account, commission)?
} else {
true
};

#[allow(clippy::collapsible_if)]
if enforce_commission_update_rule
&& feature_set
.is_active(&feature_set::commission_updates_only_allowed_in_first_half_of_epoch::id())
{
if !is_commission_update_allowed(clock.slot, epoch_schedule) {
return Err(VoteError::CommissionUpdateTooLate.into());
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This instruction isn't used all that often, so it's not a huge performance impact, but we should note that it's deserializing the vote account twice. It's being done once in is_commission_increase, and again in update_commission.

You did the right thing to make the change as small as possible while not introducing potential forking. We could have is_commission_increase take in the VoteState directly and update this function a bit like:

Suggested change
let enforce_commission_update_rule =
if feature_set.is_active(&feature_set::allow_commission_decrease_at_any_time::id()) {
is_commission_increase(vote_account, commission)?
} else {
true
};
#[allow(clippy::collapsible_if)]
if enforce_commission_update_rule
&& feature_set
.is_active(&feature_set::commission_updates_only_allowed_in_first_half_of_epoch::id())
{
if !is_commission_update_allowed(clock.slot, epoch_schedule) {
return Err(VoteError::CommissionUpdateTooLate.into());
}
}
let mut vote_state: VoteState = if feature_set.is_active(&feature_set::allow_commission_decrease_at_any_time::id()) {
let mut vote_state: VoteState = vote_account
.get_state::<VoteStateVersions>()?
.convert_to_current();
if is_commission_increase(&vote_state, commission)
&& feature_set
.is_active(&feature_set::commission_updates_only_allowed_in_first_half_of_epoch::id())
{
if !is_commission_update_allowed(clock.slot, epoch_schedule) {
return Err(VoteError::CommissionUpdateTooLate.into());
}
}
vote_state
} else {
if feature_set
.is_active(&feature_set::commission_updates_only_allowed_in_first_half_of_epoch::id())
{
if !is_commission_update_allowed(clock.slot, epoch_schedule) {
return Err(VoteError::CommissionUpdateTooLate.into());
}
}
vote_account
.get_state::<VoteStateVersions>()?
.convert_to_current()
};

I know it's a bit more code, but it isn't ridiculously ugly. What do you think? cc @AshwinSekar for another opinion

Copy link
Contributor

@AshwinSekar AshwinSekar Nov 8, 2023

Choose a reason for hiding this comment

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

Yeah in the vote program we try to deserialize only once at the beginning of each instruction using either:

vote_account.get_state::<VoteStateVersions>()?.convert_to_current()

or verify_and_get_vote_state

I think you could just let is_commission_increase take a vote state and keep it like how you have it:

    let mut vote_state: VoteState = vote_account.get_state::<VoteStateVersions>()?.convert_to_current();
    let enforce_commission_update_rule =
        if feature_set.is_active(&feature_set::allow_commission_decrease_at_any_time::id()) {
            is_commission_increase(vote_state, commission)?
        } else {
            true
        };

    #[allow(clippy::collapsible_if)]
    if enforce_commission_update_rule
        && feature_set
            .is_active(&feature_set::commission_updates_only_allowed_in_first_half_of_epoch::id())
    {
        if !is_commission_update_allowed(clock.slot, epoch_schedule) {
            return Err(VoteError::CommissionUpdateTooLate.into());
        }
    }

Copy link
Contributor

Choose a reason for hiding this comment

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

If the vote state deserialization fails though, that could cause forking between old and new versions. old could fail during the comission check, and new could fail during the earlier deserialization, which means that two validators could give different errors for the same instruction.

Does the returned error affect consensus? I always thought that was the case

Copy link
Contributor

Choose a reason for hiding this comment

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

as far as I know the returned error doesn't impact bank hash, we only check .is_ok()/is_err() in places, but I might be wrong:

if execution_status.is_ok() || is_nonce_account || is_fee_payer {
// Add to the accounts to store
accounts.push((&*address, &*account));
transactions.push(Some(tx));
}

I don't mind being safe and making sure we return the same error, doesn't look too ugly.

@@ -724,6 +724,10 @@ pub mod update_hashes_per_tick6 {
solana_sdk::declare_id!("FKu1qYwLQSiehz644H6Si65U5ZQ2cp9GxsyFUfYcuADv");
}

pub mod allow_commission_decrease_at_any_time {
solana_sdk::declare_id!("9wWpKE7vL7EmZcDTPm8n9pPVGJLynedAdAxh3BzZnAoF");
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah no problem, I ground out decoMktMcnmiq6t3u7g5BfgcQu91nKZr6RvMYf9z1Jb

@bji bji force-pushed the allow_commission_decrease_at_any_time branch from 9d30478 to 16b8c15 Compare November 17, 2023 02:52
vote account commission to be lowered at any time during the epoch
regardless of the commission_updates_only_allowed_in_first_half_of_epoch
feature.  Fixes solana-labs#33843.

SIMD: 0080
@bji bji force-pushed the allow_commission_decrease_at_any_time branch from 16b8c15 to b3aebb5 Compare November 17, 2023 03:00
@github-actions github-actions bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Dec 1, 2023
@github-actions github-actions bot closed this Dec 8, 2023
@bji bji reopened this Dec 8, 2023
@bji
Copy link
Contributor Author

bji commented Dec 8, 2023

Please complete the review and/or merge the PR. Thanks.

joncinque
joncinque previously approved these changes Dec 8, 2023
Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

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

Apologies for the lateness, I didn't see any responses so assumed that you were still working on it.

Looks great, thanks for integrating all of our feedback! @AshwinSekar can you also take a look and approve if you have a moment?

@joncinque
Copy link
Contributor

I went ahead and fixed the merge conflicts

Copy link
Contributor

@AshwinSekar AshwinSekar left a comment

Choose a reason for hiding this comment

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

looks fine to me @joncinque just to confirm, you're fine that we might be returning a different error in some scenarios?

@joncinque
Copy link
Contributor

looks fine to me @joncinque just to confirm, you're fine that we might be returning a different error in some scenarios?

Unless I'm missing something, I don't think it's possible to return a different error with this implementation.

Also, I checked with the runtime team, and they said the error code doesn't make a difference for consensus, so we're all good from my side.

@bji
Copy link
Contributor Author

bji commented Dec 8, 2023

looks fine to me @joncinque just to confirm, you're fine that we might be returning a different error in some scenarios?

Why would that be specifically? The way I altered the code to match your feedback should mean that the same errors are returned before and after the change ... unless I'm missing something?

@AshwinSekar AshwinSekar merged commit 930ce1e into solana-labs:master Dec 8, 2023
28 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
need:merge-assist stale [bot only] Added to stale content; results in auto-close after a week.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Commission decrease should be allowed at any time
4 participants