Compute Switch Threshold (#9218)

* Add switching threshold check

Co-authored-by: Carl <carl@solana.com>
This commit is contained in:
carllin
2020-05-11 22:20:11 -07:00
committed by GitHub
parent 84b6120983
commit 59de1b3b62
5 changed files with 468 additions and 99 deletions

View File

@@ -1,6 +1,7 @@
use crate::{
cluster_info_vote_listener::SlotVoteTracker, cluster_slots::SlotPubkeys,
consensus::StakeLockout, replay_stage::SUPERMINORITY_THRESHOLD,
consensus::StakeLockout, pubkey_references::PubkeyReferences,
replay_stage::SUPERMINORITY_THRESHOLD,
};
use solana_ledger::{
bank_forks::BankForks,
@@ -9,11 +10,13 @@ use solana_ledger::{
use solana_runtime::bank::Bank;
use solana_sdk::{account::Account, clock::Slot, hash::Hash, pubkey::Pubkey};
use std::{
collections::{HashMap, HashSet},
collections::{BTreeMap, HashMap, HashSet},
rc::Rc,
sync::{Arc, RwLock},
};
pub(crate) type LockoutIntervals = BTreeMap<Slot, Vec<(Slot, Rc<Pubkey>)>>;
#[derive(Default)]
pub(crate) struct ReplaySlotStats(ConfirmationTiming);
impl std::ops::Deref for ReplaySlotStats {
@@ -191,6 +194,7 @@ pub(crate) struct ForkStats {
pub(crate) stake_lockouts: HashMap<u64, StakeLockout>,
pub(crate) confirmation_reported: bool,
pub(crate) computed: bool,
pub(crate) lockout_intervals: LockoutIntervals,
}
#[derive(Clone, Default)]
@@ -210,18 +214,12 @@ impl PropagatedStats {
pub fn add_vote_pubkey(
&mut self,
vote_pubkey: &Pubkey,
all_pubkeys: &mut HashSet<Rc<Pubkey>>,
all_pubkeys: &mut PubkeyReferences,
stake: u64,
) {
if !self.propagated_validators.contains(vote_pubkey) {
let mut cached_pubkey: Option<Rc<Pubkey>> = all_pubkeys.get(vote_pubkey).cloned();
if cached_pubkey.is_none() {
let new_pubkey = Rc::new(*vote_pubkey);
all_pubkeys.insert(new_pubkey.clone());
cached_pubkey = Some(new_pubkey);
}
let vote_pubkey = cached_pubkey.unwrap();
self.propagated_validators.insert(vote_pubkey);
let cached_pubkey = all_pubkeys.get_or_insert(vote_pubkey);
self.propagated_validators.insert(cached_pubkey);
self.propagated_validators_stake += stake;
}
}
@@ -229,7 +227,7 @@ impl PropagatedStats {
pub fn add_node_pubkey(
&mut self,
node_pubkey: &Pubkey,
all_pubkeys: &mut HashSet<Rc<Pubkey>>,
all_pubkeys: &mut PubkeyReferences,
bank: &Bank,
) {
if !self.propagated_node_ids.contains(node_pubkey) {
@@ -252,18 +250,12 @@ impl PropagatedStats {
fn add_node_pubkey_internal(
&mut self,
node_pubkey: &Pubkey,
all_pubkeys: &mut HashSet<Rc<Pubkey>>,
all_pubkeys: &mut PubkeyReferences,
vote_account_pubkeys: &[Pubkey],
epoch_vote_accounts: &HashMap<Pubkey, (u64, Account)>,
) {
let mut cached_pubkey: Option<Rc<Pubkey>> = all_pubkeys.get(node_pubkey).cloned();
if cached_pubkey.is_none() {
let new_pubkey = Rc::new(*node_pubkey);
all_pubkeys.insert(new_pubkey.clone());
cached_pubkey = Some(new_pubkey);
}
let node_pubkey = cached_pubkey.unwrap();
self.propagated_node_ids.insert(node_pubkey);
let cached_pubkey = all_pubkeys.get_or_insert(node_pubkey);
self.propagated_node_ids.insert(cached_pubkey);
for vote_account_pubkey in vote_account_pubkeys.iter() {
let stake = epoch_vote_accounts
.get(vote_account_pubkey)
@@ -398,16 +390,19 @@ mod test {
#[test]
fn test_add_vote_pubkey() {
let mut stats = PropagatedStats::default();
let mut all_pubkeys = HashSet::new();
let mut all_pubkeys = PubkeyReferences::default();
let mut vote_pubkey = Pubkey::new_rand();
all_pubkeys.insert(Rc::new(vote_pubkey.clone()));
all_pubkeys.get_or_insert(&vote_pubkey);
// Add a vote pubkey, the number of references in all_pubkeys
// should be 2
stats.add_vote_pubkey(&vote_pubkey, &mut all_pubkeys, 1);
assert!(stats.propagated_validators.contains(&vote_pubkey));
assert_eq!(stats.propagated_validators_stake, 1);
assert_eq!(Rc::strong_count(all_pubkeys.get(&vote_pubkey).unwrap()), 2);
assert_eq!(
Rc::strong_count(&all_pubkeys.get_or_insert(&vote_pubkey)),
3
);
// Adding it again should change no state since the key already existed
stats.add_vote_pubkey(&vote_pubkey, &mut all_pubkeys, 1);
@@ -419,7 +414,10 @@ mod test {
stats.add_vote_pubkey(&vote_pubkey, &mut all_pubkeys, 2);
assert!(stats.propagated_validators.contains(&vote_pubkey));
assert_eq!(stats.propagated_validators_stake, 3);
assert_eq!(Rc::strong_count(all_pubkeys.get(&vote_pubkey).unwrap()), 2);
assert_eq!(
Rc::strong_count(&all_pubkeys.get_or_insert(&vote_pubkey)),
3
);
}
#[test]
@@ -436,9 +434,9 @@ mod test {
.collect();
let mut stats = PropagatedStats::default();
let mut all_pubkeys = HashSet::new();
let mut all_pubkeys = PubkeyReferences::default();
let mut node_pubkey = Pubkey::new_rand();
all_pubkeys.insert(Rc::new(node_pubkey.clone()));
all_pubkeys.get_or_insert(&node_pubkey);
// Add a vote pubkey, the number of references in all_pubkeys
// should be 2
@@ -453,7 +451,10 @@ mod test {
stats.propagated_validators_stake,
staked_vote_accounts as u64
);
assert_eq!(Rc::strong_count(all_pubkeys.get(&node_pubkey).unwrap()), 2);
assert_eq!(
Rc::strong_count(&all_pubkeys.get_or_insert(&node_pubkey)),
3
);
// Adding it again should not change any state
stats.add_node_pubkey_internal(
@@ -482,7 +483,10 @@ mod test {
stats.propagated_validators_stake,
staked_vote_accounts as u64
);
assert_eq!(Rc::strong_count(all_pubkeys.get(&node_pubkey).unwrap()), 2);
assert_eq!(
Rc::strong_count(&all_pubkeys.get_or_insert(&node_pubkey)),
3
);
// Addding another pubkey with different vote accounts should succeed
// and increase stake
@@ -506,7 +510,10 @@ mod test {
stats.propagated_validators_stake,
2 * staked_vote_accounts as u64
);
assert_eq!(Rc::strong_count(all_pubkeys.get(&node_pubkey).unwrap()), 2);
assert_eq!(
Rc::strong_count(&all_pubkeys.get_or_insert(&node_pubkey)),
3
);
}
#[test]