Add {Vote, Tower}::last_voted_slot() (#10734)

This commit is contained in:
Ryo Onodera
2020-06-23 11:59:54 +09:00
committed by GitHub
parent 44f5452013
commit 0952b76f02
4 changed files with 26 additions and 21 deletions

View File

@ -63,7 +63,7 @@ impl ForkChoice for BankWeightForkChoice {
.filter(|b| b.slot() < tower.root().unwrap_or(0)) .filter(|b| b.slot() < tower.root().unwrap_or(0))
.count(); .count();
let last_vote = tower.last_vote().slots.last().cloned(); let last_voted_slot = tower.last_voted_slot();
let mut heaviest_bank_on_same_fork = None; let mut heaviest_bank_on_same_fork = None;
let mut heaviest_same_fork_weight = 0; let mut heaviest_same_fork_weight = 0;
let stats: Vec<&ForkStats> = frozen_banks let stats: Vec<&ForkStats> = frozen_banks
@ -76,18 +76,18 @@ impl ForkChoice for BankWeightForkChoice {
.get_fork_stats(bank.slot()) .get_fork_stats(bank.slot())
.expect("All frozen banks must exist in the Progress map"); .expect("All frozen banks must exist in the Progress map");
if let Some(last_vote) = last_vote { if let Some(last_voted_slot) = last_voted_slot {
if ancestors if ancestors
.get(&bank.slot()) .get(&bank.slot())
.expect("Entry in frozen banks must exist in ancestors") .expect("Entry in frozen banks must exist in ancestors")
.contains(&last_vote) .contains(&last_voted_slot)
{ {
// Descendant of last vote cannot be locked out // Descendant of last vote cannot be locked out
assert!(!stats.is_locked_out); assert!(!stats.is_locked_out);
// ancestors(slot) should not contain the slot itself, // ancestors(slot) should not contain the slot itself,
// so we should never get the same bank as the last vote // so we should never get the same bank as the last vote
assert_ne!(bank.slot(), last_vote); assert_ne!(bank.slot(), last_voted_slot);
// highest weight, lowest slot first. frozen_banks is sorted // highest weight, lowest slot first. frozen_banks is sorted
// from least slot to greatest slot, so if two banks have // from least slot to greatest slot, so if two banks have
// the same fork weight, the lower slot will be picked // the same fork weight, the lower slot will be picked

View File

@ -326,14 +326,17 @@ impl Tower {
self.record_bank_vote(vote) self.record_bank_vote(vote)
} }
pub fn last_vote(&self) -> Vote { pub fn last_vote(&self) -> &Vote {
self.last_vote.clone() &self.last_vote
}
pub fn last_voted_slot(&self) -> Option<Slot> {
self.last_vote().last_voted_slot()
} }
pub fn last_vote_and_timestamp(&mut self) -> Vote { pub fn last_vote_and_timestamp(&mut self) -> Vote {
let mut last_vote = self.last_vote(); let mut last_vote = self.last_vote.clone();
let current_slot = last_vote.slots.iter().max().unwrap_or(&0); last_vote.timestamp = self.maybe_timestamp(last_vote.last_voted_slot().unwrap_or(0));
last_vote.timestamp = self.maybe_timestamp(*current_slot);
last_vote last_vote
} }
@ -397,14 +400,12 @@ impl Tower {
total_stake: u64, total_stake: u64,
epoch_vote_accounts: &HashMap<Pubkey, (u64, Account)>, epoch_vote_accounts: &HashMap<Pubkey, (u64, Account)>,
) -> SwitchForkDecision { ) -> SwitchForkDecision {
self.last_vote() self.last_voted_slot()
.slots .map(|last_voted_slot| {
.last() let last_vote_ancestors = ancestors.get(&last_voted_slot).unwrap();
.map(|last_vote| {
let last_vote_ancestors = ancestors.get(&last_vote).unwrap();
let switch_slot_ancestors = ancestors.get(&switch_slot).unwrap(); let switch_slot_ancestors = ancestors.get(&switch_slot).unwrap();
if switch_slot == *last_vote || switch_slot_ancestors.contains(last_vote) { if switch_slot == last_voted_slot || switch_slot_ancestors.contains(&last_voted_slot) {
// If the `switch_slot is a descendant of the last vote, // If the `switch_slot is a descendant of the last vote,
// no switching proof is necessary // no switching proof is necessary
return SwitchForkDecision::NoSwitch; return SwitchForkDecision::NoSwitch;
@ -427,14 +428,14 @@ impl Tower {
// 3) Don't consider lockouts on any descendants of // 3) Don't consider lockouts on any descendants of
// `last_vote` // `last_vote`
if !descendants.is_empty() if !descendants.is_empty()
|| candidate_slot == last_vote || *candidate_slot == last_voted_slot
|| ancestors || ancestors
.get(&candidate_slot) .get(&candidate_slot)
.expect( .expect(
"empty descendants implies this is a child, not parent of root, so must "empty descendants implies this is a child, not parent of root, so must
exist in the ancestors map", exist in the ancestors map",
) )
.contains(last_vote) .contains(&last_voted_slot)
{ {
continue; continue;
} }
@ -455,7 +456,7 @@ impl Tower {
.lockout_intervals; .lockout_intervals;
// Find any locked out intervals in this bank with endpoint >= last_vote, // Find any locked out intervals in this bank with endpoint >= last_vote,
// implies they are locked out at last_vote // implies they are locked out at last_vote
for (_, value) in lockout_intervals.range((Included(last_vote), Unbounded)) { for (_, value) in lockout_intervals.range((Included(last_voted_slot), Unbounded)) {
for (lockout_interval_start, vote_account_pubkey) in value { for (lockout_interval_start, vote_account_pubkey) in value {
// Only count lockouts on slots that are: // Only count lockouts on slots that are:
// 1) Not ancestors of `last_vote` // 1) Not ancestors of `last_vote`
@ -1747,7 +1748,7 @@ pub mod test {
for i in 0..num_votes { for i in 0..num_votes {
tower.record_vote(i as u64, Hash::default()); tower.record_vote(i as u64, Hash::default());
} }
assert_eq!(expected, tower.last_vote()) assert_eq!(expected, tower.last_vote)
} }
#[test] #[test]

View File

@ -439,8 +439,8 @@ impl ForkChoice for HeaviestSubtreeForkChoice {
_ancestors: &HashMap<u64, HashSet<u64>>, _ancestors: &HashMap<u64, HashSet<u64>>,
bank_forks: &RwLock<BankForks>, bank_forks: &RwLock<BankForks>,
) -> (Arc<Bank>, Option<Arc<Bank>>) { ) -> (Arc<Bank>, Option<Arc<Bank>>) {
let last_vote = tower.last_vote().slots.last().cloned(); let last_voted_slot = tower.last_voted_slot();
let heaviest_slot_on_same_voted_fork = last_vote.map(|last_vote| { let heaviest_slot_on_same_voted_fork = last_voted_slot.map(|last_vote| {
let heaviest_slot_on_same_voted_fork = let heaviest_slot_on_same_voted_fork =
self.best_slot(last_vote).expect("last_vote is a frozen bank so must have been added to heaviest_subtree_fork_choice at time of freezing"); self.best_slot(last_vote).expect("last_vote is a frozen bank so must have been added to heaviest_subtree_fork_choice at time of freezing");
if heaviest_slot_on_same_voted_fork == last_vote { if heaviest_slot_on_same_voted_fork == last_vote {

View File

@ -54,6 +54,10 @@ impl Vote {
timestamp: None, timestamp: None,
} }
} }
pub fn last_voted_slot(&self) -> Option<Slot> {
self.slots.last().copied()
}
} }
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]