-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Add allow_commission_decrease_at_any_time feature which will allow #33847
Add allow_commission_decrease_at_any_time feature which will allow #33847
Conversation
92e8b80
to
166c6ad
Compare
cc @joncinque the author of the original feature. |
Codecov Report
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 |
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. |
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! |
166c6ad
to
9d30478
Compare
SIMD 0079 has been added to propose this feature. |
The SIMD has been updated to respond to your comments, so it would be great to get that SIMD accepted now. Thanks. |
sdk/src/feature_set.rs
Outdated
@@ -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"); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this 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
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()); | ||
} | ||
} |
There was a problem hiding this comment.
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:
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
There was a problem hiding this comment.
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());
}
}
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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:
solana/accounts-db/src/accounts.rs
Lines 1399 to 1403 in bba6ea2
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.
sdk/src/feature_set.rs
Outdated
@@ -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"); |
There was a problem hiding this comment.
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
9d30478
to
16b8c15
Compare
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
16b8c15
to
b3aebb5
Compare
Please complete the review and/or merge the PR. Thanks. |
There was a problem hiding this 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?
I went ahead and fixed the merge conflicts |
There was a problem hiding this 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?
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. |
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? |
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.