vote account withdraw authority may change the authorized voter
This commit is contained in:
parent
3bd5a89d6f
commit
65f1e0fcc2
|
@ -86,7 +86,14 @@ pub fn process_instruction(
|
|||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
)?;
|
||||
vote_state::authorize(me, &voter_pubkey, vote_authorize, &signers, &clock)
|
||||
vote_state::authorize(
|
||||
me,
|
||||
&voter_pubkey,
|
||||
vote_authorize,
|
||||
&signers,
|
||||
&clock,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
VoteInstruction::UpdateValidatorIdentity => vote_state::update_validator_identity(
|
||||
me,
|
||||
|
@ -166,6 +173,7 @@ pub fn process_instruction(
|
|||
keyed_accounts,
|
||||
first_instruction_account + 1,
|
||||
)?)?,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
} else {
|
||||
Err(InstructionError::InvalidInstructionData)
|
||||
|
|
|
@ -10,7 +10,7 @@ use {
|
|||
account_utils::State,
|
||||
clock::{Epoch, Slot, UnixTimestamp},
|
||||
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
|
||||
feature_set::{filter_votes_outside_slot_hashes, FeatureSet},
|
||||
feature_set::{self, filter_votes_outside_slot_hashes, FeatureSet},
|
||||
hash::Hash,
|
||||
instruction::InstructionError,
|
||||
keyed_account::KeyedAccount,
|
||||
|
@ -921,21 +921,37 @@ pub fn authorize<S: std::hash::BuildHasher>(
|
|||
vote_authorize: VoteAuthorize,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
clock: &Clock,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_state: VoteState =
|
||||
State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
|
||||
|
||||
// current authorized signer must say "yay"
|
||||
match vote_authorize {
|
||||
VoteAuthorize::Voter => {
|
||||
let authorized_withdrawer_signer = if feature_set
|
||||
.is_active(&feature_set::vote_withdraw_authority_may_change_authorized_voter::id())
|
||||
{
|
||||
verify_authorized_signer(&vote_state.authorized_withdrawer, signers).is_ok()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
vote_state.set_new_authorized_voter(
|
||||
authorized,
|
||||
clock.epoch,
|
||||
clock.leader_schedule_epoch + 1,
|
||||
|epoch_authorized_voter| verify_authorized_signer(&epoch_authorized_voter, signers),
|
||||
|epoch_authorized_voter| {
|
||||
// current authorized withdrawer or authorized voter must say "yay"
|
||||
if authorized_withdrawer_signer {
|
||||
Ok(())
|
||||
} else {
|
||||
verify_authorized_signer(&epoch_authorized_voter, signers)
|
||||
}
|
||||
},
|
||||
)?;
|
||||
}
|
||||
VoteAuthorize::Withdrawer => {
|
||||
// current authorized withdrawer must say "yay"
|
||||
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?;
|
||||
vote_state.authorized_withdrawer = *authorized;
|
||||
}
|
||||
|
@ -1558,6 +1574,7 @@ mod tests {
|
|||
leader_schedule_epoch: 2,
|
||||
..Clock::default()
|
||||
},
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Err(InstructionError::MissingRequiredSignature));
|
||||
|
||||
|
@ -1573,6 +1590,7 @@ mod tests {
|
|||
leader_schedule_epoch: 2,
|
||||
..Clock::default()
|
||||
},
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Ok(()));
|
||||
|
||||
|
@ -1588,6 +1606,7 @@ mod tests {
|
|||
leader_schedule_epoch: 2,
|
||||
..Clock::default()
|
||||
},
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Err(VoteError::TooSoonToReauthorize.into()));
|
||||
|
||||
|
@ -1610,6 +1629,7 @@ mod tests {
|
|||
leader_schedule_epoch: 4,
|
||||
..Clock::default()
|
||||
},
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Ok(()));
|
||||
|
||||
|
@ -1628,6 +1648,7 @@ mod tests {
|
|||
leader_schedule_epoch: 4,
|
||||
..Clock::default()
|
||||
},
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Ok(()));
|
||||
|
||||
|
@ -1648,6 +1669,7 @@ mod tests {
|
|||
leader_schedule_epoch: 4,
|
||||
..Clock::default()
|
||||
},
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Ok(()));
|
||||
|
||||
|
@ -1690,6 +1712,39 @@ mod tests {
|
|||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Ok(()));
|
||||
|
||||
// verify authorized_withdrawer can authorize a new authorized_voter when
|
||||
// `feature_set::vote_withdraw_authority_may_change_authorized_voter` is enabled
|
||||
let keyed_accounts = &[
|
||||
KeyedAccount::new(&vote_pubkey, false, &vote_account),
|
||||
KeyedAccount::new(&authorized_withdrawer_pubkey, true, &withdrawer_account),
|
||||
];
|
||||
let another_authorized_voter_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let signers: HashSet<Pubkey> = get_signers(keyed_accounts);
|
||||
|
||||
for (feature_set, expected_res) in [
|
||||
(
|
||||
FeatureSet::default(),
|
||||
Err(InstructionError::MissingRequiredSignature),
|
||||
),
|
||||
(FeatureSet::all_enabled(), Ok(())),
|
||||
]
|
||||
.into_iter()
|
||||
{
|
||||
let res = authorize(
|
||||
&keyed_accounts[0],
|
||||
&another_authorized_voter_pubkey,
|
||||
VoteAuthorize::Voter,
|
||||
&signers,
|
||||
&Clock {
|
||||
epoch: 4,
|
||||
leader_schedule_epoch: 5,
|
||||
..Clock::default()
|
||||
},
|
||||
&feature_set,
|
||||
);
|
||||
assert_eq!(res, expected_res)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2189,6 +2244,7 @@ mod tests {
|
|||
VoteAuthorize::Withdrawer,
|
||||
&signers,
|
||||
&Clock::default(),
|
||||
&FeatureSet::default(),
|
||||
);
|
||||
assert_eq!(res, Ok(()));
|
||||
|
||||
|
|
|
@ -307,6 +307,10 @@ pub mod update_syscall_base_costs {
|
|||
solana_sdk::declare_id!("2h63t332mGCCsWK2nqqqHhN4U9ayyqhLVFvczznHDoTZ");
|
||||
}
|
||||
|
||||
pub mod vote_withdraw_authority_may_change_authorized_voter {
|
||||
solana_sdk::declare_id!("AVZS3ZsN4gi6Rkx2QUibYuSJG3S6QHib7xCYhG6vGJxU");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
|
@ -378,6 +382,7 @@ lazy_static! {
|
|||
(require_rent_exempt_accounts::id(), "require all new transaction accounts with data to be rent-exempt"),
|
||||
(filter_votes_outside_slot_hashes::id(), "filter vote slots older than the slot hashes history"),
|
||||
(update_syscall_base_costs::id(), "Update syscall base costs"),
|
||||
(vote_withdraw_authority_may_change_authorized_voter::id(), "vote account withdraw authority may change the authorized voter #22521"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
|
Loading…
Reference in New Issue