From 1430b58a6d6d9eaccc000bb063703c0dff2a957a Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Fri, 3 Dec 2021 12:59:10 -0500 Subject: [PATCH] Remove deprecated slow epoch boundary methods (#21568) --- core/src/replay_stage.rs | 9 +- core/src/tvu.rs | 2 - core/src/validator.rs | 3 - local-cluster/src/validator_configs.rs | 1 - programs/stake/src/stake_state.rs | 75 ----- runtime/src/bank.rs | 364 ++----------------------- runtime/src/stakes.rs | 69 ----- validator/src/main.rs | 10 - 8 files changed, 24 insertions(+), 509 deletions(-) diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 39eeb7759..83f633fd8 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -134,7 +134,6 @@ pub struct ReplayStageConfig { pub wait_for_vote_to_start_leader: bool, pub ancestor_hashes_replay_update_sender: AncestorHashesReplayUpdateSender, pub tower_storage: Arc, - pub disable_epoch_boundary_optimization: bool, } #[derive(Default)] @@ -345,7 +344,6 @@ impl ReplayStage { wait_for_vote_to_start_leader, ancestor_hashes_replay_update_sender, tower_storage, - disable_epoch_boundary_optimization, } = config; trace!("replay stage"); @@ -775,7 +773,6 @@ impl ReplayStage { &retransmit_slots_sender, &mut skipped_slots_info, has_new_vote_been_rooted, - disable_epoch_boundary_optimization, ); let poh_bank = poh_recorder.lock().unwrap().bank(); @@ -1359,7 +1356,6 @@ impl ReplayStage { retransmit_slots_sender: &RetransmitSlotsSender, skipped_slots_info: &mut SkippedSlotsInfo, has_new_vote_been_rooted: bool, - disable_epoch_boundary_optimization: bool, ) { // all the individual calls to poh_recorder.lock() are designed to // increase granularity, decrease contention @@ -1477,10 +1473,7 @@ impl ReplayStage { root_slot, my_pubkey, rpc_subscriptions, - NewBankOptions { - vote_only_bank, - disable_epoch_boundary_optimization, - }, + NewBankOptions { vote_only_bank }, ); let tpu_bank = bank_forks.write().unwrap().insert(tpu_bank); diff --git a/core/src/tvu.rs b/core/src/tvu.rs index adda7b0d0..9ba7b93e6 100644 --- a/core/src/tvu.rs +++ b/core/src/tvu.rs @@ -99,7 +99,6 @@ pub struct TvuConfig { pub rocksdb_max_compaction_jitter: Option, pub wait_for_vote_to_start_leader: bool, pub accounts_shrink_ratio: AccountShrinkThreshold, - pub disable_epoch_boundary_optimization: bool, } impl Tvu { @@ -288,7 +287,6 @@ impl Tvu { wait_for_vote_to_start_leader: tvu_config.wait_for_vote_to_start_leader, ancestor_hashes_replay_update_sender, tower_storage: tower_storage.clone(), - disable_epoch_boundary_optimization: tvu_config.disable_epoch_boundary_optimization, }; let (voting_sender, voting_receiver) = channel(); diff --git a/core/src/validator.rs b/core/src/validator.rs index cfa175260..f447690e8 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -165,7 +165,6 @@ pub struct ValidatorConfig { pub validator_exit: Arc>, pub no_wait_for_vote_to_start_leader: bool, pub accounts_shrink_ratio: AccountShrinkThreshold, - pub disable_epoch_boundary_optimization: bool, } impl Default for ValidatorConfig { @@ -225,7 +224,6 @@ impl Default for ValidatorConfig { no_wait_for_vote_to_start_leader: true, accounts_shrink_ratio: AccountShrinkThreshold::default(), accounts_db_config: None, - disable_epoch_boundary_optimization: false, } } } @@ -866,7 +864,6 @@ impl Validator { rocksdb_max_compaction_jitter: config.rocksdb_compaction_interval, wait_for_vote_to_start_leader, accounts_shrink_ratio: config.accounts_shrink_ratio, - disable_epoch_boundary_optimization: config.disable_epoch_boundary_optimization, }, &max_slots, &cost_model, diff --git a/local-cluster/src/validator_configs.rs b/local-cluster/src/validator_configs.rs index a38027bc3..dff84c2ec 100644 --- a/local-cluster/src/validator_configs.rs +++ b/local-cluster/src/validator_configs.rs @@ -61,7 +61,6 @@ pub fn safe_clone_config(config: &ValidatorConfig) -> ValidatorConfig { no_wait_for_vote_to_start_leader: config.no_wait_for_vote_to_start_leader, accounts_shrink_ratio: config.accounts_shrink_ratio, accounts_db_config: config.accounts_db_config.clone(), - disable_epoch_boundary_optimization: config.disable_epoch_boundary_optimization, } } diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 213c2e70b..50c56f7ae 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -1098,81 +1098,6 @@ fn stake_weighted_credits_observed( } } -// utility function, used by runtime -// returns a tuple of (stakers_reward,voters_reward) -#[doc(hidden)] -#[deprecated(note = "remove after optimize_epoch_boundary_updates feature is active")] -pub fn redeem_rewards_slow( - rewarded_epoch: Epoch, - stake_account: &mut AccountSharedData, - vote_account: &mut AccountSharedData, - vote_state: &VoteState, - point_value: &PointValue, - stake_history: Option<&StakeHistory>, - inflation_point_calc_tracer: Option, - fix_activating_credits_observed: bool, -) -> Result<(u64, u64), InstructionError> { - if let StakeState::Stake(meta, mut stake) = stake_account.state()? { - if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer.as_ref() { - inflation_point_calc_tracer( - &InflationPointCalculationEvent::EffectiveStakeAtRewardedEpoch( - stake.stake(rewarded_epoch, stake_history), - ), - ); - inflation_point_calc_tracer(&InflationPointCalculationEvent::RentExemptReserve( - meta.rent_exempt_reserve, - )); - inflation_point_calc_tracer(&InflationPointCalculationEvent::Commission( - vote_state.commission, - )); - } - - if let Some((stakers_reward, voters_reward)) = redeem_stake_rewards( - rewarded_epoch, - &mut stake, - point_value, - vote_state, - stake_history, - inflation_point_calc_tracer, - fix_activating_credits_observed, - ) { - stake_account.checked_add_lamports(stakers_reward)?; - vote_account.checked_add_lamports(voters_reward)?; - - stake_account.set_state(&StakeState::Stake(meta, stake))?; - - Ok((stakers_reward, voters_reward)) - } else { - Err(StakeError::NoCreditsToRedeem.into()) - } - } else { - Err(InstructionError::InvalidAccountData) - } -} - -// utility function, used by runtime -#[doc(hidden)] -#[deprecated(note = "remove after optimize_epoch_boundary_updates feature is active")] -pub fn calculate_points_slow( - stake_account: &AccountSharedData, - vote_account: &AccountSharedData, - stake_history: Option<&StakeHistory>, -) -> Result { - if let StakeState::Stake(_meta, stake) = stake_account.state()? { - let vote_state: VoteState = - StateMut::::state(vote_account)?.convert_to_current(); - - Ok(calculate_stake_points( - &stake, - &vote_state, - stake_history, - null_tracer(), - )) - } else { - Err(InstructionError::InvalidAccountData) - } -} - // utility function, used by runtime // returns a tuple of (stakers_reward,voters_reward) #[doc(hidden)] diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 5da708485..bb36bf192 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1057,7 +1057,6 @@ struct VoteWithStakeDelegations { #[derive(Debug, Default)] pub struct NewBankOptions { pub vote_only_bank: bool, - pub disable_epoch_boundary_optimization: bool, } impl Bank { @@ -1322,10 +1321,7 @@ impl Bank { new_bank_options: NewBankOptions, ) -> Self { let mut time = Measure::start("bank::new_from_parent"); - let NewBankOptions { - vote_only_bank, - disable_epoch_boundary_optimization, - } = new_bank_options; + let NewBankOptions { vote_only_bank } = new_bank_options; parent.freeze(); assert_ne!(slot, parent.slot()); @@ -1437,56 +1433,32 @@ impl Bank { // Following code may touch AccountsDb, requiring proper ancestors let parent_epoch = parent.epoch(); if parent_epoch < new.epoch() { + let thread_pool = ThreadPoolBuilder::new().build().unwrap(); + new.apply_feature_activations(false, false); + + // Add new entry to stakes.stake_history, set appropriate epoch and + // update vote accounts with warmed up stakes before saving a + // snapshot of stakes in epoch stakes + new.stakes + .write() + .unwrap() + .activate_epoch(epoch, &thread_pool); + + // Save a snapshot of stakes for use in consensus and stake weighted networking + let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot); + new.update_epoch_stakes(leader_schedule_epoch); + + // After saving a snapshot of stakes, apply stake rewards and commission + new.update_rewards_with_thread_pool(parent_epoch, reward_calc_tracer, &thread_pool); + } else { + // Save a snapshot of stakes for use in consensus and stake weighted networking + let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot); + new.update_epoch_stakes(leader_schedule_epoch); } - let optimize_epoch_boundary_updates = !disable_epoch_boundary_optimization - && new - .feature_set - .is_active(&feature_set::optimize_epoch_boundary_updates::id()); - - if optimize_epoch_boundary_updates { - if parent_epoch < new.epoch() { - let thread_pool = ThreadPoolBuilder::new().build().unwrap(); - - // Add new entry to stakes.stake_history, set appropriate epoch and - // update vote accounts with warmed up stakes before saving a - // snapshot of stakes in epoch stakes - new.stakes - .write() - .unwrap() - .activate_epoch(epoch, &thread_pool); - - // Save a snapshot of stakes for use in consensus and stake weighted networking - let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot); - new.update_epoch_stakes(leader_schedule_epoch); - - // After saving a snapshot of stakes, apply stake rewards and commission - new.update_rewards_with_thread_pool(parent_epoch, reward_calc_tracer, &thread_pool); - } else { - // Save a snapshot of stakes for use in consensus and stake weighted networking - let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot); - new.update_epoch_stakes(leader_schedule_epoch); - } - - // Update sysvars before processing transactions - new.update_slot_hashes(); - new.update_stake_history(Some(parent_epoch)); - new.update_clock(Some(parent_epoch)); - new.update_fees(); - new.fill_sysvar_cache(); - - return new; - } - - #[allow(deprecated)] - let cloned = new.stakes.read().unwrap().clone_with_epoch(epoch); - *new.stakes.write().unwrap() = cloned; - - let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot); - new.update_epoch_stakes(leader_schedule_epoch); + // Update sysvars before processing transactions new.update_slot_hashes(); - new.update_rewards(parent_epoch, reward_calc_tracer); new.update_stake_history(Some(parent_epoch)); new.update_clock(Some(parent_epoch)); new.update_fees(); @@ -2087,111 +2059,6 @@ impl Bank { num_slots as f64 / self.slots_per_year } - // update rewards based on the previous epoch - fn update_rewards( - &mut self, - prev_epoch: Epoch, - reward_calc_tracer: Option, - ) { - if prev_epoch == self.epoch() { - return; - } - let mut timing = Measure::start("epoch_rewards"); - // if I'm the first Bank in an epoch, count, claim, disburse rewards from Inflation - - let slot_in_year = self.slot_in_year_for_inflation(); - let epoch_duration_in_years = self.epoch_duration_in_years(prev_epoch); - - let (validator_rate, foundation_rate) = { - let inflation = self.inflation.read().unwrap(); - ( - (*inflation).validator(slot_in_year), - (*inflation).foundation(slot_in_year), - ) - }; - - let capitalization = self.capitalization(); - let validator_rewards = - (validator_rate * capitalization as f64 * epoch_duration_in_years) as u64; - - let old_vote_balance_and_staked = self.stakes.read().unwrap().vote_balance_and_staked(); - - #[allow(deprecated)] - let validator_point_value = self.pay_validator_rewards( - prev_epoch, - validator_rewards, - reward_calc_tracer, - self.stake_program_advance_activating_credits_observed(), - ); - - if !self - .feature_set - .is_active(&feature_set::deprecate_rewards_sysvar::id()) - { - // this sysvar can be retired once `pico_inflation` is enabled on all clusters - self.update_sysvar_account(&sysvar::rewards::id(), |account| { - create_account( - &sysvar::rewards::Rewards::new(validator_point_value), - self.inherit_specially_retained_account_fields(account), - ) - }); - } - - let new_vote_balance_and_staked = self.stakes.read().unwrap().vote_balance_and_staked(); - let validator_rewards_paid = new_vote_balance_and_staked - old_vote_balance_and_staked; - assert_eq!( - validator_rewards_paid, - u64::try_from( - self.rewards - .read() - .unwrap() - .iter() - .map(|(_address, reward_info)| { - match reward_info.reward_type { - RewardType::Voting | RewardType::Staking => reward_info.lamports, - _ => 0, - } - }) - .sum::() - ) - .unwrap() - ); - - // verify that we didn't pay any more than we expected to - assert!(validator_rewards >= validator_rewards_paid); - - info!( - "distributed inflation: {} (rounded from: {})", - validator_rewards_paid, validator_rewards - ); - - self.capitalization - .fetch_add(validator_rewards_paid, Relaxed); - - let active_stake = if let Some(stake_history_entry) = - self.stakes.read().unwrap().history().get(prev_epoch) - { - stake_history_entry.effective - } else { - 0 - }; - timing.stop(); - - datapoint_warn!( - "epoch_rewards", - ("slot", self.slot, i64), - ("epoch", prev_epoch, i64), - ("validator_rate", validator_rate, f64), - ("foundation_rate", foundation_rate, f64), - ("epoch_duration_in_years", epoch_duration_in_years, f64), - ("validator_rewards", validator_rewards_paid, i64), - ("active_stake", active_stake, i64), - ("pre_capitalization", capitalization, i64), - ("post_capitalization", self.capitalization(), i64), - ("time_us", timing.as_us(), i64) - ); - } - // update rewards based on the previous epoch fn update_rewards_with_thread_pool( &mut self, @@ -2290,69 +2157,6 @@ impl Bank { ); } - /// map stake delegations into resolved (pubkey, account) pairs - /// returns a map (has to be copied) of loaded - /// ( Vec<(staker info)> (voter account) ) keyed by voter pubkey - /// - /// Filters out invalid pairs - #[deprecated(note = "remove after optimize_epoch_boundary_updates feature is active")] - fn stake_delegation_accounts( - &self, - reward_calc_tracer: Option, - ) -> HashMap, AccountSharedData)> { - let mut accounts = HashMap::new(); - - self.stakes - .read() - .unwrap() - .stake_delegations() - .iter() - .for_each(|(stake_pubkey, delegation)| { - match ( - self.get_account_with_fixed_root(stake_pubkey), - self.get_account_with_fixed_root(&delegation.voter_pubkey), - ) { - (Some(stake_account), Some(vote_account)) => { - // call tracer to catch any illegal data if any - if let Some(reward_calc_tracer) = reward_calc_tracer.as_ref() { - reward_calc_tracer(&RewardCalculationEvent::Staking( - stake_pubkey, - &InflationPointCalculationEvent::Delegation( - *delegation, - *vote_account.owner(), - ), - )); - } - if self - .feature_set - .is_active(&feature_set::filter_stake_delegation_accounts::id()) - && (stake_account.owner() != &solana_stake_program::id() - || vote_account.owner() != &solana_vote_program::id()) - { - datapoint_warn!( - "bank-stake_delegation_accounts-invalid-account", - ("slot", self.slot() as i64, i64), - ("stake-address", format!("{:?}", stake_pubkey), String), - ( - "vote-address", - format!("{:?}", delegation.voter_pubkey), - String - ), - ); - return; - } - let entry = accounts - .entry(delegation.voter_pubkey) - .or_insert((Vec::new(), vote_account)); - entry.0.push((*stake_pubkey, stake_account)); - } - (_, _) => {} - } - }); - - accounts - } - /// map stake delegations into resolved (pubkey, account) pairs /// returns a map (has to be copied) of loaded /// ( Vec<(staker info)> (voter account) ) keyed by voter pubkey @@ -2460,128 +2264,6 @@ impl Bank { accounts } - /// iterate over all stakes, redeem vote credits for each stake we can - /// successfully load and parse, return the lamport value of one point - #[deprecated(note = "remove after optimize_epoch_boundary_updates feature is active")] - fn pay_validator_rewards( - &mut self, - rewarded_epoch: Epoch, - rewards: u64, - reward_calc_tracer: Option, - fix_activating_credits_observed: bool, - ) -> f64 { - let stake_history = self.stakes.read().unwrap().history().clone(); - - #[allow(deprecated)] - let mut stake_delegation_accounts = - self.stake_delegation_accounts(reward_calc_tracer.as_ref()); - - let points: u128 = stake_delegation_accounts - .iter() - .flat_map(|(_vote_pubkey, (stake_group, vote_account))| { - stake_group - .iter() - .map(move |(_stake_pubkey, stake_account)| (stake_account, vote_account)) - }) - .map(|(stake_account, vote_account)| { - #[allow(deprecated)] - stake_state::calculate_points_slow( - stake_account, - vote_account, - Some(&stake_history), - ) - .unwrap_or(0) - }) - .sum(); - - if points == 0 { - return 0.0; - } - - let point_value = PointValue { rewards, points }; - - let mut rewards = vec![]; - // pay according to point value - for (vote_pubkey, (stake_group, vote_account)) in stake_delegation_accounts.iter_mut() { - let mut vote_account_changed = false; - let voters_account_pre_balance = vote_account.lamports(); - let vote_state: VoteState = match StateMut::::state(vote_account) { - Ok(vote_state) => vote_state.convert_to_current(), - Err(err) => { - debug!( - "failed to deserialize vote account {}: {}", - vote_pubkey, err - ); - continue; - } - }; - let commission = Some(vote_state.commission); - - for (stake_pubkey, stake_account) in stake_group.iter_mut() { - // curry closure to add the contextual stake_pubkey - let reward_calc_tracer = reward_calc_tracer.as_ref().map(|outer| { - let stake_pubkey = *stake_pubkey; - // inner - move |inner_event: &_| { - outer(&RewardCalculationEvent::Staking(&stake_pubkey, inner_event)) - } - }); - #[allow(deprecated)] - let redeemed = stake_state::redeem_rewards_slow( - rewarded_epoch, - stake_account, - vote_account, - &vote_state, - &point_value, - Some(&stake_history), - reward_calc_tracer, - fix_activating_credits_observed, - ); - if let Ok((stakers_reward, _voters_reward)) = redeemed { - self.store_account(stake_pubkey, stake_account); - vote_account_changed = true; - - if stakers_reward > 0 { - rewards.push(( - *stake_pubkey, - RewardInfo { - reward_type: RewardType::Staking, - lamports: stakers_reward as i64, - post_balance: stake_account.lamports(), - commission, - }, - )); - } - } else { - debug!( - "stake_state::redeem_rewards() failed for {}: {:?}", - stake_pubkey, redeemed - ); - } - } - - if vote_account_changed { - let post_balance = vote_account.lamports(); - let lamports = (post_balance - voters_account_pre_balance) as i64; - if lamports != 0 { - rewards.push(( - *vote_pubkey, - RewardInfo { - reward_type: RewardType::Voting, - lamports, - post_balance, - commission, - }, - )); - } - self.store_account(vote_pubkey, vote_account); - } - } - self.rewards.write().unwrap().append(&mut rewards); - - point_value.rewards as f64 / point_value.points as f64 - } - /// iterate over all stakes, redeem vote credits for each stake we can /// successfully load and parse, return the lamport value of one point fn pay_validator_rewards_with_thread_pool( diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index e1db78324..0663e52c2 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -47,46 +47,6 @@ impl Stakes { &self.stake_history } - #[deprecated(note = "remove after optimize_epoch_boundary_updates feature is active")] - pub fn clone_with_epoch(&self, next_epoch: Epoch) -> Self { - let prev_epoch = self.epoch; - if prev_epoch == next_epoch { - self.clone() - } else { - // wrap up the prev epoch by adding new stake history entry for the prev epoch - let mut stake_history_upto_prev_epoch = self.stake_history.clone(); - stake_history_upto_prev_epoch.add( - prev_epoch, - stake_state::new_stake_history_entry( - prev_epoch, - self.stake_delegations - .iter() - .map(|(_pubkey, stake_delegation)| stake_delegation), - Some(&self.stake_history), - ), - ); - - // refresh the stake distribution of vote accounts for the next epoch, using new stake history - let vote_accounts_for_next_epoch = self - .vote_accounts - .iter() - .map(|(pubkey, (_ /*stake*/, account))| { - let stake = - self.calculate_stake(pubkey, next_epoch, &stake_history_upto_prev_epoch); - (*pubkey, (stake, account.clone())) - }) - .collect(); - - Stakes { - stake_delegations: self.stake_delegations.clone(), - unused: self.unused, - epoch: next_epoch, - stake_history: stake_history_upto_prev_epoch, - vote_accounts: vote_accounts_for_next_epoch, - } - } - } - pub fn activate_epoch(&mut self, next_epoch: Epoch, thread_pool: &ThreadPool) { let prev_epoch = self.epoch; self.epoch = next_epoch; @@ -583,35 +543,6 @@ pub mod tests { } } - #[test] - fn test_clone_with_epoch() { - let mut stakes = Stakes::default(); - - let ((vote_pubkey, vote_account), (stake_pubkey, stake_account)) = - create_staked_node_accounts(10); - - stakes.store(&vote_pubkey, &vote_account, true); - stakes.store(&stake_pubkey, &stake_account, true); - let stake = stake_state::stake_from(&stake_account).unwrap(); - - { - let vote_accounts = stakes.vote_accounts(); - assert_eq!( - vote_accounts.get(&vote_pubkey).unwrap().0, - stake.stake(stakes.epoch, Some(&stakes.stake_history)) - ); - } - #[allow(deprecated)] - let stakes = stakes.clone_with_epoch(3); - { - let vote_accounts = stakes.vote_accounts(); - assert_eq!( - vote_accounts.get(&vote_pubkey).unwrap().0, - stake.stake(stakes.epoch, Some(&stakes.stake_history)) - ); - } - } - #[test] fn test_activate_epoch() { let mut stakes = Stakes::default(); diff --git a/validator/src/main.rs b/validator/src/main.rs index 7d2a8a7ce..67ac40cb2 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -1613,14 +1613,6 @@ pub fn main() { .help("Allow contacting private ip addresses") .hidden(true), ) - .arg( - Arg::with_name("disable_epoch_boundary_optimization") - .long("disable-epoch-boundary-optimization") - .takes_value(false) - .help("Disables epoch boundary optimization and overrides the \ - optimize_epoch_boundary_updates feature switch if enabled.") - .hidden(true), - ) .after_help("The default subcommand is run") .subcommand( SubCommand::with_name("exit") @@ -2291,8 +2283,6 @@ pub fn main() { tpu_coalesce_ms, no_wait_for_vote_to_start_leader: matches.is_present("no_wait_for_vote_to_start_leader"), accounts_shrink_ratio, - disable_epoch_boundary_optimization: matches - .is_present("disable_epoch_boundary_optimization"), ..ValidatorConfig::default() };