From 9886d085a69d695f48970f48f2f567e62ba05414 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Sat, 18 Jul 2020 00:32:25 +0900 Subject: [PATCH] Don't overwrite accounts with stale copies --- runtime/src/bank.rs | 86 ++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index de7f41b97b..cdc54d2c7a 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -935,11 +935,11 @@ impl Bank { .fetch_add(validator_rewards_paid, Ordering::Relaxed); } - /// map stake delegations into resolved (pubkey, account) pairs + /// map stake delegations into resolved pubkeys /// returns a vector (has to be copied) of loaded - /// ( (staker info) (voter info) ) + /// ( staker pubkey voter pubkey ) /// - fn stake_delegation_accounts(&self) -> Vec<((Pubkey, Account), (Pubkey, Account))> { + fn stake_delegation_pubkeys(&self) -> Vec<(Pubkey, Pubkey)> { self.stakes .read() .unwrap() @@ -950,25 +950,35 @@ impl Bank { self.get_account(&stake_pubkey), self.get_account(&delegation.voter_pubkey), ) { - (Some(stake_account), Some(vote_account)) => Some(( - (*stake_pubkey, stake_account), - (delegation.voter_pubkey, vote_account), - )), + (Some(_stake_account), Some(_vote_account)) => { + Some((*stake_pubkey, delegation.voter_pubkey)) + } (_, _) => None, } }) .collect() } + fn paired_accounts( + &self, + (stake_pubkey, vote_pubkey): (Pubkey, Pubkey), + ) -> ((Pubkey, Account), (Pubkey, Account)) { + ( + (stake_pubkey, self.get_account(&stake_pubkey).unwrap()), + (vote_pubkey, self.get_account(&vote_pubkey).unwrap()), + ) + } + /// iterate over all stakes, redeem vote credits for each stake we can /// successfully load and parse, return total payout fn pay_validator_rewards(&mut self, rewards: u64) -> f64 { let stake_history = self.stakes.read().unwrap().history().clone(); - let mut stake_delegation_accounts = self.stake_delegation_accounts(); + let stake_delegation_pubkeys = self.stake_delegation_pubkeys(); - let points: u128 = stake_delegation_accounts + let points: u128 = stake_delegation_pubkeys .iter() + .map(|pubkeys| self.paired_accounts(*pubkeys)) .map( |((_stake_pubkey, stake_account), (_vote_pubkey, vote_account))| { stake_state::calculate_points( @@ -990,33 +1000,36 @@ impl Bank { let mut rewards = HashMap::new(); // pay according to point value - stake_delegation_accounts.iter_mut().for_each( - |((stake_pubkey, stake_account), (vote_pubkey, vote_account))| { - let redeemed = stake_state::redeem_rewards( - stake_account, - vote_account, - &point_value, - Some(&stake_history), - ); - if let Ok((stakers_reward, voters_reward)) = redeemed { - self.store_account(&stake_pubkey, &stake_account); - self.store_account(&vote_pubkey, &vote_account); - - if voters_reward > 0 { - *rewards.entry(*vote_pubkey).or_insert(0i64) += voters_reward as i64; - } - - if stakers_reward > 0 { - *rewards.entry(*stake_pubkey).or_insert(0i64) += stakers_reward as i64; - } - } else { - debug!( - "stake_state::redeem_rewards() failed for {}: {:?}", - stake_pubkey, redeemed + stake_delegation_pubkeys + .into_iter() + .map(|pubkeys| self.paired_accounts(pubkeys)) + .for_each( + |((stake_pubkey, mut stake_account), (vote_pubkey, mut vote_account))| { + let redeemed = stake_state::redeem_rewards( + &mut stake_account, + &mut vote_account, + &point_value, + Some(&stake_history), ); - } - }, - ); + if let Ok((stakers_reward, voters_reward)) = redeemed { + self.store_account(&stake_pubkey, &stake_account); + self.store_account(&vote_pubkey, &vote_account); + + if voters_reward > 0 { + *rewards.entry(vote_pubkey).or_insert(0i64) += voters_reward as i64; + } + + if stakers_reward > 0 { + *rewards.entry(stake_pubkey).or_insert(0i64) += stakers_reward as i64; + } + } else { + debug!( + "stake_state::redeem_rewards() failed for {}: {:?}", + stake_pubkey, redeemed + ); + } + }, + ); assert_eq!(self.rewards, None); self.rewards = Some(rewards.drain().collect()); @@ -4768,8 +4781,9 @@ mod tests { bank.store_account(&vote_id, &vote_account); let validator_points: u128 = bank - .stake_delegation_accounts() + .stake_delegation_pubkeys() .iter() + .map(|pubkeys| bank.paired_accounts(*pubkeys)) .map( |((_stake_pubkey, stake_account), (_vote_pubkey, vote_account))| { stake_state::calculate_points(&stake_account, &vote_account, None).unwrap_or(0)