1pub mod fork_choice;
2pub mod heaviest_subtree_fork_choice;
3pub(crate) mod latest_validator_votes_for_frozen_banks;
4pub mod progress_map;
5mod tower1_14_11;
6mod tower1_7_14;
7pub mod tower_storage;
8pub(crate) mod tower_vote_state;
9pub mod tree_diff;
10pub mod vote_stake_tracker;
11
12use {
13 self::{
14 heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
15 latest_validator_votes_for_frozen_banks::LatestValidatorVotesForFrozenBanks,
16 progress_map::{LockoutIntervals, ProgressMap},
17 tower_storage::{SavedTower, SavedTowerVersions, TowerStorage},
18 tower_vote_state::TowerVoteState,
19 tower1_7_14::Tower1_7_14,
20 tower1_14_11::Tower1_14_11,
21 },
22 crate::{consensus::progress_map::LockoutInterval, replay_stage::DUPLICATE_THRESHOLD},
23 agave_votor_messages::{fraction::Fraction, migration::GENESIS_VOTE_THRESHOLD},
24 chrono::prelude::*,
25 solana_clock::{Slot, UnixTimestamp},
26 solana_hash::Hash,
27 solana_instruction::Instruction,
28 solana_keypair::Keypair,
29 solana_ledger::{
30 ancestor_iterator::AncestorIterator,
31 blockstore::{self, Blockstore},
32 },
33 solana_pubkey::Pubkey,
34 solana_runtime::{bank::Bank, bank_forks::BankForks, commitment::VOTE_THRESHOLD_SIZE},
35 solana_slot_history::{Check, SlotHistory},
36 solana_vote::{vote_account::VoteAccountsHashMap, vote_transaction::VoteTransaction},
37 solana_vote_program::{
38 vote_error::VoteError,
39 vote_instruction,
40 vote_state::{BlockTimestamp, Lockout, TowerSync, Vote, VoteState1_14_11, VoteStateUpdate},
41 },
42 std::{
43 cmp::Ordering,
44 collections::{HashMap, HashSet},
45 num::NonZeroU64,
46 ops::Deref,
47 },
48 thiserror::Error,
49};
50
51#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
52pub enum ThresholdDecision {
53 #[default]
54 PassedThreshold,
55 FailedThreshold(u64, u64),
56}
57
58impl ThresholdDecision {
59 pub fn passed(&self) -> bool {
60 matches!(self, Self::PassedThreshold)
61 }
62}
63
64#[cfg_attr(feature = "frozen-abi", derive(AbiExample, StableAbi, StableAbiSample))]
65#[derive(PartialEq, Eq, Clone, Debug)]
66pub enum SwitchForkDecision {
67 SwitchProof(Hash),
68 SameFork,
69 FailedSwitchThreshold(
70 u64,
71 u64,
72 ),
73 FailedSwitchDuplicateRollback(Slot),
74}
75
76impl SwitchForkDecision {
77 pub fn to_vote_instruction(
78 &self,
79 vote: VoteTransaction,
80 vote_account_pubkey: &Pubkey,
81 authorized_voter_pubkey: &Pubkey,
82 ) -> Option<Instruction> {
83 match (self, vote) {
84 (SwitchForkDecision::FailedSwitchThreshold(_, total_stake), _) => {
85 assert_ne!(*total_stake, 0);
86 None
87 }
88 (SwitchForkDecision::FailedSwitchDuplicateRollback(_), _) => None,
89 (SwitchForkDecision::SameFork, VoteTransaction::Vote(v)) => Some(
90 vote_instruction::vote(vote_account_pubkey, authorized_voter_pubkey, v),
91 ),
92 (SwitchForkDecision::SameFork, VoteTransaction::VoteStateUpdate(v)) => {
93 Some(vote_instruction::update_vote_state(
94 vote_account_pubkey,
95 authorized_voter_pubkey,
96 v,
97 ))
98 }
99 (SwitchForkDecision::SameFork, VoteTransaction::TowerSync(t)) => Some(
100 vote_instruction::tower_sync(vote_account_pubkey, authorized_voter_pubkey, t),
101 ),
102 (SwitchForkDecision::SwitchProof(switch_proof_hash), VoteTransaction::Vote(v)) => {
103 Some(vote_instruction::vote_switch(
104 vote_account_pubkey,
105 authorized_voter_pubkey,
106 v,
107 *switch_proof_hash,
108 ))
109 }
110 (
111 SwitchForkDecision::SwitchProof(switch_proof_hash),
112 VoteTransaction::VoteStateUpdate(v),
113 ) => Some(vote_instruction::update_vote_state_switch(
114 vote_account_pubkey,
115 authorized_voter_pubkey,
116 v,
117 *switch_proof_hash,
118 )),
119 (SwitchForkDecision::SwitchProof(switch_proof_hash), VoteTransaction::TowerSync(t)) => {
120 Some(vote_instruction::tower_sync_switch(
121 vote_account_pubkey,
122 authorized_voter_pubkey,
123 t,
124 *switch_proof_hash,
125 ))
126 }
127 (SwitchForkDecision::SameFork, VoteTransaction::CompactVoteStateUpdate(v)) => {
128 Some(vote_instruction::compact_update_vote_state(
129 vote_account_pubkey,
130 authorized_voter_pubkey,
131 v,
132 ))
133 }
134 (
135 SwitchForkDecision::SwitchProof(switch_proof_hash),
136 VoteTransaction::CompactVoteStateUpdate(v),
137 ) => Some(vote_instruction::compact_update_vote_state_switch(
138 vote_account_pubkey,
139 authorized_voter_pubkey,
140 v,
141 *switch_proof_hash,
142 )),
143 }
144 }
145
146 pub fn can_vote(&self) -> bool {
147 match self {
148 SwitchForkDecision::FailedSwitchThreshold(_, _) => false,
149 SwitchForkDecision::FailedSwitchDuplicateRollback(_) => false,
150 SwitchForkDecision::SameFork => true,
151 SwitchForkDecision::SwitchProof(_) => true,
152 }
153 }
154}
155
156const VOTE_THRESHOLD_DEPTH_SHALLOW: usize = 4;
157pub const VOTE_THRESHOLD_DEPTH: usize = 8;
158pub const SWITCH_FORK_THRESHOLD: f64 = 0.38;
159
160pub type Result<T> = std::result::Result<T, TowerError>;
161
162pub type Stake = u64;
163pub type VotedStakes = HashMap<Slot, Stake, ahash::RandomState>;
164pub type PubkeyVotes = Vec<(Pubkey, Slot)>;
165
166pub(crate) struct ComputedBankState {
167 pub voted_stakes: VotedStakes,
168 pub total_stake: Stake,
169 pub fork_stake: Stake,
170
171 pub parent_is_super_oc: bool,
174
175 pub lockout_intervals: LockoutIntervals,
178 pub my_latest_landed_vote: Option<Slot>,
179}
180
181#[derive(Debug, PartialEq, Clone)]
182#[allow(clippy::large_enum_variant)]
183pub enum TowerVersions {
184 V1_7_14(Tower1_7_14),
185 V1_14_11(Tower1_14_11),
186 Current(Tower),
187}
188
189impl TowerVersions {
190 pub fn new_current(tower: Tower) -> Self {
191 Self::Current(tower)
192 }
193
194 pub fn convert_to_current(self) -> Tower {
195 match self {
196 TowerVersions::V1_7_14(tower) => tower.into(),
197 TowerVersions::V1_14_11(tower) => tower.into(),
198 TowerVersions::Current(tower) => tower,
199 }
200 }
201}
202
203#[cfg_attr(feature = "frozen-abi", derive(AbiExample, StableAbi, StableAbiSample))]
204#[derive(PartialEq, Eq, Debug, Default, Clone, Copy)]
205pub(crate) enum BlockhashStatus {
206 #[default]
208 Uninitialized,
209 NonVoting,
211 HotSpare,
213 Blockhash(Hash),
215}
216
217#[derive(Clone, Debug, PartialEq)]
218pub struct Tower {
219 pub node_pubkey: Pubkey,
220 pub(crate) threshold_depth: usize,
221 threshold_size: f64,
222 pub(crate) vote_state: TowerVoteState,
223 last_vote: VoteTransaction,
224 last_vote_tx_blockhash: BlockhashStatus,
230 last_timestamp: BlockTimestamp,
231 stray_restored_slot: Option<Slot>,
238 pub last_switch_threshold_check: Option<(Slot, SwitchForkDecision)>,
239}
240
241impl Default for Tower {
242 fn default() -> Self {
243 let mut tower = Self {
244 node_pubkey: Pubkey::default(),
245 threshold_depth: VOTE_THRESHOLD_DEPTH,
246 threshold_size: VOTE_THRESHOLD_SIZE,
247 vote_state: TowerVoteState::default(),
248 last_vote: VoteTransaction::from(TowerSync::default()),
249 last_timestamp: BlockTimestamp::default(),
250 last_vote_tx_blockhash: BlockhashStatus::default(),
251 stray_restored_slot: Option::default(),
252 last_switch_threshold_check: Option::default(),
253 };
254 tower.vote_state.root_slot = Some(Slot::default());
256 tower
257 }
258}
259
260impl From<Tower> for Tower1_14_11 {
263 fn from(tower: Tower) -> Self {
264 Self {
265 node_pubkey: tower.node_pubkey,
266 threshold_depth: tower.threshold_depth,
267 threshold_size: tower.threshold_size,
268 vote_state: VoteState1_14_11::from(tower.vote_state),
269 last_vote: tower.last_vote,
270 last_vote_tx_blockhash: tower.last_vote_tx_blockhash,
271 last_timestamp: tower.last_timestamp,
272 stray_restored_slot: tower.stray_restored_slot,
273 last_switch_threshold_check: tower.last_switch_threshold_check,
274 }
275 }
276}
277
278impl From<Tower1_14_11> for Tower {
281 fn from(tower: Tower1_14_11) -> Self {
282 Self {
283 node_pubkey: tower.node_pubkey,
284 threshold_depth: tower.threshold_depth,
285 threshold_size: tower.threshold_size,
286 vote_state: TowerVoteState::from(tower.vote_state),
287 last_vote: tower.last_vote,
288 last_vote_tx_blockhash: tower.last_vote_tx_blockhash,
289 last_timestamp: tower.last_timestamp,
290 stray_restored_slot: tower.stray_restored_slot,
291 last_switch_threshold_check: tower.last_switch_threshold_check,
292 }
293 }
294}
295
296impl From<Tower1_7_14> for Tower {
297 fn from(tower: Tower1_7_14) -> Self {
298 let box_last_vote = VoteTransaction::from(tower.last_vote.clone());
299
300 Self {
301 node_pubkey: tower.node_pubkey,
302 threshold_depth: tower.threshold_depth,
303 threshold_size: tower.threshold_size,
304 vote_state: TowerVoteState::from(tower.vote_state),
305 last_vote: box_last_vote,
306 last_vote_tx_blockhash: tower.last_vote_tx_blockhash,
307 last_timestamp: tower.last_timestamp,
308 stray_restored_slot: tower.stray_restored_slot,
309 last_switch_threshold_check: tower.last_switch_threshold_check,
310 }
311 }
312}
313
314impl Tower {
315 pub fn new(
316 node_pubkey: &Pubkey,
317 vote_account_pubkey: &Pubkey,
318 root: Slot,
319 bank: &Bank,
320 ) -> Self {
321 let mut tower = Tower {
322 node_pubkey: *node_pubkey,
323 ..Tower::default()
324 };
325 tower.initialize_lockouts_from_bank(vote_account_pubkey, root, bank);
326 tower
327 }
328
329 #[cfg(test)]
330 pub fn new_for_tests(threshold_depth: usize, threshold_size: f64) -> Self {
331 Self {
332 threshold_depth,
333 threshold_size,
334 ..Tower::default()
335 }
336 }
337
338 #[cfg(test)]
339 pub fn new_random(node_pubkey: Pubkey) -> Self {
340 use {
341 rand::Rng,
342 solana_vote_program::vote_state::{LandedVote, VoteStateV4},
343 };
344
345 let mut rng = rand::rng();
346 let root_slot = rng.random();
347 let votes = (1..32)
348 .map(|x| LandedVote {
349 latency: 0,
350 lockout: Lockout::new_with_confirmation_count(
351 u64::from(x).saturating_add(root_slot),
352 32_u32.saturating_sub(x),
353 ),
354 })
355 .collect();
356 let vote_state = VoteStateV4 {
357 node_pubkey,
358 root_slot: Some(root_slot),
359 votes,
360 ..VoteStateV4::default()
361 };
362 let last_vote = TowerSync::from(
363 vote_state
364 .votes
365 .iter()
366 .map(|lv| (lv.slot(), lv.confirmation_count()))
367 .collect::<Vec<_>>(),
368 );
369 Self {
370 node_pubkey,
371 vote_state: TowerVoteState::from(vote_state),
372 last_vote: VoteTransaction::from(last_vote),
373 ..Tower::default()
374 }
375 }
376
377 pub fn new_from_bankforks(
378 bank_forks: &BankForks,
379 node_pubkey: &Pubkey,
380 vote_account: &Pubkey,
381 ) -> Self {
382 let root_bank = bank_forks.root_bank();
383 let frozen_banks: Vec<_> = bank_forks
384 .frozen_banks()
385 .map(|(_slot, bank)| bank)
386 .collect();
387 let (_progress, heaviest_subtree_fork_choice) =
388 crate::replay_stage::ReplayStage::initialize_progress_and_fork_choice(
389 root_bank.deref(),
390 frozen_banks,
391 node_pubkey,
392 vote_account,
393 vec![],
394 );
395 let root = root_bank.slot();
396
397 let (best_slot, best_hash) = heaviest_subtree_fork_choice.best_overall_slot();
398 let heaviest_bank = bank_forks
399 .get_with_checked_hash((best_slot, best_hash))
400 .expect(
401 "The best overall slot must be one of `frozen_banks` which all exist in bank_forks",
402 );
403
404 Self::new(node_pubkey, vote_account, root, &heaviest_bank)
405 }
406
407 pub(crate) fn collect_vote_lockouts(
408 vote_account_pubkey: &Pubkey,
409 bank_slot: Slot,
410 parent_slot: Slot,
411 root_slot: Slot,
412 vote_accounts: &VoteAccountsHashMap,
413 ancestors: &HashMap<Slot, HashSet<Slot>>,
414 get_frozen_hash: impl Fn(Slot) -> Option<Hash>,
415 latest_validator_votes_for_frozen_banks: &mut LatestValidatorVotesForFrozenBanks,
416 vote_slots: &mut HashSet<Slot, ahash::RandomState>,
417 ) -> ComputedBankState {
418 let total_slots = bank_slot.saturating_sub(root_slot) as usize;
419 vote_slots.reserve(total_slots);
420 let mut voted_stakes =
421 HashMap::with_capacity_and_hasher(total_slots, ahash::RandomState::default());
422 let mut super_oc_stake = 0;
423 let mut total_stake = 0;
424
425 let total_votes = vote_accounts
426 .values()
427 .filter(|(voted_stake, _)| *voted_stake != 0)
428 .map(|(_, account)| account.vote_state_view().votes_len())
429 .sum();
430 let mut lockout_intervals = LockoutIntervals::with_capacity(total_votes);
432 let mut my_latest_landed_vote = None;
433 for (&key, (voted_stake, account)) in vote_accounts.iter() {
434 let voted_stake = *voted_stake;
435 if voted_stake == 0 {
436 continue;
437 }
438 trace!("{vote_account_pubkey} {key} with stake {voted_stake}");
439 let mut vote_state = TowerVoteState::from(account.vote_state_view());
440 lockout_intervals.extend(vote_state.votes.iter().map(|v| LockoutInterval {
441 start: v.slot(),
442 end: v.last_locked_out_slot(),
443 voter: key,
444 }));
445
446 if key == *vote_account_pubkey {
447 my_latest_landed_vote = vote_state.nth_recent_lockout(0).map(|l| l.slot());
448 debug!("vote state {vote_state:?}");
449 debug!(
450 "observed slot {}",
451 vote_state
452 .nth_recent_lockout(0)
453 .map(|l| l.slot())
454 .unwrap_or(0) as i64
455 );
456 debug!("observed root {}", vote_state.root_slot.unwrap_or(0) as i64);
457 datapoint_info!(
458 "tower-observed",
459 (
460 "slot",
461 vote_state
462 .nth_recent_lockout(0)
463 .map(|l| l.slot())
464 .unwrap_or(0),
465 i64
466 ),
467 ("root", vote_state.root_slot.unwrap_or(0), i64)
468 );
469 }
470 let start_root = vote_state.root_slot;
471
472 if let Some(last_landed_voted_slot) = vote_state.last_voted_slot() {
473 latest_validator_votes_for_frozen_banks.check_add_vote(
475 key,
476 last_landed_voted_slot,
477 get_frozen_hash(last_landed_voted_slot),
478 true,
479 );
480
481 if last_landed_voted_slot == parent_slot {
483 super_oc_stake += voted_stake;
484 }
485 }
486
487 vote_state.process_next_vote_slot(bank_slot);
488
489 for slot in vote_state.votes.iter().filter_map(|v| {
495 let slot = v.slot();
496 (slot > root_slot).then_some(slot)
497 }) {
498 vote_slots.insert(slot);
499 }
500
501 if start_root != vote_state.root_slot
502 && let Some(root) = start_root
503 {
504 if root > root_slot {
507 trace!("ROOT: {root}");
508 vote_slots.insert(root);
509 }
510 }
511 if let Some(root) = vote_state.root_slot {
512 if root > root_slot {
515 vote_slots.insert(root);
516 }
517 }
518
519 assert_eq!(
529 vote_state.nth_recent_lockout(0).map(|l| l.slot()),
530 Some(bank_slot)
531 );
532 if let Some(vote) = vote_state.nth_recent_lockout(1) {
533 Self::update_ancestor_voted_stakes(
535 &mut voted_stakes,
536 vote.slot(),
537 voted_stake,
538 ancestors,
539 );
540 }
541 total_stake += voted_stake;
542 }
543
544 debug_assert!(total_stake > 0);
545 let parent_is_super_oc = bank_slot == parent_slot + 1
546 && Fraction::new(super_oc_stake, NonZeroU64::new(total_stake).unwrap())
547 > GENESIS_VOTE_THRESHOLD;
548
549 Self::populate_ancestor_voted_stakes(
552 &mut voted_stakes,
553 vote_slots.iter().copied(),
554 ancestors,
555 );
556
557 let fork_stake = ancestors
562 .get(&bank_slot)
563 .and_then(|ancestors| {
564 ancestors
565 .iter()
566 .max()
567 .and_then(|parent| voted_stakes.get(parent))
568 .copied()
569 })
570 .unwrap_or(0);
571
572 vote_slots.clear();
573
574 ComputedBankState {
575 voted_stakes,
576 total_stake,
577 fork_stake,
578 parent_is_super_oc,
579 lockout_intervals,
580 my_latest_landed_vote,
581 }
582 }
583
584 #[cfg(test)]
585 fn is_slot_confirmed(
586 &self,
587 slot: Slot,
588 voted_stakes: &VotedStakes,
589 total_stake: Stake,
590 ) -> bool {
591 voted_stakes
592 .get(&slot)
593 .map(|stake| (*stake as f64 / total_stake as f64) > self.threshold_size)
594 .unwrap_or(false)
595 }
596
597 pub(crate) fn is_slot_duplicate_confirmed(
598 &self,
599 slot: Slot,
600 voted_stakes: &VotedStakes,
601 total_stake: Stake,
602 ) -> bool {
603 voted_stakes
604 .get(&slot)
605 .map(|stake| (*stake as f64 / total_stake as f64) > DUPLICATE_THRESHOLD)
606 .unwrap_or(false)
607 }
608
609 pub fn tower_slots(&self) -> Vec<Slot> {
610 self.vote_state.tower()
611 }
612
613 pub(crate) fn last_vote_tx_blockhash(&self) -> BlockhashStatus {
614 self.last_vote_tx_blockhash
615 }
616
617 pub fn refresh_last_vote_timestamp(&mut self, heaviest_slot_on_same_fork: Slot) {
618 let timestamp = if let Some(last_vote_timestamp) = self.last_vote.timestamp() {
619 last_vote_timestamp.saturating_add(1)
623 } else {
624 datapoint_info!(
627 "refresh-timestamp-missing",
628 ("heaviest-slot", heaviest_slot_on_same_fork, i64),
629 ("last-timestamp", self.last_timestamp.timestamp, i64),
630 ("last-slot", self.last_timestamp.slot, i64),
631 );
632 self.last_timestamp.timestamp.saturating_add(1)
633 };
634
635 if let Some(last_voted_slot) = self.last_vote.last_voted_slot() {
636 if heaviest_slot_on_same_fork <= last_voted_slot {
637 warn!(
638 "Trying to refresh timestamp for vote on {last_voted_slot} using smaller \
639 heaviest bank {heaviest_slot_on_same_fork}"
640 );
641 return;
642 }
643 self.last_timestamp = BlockTimestamp {
644 slot: last_voted_slot,
645 timestamp,
646 };
647 self.last_vote.set_timestamp(Some(timestamp));
648 } else {
649 warn!(
650 "Trying to refresh timestamp for last vote on heaviest bank on same fork \
651 {heaviest_slot_on_same_fork}, but there is no vote to refresh"
652 );
653 }
654 }
655
656 pub fn refresh_last_vote_tx_blockhash(&mut self, new_vote_tx_blockhash: Hash) {
657 self.last_vote_tx_blockhash = BlockhashStatus::Blockhash(new_vote_tx_blockhash);
658 }
659
660 pub(crate) fn mark_last_vote_tx_blockhash_non_voting(&mut self) {
661 self.last_vote_tx_blockhash = BlockhashStatus::NonVoting;
662 }
663
664 pub(crate) fn mark_last_vote_tx_blockhash_hot_spare(&mut self) {
665 self.last_vote_tx_blockhash = BlockhashStatus::HotSpare;
666 }
667
668 pub fn last_voted_slot_in_bank(bank: &Bank, vote_account_pubkey: &Pubkey) -> Option<Slot> {
669 let vote_account = bank.get_vote_account(vote_account_pubkey)?;
670 vote_account.vote_state_view().last_voted_slot()
671 }
672
673 pub fn record_bank_vote(&mut self, bank: &Bank) -> Option<Slot> {
674 let block_id = bank.block_id().unwrap_or_else(|| {
677 Hash::default()
682 });
683 self.record_bank_vote_and_update_lockouts(bank.slot(), bank.hash(), block_id)
684 }
685
686 pub(crate) fn update_last_vote_from_vote_state(&mut self, vote_hash: Hash, block_id: Hash) {
689 let mut new_vote = VoteTransaction::from(TowerSync::new(
690 self.vote_state.votes.clone(),
691 self.vote_state.root_slot,
692 vote_hash,
693 block_id,
694 ));
695
696 new_vote.set_timestamp(self.maybe_timestamp(self.last_voted_slot().unwrap_or_default()));
697 self.last_vote = new_vote;
698 }
699
700 fn record_bank_vote_and_update_lockouts(
701 &mut self,
702 vote_slot: Slot,
703 vote_hash: Hash,
704 block_id: Hash,
705 ) -> Option<Slot> {
706 if let Some(last_voted_slot) = self.vote_state.last_voted_slot()
707 && vote_slot <= last_voted_slot
708 {
709 panic!(
710 "Error while recording vote {} {} in local tower {:?}",
711 vote_slot,
712 vote_hash,
713 VoteError::VoteTooOld
714 );
715 }
716
717 trace!("{} record_vote for {}", self.node_pubkey, vote_slot);
718 let old_root = self.root();
719
720 self.vote_state.process_next_vote_slot(vote_slot);
721 self.update_last_vote_from_vote_state(vote_hash, block_id);
722
723 let new_root = self.root();
724
725 datapoint_info!(
726 "tower-vote",
727 ("latest", vote_slot, i64),
728 ("root", new_root, i64)
729 );
730 if old_root != new_root {
731 Some(new_root)
732 } else {
733 None
734 }
735 }
736
737 #[cfg(feature = "dev-context-only-utils")]
738 pub fn record_vote(&mut self, slot: Slot, hash: Hash) -> Option<Slot> {
739 self.record_bank_vote_and_update_lockouts(slot, hash, Hash::default())
740 }
741
742 #[cfg(feature = "dev-context-only-utils")]
743 pub fn increase_lockout(&mut self, confirmation_count_increase: u32) {
744 for vote in self.vote_state.votes.iter_mut() {
745 vote.increase_confirmation_count(confirmation_count_increase);
746 }
747 }
748
749 pub fn last_voted_slot(&self) -> Option<Slot> {
750 if self.last_vote.is_empty() {
751 None
752 } else {
753 Some(self.last_vote.slot(self.last_vote.len() - 1))
754 }
755 }
756
757 pub fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)> {
758 Some((self.last_voted_slot()?, self.last_vote.hash()))
759 }
760
761 pub fn stray_restored_slot(&self) -> Option<Slot> {
762 self.stray_restored_slot
763 }
764
765 pub fn last_vote(&self) -> VoteTransaction {
766 self.last_vote.clone()
767 }
768
769 fn maybe_timestamp(&mut self, current_slot: Slot) -> Option<UnixTimestamp> {
770 if current_slot > self.last_timestamp.slot
771 || self.last_timestamp.slot == 0 && current_slot == self.last_timestamp.slot
772 {
773 let timestamp = Utc::now().timestamp();
774 if timestamp >= self.last_timestamp.timestamp {
775 self.last_timestamp = BlockTimestamp {
776 slot: current_slot,
777 timestamp,
778 };
779 return Some(timestamp);
780 } else {
781 datapoint_info!(
782 "backwards-timestamp",
783 ("slot", current_slot, i64),
784 ("timestamp", timestamp, i64),
785 ("last-timestamp", self.last_timestamp.timestamp, i64),
786 )
787 }
788 }
789 None
790 }
791
792 pub fn root(&self) -> Slot {
800 self.vote_state.root_slot.unwrap()
801 }
802
803 pub fn is_recent(&self, slot: Slot) -> bool {
806 if let Some(last_voted_slot) = self.vote_state.last_voted_slot() {
807 if slot <= last_voted_slot {
808 return false;
809 }
810 } else if let Some(root) = self.vote_state.root_slot
811 && slot <= root
812 {
813 return false;
814 }
815 true
816 }
817
818 pub fn has_voted(&self, slot: Slot) -> bool {
819 for vote in &self.vote_state.votes {
820 if slot == vote.slot() {
821 return true;
822 }
823 }
824 false
825 }
826
827 pub fn is_locked_out(&self, slot: Slot, ancestors: &HashSet<Slot>) -> bool {
828 if !self.is_recent(slot) {
829 return true;
830 }
831
832 let mut vote_state = self.vote_state.clone();
837 vote_state.process_next_vote_slot(slot);
838 for vote in &vote_state.votes {
839 if slot != vote.slot() && !ancestors.contains(&vote.slot()) {
840 return true;
841 }
842 }
843
844 if let Some(root_slot) = vote_state.root_slot
845 && slot != root_slot
846 {
847 assert!(
850 ancestors.contains(&root_slot),
851 "ancestors: {ancestors:?}, slot: {slot} root: {root_slot}"
852 );
853 }
854
855 false
856 }
857
858 fn is_valid_switching_proof_vote(
864 &self,
865 candidate_slot: Slot,
866 last_voted_slot: Slot,
867 switch_slot: Slot,
868 ancestors: &HashMap<Slot, HashSet<Slot>>,
869 last_vote_ancestors: &HashSet<Slot>,
870 ) -> Option<bool> {
871 trace!(
872 "Checking if {candidate_slot} is a valid switching proof vote from {last_voted_slot} \
873 to {switch_slot}"
874 );
875 if Self::is_descendant_slot(candidate_slot, last_voted_slot, ancestors)? {
878 return Some(false);
879 }
880
881 if last_vote_ancestors.is_empty() {
882 assert!(self.is_stray_last_vote());
897 return Some(true);
898 }
899
900 Self::greatest_common_ancestor(ancestors, candidate_slot, last_voted_slot)
924 .and_then(|ancestor| Self::is_descendant_slot(switch_slot, ancestor, ancestors))
925 }
926
927 fn is_descendant_slot(
931 maybe_descendant: Slot,
932 slot: Slot,
933 ancestors: &HashMap<Slot, HashSet<u64>>,
934 ) -> Option<bool> {
935 ancestors
936 .get(&maybe_descendant)
937 .map(|candidate_slot_ancestors| candidate_slot_ancestors.contains(&slot))
938 }
939
940 fn greatest_common_ancestor(
948 ancestors: &HashMap<Slot, HashSet<Slot>>,
949 slot_a: Slot,
950 slot_b: Slot,
951 ) -> Option<Slot> {
952 (ancestors.get(&slot_a)?)
953 .intersection(ancestors.get(&slot_b)?)
954 .max()
955 .copied()
956 }
957
958 #[allow(clippy::too_many_arguments)]
959 fn make_check_switch_threshold_decision(
960 &self,
961 switch_slot: Slot,
962 ancestors: &HashMap<Slot, HashSet<u64>>,
963 descendants: &HashMap<Slot, HashSet<u64>>,
964 progress: &ProgressMap,
965 total_stake: u64,
966 epoch_vote_accounts: &VoteAccountsHashMap,
967 latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks,
968 heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice,
969 ) -> SwitchForkDecision {
970 let Some((last_voted_slot, last_voted_hash)) = self.last_voted_slot_hash() else {
971 return SwitchForkDecision::SameFork;
972 };
973 let root = self.root();
974 let empty_ancestors = HashSet::default();
975 let empty_ancestors_due_to_minor_unsynced_ledger = || {
976 if self.is_first_switch_check() && switch_slot < last_voted_slot {
994 let message = format!(
997 "bank_forks doesn't have corresponding data for the stray restored last \
998 vote({last_voted_slot}), meaning some inconsistency between saved tower and \
999 ledger."
1000 );
1001 warn!("{message}");
1002 datapoint_warn!("tower_warn", ("warn", message, String));
1003 }
1004 &empty_ancestors
1005 };
1006
1007 let suspended_decision_due_to_major_unsynced_ledger = || {
1008 SwitchForkDecision::FailedSwitchThreshold(0, total_stake)
1027 };
1028
1029 let rollback_due_to_duplicate_ancestor = |latest_duplicate_ancestor| {
1030 SwitchForkDecision::FailedSwitchDuplicateRollback(latest_duplicate_ancestor)
1031 };
1032
1033 let switch_hash = progress
1042 .get_hash(switch_slot)
1043 .expect("Slot we're trying to switch to must exist AND be frozen in progress map");
1044 if let Some(latest_duplicate_ancestor) = heaviest_subtree_fork_choice
1045 .latest_invalid_ancestor(&(last_voted_slot, last_voted_hash))
1046 {
1047 if heaviest_subtree_fork_choice.is_strict_ancestor(
1054 &(switch_slot, switch_hash),
1055 &(last_voted_slot, last_voted_hash),
1056 ) {
1057 return rollback_due_to_duplicate_ancestor(latest_duplicate_ancestor);
1058 } else if progress
1059 .get_hash(last_voted_slot)
1060 .map(|current_slot_hash| current_slot_hash != last_voted_hash)
1061 .unwrap_or(true)
1062 {
1063 info!(
1070 "Allowing switch vote on {:?} because last vote {:?} was rolled back",
1071 (switch_slot, switch_hash),
1072 (last_voted_slot, last_voted_hash)
1073 );
1074 return SwitchForkDecision::SwitchProof(Hash::default());
1075 }
1076 }
1077
1078 let last_vote_ancestors = ancestors.get(&last_voted_slot).unwrap_or_else(|| {
1079 if self.is_stray_last_vote() {
1080 empty_ancestors_due_to_minor_unsynced_ledger()
1089 } else {
1090 panic!("no ancestors found with slot: {last_voted_slot}");
1091 }
1092 });
1093
1094 let switch_slot_ancestors = ancestors.get(&switch_slot).unwrap();
1095
1096 if switch_slot == last_voted_slot || switch_slot_ancestors.contains(&last_voted_slot) {
1097 return SwitchForkDecision::SameFork;
1100 }
1101
1102 if last_vote_ancestors.contains(&switch_slot) {
1103 if self.is_stray_last_vote() {
1104 return suspended_decision_due_to_major_unsynced_ledger();
1105 } else {
1106 panic!(
1107 "Should never consider switching to ancestor ({switch_slot}) of last vote: \
1108 {last_voted_slot}, ancestors({last_vote_ancestors:?})",
1109 );
1110 }
1111 }
1112
1113 let switch_proof = Hash::default();
1117 let mut locked_out_stake = 0;
1118 let mut locked_out_vote_accounts = HashSet::new();
1119 for (candidate_slot, descendants) in descendants.iter() {
1120 if !progress
1131 .get_fork_stats(*candidate_slot)
1132 .map(|stats| stats.computed)
1133 .unwrap_or(false)
1134 || {
1135 descendants.iter().any(|d| {
1140 progress
1141 .get_fork_stats(*d)
1142 .map(|stats| stats.computed)
1143 .unwrap_or(false)
1144 })
1145 }
1146 || *candidate_slot == last_voted_slot
1147 || *candidate_slot <= root
1148 || {
1149 !self
1150 .is_valid_switching_proof_vote(
1151 *candidate_slot,
1152 last_voted_slot,
1153 switch_slot,
1154 ancestors,
1155 last_vote_ancestors,
1156 )
1157 .expect(
1158 "candidate_slot and switch_slot exist in descendants map, so they \
1159 must exist in ancestors map",
1160 )
1161 }
1162 {
1163 continue;
1164 }
1165
1166 assert!(!last_vote_ancestors.contains(candidate_slot));
1170
1171 let lockout_intervals = &progress
1176 .get(candidate_slot)
1177 .unwrap()
1178 .fork_stats
1179 .lockout_intervals;
1180 for LockoutInterval {
1185 start: lockout_interval_start,
1186 voter: vote_account_pubkey,
1187 ..
1188 } in lockout_intervals
1189 .iter()
1190 .filter(|interval| interval.end >= last_voted_slot)
1191 {
1192 if locked_out_vote_accounts.contains(vote_account_pubkey) {
1193 continue;
1194 }
1195
1196 if !last_vote_ancestors.contains(lockout_interval_start) && {
1201 *lockout_interval_start > root
1206 } {
1207 let stake = epoch_vote_accounts
1208 .get(vote_account_pubkey)
1209 .map(|(stake, _)| *stake)
1210 .unwrap_or(0);
1211 locked_out_stake += stake;
1212 if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
1213 return SwitchForkDecision::SwitchProof(switch_proof);
1214 }
1215 locked_out_vote_accounts.insert(vote_account_pubkey);
1216 }
1217 }
1218 }
1219
1220 for (
1222 vote_account_pubkey,
1223 (candidate_latest_frozen_vote, _candidate_latest_frozen_vote_hash),
1224 ) in latest_validator_votes_for_frozen_banks.max_gossip_frozen_votes()
1225 {
1226 if locked_out_vote_accounts.contains(&vote_account_pubkey) {
1227 continue;
1228 }
1229
1230 if *candidate_latest_frozen_vote > last_voted_slot && {
1231 self.is_valid_switching_proof_vote(
1252 *candidate_latest_frozen_vote,
1253 last_voted_slot,
1254 switch_slot,
1255 ancestors,
1256 last_vote_ancestors,
1257 )
1258 .unwrap_or(false)
1259 } {
1260 let stake = epoch_vote_accounts
1261 .get(vote_account_pubkey)
1262 .map(|(stake, _)| *stake)
1263 .unwrap_or(0);
1264 locked_out_stake += stake;
1265 if (locked_out_stake as f64 / total_stake as f64) > SWITCH_FORK_THRESHOLD {
1266 return SwitchForkDecision::SwitchProof(switch_proof);
1267 }
1268 locked_out_vote_accounts.insert(vote_account_pubkey);
1269 }
1270 }
1271
1272 SwitchForkDecision::FailedSwitchThreshold(locked_out_stake, total_stake)
1275 }
1276
1277 #[allow(clippy::too_many_arguments)]
1278 pub(crate) fn check_switch_threshold(
1279 &mut self,
1280 switch_slot: Slot,
1281 ancestors: &HashMap<Slot, HashSet<u64>>,
1282 descendants: &HashMap<Slot, HashSet<u64>>,
1283 progress: &ProgressMap,
1284 total_stake: u64,
1285 epoch_vote_accounts: &VoteAccountsHashMap,
1286 latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks,
1287 heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice,
1288 ) -> SwitchForkDecision {
1289 let decision = self.make_check_switch_threshold_decision(
1290 switch_slot,
1291 ancestors,
1292 descendants,
1293 progress,
1294 total_stake,
1295 epoch_vote_accounts,
1296 latest_validator_votes_for_frozen_banks,
1297 heaviest_subtree_fork_choice,
1298 );
1299 let new_check = Some((switch_slot, decision.clone()));
1300 if new_check != self.last_switch_threshold_check {
1301 trace!("new switch threshold check: slot {switch_slot}: {decision:?}",);
1302 self.last_switch_threshold_check = new_check;
1303 }
1304 decision
1305 }
1306
1307 fn is_first_switch_check(&self) -> bool {
1308 self.last_switch_threshold_check.is_none()
1309 }
1310
1311 fn optimistically_bypass_vote_stake_threshold_check<'a>(
1319 tower_before_applying_vote: impl Iterator<Item = &'a Lockout>,
1320 threshold_vote: &Lockout,
1321 ) -> bool {
1322 for old_vote in tower_before_applying_vote {
1323 if old_vote.slot() == threshold_vote.slot()
1324 && old_vote.confirmation_count() == threshold_vote.confirmation_count()
1325 {
1326 return true;
1327 }
1328 }
1329 false
1330 }
1331
1332 fn check_vote_stake_threshold<'a>(
1334 threshold_vote: Option<&Lockout>,
1335 tower_before_applying_vote: impl Iterator<Item = &'a Lockout>,
1336 threshold_depth: usize,
1337 threshold_size: f64,
1338 slot: Slot,
1339 voted_stakes: &VotedStakes,
1340 total_stake: u64,
1341 ) -> ThresholdDecision {
1342 let Some(threshold_vote) = threshold_vote else {
1343 return ThresholdDecision::PassedThreshold;
1345 };
1346 let Some(fork_stake) = voted_stakes.get(&threshold_vote.slot()) else {
1347 return ThresholdDecision::FailedThreshold(threshold_depth as u64, 0);
1349 };
1350
1351 let lockout = *fork_stake as f64 / total_stake as f64;
1352 trace!(
1353 "fork_stake slot: {}, threshold_vote slot: {}, lockout: {} fork_stake: {} \
1354 total_stake: {}",
1355 slot,
1356 threshold_vote.slot(),
1357 lockout,
1358 fork_stake,
1359 total_stake
1360 );
1361 if Self::optimistically_bypass_vote_stake_threshold_check(
1362 tower_before_applying_vote,
1363 threshold_vote,
1364 ) || lockout > threshold_size
1365 {
1366 return ThresholdDecision::PassedThreshold;
1367 }
1368 ThresholdDecision::FailedThreshold(threshold_depth as u64, *fork_stake)
1369 }
1370
1371 pub fn check_vote_stake_thresholds(
1373 &self,
1374 slot: Slot,
1375 voted_stakes: &VotedStakes,
1376 total_stake: Stake,
1377 ) -> Vec<ThresholdDecision> {
1378 let mut threshold_decisions = vec![];
1379 let mut vote_state = self.vote_state.clone();
1381 vote_state.process_next_vote_slot(slot);
1382
1383 let vote_thresholds_and_depths = vec![
1385 (VOTE_THRESHOLD_DEPTH_SHALLOW, SWITCH_FORK_THRESHOLD),
1390 (VOTE_THRESHOLD_DEPTH_SHALLOW + 1, SWITCH_FORK_THRESHOLD),
1391 (self.threshold_depth, self.threshold_size),
1392 ];
1393
1394 for (threshold_depth, threshold_size) in vote_thresholds_and_depths {
1396 if let ThresholdDecision::FailedThreshold(vote_depth, stake) =
1397 Self::check_vote_stake_threshold(
1398 vote_state.nth_recent_lockout(threshold_depth),
1399 self.vote_state.votes.iter(),
1400 threshold_depth,
1401 threshold_size,
1402 slot,
1403 voted_stakes,
1404 total_stake,
1405 )
1406 {
1407 threshold_decisions.push(ThresholdDecision::FailedThreshold(vote_depth, stake));
1408 }
1409 }
1410 threshold_decisions
1411 }
1412
1413 pub(crate) fn populate_ancestor_voted_stakes(
1415 voted_stakes: &mut VotedStakes,
1416 vote_slots: impl IntoIterator<Item = Slot>,
1417 ancestors: &HashMap<Slot, HashSet<Slot>>,
1418 ) {
1419 for vote_slot in vote_slots {
1423 if let Some(slot_ancestors) = ancestors.get(&vote_slot) {
1424 voted_stakes.entry(vote_slot).or_default();
1425 for slot in slot_ancestors {
1426 voted_stakes.entry(*slot).or_default();
1427 }
1428 }
1429 }
1430 }
1431
1432 fn update_ancestor_voted_stakes(
1435 voted_stakes: &mut VotedStakes,
1436 voted_slot: Slot,
1437 voted_stake: u64,
1438 ancestors: &HashMap<Slot, HashSet<Slot>>,
1439 ) {
1440 if let Some(vote_slot_ancestors) = ancestors.get(&voted_slot) {
1443 *voted_stakes.entry(voted_slot).or_default() += voted_stake;
1444 for slot in vote_slot_ancestors {
1445 *voted_stakes.entry(*slot).or_default() += voted_stake;
1446 }
1447 }
1448 }
1449
1450 fn voted_slots(&self) -> Vec<Slot> {
1451 self.vote_state
1452 .votes
1453 .iter()
1454 .map(|lockout| lockout.slot())
1455 .collect()
1456 }
1457
1458 pub fn is_stray_last_vote(&self) -> bool {
1459 self.stray_restored_slot.is_some() && self.stray_restored_slot == self.last_voted_slot()
1460 }
1461
1462 pub fn adjust_lockouts_after_replay(
1465 mut self,
1466 replayed_root: Slot,
1467 slot_history: &SlotHistory,
1468 ) -> Result<Self> {
1469 let tower_root = self.root();
1471 info!(
1472 "adjusting lockouts (after replay up to {}): {:?} tower root: {} replayed root: {}",
1473 replayed_root,
1474 self.voted_slots(),
1475 tower_root,
1476 replayed_root,
1477 );
1478 assert_eq!(slot_history.check(replayed_root), Check::Found);
1479
1480 assert!(
1481 self.last_vote == VoteTransaction::from(VoteStateUpdate::default())
1482 && self.vote_state.votes.is_empty()
1483 || self.last_vote == VoteTransaction::from(TowerSync::default())
1484 && self.vote_state.votes.is_empty()
1485 || !self.vote_state.votes.is_empty(),
1486 "last vote: {:?} vote_state.votes: {:?}",
1487 self.last_vote,
1488 self.vote_state.votes
1489 );
1490
1491 if let Some(last_voted_slot) = self.last_voted_slot() {
1492 if tower_root <= replayed_root {
1493 if slot_history.check(last_voted_slot) == Check::TooOld {
1496 return Err(TowerError::TooOldTower(
1499 last_voted_slot,
1500 slot_history.oldest(),
1501 ));
1502 }
1503
1504 self.adjust_lockouts_with_slot_history(slot_history)?;
1505 self.initialize_root(replayed_root);
1506 } else {
1507 let message = format!(
1511 "For some reason, we're REPROCESSING slots which has already been voted and \
1512 ROOTED by us; VOTING will be SUSPENDED UNTIL {last_voted_slot}!",
1513 );
1514 error!("{message}");
1515 datapoint_error!("tower_error", ("error", message, String));
1516
1517 let mut warped_slot_history = (*slot_history).clone();
1521 warped_slot_history.add(tower_root);
1532
1533 self.adjust_lockouts_with_slot_history(&warped_slot_history)?;
1534 }
1538 } else {
1539 assert_eq!(tower_root, replayed_root);
1543 }
1544
1545 Ok(self)
1546 }
1547
1548 fn adjust_lockouts_with_slot_history(&mut self, slot_history: &SlotHistory) -> Result<()> {
1549 let tower_root = self.root();
1550 let mut retain_flags_for_each_vote_in_reverse: Vec<_> =
1552 Vec::with_capacity(self.vote_state.votes.len());
1553
1554 let mut still_in_future = true;
1555 let mut past_outside_history = false;
1556 let mut checked_slot = None;
1557 let mut anchored_slot = None;
1558
1559 let mut slots_in_tower = vec![tower_root];
1560 slots_in_tower.extend(self.voted_slots());
1561
1562 for slot_in_tower in slots_in_tower.iter().rev() {
1565 let check = slot_history.check(*slot_in_tower);
1566
1567 if anchored_slot.is_none() && check == Check::Found {
1568 anchored_slot = Some(*slot_in_tower);
1569 } else if anchored_slot.is_some() && check == Check::NotFound {
1570 return Err(TowerError::FatallyInconsistent("diverged ancestor?"));
1572 }
1573
1574 if still_in_future && check != Check::Future {
1575 still_in_future = false;
1576 } else if !still_in_future && check == Check::Future {
1577 return Err(TowerError::FatallyInconsistent("time warped?"));
1579 }
1580 if !past_outside_history && check == Check::TooOld {
1581 past_outside_history = true;
1582 } else if past_outside_history && check != Check::TooOld {
1583 return Err(TowerError::FatallyInconsistent(
1585 "not too old once after got too old?",
1586 ));
1587 }
1588
1589 if let Some(checked_slot) = checked_slot {
1590 let voting_for_root =
1593 *slot_in_tower == checked_slot && *slot_in_tower == tower_root;
1594
1595 if !voting_for_root {
1596 assert!(
1599 *slot_in_tower < checked_slot,
1600 "slot_in_tower({}) < checked_slot({})",
1601 *slot_in_tower,
1602 checked_slot
1603 );
1604 }
1605 }
1606
1607 checked_slot = Some(*slot_in_tower);
1608
1609 retain_flags_for_each_vote_in_reverse.push(anchored_slot.is_none());
1610 }
1611
1612 info!("adjusted tower's anchored slot: {anchored_slot:?}");
1614 if anchored_slot.is_none() {
1615 return Err(TowerError::FatallyInconsistent(
1617 "no common slot for rooted tower",
1618 ));
1619 }
1620
1621 assert_eq!(
1622 slots_in_tower.len(),
1623 retain_flags_for_each_vote_in_reverse.len()
1624 );
1625 retain_flags_for_each_vote_in_reverse.pop();
1627 let mut retain_flags_for_each_vote =
1628 retain_flags_for_each_vote_in_reverse.into_iter().rev();
1629
1630 let original_votes_len = self.vote_state.votes.len();
1631 self.initialize_lockouts(move |_| retain_flags_for_each_vote.next().unwrap());
1632
1633 if self.vote_state.votes.is_empty() {
1634 info!("All restored votes were behind; resetting root_slot and last_vote in tower!");
1635 self.last_vote = VoteTransaction::from(Vote::default());
1638 } else {
1639 info!(
1640 "{} restored votes (out of {}) were on different fork or are upcoming votes on \
1641 unrooted slots: {:?}!",
1642 self.voted_slots().len(),
1643 original_votes_len,
1644 self.voted_slots()
1645 );
1646
1647 assert_eq!(self.last_voted_slot(), self.voted_slots().last().copied());
1648 self.stray_restored_slot = self.last_vote.last_voted_slot()
1649 }
1650
1651 Ok(())
1652 }
1653
1654 fn initialize_lockouts_from_bank(
1655 &mut self,
1656 vote_account_pubkey: &Pubkey,
1657 root: Slot,
1658 bank: &Bank,
1659 ) {
1660 if let Some(vote_account) = bank.get_vote_account(vote_account_pubkey) {
1661 self.vote_state = TowerVoteState::from(vote_account.vote_state_view());
1662 self.initialize_root(root);
1663 self.initialize_lockouts(|v| v.slot() > root);
1664 } else {
1665 self.initialize_root(root);
1666 info!(
1667 "vote account({}) not found in bank (slot={})",
1668 vote_account_pubkey,
1669 bank.slot()
1670 );
1671 }
1672 }
1673
1674 fn initialize_lockouts<F: FnMut(&Lockout) -> bool>(&mut self, should_retain: F) {
1675 self.vote_state.votes.retain(should_retain);
1676 }
1677
1678 fn initialize_root(&mut self, root: Slot) {
1681 self.vote_state.root_slot = Some(root);
1682 }
1683
1684 pub fn save(&self, tower_storage: &dyn TowerStorage, node_keypair: &Keypair) -> Result<()> {
1685 let saved_tower = SavedTower::new(self, node_keypair)?;
1686 tower_storage.store(&SavedTowerVersions::from(saved_tower))?;
1687 Ok(())
1688 }
1689
1690 pub fn restore(tower_storage: &dyn TowerStorage, node_pubkey: &Pubkey) -> Result<Self> {
1691 tower_storage.load(node_pubkey)
1692 }
1693}
1694
1695#[derive(Error, Debug)]
1696pub enum TowerError {
1697 #[error("IO Error: {0}")]
1698 IoError(#[from] std::io::Error),
1699
1700 #[error("Serialization Error: {0}")]
1701 SerializeError(#[from] bincode::Error),
1702
1703 #[error("The signature on the saved tower is invalid")]
1704 InvalidSignature,
1705
1706 #[error("The tower does not match this validator: {0}")]
1707 WrongTower(String),
1708
1709 #[error(
1710 "The tower is too old: newest slot in tower ({0}) << oldest slot in available history \
1711 ({1})"
1712 )]
1713 TooOldTower(Slot, Slot),
1714
1715 #[error("The tower is fatally inconsistent with blockstore: {0}")]
1716 FatallyInconsistent(&'static str),
1717
1718 #[error("The tower is useless because of new hard fork: {0}")]
1719 HardFork(Slot),
1720}
1721
1722impl TowerError {
1723 pub fn is_file_missing(&self) -> bool {
1724 if let TowerError::IoError(io_err) = &self {
1725 io_err.kind() == std::io::ErrorKind::NotFound
1726 } else {
1727 false
1728 }
1729 }
1730 pub fn is_too_old(&self) -> bool {
1731 matches!(self, TowerError::TooOldTower(_, _))
1732 }
1733}
1734
1735#[derive(Debug)]
1736pub enum ExternalRootSource {
1737 Tower(Slot),
1738 VoteHistory(Slot),
1739 HardFork(Slot),
1740}
1741
1742impl ExternalRootSource {
1743 fn root(&self) -> Slot {
1744 match self {
1745 ExternalRootSource::Tower(slot) => *slot,
1746 ExternalRootSource::VoteHistory(slot) => *slot,
1747 ExternalRootSource::HardFork(slot) => *slot,
1748 }
1749 }
1750}
1751
1752pub fn reconcile_blockstore_roots_with_external_source(
1758 external_source: ExternalRootSource,
1759 blockstore: &Blockstore,
1760 last_blockstore_root: &mut Slot,
1763) -> blockstore::Result<()> {
1764 let external_root = external_source.root();
1765 if *last_blockstore_root < external_root {
1766 let new_roots: Vec<_> = AncestorIterator::new_inclusive(external_root, blockstore)
1769 .take_while(|current| match current.cmp(last_blockstore_root) {
1770 Ordering::Greater => true,
1771 Ordering::Equal => false,
1772 Ordering::Less => panic!(
1773 "last_blockstore_root({last_blockstore_root}) is skipped while traversing \
1774 blockstore (currently at {current}) from external root \
1775 ({external_source:?})!?",
1776 ),
1777 })
1778 .collect();
1779 if !new_roots.is_empty() {
1780 info!(
1781 "Reconciling slots as root based on external root: {new_roots:?} (external: \
1782 {external_source:?}, blockstore: {last_blockstore_root})"
1783 );
1784
1785 blockstore.mark_slots_as_if_rooted_normally_at_startup(
1791 new_roots.into_iter().map(|root| (root, None)).collect(),
1792 false,
1793 )?;
1794
1795 *last_blockstore_root = blockstore.max_root();
1799 } else {
1800 warn!(
1804 "Couldn't find any ancestor slots from external source ({external_source:?}) \
1805 towards blockstore root ({last_blockstore_root}); blockstore pruned or only \
1806 tower moved into new ledger or just hard fork?",
1807 );
1808 }
1809 }
1810 Ok(())
1811}
1812
1813#[cfg(test)]
1814pub mod test {
1815 use {
1816 super::*,
1817 crate::{
1818 consensus::{
1819 fork_choice::ForkChoice, heaviest_subtree_fork_choice::SlotHashKey,
1820 tower_storage::FileTowerStorage,
1821 },
1822 replay_stage::HeaviestForkFailures,
1823 vote_simulator::VoteSimulator,
1824 },
1825 itertools::Itertools,
1826 solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
1827 solana_clock::Slot,
1828 solana_hash::Hash,
1829 solana_ledger::{blockstore::make_slot_entries, get_tmp_ledger_path_auto_delete},
1830 solana_pubkey::Pubkey,
1831 solana_runtime::bank::Bank,
1832 solana_signer::Signer,
1833 solana_slot_history::SlotHistory,
1834 solana_vote::vote_account::VoteAccount,
1835 solana_vote_program::vote_state::{
1836 MAX_LOCKOUT_HISTORY, Vote, VoteStateV4, VoteStateVersions, handler::VoteStateHandler,
1837 process_slot_vote_unchecked,
1838 },
1839 std::{
1840 collections::{HashMap, VecDeque},
1841 fs::{OpenOptions, remove_file},
1842 io::{Read, Seek, SeekFrom, Write},
1843 path::PathBuf,
1844 sync::Arc,
1845 },
1846 tempfile::TempDir,
1847 trees::tr,
1848 };
1849
1850 fn gen_stakes(stake_votes: &[(u64, &[u64])]) -> VoteAccountsHashMap {
1851 stake_votes
1852 .iter()
1853 .map(|(lamports, votes)| {
1854 let mut account = AccountSharedData::from(Account {
1855 data: vec![0; VoteStateV4::size_of()],
1856 lamports: *lamports,
1857 owner: solana_vote_program::id(),
1858 ..Account::default()
1859 });
1860 let mut vote_state = VoteStateHandler::new_v4(VoteStateV4::default());
1861 for slot in *votes {
1862 process_slot_vote_unchecked(&mut vote_state, *slot);
1863 }
1864 VoteStateV4::serialize(
1865 &VoteStateVersions::new_v4(vote_state.unwrap_v4()),
1866 account.data_as_mut_slice(),
1867 )
1868 .expect("serialize state");
1869 (
1870 solana_pubkey::new_rand(),
1871 (*lamports, VoteAccount::try_from(account).unwrap()),
1872 )
1873 })
1874 .collect()
1875 }
1876
1877 #[test]
1878 fn test_to_vote_instruction() {
1879 let vote = Vote::default();
1880 let mut decision = SwitchForkDecision::FailedSwitchThreshold(0, 1);
1881 assert!(
1882 decision
1883 .to_vote_instruction(
1884 VoteTransaction::from(vote.clone()),
1885 &Pubkey::default(),
1886 &Pubkey::default()
1887 )
1888 .is_none()
1889 );
1890
1891 decision = SwitchForkDecision::FailedSwitchDuplicateRollback(0);
1892 assert!(
1893 decision
1894 .to_vote_instruction(
1895 VoteTransaction::from(vote.clone()),
1896 &Pubkey::default(),
1897 &Pubkey::default()
1898 )
1899 .is_none()
1900 );
1901
1902 decision = SwitchForkDecision::SameFork;
1903 assert_eq!(
1904 decision.to_vote_instruction(
1905 VoteTransaction::from(vote.clone()),
1906 &Pubkey::default(),
1907 &Pubkey::default()
1908 ),
1909 Some(vote_instruction::vote(
1910 &Pubkey::default(),
1911 &Pubkey::default(),
1912 vote.clone(),
1913 ))
1914 );
1915
1916 decision = SwitchForkDecision::SwitchProof(Hash::default());
1917 assert_eq!(
1918 decision.to_vote_instruction(
1919 VoteTransaction::from(vote.clone()),
1920 &Pubkey::default(),
1921 &Pubkey::default()
1922 ),
1923 Some(vote_instruction::vote_switch(
1924 &Pubkey::default(),
1925 &Pubkey::default(),
1926 vote,
1927 Hash::default()
1928 ))
1929 );
1930 }
1931
1932 #[test]
1933 fn test_simple_votes() {
1934 let mut vote_simulator = VoteSimulator::new(1);
1936 let node_pubkey = vote_simulator.node_pubkeys[0];
1937 let mut tower = Tower::default();
1938
1939 let forks = tr(0) / (tr(1) / (tr(2) / (tr(3) / (tr(4) / tr(5)))));
1941
1942 let mut cluster_votes = HashMap::new();
1944 let votes = vec![1, 2, 3, 4, 5];
1945 cluster_votes.insert(node_pubkey, votes.clone());
1946 vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
1947
1948 for vote in votes {
1950 assert!(
1951 vote_simulator
1952 .simulate_vote(vote, &node_pubkey, &mut tower,)
1953 .is_empty()
1954 );
1955 }
1956
1957 for i in 1..5 {
1958 assert_eq!(tower.vote_state.votes[i - 1].slot() as usize, i);
1959 assert_eq!(
1960 tower.vote_state.votes[i - 1].confirmation_count() as usize,
1961 6 - i
1962 );
1963 }
1964 }
1965
1966 #[test]
1967 fn test_switch_threshold_duplicate_rollback() {
1968 run_test_switch_threshold_duplicate_rollback(false);
1969 }
1970
1971 #[test]
1972 #[should_panic]
1973 fn test_switch_threshold_duplicate_rollback_panic() {
1974 run_test_switch_threshold_duplicate_rollback(true);
1975 }
1976
1977 fn setup_switch_test(num_accounts: usize) -> (Arc<Bank>, VoteSimulator, u64) {
1978 assert!(num_accounts > 1);
1980 let mut vote_simulator = VoteSimulator::new(num_accounts);
1981 let bank0 = vote_simulator.bank_forks.read().unwrap().get(0).unwrap();
1982 let total_stake = bank0.total_epoch_stake();
1983 assert_eq!(
1984 total_stake,
1985 vote_simulator.validator_keypairs.len() as u64 * 10_000
1986 );
1987
1988 let forks = tr(0)
1990 / (tr(1)
1991 / (tr(2)
1992 / (tr(10) / (tr(11) / (tr(12) / (tr(13) / (tr(14))))))
1994 / (tr(43)
1995 / (tr(44)
1996 / (tr(45) / (tr(46) / (tr(47) / (tr(48) / (tr(49) / (tr(50)))))))
1998 / (tr(110)))
1999 / tr(112))));
2000
2001 vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
2003 for fork_progress in vote_simulator.progress.values_mut() {
2004 fork_progress.fork_stats.computed = true;
2005 }
2006
2007 (bank0, vote_simulator, total_stake)
2008 }
2009
2010 fn run_test_switch_threshold_duplicate_rollback(should_panic: bool) {
2011 let (bank0, mut vote_simulator, total_stake) = setup_switch_test(2);
2012 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
2013 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
2014 let mut tower = Tower::default();
2015
2016 tower.record_vote(
2018 47,
2019 vote_simulator
2020 .bank_forks
2021 .read()
2022 .unwrap()
2023 .get(47)
2024 .unwrap()
2025 .hash(),
2026 );
2027
2028 let ancestor_of_voted_slot = 43;
2031 let duplicate_ancestor1 = 44;
2032 let duplicate_ancestor2 = 45;
2033 vote_simulator
2034 .tbft_structs
2035 .heaviest_subtree_fork_choice
2036 .mark_fork_invalid_candidate(&(
2037 duplicate_ancestor1,
2038 vote_simulator
2039 .bank_forks
2040 .read()
2041 .unwrap()
2042 .get(duplicate_ancestor1)
2043 .unwrap()
2044 .hash(),
2045 ));
2046 vote_simulator
2047 .tbft_structs
2048 .heaviest_subtree_fork_choice
2049 .mark_fork_invalid_candidate(&(
2050 duplicate_ancestor2,
2051 vote_simulator
2052 .bank_forks
2053 .read()
2054 .unwrap()
2055 .get(duplicate_ancestor2)
2056 .unwrap()
2057 .hash(),
2058 ));
2059 assert_eq!(
2060 tower.check_switch_threshold(
2061 ancestor_of_voted_slot,
2062 &ancestors,
2063 &descendants,
2064 &vote_simulator.progress,
2065 total_stake,
2066 bank0.epoch_vote_accounts(0).unwrap(),
2067 &vote_simulator.latest_validator_votes_for_frozen_banks,
2068 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2069 ),
2070 SwitchForkDecision::FailedSwitchDuplicateRollback(duplicate_ancestor2)
2071 );
2072 let mut confirm_ancestors = vec![duplicate_ancestor1];
2073 if should_panic {
2074 confirm_ancestors.push(duplicate_ancestor2);
2079 }
2080 for (i, duplicate_ancestor) in confirm_ancestors.into_iter().enumerate() {
2081 vote_simulator
2082 .tbft_structs
2083 .heaviest_subtree_fork_choice
2084 .mark_fork_valid_candidate(&(
2085 duplicate_ancestor,
2086 vote_simulator
2087 .bank_forks
2088 .read()
2089 .unwrap()
2090 .get(duplicate_ancestor)
2091 .unwrap()
2092 .hash(),
2093 ));
2094 let res = tower.check_switch_threshold(
2095 ancestor_of_voted_slot,
2096 &ancestors,
2097 &descendants,
2098 &vote_simulator.progress,
2099 total_stake,
2100 bank0.epoch_vote_accounts(0).unwrap(),
2101 &vote_simulator.latest_validator_votes_for_frozen_banks,
2102 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2103 );
2104 if i == 0 {
2105 assert_eq!(
2106 res,
2107 SwitchForkDecision::FailedSwitchDuplicateRollback(duplicate_ancestor2)
2108 );
2109 }
2110 }
2111 }
2112
2113 #[test]
2114 fn test_switch_threshold() {
2115 let (bank0, mut vote_simulator, total_stake) = setup_switch_test(2);
2116 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
2117 let mut descendants = vote_simulator.bank_forks.read().unwrap().descendants();
2118 let mut tower = Tower::default();
2119 let other_vote_account = vote_simulator.vote_pubkeys[1];
2120
2121 tower.record_vote(47, Hash::default());
2123
2124 assert_eq!(
2126 tower.check_switch_threshold(
2127 48,
2128 &ancestors,
2129 &descendants,
2130 &vote_simulator.progress,
2131 total_stake,
2132 bank0.epoch_vote_accounts(0).unwrap(),
2133 &vote_simulator.latest_validator_votes_for_frozen_banks,
2134 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2135 ),
2136 SwitchForkDecision::SameFork
2137 );
2138
2139 assert_eq!(
2141 tower.check_switch_threshold(
2142 110,
2143 &ancestors,
2144 &descendants,
2145 &vote_simulator.progress,
2146 total_stake,
2147 bank0.epoch_vote_accounts(0).unwrap(),
2148 &vote_simulator.latest_validator_votes_for_frozen_banks,
2149 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2150 ),
2151 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2152 );
2153
2154 vote_simulator.simulate_lockout_interval(50, (49, 100), &other_vote_account);
2157 assert_eq!(
2158 tower.check_switch_threshold(
2159 110,
2160 &ancestors,
2161 &descendants,
2162 &vote_simulator.progress,
2163 total_stake,
2164 bank0.epoch_vote_accounts(0).unwrap(),
2165 &vote_simulator.latest_validator_votes_for_frozen_banks,
2166 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2167 ),
2168 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2169 );
2170
2171 vote_simulator.simulate_lockout_interval(50, (45, 100), &other_vote_account);
2174 assert_eq!(
2175 tower.check_switch_threshold(
2176 110,
2177 &ancestors,
2178 &descendants,
2179 &vote_simulator.progress,
2180 total_stake,
2181 bank0.epoch_vote_accounts(0).unwrap(),
2182 &vote_simulator.latest_validator_votes_for_frozen_banks,
2183 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2184 ),
2185 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2186 );
2187
2188 vote_simulator.simulate_lockout_interval(14, (12, 46), &other_vote_account);
2191 assert_eq!(
2192 tower.check_switch_threshold(
2193 110,
2194 &ancestors,
2195 &descendants,
2196 &vote_simulator.progress,
2197 total_stake,
2198 bank0.epoch_vote_accounts(0).unwrap(),
2199 &vote_simulator.latest_validator_votes_for_frozen_banks,
2200 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2201 ),
2202 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2203 );
2204
2205 vote_simulator.simulate_lockout_interval(13, (12, 47), &other_vote_account);
2210 assert_eq!(
2211 tower.check_switch_threshold(
2212 110,
2213 &ancestors,
2214 &descendants,
2215 &vote_simulator.progress,
2216 total_stake,
2217 bank0.epoch_vote_accounts(0).unwrap(),
2218 &vote_simulator.latest_validator_votes_for_frozen_banks,
2219 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2220 ),
2221 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2222 );
2223
2224 vote_simulator.simulate_lockout_interval(14, (12, 47), &other_vote_account);
2227 assert_eq!(
2228 tower.check_switch_threshold(
2229 110,
2230 &ancestors,
2231 &descendants,
2232 &vote_simulator.progress,
2233 total_stake,
2234 bank0.epoch_vote_accounts(0).unwrap(),
2235 &vote_simulator.latest_validator_votes_for_frozen_banks,
2236 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2237 ),
2238 SwitchForkDecision::SwitchProof(Hash::default())
2239 );
2240
2241 descendants.get_mut(&14).unwrap().insert(10000);
2245 assert_eq!(
2246 tower.check_switch_threshold(
2247 110,
2248 &ancestors,
2249 &descendants,
2250 &vote_simulator.progress,
2251 total_stake,
2252 bank0.epoch_vote_accounts(0).unwrap(),
2253 &vote_simulator.latest_validator_votes_for_frozen_banks,
2254 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2255 ),
2256 SwitchForkDecision::SwitchProof(Hash::default())
2257 );
2258
2259 tower.vote_state.root_slot = Some(43);
2263 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
2265 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
2266
2267 assert_eq!(
2268 tower.check_switch_threshold(
2269 110,
2270 &ancestors,
2271 &descendants,
2272 &vote_simulator.progress,
2273 total_stake,
2274 bank0.epoch_vote_accounts(0).unwrap(),
2275 &vote_simulator.latest_validator_votes_for_frozen_banks,
2276 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2277 ),
2278 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2279 );
2280 }
2281
2282 #[test]
2283 fn test_switch_threshold_use_gossip_votes() {
2284 let num_validators = 2;
2285 let (bank0, mut vote_simulator, total_stake) = setup_switch_test(2);
2286 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
2287 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
2288 let mut tower = Tower::default();
2289 let other_vote_account = vote_simulator.vote_pubkeys[1];
2290
2291 tower.record_vote(47, Hash::default());
2293
2294 assert_eq!(
2296 tower.check_switch_threshold(
2297 110,
2298 &ancestors,
2299 &descendants,
2300 &vote_simulator.progress,
2301 total_stake,
2302 bank0.epoch_vote_accounts(0).unwrap(),
2303 &vote_simulator.latest_validator_votes_for_frozen_banks,
2304 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2305 ),
2306 SwitchForkDecision::FailedSwitchThreshold(0, num_validators * 10000)
2307 );
2308
2309 vote_simulator.simulate_lockout_interval(50, (49, 100), &other_vote_account);
2311 assert_eq!(
2312 tower.check_switch_threshold(
2313 110,
2314 &ancestors,
2315 &descendants,
2316 &vote_simulator.progress,
2317 total_stake,
2318 bank0.epoch_vote_accounts(0).unwrap(),
2319 &vote_simulator.latest_validator_votes_for_frozen_banks,
2320 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2321 ),
2322 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2323 );
2324
2325 vote_simulator
2328 .latest_validator_votes_for_frozen_banks
2329 .check_add_vote(
2330 other_vote_account,
2331 112,
2332 Some(
2333 vote_simulator
2334 .bank_forks
2335 .read()
2336 .unwrap()
2337 .get(112)
2338 .unwrap()
2339 .hash(),
2340 ),
2341 false,
2342 );
2343
2344 assert_eq!(
2345 tower.check_switch_threshold(
2346 110,
2347 &ancestors,
2348 &descendants,
2349 &vote_simulator.progress,
2350 total_stake,
2351 bank0.epoch_vote_accounts(0).unwrap(),
2352 &vote_simulator.latest_validator_votes_for_frozen_banks,
2353 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2354 ),
2355 SwitchForkDecision::SwitchProof(Hash::default())
2356 );
2357
2358 vote_simulator.set_root(44);
2362 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
2363 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
2364 assert_eq!(
2365 tower.check_switch_threshold(
2366 110,
2367 &ancestors,
2368 &descendants,
2369 &vote_simulator.progress,
2370 total_stake,
2371 bank0.epoch_vote_accounts(0).unwrap(),
2372 &vote_simulator.latest_validator_votes_for_frozen_banks,
2373 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
2374 ),
2375 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
2376 );
2377 }
2378
2379 #[test]
2380 fn test_switch_threshold_votes() {
2381 let mut vote_simulator = VoteSimulator::new(4);
2383 let node_pubkey = vote_simulator.node_pubkeys[0];
2384 let mut tower = Tower::default();
2385 let forks = tr(0)
2386 / (tr(1)
2387 / (tr(2)
2388 / (tr(10) / (tr(11) / (tr(12) / (tr(13) / (tr(14))))))
2390 / (tr(43)
2391 / (tr(44)
2392 / (tr(45) / (tr(46))))
2394 / (tr(110)))));
2395
2396 let mut cluster_votes: HashMap<Pubkey, Vec<Slot>> = HashMap::new();
2399 cluster_votes.insert(vote_simulator.node_pubkeys[1], vec![46]);
2400 cluster_votes.insert(vote_simulator.node_pubkeys[2], vec![47]);
2401 vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
2402
2403 assert!(
2405 vote_simulator
2406 .simulate_vote(14, &node_pubkey, &mut tower,)
2407 .is_empty()
2408 );
2409
2410 let votes_to_simulate = (46..=48).collect();
2415 let results = vote_simulator.create_and_vote_new_branch(
2416 45,
2417 48,
2418 &cluster_votes,
2419 &votes_to_simulate,
2420 &node_pubkey,
2421 &mut tower,
2422 );
2423 assert_eq!(
2424 *results.get(&46).unwrap(),
2425 vec![HeaviestForkFailures::FailedSwitchThreshold(46, 0, 40000)]
2426 );
2427 assert_eq!(
2428 *results.get(&47).unwrap(),
2429 vec![HeaviestForkFailures::FailedSwitchThreshold(
2430 47, 10000, 40000
2431 )]
2432 );
2433 assert!(results.get(&48).unwrap().is_empty());
2434 }
2435
2436 #[test]
2437 fn test_double_partition() {
2438 let mut vote_simulator = VoteSimulator::new(2);
2440 let node_pubkey = vote_simulator.node_pubkeys[0];
2441 let vote_pubkey = vote_simulator.vote_pubkeys[0];
2442 let mut tower = Tower::default();
2443
2444 let num_slots_to_try = 200;
2445 let forks = tr(0)
2447 / (tr(1)
2448 / (tr(2)
2449 / (tr(3)
2450 / (tr(4)
2451 / (tr(5)
2452 / (tr(6)
2453 / (tr(7)
2454 / (tr(8)
2455 / (tr(9)
2456 / (tr(10) / (tr(11) / (tr(12) / (tr(13) / (tr(14))))))
2458 / (tr(43)
2459 / (tr(44)
2460 / (tr(45) / (tr(46) / (tr(47) / (tr(48) / (tr(49) / (tr(50)))))))
2462 / (tr(110) / (tr(110 + 2 * num_slots_to_try))))))))))))));
2463
2464 let mut cluster_votes = HashMap::new();
2466 let mut my_votes: Vec<Slot> = vec![];
2467 let next_unlocked_slot = 110;
2468 my_votes.extend(1..=14);
2470 my_votes.extend(43..=44);
2472 my_votes.extend(45..=50);
2474 my_votes.push(next_unlocked_slot);
2476 cluster_votes.insert(node_pubkey, my_votes.clone());
2477 let other_votes = my_votes.clone();
2479 cluster_votes.insert(vote_simulator.node_pubkeys[1], other_votes);
2480 vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
2481
2482 for vote in &my_votes {
2484 assert!(
2486 vote_simulator
2487 .simulate_vote(*vote, &node_pubkey, &mut tower,)
2488 .is_empty()
2489 );
2490 }
2491
2492 info!("local tower: {:#?}", tower.vote_state.votes);
2493 let observed = vote_simulator
2494 .bank_forks
2495 .read()
2496 .unwrap()
2497 .get(next_unlocked_slot)
2498 .unwrap()
2499 .get_vote_account(&vote_pubkey)
2500 .unwrap();
2501 let state = observed.vote_state_view();
2502 info!("observed tower: {:#?}", state.votes_iter().collect_vec());
2503
2504 let num_slots_to_try = 200;
2505 cluster_votes
2506 .get_mut(&vote_simulator.node_pubkeys[1])
2507 .unwrap()
2508 .extend(next_unlocked_slot + 1..next_unlocked_slot + num_slots_to_try);
2509 assert!(vote_simulator.can_progress_on_fork(
2510 &node_pubkey,
2511 &mut tower,
2512 next_unlocked_slot,
2513 num_slots_to_try,
2514 &mut cluster_votes,
2515 ));
2516 }
2517
2518 #[test]
2519 fn test_collect_vote_lockouts_sums() {
2520 let accounts = gen_stakes(&[(1, &[0]), (1, &[0])]);
2522 let account_latest_votes: Vec<(Pubkey, SlotHashKey)> = accounts
2523 .iter()
2524 .sorted_by_key(|(pk, _)| *pk)
2525 .map(|(pubkey, _)| (*pubkey, (0, Hash::default())))
2526 .collect();
2527
2528 let ancestors = vec![(1, vec![0].into_iter().collect()), (0, HashSet::new())]
2529 .into_iter()
2530 .collect();
2531 let mut latest_validator_votes_for_frozen_banks =
2532 LatestValidatorVotesForFrozenBanks::default();
2533 let ComputedBankState {
2534 voted_stakes,
2535 total_stake,
2536 ..
2537 } = Tower::collect_vote_lockouts(
2538 &Pubkey::default(),
2539 1,
2540 0,
2541 0,
2542 &accounts,
2543 &ancestors,
2544 |_| Some(Hash::default()),
2545 &mut latest_validator_votes_for_frozen_banks,
2546 &mut HashSet::default(),
2547 );
2548 assert_eq!(voted_stakes[&0], 2);
2549 assert_eq!(total_stake, 2);
2550 let mut new_votes: Vec<_> = latest_validator_votes_for_frozen_banks
2551 .take_votes_dirty_set(0)
2552 .collect();
2553 new_votes.sort();
2554 assert_eq!(new_votes, account_latest_votes);
2555 }
2556
2557 #[test]
2558 fn test_collect_vote_lockouts_root() {
2559 let votes: Vec<u64> = (0..MAX_LOCKOUT_HISTORY as u64).collect();
2560 let accounts = gen_stakes(&[(1, &votes), (1, &votes)]);
2562 let account_latest_votes: Vec<(Pubkey, SlotHashKey)> = accounts
2563 .iter()
2564 .sorted_by_key(|(pk, _)| *pk)
2565 .map(|(pubkey, _)| {
2566 (
2567 *pubkey,
2568 ((MAX_LOCKOUT_HISTORY - 1) as Slot, Hash::default()),
2569 )
2570 })
2571 .collect();
2572 let mut tower = Tower::new_for_tests(0, 0.67);
2573 let mut ancestors = HashMap::new();
2574 for i in 0..(MAX_LOCKOUT_HISTORY + 1) {
2575 tower.record_vote(i as u64, Hash::default());
2576 ancestors.insert(i as u64, (0..i as u64).collect());
2577 }
2578 let root = Lockout::new_with_confirmation_count(0, MAX_LOCKOUT_HISTORY as u32);
2579 let expected_bank_stake = 2;
2580 let expected_total_stake = 2;
2581 assert_eq!(tower.vote_state.root_slot, Some(0));
2582 let mut latest_validator_votes_for_frozen_banks =
2583 LatestValidatorVotesForFrozenBanks::default();
2584 let ComputedBankState {
2585 voted_stakes,
2586 fork_stake,
2587 total_stake,
2588 ..
2589 } = Tower::collect_vote_lockouts(
2590 &Pubkey::default(),
2591 MAX_LOCKOUT_HISTORY as u64,
2592 (MAX_LOCKOUT_HISTORY - 1) as Slot,
2593 0,
2594 &accounts,
2595 &ancestors,
2596 |_| Some(Hash::default()),
2597 &mut latest_validator_votes_for_frozen_banks,
2598 &mut HashSet::default(),
2599 );
2600 for i in 0..MAX_LOCKOUT_HISTORY {
2601 assert_eq!(voted_stakes[&(i as u64)], 2);
2602 }
2603
2604 assert_eq!(fork_stake, expected_bank_stake);
2606 assert_eq!(total_stake, expected_total_stake);
2607 let mut new_votes: Vec<_> = latest_validator_votes_for_frozen_banks
2608 .take_votes_dirty_set(root.slot())
2609 .collect();
2610 new_votes.sort();
2611 assert_eq!(new_votes, account_latest_votes);
2612 }
2613
2614 #[test]
2615 fn test_check_vote_threshold_without_votes() {
2616 let tower = Tower::new_for_tests(1, 0.67);
2617 let stakes = vec![(0, 1)].into_iter().collect();
2618 assert!(tower.check_vote_stake_thresholds(0, &stakes, 2).is_empty());
2619 }
2620
2621 #[test]
2622 fn test_check_vote_threshold_no_skip_lockout_with_new_root() {
2623 agave_logger::setup();
2624 let mut tower = Tower::new_for_tests(4, 0.67);
2625 let mut stakes = HashMap::default();
2626 for i in 0..(MAX_LOCKOUT_HISTORY as u64 + 1) {
2627 stakes.insert(i, 1);
2628 tower.record_vote(i, Hash::default());
2629 }
2630 assert!(
2631 !tower
2632 .check_vote_stake_thresholds(MAX_LOCKOUT_HISTORY as u64 + 1, &stakes, 2)
2633 .is_empty()
2634 );
2635 }
2636
2637 #[test]
2638 fn test_is_slot_confirmed_not_enough_stake_failure() {
2639 let tower = Tower::new_for_tests(1, 0.67);
2640 let stakes = vec![(0, 1)].into_iter().collect();
2641 assert!(!tower.is_slot_confirmed(0, &stakes, 2));
2642 }
2643
2644 #[test]
2645 fn test_is_slot_confirmed_unknown_slot() {
2646 let tower = Tower::new_for_tests(1, 0.67);
2647 let stakes = HashMap::default();
2648 assert!(!tower.is_slot_confirmed(0, &stakes, 2));
2649 }
2650
2651 #[test]
2652 fn test_is_slot_confirmed_pass() {
2653 let tower = Tower::new_for_tests(1, 0.67);
2654 let stakes = vec![(0, 2)].into_iter().collect();
2655 assert!(tower.is_slot_confirmed(0, &stakes, 2));
2656 }
2657
2658 #[test]
2659 fn test_is_slot_duplicate_confirmed_not_enough_stake_failure() {
2660 let tower = Tower::new_for_tests(1, 0.67);
2661 let stakes = vec![(0, 52)].into_iter().collect();
2662 assert!(!tower.is_slot_duplicate_confirmed(0, &stakes, 100));
2663 }
2664
2665 #[test]
2666 fn test_is_slot_duplicate_confirmed_unknown_slot() {
2667 let tower = Tower::new_for_tests(1, 0.67);
2668 let stakes = HashMap::default();
2669 assert!(!tower.is_slot_duplicate_confirmed(0, &stakes, 100));
2670 }
2671
2672 #[test]
2673 fn test_is_slot_duplicate_confirmed_pass() {
2674 let tower = Tower::new_for_tests(1, 0.67);
2675 let stakes = vec![(0, 53)].into_iter().collect();
2676 assert!(tower.is_slot_duplicate_confirmed(0, &stakes, 100));
2677 }
2678
2679 #[test]
2680 fn test_is_locked_out_empty() {
2681 let tower = Tower::new_for_tests(0, 0.67);
2682 let ancestors = HashSet::from([0]);
2683 assert!(!tower.is_locked_out(1, &ancestors));
2684 }
2685
2686 #[test]
2687 fn test_is_locked_out_root_slot_child_pass() {
2688 let mut tower = Tower::new_for_tests(0, 0.67);
2689 let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
2690 tower.vote_state.root_slot = Some(0);
2691 assert!(!tower.is_locked_out(1, &ancestors));
2692 }
2693
2694 #[test]
2695 fn test_is_locked_out_root_slot_sibling_fail() {
2696 let mut tower = Tower::new_for_tests(0, 0.67);
2697 let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
2698 tower.vote_state.root_slot = Some(0);
2699 tower.record_vote(1, Hash::default());
2700 assert!(tower.is_locked_out(2, &ancestors));
2701 }
2702
2703 #[test]
2704 fn test_check_already_voted() {
2705 let mut tower = Tower::new_for_tests(0, 0.67);
2706 tower.record_vote(0, Hash::default());
2707 assert!(tower.has_voted(0));
2708 assert!(!tower.has_voted(1));
2709 }
2710
2711 #[test]
2712 fn test_check_recent_slot() {
2713 let mut tower = Tower::new_for_tests(0, 0.67);
2714 assert!(tower.is_recent(1));
2715 assert!(tower.is_recent(32));
2716 for i in 0..64 {
2717 tower.record_vote(i, Hash::default());
2718 }
2719 assert!(!tower.is_recent(0));
2720 assert!(!tower.is_recent(32));
2721 assert!(!tower.is_recent(63));
2722 assert!(tower.is_recent(65));
2723 }
2724
2725 #[test]
2726 fn test_is_locked_out_double_vote() {
2727 let mut tower = Tower::new_for_tests(0, 0.67);
2728 let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
2729 tower.record_vote(0, Hash::default());
2730 tower.record_vote(1, Hash::default());
2731 assert!(tower.is_locked_out(0, &ancestors));
2732 }
2733
2734 #[test]
2735 fn test_is_locked_out_child() {
2736 let mut tower = Tower::new_for_tests(0, 0.67);
2737 let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
2738 tower.record_vote(0, Hash::default());
2739 assert!(!tower.is_locked_out(1, &ancestors));
2740 }
2741
2742 #[test]
2743 fn test_is_locked_out_sibling() {
2744 let mut tower = Tower::new_for_tests(0, 0.67);
2745 let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
2746 tower.record_vote(0, Hash::default());
2747 tower.record_vote(1, Hash::default());
2748 assert!(tower.is_locked_out(2, &ancestors));
2749 }
2750
2751 #[test]
2752 fn test_is_locked_out_last_vote_expired() {
2753 let mut tower = Tower::new_for_tests(0, 0.67);
2754 let ancestors: HashSet<Slot> = vec![0].into_iter().collect();
2755 tower.record_vote(0, Hash::default());
2756 tower.record_vote(1, Hash::default());
2757 assert!(!tower.is_locked_out(4, &ancestors));
2758 tower.record_vote(4, Hash::default());
2759 assert_eq!(tower.vote_state.votes[0].slot(), 0);
2760 assert_eq!(tower.vote_state.votes[0].confirmation_count(), 2);
2761 assert_eq!(tower.vote_state.votes[1].slot(), 4);
2762 assert_eq!(tower.vote_state.votes[1].confirmation_count(), 1);
2763 }
2764
2765 #[test]
2766 fn test_check_vote_threshold_below_threshold() {
2767 let mut tower = Tower::new_for_tests(1, 0.67);
2768 let stakes = vec![(0, 1)].into_iter().collect();
2769 tower.record_vote(0, Hash::default());
2770 assert!(!tower.check_vote_stake_thresholds(1, &stakes, 2).is_empty());
2771 }
2772 #[test]
2773 fn test_check_vote_threshold_above_threshold() {
2774 let mut tower = Tower::new_for_tests(1, 0.67);
2775 let stakes = vec![(0, 2)].into_iter().collect();
2776 tower.record_vote(0, Hash::default());
2777 assert!(tower.check_vote_stake_thresholds(1, &stakes, 2).is_empty());
2778 }
2779
2780 #[test]
2781 fn test_check_vote_thresholds_above_thresholds() {
2782 let mut tower = Tower::new_for_tests(VOTE_THRESHOLD_DEPTH, 0.67);
2783 let stakes = vec![
2784 (0, 3),
2785 (VOTE_THRESHOLD_DEPTH_SHALLOW as u64, 2),
2786 ((VOTE_THRESHOLD_DEPTH_SHALLOW as u64) - 1, 2),
2787 ]
2788 .into_iter()
2789 .collect();
2790 for slot in 0..VOTE_THRESHOLD_DEPTH {
2791 tower.record_vote(slot as Slot, Hash::default());
2792 }
2793 assert!(
2794 tower
2795 .check_vote_stake_thresholds(VOTE_THRESHOLD_DEPTH.try_into().unwrap(), &stakes, 4)
2796 .is_empty()
2797 );
2798 }
2799
2800 #[test]
2801 fn test_check_vote_threshold_deep_below_threshold() {
2802 let mut tower = Tower::new_for_tests(VOTE_THRESHOLD_DEPTH, 0.67);
2803 let stakes = vec![(0, 6), (VOTE_THRESHOLD_DEPTH_SHALLOW as u64, 4)]
2804 .into_iter()
2805 .collect();
2806 for slot in 0..VOTE_THRESHOLD_DEPTH {
2807 tower.record_vote(slot as Slot, Hash::default());
2808 }
2809 assert!(
2810 !tower
2811 .check_vote_stake_thresholds(VOTE_THRESHOLD_DEPTH.try_into().unwrap(), &stakes, 10)
2812 .is_empty()
2813 );
2814 }
2815
2816 #[test]
2817 fn test_check_vote_threshold_shallow_below_threshold() {
2818 let mut tower = Tower::new_for_tests(VOTE_THRESHOLD_DEPTH, 0.67);
2819 let stakes = vec![(0, 7), (VOTE_THRESHOLD_DEPTH_SHALLOW as u64, 1)]
2820 .into_iter()
2821 .collect();
2822 for slot in 0..VOTE_THRESHOLD_DEPTH {
2823 tower.record_vote(slot as Slot, Hash::default());
2824 }
2825 assert!(
2826 !tower
2827 .check_vote_stake_thresholds(VOTE_THRESHOLD_DEPTH.try_into().unwrap(), &stakes, 10)
2828 .is_empty()
2829 );
2830 }
2831
2832 #[test]
2833 fn test_check_vote_threshold_above_threshold_after_pop() {
2834 let mut tower = Tower::new_for_tests(1, 0.67);
2835 let stakes = vec![(0, 2)].into_iter().collect();
2836 tower.record_vote(0, Hash::default());
2837 tower.record_vote(1, Hash::default());
2838 tower.record_vote(2, Hash::default());
2839 assert!(tower.check_vote_stake_thresholds(6, &stakes, 2).is_empty());
2840 }
2841
2842 #[test]
2843 fn test_check_vote_threshold_above_threshold_no_stake() {
2844 let mut tower = Tower::new_for_tests(1, 0.67);
2845 let stakes = HashMap::default();
2846 tower.record_vote(0, Hash::default());
2847 assert!(!tower.check_vote_stake_thresholds(1, &stakes, 2).is_empty());
2848 }
2849
2850 #[test]
2851 fn test_check_vote_threshold_lockouts_not_updated() {
2852 agave_logger::setup();
2853 let mut tower = Tower::new_for_tests(1, 0.67);
2854 let stakes = vec![(0, 1), (1, 2)].into_iter().collect();
2855 tower.record_vote(0, Hash::default());
2856 tower.record_vote(1, Hash::default());
2857 tower.record_vote(2, Hash::default());
2858 assert!(tower.check_vote_stake_thresholds(6, &stakes, 2).is_empty());
2859 }
2860
2861 #[test]
2862 fn test_stake_is_updated_for_entire_branch() {
2863 let mut voted_stakes = HashMap::default();
2864 let account = AccountSharedData::from(Account {
2865 lamports: 1,
2866 ..Account::default()
2867 });
2868 let set: HashSet<u64> = vec![0u64, 1u64].into_iter().collect();
2869 let ancestors: HashMap<u64, HashSet<u64>> = [(2u64, set)].iter().cloned().collect();
2870 Tower::update_ancestor_voted_stakes(&mut voted_stakes, 2, account.lamports(), &ancestors);
2871 assert_eq!(voted_stakes[&0], 1);
2872 assert_eq!(voted_stakes[&1], 1);
2873 assert_eq!(voted_stakes[&2], 1);
2874 }
2875
2876 #[test]
2877 fn test_check_vote_threshold_forks() {
2878 let ancestors = (0..=(VOTE_THRESHOLD_DEPTH + 1) as u64)
2880 .map(|slot| {
2881 let slot_parents: HashSet<_> = (0..slot).collect();
2882 (slot, slot_parents)
2883 })
2884 .collect();
2885
2886 let total_stake = 4;
2890 let threshold_size = 0.67;
2891 let threshold_stake = (f64::ceil(total_stake as f64 * threshold_size)) as u64;
2892 let tower_votes: Vec<Slot> = (0..VOTE_THRESHOLD_DEPTH as u64).collect();
2893 let accounts = gen_stakes(&[
2894 (threshold_stake, &[(VOTE_THRESHOLD_DEPTH - 2) as u64]),
2895 (total_stake - threshold_stake, &tower_votes[..]),
2896 ]);
2897
2898 let mut tower = Tower::new_for_tests(VOTE_THRESHOLD_DEPTH, threshold_size);
2900 let mut vote_slots = HashSet::default();
2901 let vote_to_evaluate = VOTE_THRESHOLD_DEPTH as u64;
2906 for vote in &tower_votes {
2907 tower.record_vote(*vote, Hash::default());
2908 }
2909 let ComputedBankState {
2910 voted_stakes,
2911 total_stake,
2912 ..
2913 } = Tower::collect_vote_lockouts(
2914 &Pubkey::default(),
2915 vote_to_evaluate,
2916 vote_to_evaluate - 1,
2917 0,
2918 &accounts,
2919 &ancestors,
2920 |_| None,
2921 &mut LatestValidatorVotesForFrozenBanks::default(),
2922 &mut vote_slots,
2923 );
2924 assert!(
2925 tower
2926 .check_vote_stake_thresholds(vote_to_evaluate, &voted_stakes, total_stake)
2927 .is_empty()
2928 );
2929
2930 let vote_to_evaluate = VOTE_THRESHOLD_DEPTH as u64 + 1;
2934 let ComputedBankState {
2935 voted_stakes,
2936 total_stake,
2937 ..
2938 } = Tower::collect_vote_lockouts(
2939 &Pubkey::default(),
2940 vote_to_evaluate,
2941 vote_to_evaluate - 1,
2942 0,
2943 &accounts,
2944 &ancestors,
2945 |_| None,
2946 &mut LatestValidatorVotesForFrozenBanks::default(),
2947 &mut vote_slots,
2948 );
2949 assert!(
2950 !tower
2951 .check_vote_stake_thresholds(vote_to_evaluate, &voted_stakes, total_stake)
2952 .is_empty()
2953 );
2954 }
2955
2956 fn vote_and_check_recent(num_votes: usize) {
2957 let mut tower = Tower::new_for_tests(1, 0.67);
2958 let slots = if num_votes > 0 {
2959 { 0..num_votes }
2960 .map(|i| {
2961 Lockout::new_with_confirmation_count(i as Slot, (num_votes as u32) - (i as u32))
2962 })
2963 .collect()
2964 } else {
2965 vec![]
2966 };
2967 let mut expected = TowerSync::new(
2968 VecDeque::from(slots),
2969 if num_votes > 0 { Some(0) } else { None },
2970 Hash::default(),
2971 Hash::default(),
2972 );
2973 for i in 0..num_votes {
2974 tower.record_vote(i as u64, Hash::default());
2975 }
2976
2977 expected.timestamp = tower.last_vote.timestamp();
2978 assert_eq!(VoteTransaction::from(expected), tower.last_vote)
2979 }
2980
2981 #[test]
2982 fn test_recent_votes_full() {
2983 vote_and_check_recent(MAX_LOCKOUT_HISTORY)
2984 }
2985
2986 #[test]
2987 fn test_recent_votes_empty() {
2988 vote_and_check_recent(0)
2989 }
2990
2991 #[test]
2992 fn test_recent_votes_exact() {
2993 vote_and_check_recent(5)
2994 }
2995
2996 #[test]
2997 fn test_maybe_timestamp() {
2998 let mut tower = Tower::default();
2999 assert!(tower.maybe_timestamp(0).is_some());
3000 assert!(tower.maybe_timestamp(1).is_some());
3001 assert!(tower.maybe_timestamp(0).is_none()); assert!(tower.maybe_timestamp(1).is_none()); tower.last_timestamp.timestamp -= 1; assert!(tower.maybe_timestamp(2).is_some()); tower.last_timestamp.timestamp += 1_000_000; assert!(tower.maybe_timestamp(3).is_none()); }
3010
3011 #[test]
3012 fn test_refresh_last_vote_timestamp() {
3013 let mut tower = Tower::default();
3014
3015 tower.last_vote.set_timestamp(None);
3017 tower.refresh_last_vote_timestamp(5);
3018 assert_eq!(tower.last_vote.timestamp(), None);
3019 assert_eq!(tower.last_timestamp.slot, 0);
3020 assert_eq!(tower.last_timestamp.timestamp, 0);
3021
3022 tower.last_vote = VoteTransaction::from(TowerSync::from(vec![(0, 3), (1, 2), (6, 1)]));
3024 assert_eq!(tower.last_vote.timestamp(), None);
3025 tower.refresh_last_vote_timestamp(5);
3026 assert_eq!(tower.last_vote.timestamp(), None);
3027 assert_eq!(tower.last_timestamp.slot, 0);
3028 assert_eq!(tower.last_timestamp.timestamp, 0);
3029
3030 tower.last_vote = VoteTransaction::from(TowerSync::from(vec![(0, 3), (1, 2), (2, 1)]));
3032 assert_eq!(tower.last_vote.timestamp(), None);
3033 tower.refresh_last_vote_timestamp(5);
3034 assert_eq!(tower.last_vote.timestamp(), Some(1));
3035 assert_eq!(tower.last_timestamp.slot, 2);
3036 assert_eq!(tower.last_timestamp.timestamp, 1);
3037
3038 tower.last_vote = VoteTransaction::from(TowerSync::from(vec![(0, 3), (1, 2), (2, 1)]));
3040 tower.refresh_last_vote_timestamp(5);
3041 assert_eq!(tower.last_vote.timestamp(), Some(2));
3042 assert_eq!(tower.last_timestamp.slot, 2);
3043 assert_eq!(tower.last_timestamp.timestamp, 2);
3044 }
3045
3046 fn run_test_load_tower_snapshot<F, G>(
3047 modify_original: F,
3048 modify_serialized: G,
3049 ) -> (Tower, Result<Tower>)
3050 where
3051 F: Fn(&mut Tower, &Pubkey),
3052 G: Fn(&PathBuf),
3053 {
3054 let tower_path = TempDir::new().unwrap();
3055 let identity_keypair = Arc::new(Keypair::new());
3056 let node_pubkey = identity_keypair.pubkey();
3057
3058 let mut tower = Tower::new_for_tests(10, 0.9);
3060
3061 let tower_storage = FileTowerStorage::new(tower_path.path().to_path_buf());
3062
3063 modify_original(&mut tower, &node_pubkey);
3064
3065 tower.save(&tower_storage, &identity_keypair).unwrap();
3066 modify_serialized(&tower_storage.filename(&node_pubkey));
3067 let loaded = Tower::restore(&tower_storage, &node_pubkey);
3068
3069 (tower, loaded)
3070 }
3071
3072 #[test]
3073 fn test_switch_threshold_across_tower_reload() {
3074 agave_logger::setup();
3075 let mut vote_simulator = VoteSimulator::new(2);
3077 let other_vote_account = vote_simulator.vote_pubkeys[1];
3078 let bank0 = vote_simulator.bank_forks.read().unwrap().get(0).unwrap();
3079 let total_stake = bank0.total_epoch_stake();
3080 assert_eq!(
3081 total_stake,
3082 vote_simulator.validator_keypairs.len() as u64 * 10_000
3083 );
3084
3085 let forks = tr(0)
3087 / (tr(1)
3088 / (tr(2)
3089 / tr(10)
3090 / (tr(43)
3091 / (tr(44)
3092 / (tr(45) / (tr(46) / (tr(47) / (tr(48) / (tr(49) / (tr(50)))))))
3094 / (tr(110) / tr(111))))));
3095
3096 vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
3098 for fork_progress in vote_simulator.progress.values_mut() {
3099 fork_progress.fork_stats.computed = true;
3100 }
3101
3102 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
3103 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
3104 let mut tower = Tower::default();
3105
3106 tower.record_vote(43, Hash::default());
3107 tower.record_vote(44, Hash::default());
3108 tower.record_vote(45, Hash::default());
3109 tower.record_vote(46, Hash::default());
3110 tower.record_vote(47, Hash::default());
3111 tower.record_vote(48, Hash::default());
3112 tower.record_vote(49, Hash::default());
3113
3114 assert_eq!(
3116 tower.check_switch_threshold(
3117 50,
3118 &ancestors,
3119 &descendants,
3120 &vote_simulator.progress,
3121 total_stake,
3122 bank0.epoch_vote_accounts(0).unwrap(),
3123 &vote_simulator.latest_validator_votes_for_frozen_banks,
3124 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3125 ),
3126 SwitchForkDecision::SameFork
3127 );
3128
3129 assert_eq!(
3131 tower.check_switch_threshold(
3132 110,
3133 &ancestors,
3134 &descendants,
3135 &vote_simulator.progress,
3136 total_stake,
3137 bank0.epoch_vote_accounts(0).unwrap(),
3138 &vote_simulator.latest_validator_votes_for_frozen_banks,
3139 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3140 ),
3141 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
3142 );
3143
3144 vote_simulator.simulate_lockout_interval(111, (10, 49), &other_vote_account);
3145
3146 assert_eq!(
3147 tower.check_switch_threshold(
3148 110,
3149 &ancestors,
3150 &descendants,
3151 &vote_simulator.progress,
3152 total_stake,
3153 bank0.epoch_vote_accounts(0).unwrap(),
3154 &vote_simulator.latest_validator_votes_for_frozen_banks,
3155 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3156 ),
3157 SwitchForkDecision::SwitchProof(Hash::default())
3158 );
3159
3160 assert_eq!(tower.voted_slots(), vec![43, 44, 45, 46, 47, 48, 49]);
3161 {
3162 let mut tower = tower.clone();
3163 tower.record_vote(110, Hash::default());
3164 tower.record_vote(111, Hash::default());
3165 assert_eq!(tower.voted_slots(), vec![43, 110, 111]);
3166 assert_eq!(tower.vote_state.root_slot, Some(0));
3167 }
3168
3169 let mut vote_simulator = VoteSimulator::new(2);
3171 let other_vote_account = vote_simulator.vote_pubkeys[1];
3172 let bank0 = vote_simulator.bank_forks.read().unwrap().get(0).unwrap();
3173 let total_stake = bank0.total_epoch_stake();
3174 let forks = tr(0)
3175 / (tr(1)
3176 / (tr(2)
3177 / tr(10)
3178 / (tr(43)
3179 / (tr(44)
3180 / (tr(45) / (tr(46) / (tr(47) / (tr(48) / (tr(49) / (tr(50)))))))
3182 / (tr(110) / tr(111))))));
3183 let replayed_root_slot = 44;
3184
3185 vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
3187 for fork_progress in vote_simulator.progress.values_mut() {
3188 fork_progress.fork_stats.computed = true;
3189 }
3190
3191 let mut slot_history = SlotHistory::default();
3193 vote_simulator.set_root(replayed_root_slot);
3194 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
3195 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
3196 for slot in &[0, 1, 2, 43, replayed_root_slot] {
3197 slot_history.add(*slot);
3198 }
3199 let mut tower = tower
3200 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3201 .unwrap();
3202
3203 assert_eq!(tower.voted_slots(), vec![45, 46, 47, 48, 49]);
3204
3205 assert_eq!(
3207 tower.check_switch_threshold(
3208 110,
3209 &ancestors,
3210 &descendants,
3211 &vote_simulator.progress,
3212 total_stake,
3213 bank0.epoch_vote_accounts(0).unwrap(),
3214 &vote_simulator.latest_validator_votes_for_frozen_banks,
3215 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3216 ),
3217 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
3218 );
3219
3220 vote_simulator.simulate_lockout_interval(111, (45, 50), &other_vote_account);
3222 assert_eq!(
3223 tower.check_switch_threshold(
3224 110,
3225 &ancestors,
3226 &descendants,
3227 &vote_simulator.progress,
3228 total_stake,
3229 bank0.epoch_vote_accounts(0).unwrap(),
3230 &vote_simulator.latest_validator_votes_for_frozen_banks,
3231 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3232 ),
3233 SwitchForkDecision::FailedSwitchThreshold(0, 20000)
3234 );
3235
3236 vote_simulator.simulate_lockout_interval(111, (110, 200), &other_vote_account);
3238 assert_eq!(
3239 tower.check_switch_threshold(
3240 110,
3241 &ancestors,
3242 &descendants,
3243 &vote_simulator.progress,
3244 total_stake,
3245 bank0.epoch_vote_accounts(0).unwrap(),
3246 &vote_simulator.latest_validator_votes_for_frozen_banks,
3247 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3248 ),
3249 SwitchForkDecision::SwitchProof(Hash::default())
3250 );
3251
3252 tower.record_vote(110, Hash::default());
3253 tower.record_vote(111, Hash::default());
3254 assert_eq!(tower.voted_slots(), vec![110, 111]);
3255 assert_eq!(tower.vote_state.root_slot, Some(replayed_root_slot));
3256 }
3257
3258 #[test]
3259 fn test_load_tower_ok() {
3260 let (tower, loaded) =
3261 run_test_load_tower_snapshot(|tower, pubkey| tower.node_pubkey = *pubkey, |_| ());
3262 let loaded = loaded.unwrap();
3263 assert_eq!(loaded, tower);
3264 assert_eq!(tower.threshold_depth, 10);
3265 assert!((tower.threshold_size - 0.9_f64).abs() < f64::EPSILON);
3266 assert_eq!(loaded.threshold_depth, 10);
3267 assert!((loaded.threshold_size - 0.9_f64).abs() < f64::EPSILON);
3268 }
3269
3270 #[test]
3271 fn test_load_tower_wrong_identity() {
3272 let identity_keypair = Arc::new(Keypair::new());
3273 let tower = Tower::default();
3274 let tower_storage = FileTowerStorage::default();
3275 assert_matches!(
3276 tower.save(&tower_storage, &identity_keypair),
3277 Err(TowerError::WrongTower(_))
3278 )
3279 }
3280
3281 #[test]
3282 fn test_load_tower_invalid_signature() {
3283 let (_, loaded) = run_test_load_tower_snapshot(
3284 |tower, pubkey| tower.node_pubkey = *pubkey,
3285 |path| {
3286 let mut file = OpenOptions::new()
3287 .read(true)
3288 .write(true)
3289 .open(path)
3290 .unwrap();
3291 assert_eq!(file.seek(SeekFrom::Start(4)).unwrap(), 4);
3293 let mut buf = [0u8];
3294 assert_eq!(file.read(&mut buf).unwrap(), 1);
3295 buf[0] = !buf[0];
3296 assert_eq!(file.seek(SeekFrom::Start(4)).unwrap(), 4);
3297 assert_eq!(file.write(&buf).unwrap(), 1);
3298 },
3299 );
3300 assert_matches!(loaded, Err(TowerError::InvalidSignature))
3301 }
3302
3303 #[test]
3304 fn test_load_tower_deser_failure() {
3305 let (_, loaded) = run_test_load_tower_snapshot(
3306 |tower, pubkey| tower.node_pubkey = *pubkey,
3307 |path| {
3308 OpenOptions::new()
3309 .write(true)
3310 .truncate(true)
3311 .open(path)
3312 .unwrap_or_else(|_| panic!("Failed to truncate file: {path:?}"));
3313 },
3314 );
3315 assert_matches!(loaded, Err(TowerError::SerializeError(_)))
3316 }
3317
3318 #[test]
3319 fn test_load_tower_missing() {
3320 let (_, loaded) = run_test_load_tower_snapshot(
3321 |tower, pubkey| tower.node_pubkey = *pubkey,
3322 |path| {
3323 remove_file(path).unwrap();
3324 },
3325 );
3326 assert_matches!(loaded, Err(TowerError::IoError(_)))
3327 }
3328
3329 #[test]
3330 fn test_reconcile_blockstore_roots_with_tower_normal() {
3331 agave_logger::setup();
3332 let ledger_path = get_tmp_ledger_path_auto_delete!();
3333 let blockstore = Blockstore::open(ledger_path.path()).unwrap();
3334
3335 let (shreds, _) = make_slot_entries(1, 0, 42);
3336 blockstore.insert_shreds(shreds, None, false).unwrap();
3337 let (shreds, _) = make_slot_entries(3, 1, 42);
3338 blockstore.insert_shreds(shreds, None, false).unwrap();
3339 let (shreds, _) = make_slot_entries(4, 1, 42);
3340 blockstore.insert_shreds(shreds, None, false).unwrap();
3341 assert!(!blockstore.is_root(0));
3342 assert!(!blockstore.is_root(1));
3343 assert!(!blockstore.is_root(3));
3344 assert!(!blockstore.is_root(4));
3345
3346 let mut tower = Tower::default();
3347 tower.vote_state.root_slot = Some(4);
3348 reconcile_blockstore_roots_with_external_source(
3349 ExternalRootSource::Tower(tower.root()),
3350 &blockstore,
3351 &mut blockstore.max_root(),
3352 )
3353 .unwrap();
3354
3355 assert!(!blockstore.is_root(0));
3356 assert!(blockstore.is_root(1));
3357 assert!(!blockstore.is_root(3));
3358 assert!(blockstore.is_root(4));
3359 }
3360
3361 #[test]
3362 #[should_panic(
3363 expected = "last_blockstore_root(3) is skipped while traversing blockstore (currently at \
3364 1) from external root (Tower(4))!?"
3365 )]
3366 fn test_reconcile_blockstore_roots_with_tower_panic_no_common_root() {
3367 agave_logger::setup();
3368 let ledger_path = get_tmp_ledger_path_auto_delete!();
3369 let blockstore = Blockstore::open(ledger_path.path()).unwrap();
3370
3371 let (shreds, _) = make_slot_entries(1, 0, 42);
3372 blockstore.insert_shreds(shreds, None, false).unwrap();
3373 let (shreds, _) = make_slot_entries(3, 1, 42);
3374 blockstore.insert_shreds(shreds, None, false).unwrap();
3375 let (shreds, _) = make_slot_entries(4, 1, 42);
3376 blockstore.insert_shreds(shreds, None, false).unwrap();
3377 blockstore.set_roots(std::iter::once(&3)).unwrap();
3378 assert!(!blockstore.is_root(0));
3379 assert!(!blockstore.is_root(1));
3380 assert!(blockstore.is_root(3));
3381 assert!(!blockstore.is_root(4));
3382
3383 let mut tower = Tower::default();
3384 tower.vote_state.root_slot = Some(4);
3385 reconcile_blockstore_roots_with_external_source(
3386 ExternalRootSource::Tower(tower.root()),
3387 &blockstore,
3388 &mut blockstore.max_root(),
3389 )
3390 .unwrap();
3391 }
3392
3393 #[test]
3394 fn test_reconcile_blockstore_roots_with_tower_nop_no_parent() {
3395 agave_logger::setup();
3396 let ledger_path = get_tmp_ledger_path_auto_delete!();
3397 let blockstore = Blockstore::open(ledger_path.path()).unwrap();
3398
3399 let (shreds, _) = make_slot_entries(1, 0, 42);
3400 blockstore.insert_shreds(shreds, None, false).unwrap();
3401 let (shreds, _) = make_slot_entries(3, 1, 42);
3402 blockstore.insert_shreds(shreds, None, false).unwrap();
3403 assert!(!blockstore.is_root(0));
3404 assert!(!blockstore.is_root(1));
3405 assert!(!blockstore.is_root(3));
3406
3407 let mut tower = Tower::default();
3408 tower.vote_state.root_slot = Some(4);
3409 assert_eq!(blockstore.max_root(), 0);
3410 reconcile_blockstore_roots_with_external_source(
3411 ExternalRootSource::Tower(tower.root()),
3412 &blockstore,
3413 &mut blockstore.max_root(),
3414 )
3415 .unwrap();
3416 assert_eq!(blockstore.max_root(), 0);
3417 }
3418
3419 #[test]
3420 fn test_adjust_lockouts_after_replay_future_slots() {
3421 agave_logger::setup();
3422 let mut tower = Tower::new_for_tests(10, 0.9);
3423 tower.record_vote(0, Hash::default());
3424 tower.record_vote(1, Hash::default());
3425 tower.record_vote(2, Hash::default());
3426 tower.record_vote(3, Hash::default());
3427
3428 let mut slot_history = SlotHistory::default();
3429 slot_history.add(0);
3430 slot_history.add(1);
3431
3432 let replayed_root_slot = 1;
3433 tower = tower
3434 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3435 .unwrap();
3436
3437 assert_eq!(tower.voted_slots(), vec![2, 3]);
3438 assert_eq!(tower.root(), replayed_root_slot);
3439
3440 tower = tower
3441 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3442 .unwrap();
3443 assert_eq!(tower.voted_slots(), vec![2, 3]);
3444 assert_eq!(tower.root(), replayed_root_slot);
3445 }
3446
3447 #[test]
3448 fn test_adjust_lockouts_after_replay_not_found_slots() {
3449 let mut tower = Tower::new_for_tests(10, 0.9);
3450 tower.record_vote(0, Hash::default());
3451 tower.record_vote(1, Hash::default());
3452 tower.record_vote(2, Hash::default());
3453 tower.record_vote(3, Hash::default());
3454
3455 let mut slot_history = SlotHistory::default();
3456 slot_history.add(0);
3457 slot_history.add(1);
3458 slot_history.add(4);
3459
3460 let replayed_root_slot = 4;
3461 tower = tower
3462 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3463 .unwrap();
3464
3465 assert_eq!(tower.voted_slots(), vec![2, 3]);
3466 assert_eq!(tower.root(), replayed_root_slot);
3467 }
3468
3469 #[test]
3470 fn test_adjust_lockouts_after_replay_all_rooted_with_no_too_old() {
3471 let mut tower = Tower::new_for_tests(10, 0.9);
3472 tower.record_vote(0, Hash::default());
3473 tower.record_vote(1, Hash::default());
3474 tower.record_vote(2, Hash::default());
3475
3476 let mut slot_history = SlotHistory::default();
3477 slot_history.add(0);
3478 slot_history.add(1);
3479 slot_history.add(2);
3480 slot_history.add(3);
3481 slot_history.add(4);
3482 slot_history.add(5);
3483
3484 let replayed_root_slot = 5;
3485 tower = tower
3486 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3487 .unwrap();
3488
3489 assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
3490 assert_eq!(tower.root(), replayed_root_slot);
3491 assert_eq!(tower.stray_restored_slot, None);
3492 }
3493
3494 #[test]
3495 fn test_adjust_lockouts_after_replay_all_rooted_with_too_old() {
3496 use solana_slot_history::MAX_ENTRIES;
3497
3498 let mut tower = Tower::new_for_tests(10, 0.9);
3499 tower.record_vote(0, Hash::default());
3500 tower.record_vote(1, Hash::default());
3501 tower.record_vote(2, Hash::default());
3502
3503 let mut slot_history = SlotHistory::default();
3504 slot_history.add(0);
3505 slot_history.add(1);
3506 slot_history.add(2);
3507 slot_history.add(MAX_ENTRIES);
3508
3509 tower = tower
3510 .adjust_lockouts_after_replay(MAX_ENTRIES, &slot_history)
3511 .unwrap();
3512 assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
3513 assert_eq!(tower.root(), MAX_ENTRIES);
3514 }
3515
3516 #[test]
3517 fn test_adjust_lockouts_after_replay_anchored_future_slots() {
3518 let mut tower = Tower::new_for_tests(10, 0.9);
3519 tower.record_vote(0, Hash::default());
3520 tower.record_vote(1, Hash::default());
3521 tower.record_vote(2, Hash::default());
3522 tower.record_vote(3, Hash::default());
3523 tower.record_vote(4, Hash::default());
3524
3525 let mut slot_history = SlotHistory::default();
3526 slot_history.add(0);
3527 slot_history.add(1);
3528 slot_history.add(2);
3529
3530 let replayed_root_slot = 2;
3531 tower = tower
3532 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3533 .unwrap();
3534
3535 assert_eq!(tower.voted_slots(), vec![3, 4]);
3536 assert_eq!(tower.root(), replayed_root_slot);
3537 }
3538
3539 #[test]
3540 fn test_adjust_lockouts_after_replay_all_not_found() {
3541 let mut tower = Tower::new_for_tests(10, 0.9);
3542 tower.record_vote(5, Hash::default());
3543 tower.record_vote(6, Hash::default());
3544
3545 let mut slot_history = SlotHistory::default();
3546 slot_history.add(0);
3547 slot_history.add(1);
3548 slot_history.add(2);
3549 slot_history.add(7);
3550
3551 let replayed_root_slot = 7;
3552 tower = tower
3553 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3554 .unwrap();
3555
3556 assert_eq!(tower.voted_slots(), vec![5, 6]);
3557 assert_eq!(tower.root(), replayed_root_slot);
3558 }
3559
3560 #[test]
3561 fn test_adjust_lockouts_after_replay_all_not_found_even_if_rooted() {
3562 let mut tower = Tower::new_for_tests(10, 0.9);
3563 tower.vote_state.root_slot = Some(4);
3564 tower.record_vote(5, Hash::default());
3565 tower.record_vote(6, Hash::default());
3566
3567 let mut slot_history = SlotHistory::default();
3568 slot_history.add(0);
3569 slot_history.add(1);
3570 slot_history.add(2);
3571 slot_history.add(7);
3572
3573 let replayed_root_slot = 7;
3574 let result = tower.adjust_lockouts_after_replay(replayed_root_slot, &slot_history);
3575
3576 assert_eq!(
3577 format!("{}", result.unwrap_err()),
3578 "The tower is fatally inconsistent with blockstore: no common slot for rooted tower"
3579 );
3580 }
3581
3582 #[test]
3583 fn test_adjust_lockouts_after_replay_all_future_votes_only_root_found() {
3584 let mut tower = Tower::new_for_tests(10, 0.9);
3585 tower.vote_state.root_slot = Some(2);
3586 tower.record_vote(3, Hash::default());
3587 tower.record_vote(4, Hash::default());
3588 tower.record_vote(5, Hash::default());
3589
3590 let mut slot_history = SlotHistory::default();
3591 slot_history.add(0);
3592 slot_history.add(1);
3593 slot_history.add(2);
3594
3595 let replayed_root_slot = 2;
3596 tower = tower
3597 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3598 .unwrap();
3599
3600 assert_eq!(tower.voted_slots(), vec![3, 4, 5]);
3601 assert_eq!(tower.root(), replayed_root_slot);
3602 }
3603
3604 #[test]
3605 fn test_adjust_lockouts_after_replay_empty() {
3606 let mut tower = Tower::new_for_tests(10, 0.9);
3607
3608 let mut slot_history = SlotHistory::default();
3609 slot_history.add(0);
3610
3611 let replayed_root_slot = 0;
3612 tower = tower
3613 .adjust_lockouts_after_replay(replayed_root_slot, &slot_history)
3614 .unwrap();
3615
3616 assert_eq!(tower.voted_slots(), vec![] as Vec<Slot>);
3617 assert_eq!(tower.root(), replayed_root_slot);
3618 }
3619
3620 #[test]
3621 fn test_adjust_lockouts_after_replay_too_old_tower() {
3622 use solana_slot_history::MAX_ENTRIES;
3623
3624 let mut tower = Tower::new_for_tests(10, 0.9);
3625 tower.record_vote(0, Hash::default());
3626
3627 let mut slot_history = SlotHistory::default();
3628 slot_history.add(0);
3629 slot_history.add(MAX_ENTRIES);
3630
3631 let result = tower.adjust_lockouts_after_replay(MAX_ENTRIES, &slot_history);
3632 assert_eq!(
3633 format!("{}", result.unwrap_err()),
3634 "The tower is too old: newest slot in tower (0) << oldest slot in available history \
3635 (1)"
3636 );
3637 }
3638
3639 #[test]
3640 fn test_adjust_lockouts_after_replay_time_warped() {
3641 let mut tower = Tower::new_for_tests(10, 0.9);
3642 tower.vote_state.votes.push_back(Lockout::new(1));
3643 tower.vote_state.votes.push_back(Lockout::new(0));
3644 let vote = Vote::new(vec![0], Hash::default());
3645 tower.last_vote = VoteTransaction::from(vote);
3646
3647 let mut slot_history = SlotHistory::default();
3648 slot_history.add(0);
3649
3650 let result = tower.adjust_lockouts_after_replay(0, &slot_history);
3651 assert_eq!(
3652 format!("{}", result.unwrap_err()),
3653 "The tower is fatally inconsistent with blockstore: time warped?"
3654 );
3655 }
3656
3657 #[test]
3658 fn test_adjust_lockouts_after_replay_diverged_ancestor() {
3659 let mut tower = Tower::new_for_tests(10, 0.9);
3660 tower.vote_state.votes.push_back(Lockout::new(1));
3661 tower.vote_state.votes.push_back(Lockout::new(2));
3662 let vote = Vote::new(vec![2], Hash::default());
3663 tower.last_vote = VoteTransaction::from(vote);
3664
3665 let mut slot_history = SlotHistory::default();
3666 slot_history.add(0);
3667 slot_history.add(2);
3668
3669 let result = tower.adjust_lockouts_after_replay(2, &slot_history);
3670 assert_eq!(
3671 format!("{}", result.unwrap_err()),
3672 "The tower is fatally inconsistent with blockstore: diverged ancestor?"
3673 );
3674 }
3675
3676 #[test]
3677 fn test_adjust_lockouts_after_replay_out_of_order() {
3678 use solana_slot_history::MAX_ENTRIES;
3679
3680 let mut tower = Tower::new_for_tests(10, 0.9);
3681 tower
3682 .vote_state
3683 .votes
3684 .push_back(Lockout::new(MAX_ENTRIES - 1));
3685 tower.vote_state.votes.push_back(Lockout::new(0));
3686 tower.vote_state.votes.push_back(Lockout::new(1));
3687 let vote = Vote::new(vec![1], Hash::default());
3688 tower.last_vote = VoteTransaction::from(vote);
3689
3690 let mut slot_history = SlotHistory::default();
3691 slot_history.add(MAX_ENTRIES);
3692
3693 let result = tower.adjust_lockouts_after_replay(MAX_ENTRIES, &slot_history);
3694 assert_eq!(
3695 format!("{}", result.unwrap_err()),
3696 "The tower is fatally inconsistent with blockstore: not too old once after got too \
3697 old?"
3698 );
3699 }
3700
3701 #[test]
3702 #[should_panic(expected = "slot_in_tower(2) < checked_slot(1)")]
3703 fn test_adjust_lockouts_after_replay_reversed_votes() {
3704 let mut tower = Tower::new_for_tests(10, 0.9);
3705 tower.vote_state.votes.push_back(Lockout::new(2));
3706 tower.vote_state.votes.push_back(Lockout::new(1));
3707 let vote = Vote::new(vec![1], Hash::default());
3708 tower.last_vote = VoteTransaction::from(vote);
3709
3710 let mut slot_history = SlotHistory::default();
3711 slot_history.add(0);
3712 slot_history.add(2);
3713
3714 tower
3715 .adjust_lockouts_after_replay(2, &slot_history)
3716 .unwrap();
3717 }
3718
3719 #[test]
3720 #[should_panic(expected = "slot_in_tower(3) < checked_slot(3)")]
3721 fn test_adjust_lockouts_after_replay_repeated_non_root_votes() {
3722 let mut tower = Tower::new_for_tests(10, 0.9);
3723 tower.vote_state.votes.push_back(Lockout::new(2));
3724 tower.vote_state.votes.push_back(Lockout::new(3));
3725 tower.vote_state.votes.push_back(Lockout::new(3));
3726 let vote = Vote::new(vec![3], Hash::default());
3727 tower.last_vote = VoteTransaction::from(vote);
3728
3729 let mut slot_history = SlotHistory::default();
3730 slot_history.add(0);
3731 slot_history.add(2);
3732
3733 tower
3734 .adjust_lockouts_after_replay(2, &slot_history)
3735 .unwrap();
3736 }
3737
3738 #[test]
3739 fn test_adjust_lockouts_after_replay_vote_on_root() {
3740 let mut tower = Tower::new_for_tests(10, 0.9);
3741 tower.vote_state.root_slot = Some(42);
3742 tower.vote_state.votes.push_back(Lockout::new(42));
3743 tower.vote_state.votes.push_back(Lockout::new(43));
3744 tower.vote_state.votes.push_back(Lockout::new(44));
3745 let vote = Vote::new(vec![44], Hash::default());
3746 tower.last_vote = VoteTransaction::from(vote);
3747
3748 let mut slot_history = SlotHistory::default();
3749 slot_history.add(42);
3750
3751 let tower = tower.adjust_lockouts_after_replay(42, &slot_history);
3752 assert_eq!(tower.unwrap().voted_slots(), [43, 44]);
3753 }
3754
3755 #[test]
3756 fn test_adjust_lockouts_after_replay_vote_on_genesis() {
3757 let mut tower = Tower::new_for_tests(10, 0.9);
3758 tower.vote_state.votes.push_back(Lockout::new(0));
3759 let vote = Vote::new(vec![0], Hash::default());
3760 tower.last_vote = VoteTransaction::from(vote);
3761
3762 let mut slot_history = SlotHistory::default();
3763 slot_history.add(0);
3764
3765 assert!(tower.adjust_lockouts_after_replay(0, &slot_history).is_ok());
3766 }
3767
3768 #[test]
3769 fn test_adjust_lockouts_after_replay_future_tower() {
3770 let mut tower = Tower::new_for_tests(10, 0.9);
3771 tower.vote_state.votes.push_back(Lockout::new(13));
3772 tower.vote_state.votes.push_back(Lockout::new(14));
3773 let vote = Vote::new(vec![14], Hash::default());
3774 tower.last_vote = VoteTransaction::from(vote);
3775 tower.initialize_root(12);
3776
3777 let mut slot_history = SlotHistory::default();
3778 slot_history.add(0);
3779 slot_history.add(2);
3780
3781 let tower = tower
3782 .adjust_lockouts_after_replay(2, &slot_history)
3783 .unwrap();
3784 assert_eq!(tower.root(), 12);
3785 assert_eq!(tower.voted_slots(), vec![13, 14]);
3786 assert_eq!(tower.stray_restored_slot, Some(14));
3787 }
3788
3789 #[test]
3790 fn test_default_tower_has_no_stray_last_vote() {
3791 let tower = Tower::default();
3792 assert!(!tower.is_stray_last_vote());
3793 }
3794
3795 #[test]
3796 fn test_switch_threshold_common_ancestor() {
3797 let mut vote_simulator = VoteSimulator::new(2);
3798 let other_vote_account = vote_simulator.vote_pubkeys[1];
3799 let bank0 = vote_simulator.bank_forks.read().unwrap().get(0).unwrap();
3800 let total_stake = bank0.total_epoch_stake();
3801 assert_eq!(
3802 total_stake,
3803 vote_simulator.validator_keypairs.len() as u64 * 10_000
3804 );
3805
3806 let forks = tr(0)
3813 / (tr(1)
3814 / (tr(2)
3815 / tr(51)
3816 / (tr(43)
3817 / (tr(44)
3818 / (tr(45) / (tr(46) / (tr(47) / (tr(48) / tr(49) / tr(50)))))
3819 / tr(113)
3820 / (tr(110) / tr(111) / tr(112))))));
3821 let switch_slot = 111;
3822
3823 vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
3825 for fork_progress in vote_simulator.progress.values_mut() {
3826 fork_progress.fork_stats.computed = true;
3827 }
3828
3829 let ancestors = vote_simulator.bank_forks.read().unwrap().ancestors();
3830 let descendants = vote_simulator.bank_forks.read().unwrap().descendants();
3831 let mut tower = Tower::default();
3832
3833 tower.record_vote(43, Hash::default());
3834 tower.record_vote(44, Hash::default());
3835 tower.record_vote(45, Hash::default());
3836 tower.record_vote(46, Hash::default());
3837 tower.record_vote(47, Hash::default());
3838 tower.record_vote(48, Hash::default());
3839 tower.record_vote(49, Hash::default());
3840
3841 vote_simulator.simulate_lockout_interval(50, (10, 49), &other_vote_account);
3843 assert_eq!(
3844 tower.check_switch_threshold(
3845 switch_slot,
3846 &ancestors,
3847 &descendants,
3848 &vote_simulator.progress,
3849 total_stake,
3850 bank0.epoch_vote_accounts(0).unwrap(),
3851 &vote_simulator.latest_validator_votes_for_frozen_banks,
3852 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3853 ),
3854 SwitchForkDecision::FailedSwitchThreshold(0, 20_000)
3855 );
3856 vote_simulator.clear_lockout_intervals(50);
3857
3858 for candidate_slot in [51, 111, 113] {
3860 vote_simulator.simulate_lockout_interval(candidate_slot, (10, 49), &other_vote_account);
3861 assert_eq!(
3862 tower.check_switch_threshold(
3863 switch_slot,
3864 &ancestors,
3865 &descendants,
3866 &vote_simulator.progress,
3867 total_stake,
3868 bank0.epoch_vote_accounts(0).unwrap(),
3869 &vote_simulator.latest_validator_votes_for_frozen_banks,
3870 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3871 ),
3872 SwitchForkDecision::SwitchProof(Hash::default())
3873 );
3874 vote_simulator.clear_lockout_intervals(candidate_slot);
3875 }
3876
3877 let insert_gossip_vote = |vote_simulator: &mut VoteSimulator, slot| {
3879 vote_simulator
3880 .latest_validator_votes_for_frozen_banks
3881 .check_add_vote(
3882 other_vote_account,
3883 slot,
3884 Some(
3885 vote_simulator
3886 .bank_forks
3887 .read()
3888 .unwrap()
3889 .get(slot)
3890 .unwrap()
3891 .hash(),
3892 ),
3893 false,
3894 );
3895 };
3896
3897 insert_gossip_vote(&mut vote_simulator, 50);
3899 assert_eq!(
3900 tower.check_switch_threshold(
3901 switch_slot,
3902 &ancestors,
3903 &descendants,
3904 &vote_simulator.progress,
3905 total_stake,
3906 bank0.epoch_vote_accounts(0).unwrap(),
3907 &vote_simulator.latest_validator_votes_for_frozen_banks,
3908 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3909 ),
3910 SwitchForkDecision::FailedSwitchThreshold(0, 20_000)
3911 );
3912 vote_simulator.latest_validator_votes_for_frozen_banks =
3913 LatestValidatorVotesForFrozenBanks::default();
3914
3915 for candidate_slot in [51, 110, 111, 112, 113] {
3918 insert_gossip_vote(&mut vote_simulator, candidate_slot);
3919 assert_eq!(
3920 tower.check_switch_threshold(
3921 switch_slot,
3922 &ancestors,
3923 &descendants,
3924 &vote_simulator.progress,
3925 total_stake,
3926 bank0.epoch_vote_accounts(0).unwrap(),
3927 &vote_simulator.latest_validator_votes_for_frozen_banks,
3928 &vote_simulator.tbft_structs.heaviest_subtree_fork_choice,
3929 ),
3930 SwitchForkDecision::SwitchProof(Hash::default())
3931 );
3932 vote_simulator.latest_validator_votes_for_frozen_banks =
3933 LatestValidatorVotesForFrozenBanks::default();
3934 }
3935 }
3936}