fix is_locked_out logic

This commit is contained in:
Anatoly Yakovenko 2019-03-19 16:00:52 -07:00 committed by Grimes
parent 70b21b3795
commit 7246d72f03
2 changed files with 46 additions and 19 deletions

View File

@ -7,8 +7,8 @@ use solana_sdk::pubkey::Pubkey;
use solana_vote_api::vote_instruction::Vote; use solana_vote_api::vote_instruction::Vote;
use solana_vote_api::vote_state::{Lockout, VoteState, MAX_LOCKOUT_HISTORY}; use solana_vote_api::vote_state::{Lockout, VoteState, MAX_LOCKOUT_HISTORY};
const VOTE_THRESHOLD_DEPTH: usize = 8; pub const VOTE_THRESHOLD_DEPTH: usize = 8;
const VOTE_THRESHOLD_SIZE: f64 = 2f64 / 3f64; pub const VOTE_THRESHOLD_SIZE: f64 = 2f64 / 3f64;
#[derive(Default)] #[derive(Default)]
pub struct EpochStakes { pub struct EpochStakes {
@ -191,13 +191,13 @@ impl Locktower {
continue; continue;
} }
if !descendants[&vote.slot].contains(&slot) { if !descendants[&vote.slot].contains(&slot) {
return false; return true;
} }
} }
if let Some(root) = lockouts.root_slot { if let Some(root) = lockouts.root_slot {
descendants[&root].contains(&slot) !descendants[&root].contains(&slot)
} else { } else {
true false
} }
} }
@ -385,27 +385,27 @@ mod test {
fn test_is_locked_out_empty() { fn test_is_locked_out_empty() {
let locktower = Locktower::new(EpochStakes::new_for_tests(2), 0, 0.67); let locktower = Locktower::new(EpochStakes::new_for_tests(2), 0, 0.67);
let descendants = HashMap::new(); let descendants = HashMap::new();
assert!(locktower.is_locked_out(0, &descendants)); assert!(!locktower.is_locked_out(0, &descendants));
} }
#[test] #[test]
fn test_is_locked_out_root_slot_child() { fn test_is_locked_out_root_slot_child_pass() {
let mut locktower = Locktower::new(EpochStakes::new_for_tests(2), 0, 0.67); let mut locktower = Locktower::new(EpochStakes::new_for_tests(2), 0, 0.67);
let descendants = vec![(0, vec![1].into_iter().collect())] let descendants = vec![(0, vec![1].into_iter().collect())]
.into_iter() .into_iter()
.collect(); .collect();
locktower.lockouts.root_slot = Some(0); locktower.lockouts.root_slot = Some(0);
assert!(locktower.is_locked_out(1, &descendants)); assert!(!locktower.is_locked_out(1, &descendants));
} }
#[test] #[test]
fn test_is_locked_out_root_slot_sibling() { fn test_is_locked_out_root_slot_sibling_fail() {
let mut locktower = Locktower::new(EpochStakes::new_for_tests(2), 0, 0.67); let mut locktower = Locktower::new(EpochStakes::new_for_tests(2), 0, 0.67);
let descendants = vec![(0, vec![1].into_iter().collect())] let descendants = vec![(0, vec![1].into_iter().collect())]
.into_iter() .into_iter()
.collect(); .collect();
locktower.lockouts.root_slot = Some(0); locktower.lockouts.root_slot = Some(0);
assert!(!locktower.is_locked_out(2, &descendants)); assert!(locktower.is_locked_out(2, &descendants));
} }
#[test] #[test]
@ -424,7 +424,7 @@ mod test {
.collect(); .collect();
locktower.record_vote(0); locktower.record_vote(0);
locktower.record_vote(1); locktower.record_vote(1);
assert!(!locktower.is_locked_out(0, &descendants)); assert!(locktower.is_locked_out(0, &descendants));
} }
#[test] #[test]
@ -434,7 +434,7 @@ mod test {
.into_iter() .into_iter()
.collect(); .collect();
locktower.record_vote(0); locktower.record_vote(0);
assert!(locktower.is_locked_out(1, &descendants)); assert!(!locktower.is_locked_out(1, &descendants));
} }
#[test] #[test]
@ -449,7 +449,7 @@ mod test {
.collect(); .collect();
locktower.record_vote(0); locktower.record_vote(0);
locktower.record_vote(1); locktower.record_vote(1);
assert!(!locktower.is_locked_out(2, &descendants)); assert!(locktower.is_locked_out(2, &descendants));
} }
#[test] #[test]
@ -460,7 +460,7 @@ mod test {
.collect(); .collect();
locktower.record_vote(0); locktower.record_vote(0);
locktower.record_vote(1); locktower.record_vote(1);
assert!(locktower.is_locked_out(4, &descendants)); assert!(!locktower.is_locked_out(4, &descendants));
locktower.record_vote(4); locktower.record_vote(4);
assert_eq!(locktower.lockouts.votes[0].slot, 0); assert_eq!(locktower.lockouts.votes[0].slot, 0);
assert_eq!(locktower.lockouts.votes[0].confirmation_count, 2); assert_eq!(locktower.lockouts.votes[0].confirmation_count, 2);

View File

@ -130,11 +130,25 @@ impl ReplayStage {
let descendants = bank_forks.read().unwrap().descendants(); let descendants = bank_forks.read().unwrap().descendants();
let ancestors = bank_forks.read().unwrap().ancestors(); let ancestors = bank_forks.read().unwrap().ancestors();
let frozen_banks = bank_forks.read().unwrap().frozen_banks(); let frozen_banks = bank_forks.read().unwrap().frozen_banks();
trace!("frozen_banks {}", frozen_banks.len());
let mut votable: Vec<(u128, Arc<Bank>)> = frozen_banks let mut votable: Vec<(u128, Arc<Bank>)> = frozen_banks
.values() .values()
.filter(|b| b.is_votable()) .filter(|b| {
.filter(|b| !locktower.has_voted(b.slot())) let is_votable = b.is_votable();
.filter(|b| !locktower.is_locked_out(b.slot(), &descendants)) trace!("bank is votable: {} {}", b.slot(), is_votable);
is_votable
})
.filter(|b| {
let has_voted = locktower.has_voted(b.slot());
trace!("bank is has_voted: {} {}", b.slot(), has_voted);
!has_voted
})
.filter(|b| {
let is_locked_out = locktower.is_locked_out(b.slot(), &descendants);
trace!("bank is is_locked_out: {} {}", b.slot(), is_locked_out);
!is_locked_out
})
.map(|bank| { .map(|bank| {
( (
bank, bank,
@ -146,7 +160,10 @@ impl ReplayStage {
) )
}) })
.filter(|(b, stake_lockouts)| { .filter(|(b, stake_lockouts)| {
locktower.check_vote_stake_threshold(b.slot(), &stake_lockouts) let vote_threshold =
locktower.check_vote_stake_threshold(b.slot(), &stake_lockouts);
trace!("bank vote_threshold: {} {}", b.slot(), vote_threshold);
vote_threshold
}) })
.map(|(b, stake_lockouts)| { .map(|(b, stake_lockouts)| {
(locktower.calculate_weight(&stake_lockouts), b.clone()) (locktower.calculate_weight(&stake_lockouts), b.clone())
@ -154,8 +171,18 @@ impl ReplayStage {
.collect(); .collect();
votable.sort_by_key(|b| b.0); votable.sort_by_key(|b| b.0);
trace!("votable_banks {}", votable.len());
let ms = timing::duration_as_ms(&locktower_start.elapsed()); let ms = timing::duration_as_ms(&locktower_start.elapsed());
info!("@{:?} locktower duration: {:?}", timing::timestamp(), ms,); if !votable.is_empty() {
let weights: Vec<u128> = votable.iter().map(|x| x.0).collect();
info!(
"@{:?} locktower duration: {:?} len: {} weights: {:?}",
timing::timestamp(),
ms,
votable.len(),
weights
);
}
inc_new_counter_info!("replay_stage-locktower_duration", ms as usize); inc_new_counter_info!("replay_stage-locktower_duration", ms as usize);
if let Some((_, bank)) = votable.last() { if let Some((_, bank)) = votable.last() {