Add {Vote, Tower}::last_voted_slot() (#10734)
This commit is contained in:
@ -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
|
||||||
|
@ -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]
|
||||||
|
@ -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 {
|
||||||
|
@ -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)]
|
||||||
|
Reference in New Issue
Block a user