1use {
4 crate::{
5 bank::{bank_hash_details, Bank, SquashTiming},
6 bank_hash_cache::DumpedSlotSubscription,
7 installed_scheduler_pool::{
8 BankWithScheduler, InstalledSchedulerPoolArc, SchedulingContext,
9 },
10 snapshot_controller::SnapshotController,
11 },
12 arc_swap::ArcSwap,
13 log::*,
14 solana_clock::{BankId, Slot},
15 solana_hash::Hash,
16 solana_measure::measure::Measure,
17 solana_program_runtime::loaded_programs::{BlockRelation, ForkGraph},
18 solana_unified_scheduler_logic::SchedulingMode,
19 std::{
20 collections::{hash_map::Entry, HashMap, HashSet},
21 ops::Index,
22 sync::{
23 atomic::{AtomicBool, AtomicU64, Ordering},
24 Arc, RwLock,
25 },
26 time::Instant,
27 },
28 thiserror::Error,
29};
30
31pub const MAX_ROOT_DISTANCE_FOR_VOTE_ONLY: Slot = 400;
32pub type AtomicSlot = AtomicU64;
33#[derive(Clone)]
34pub struct ReadOnlyAtomicSlot {
35 slot: Arc<AtomicSlot>,
36}
37
38impl ReadOnlyAtomicSlot {
39 pub fn get(&self) -> Slot {
40 self.slot.load(Ordering::Acquire)
44 }
45}
46
47#[derive(Clone)]
48pub struct SharableBank(Arc<ArcSwap<Bank>>);
49
50impl SharableBank {
51 pub fn load(&self) -> Arc<Bank> {
52 self.0.load_full()
53 }
54
55 fn store(&self, bank: Arc<Bank>) {
56 self.0.store(bank);
57 }
58}
59
60#[derive(Error, Debug)]
61pub enum SetRootError {}
62
63#[derive(Debug, Default, Copy, Clone)]
64struct SetRootMetrics {
65 timings: SetRootTimings,
66 total_parent_banks: i64,
67 tx_count: i64,
68 dropped_banks_len: i64,
69 accounts_data_len: i64,
70}
71
72#[derive(Debug, Default, Copy, Clone)]
73struct SetRootTimings {
74 total_squash_time: SquashTiming,
75 total_snapshot_ms: i64,
76 prune_non_rooted_ms: i64,
77 drop_parent_banks_ms: i64,
78 prune_slots_ms: i64,
79 prune_remove_ms: i64,
80}
81
82pub struct BankForks {
83 banks: HashMap<Slot, BankWithScheduler>,
84 descendants: HashMap<Slot, HashSet<Slot>>,
85 root: Arc<AtomicSlot>,
86 root_bank: SharableBank,
87 in_vote_only_mode: Arc<AtomicBool>,
88 highest_slot_at_startup: Slot,
89 scheduler_pool: Option<InstalledSchedulerPoolArc>,
90 dumped_slot_subscribers: Vec<DumpedSlotSubscription>,
91}
92
93impl Index<u64> for BankForks {
94 type Output = Arc<Bank>;
95 fn index(&self, bank_slot: Slot) -> &Self::Output {
96 &self.banks[&bank_slot]
97 }
98}
99
100impl BankForks {
101 pub fn new_rw_arc(root_bank: Bank) -> Arc<RwLock<Self>> {
102 let root_bank = Arc::new(root_bank);
103 let root_slot = root_bank.slot();
104
105 let mut banks = HashMap::new();
106 banks.insert(
107 root_slot,
108 BankWithScheduler::new_without_scheduler(root_bank.clone()),
109 );
110
111 let parents = root_bank.parents();
112 for parent in parents {
113 if banks
114 .insert(
115 parent.slot(),
116 BankWithScheduler::new_without_scheduler(parent.clone()),
117 )
118 .is_some()
119 {
120 break;
122 }
123 }
124
125 let mut descendants = HashMap::<_, HashSet<_>>::new();
126 descendants.entry(root_slot).or_default();
127 for parent in root_bank.proper_ancestors() {
128 descendants.entry(parent).or_default().insert(root_slot);
129 }
130
131 let bank_forks = Arc::new(RwLock::new(Self {
132 root: Arc::new(AtomicSlot::new(root_slot)),
133 root_bank: SharableBank(Arc::new(ArcSwap::from(Arc::clone(&root_bank)))),
134 banks,
135 descendants,
136 in_vote_only_mode: Arc::new(AtomicBool::new(false)),
137 highest_slot_at_startup: 0,
138 scheduler_pool: None,
139 dumped_slot_subscribers: vec![],
140 }));
141
142 root_bank.set_fork_graph_in_program_cache(Arc::downgrade(&bank_forks));
143 bank_forks
144 }
145
146 pub fn banks(&self) -> &HashMap<Slot, BankWithScheduler> {
147 &self.banks
148 }
149
150 pub fn get_vote_only_mode_signal(&self) -> Arc<AtomicBool> {
151 self.in_vote_only_mode.clone()
152 }
153
154 pub fn len(&self) -> usize {
155 self.banks.len()
156 }
157
158 pub fn is_empty(&self) -> bool {
159 self.banks.is_empty()
160 }
161
162 pub fn ancestors(&self) -> HashMap<Slot, HashSet<Slot>> {
164 let root = self.root();
165 self.banks
166 .iter()
167 .map(|(slot, bank)| {
168 let ancestors = bank.proper_ancestors().filter(|k| *k >= root);
169 (*slot, ancestors.collect())
170 })
171 .collect()
172 }
173
174 pub fn descendants(&self) -> HashMap<Slot, HashSet<Slot>> {
176 self.descendants.clone()
177 }
178
179 pub fn frozen_banks(&self) -> impl Iterator<Item = (Slot, Arc<Bank>)> + '_ {
180 self.banks
181 .iter()
182 .filter(|(_, b)| b.is_frozen())
183 .map(|(&k, b)| (k, b.clone_without_scheduler()))
184 }
185
186 pub fn active_bank_slots(&self) -> Vec<Slot> {
187 self.banks
188 .iter()
189 .filter(|(_, v)| !v.is_frozen())
190 .map(|(k, _v)| *k)
191 .collect()
192 }
193
194 pub fn get_with_scheduler(&self, bank_slot: Slot) -> Option<BankWithScheduler> {
195 self.banks.get(&bank_slot).map(|b| b.clone_with_scheduler())
196 }
197
198 pub fn get(&self, bank_slot: Slot) -> Option<Arc<Bank>> {
199 self.get_with_scheduler(bank_slot)
200 .map(|b| b.clone_without_scheduler())
201 }
202
203 pub fn get_with_checked_hash(
204 &self,
205 (bank_slot, expected_hash): (Slot, Hash),
206 ) -> Option<Arc<Bank>> {
207 let maybe_bank = self.get(bank_slot);
208 if let Some(bank) = &maybe_bank {
209 assert_eq!(bank.hash(), expected_hash);
210 }
211 maybe_bank
212 }
213
214 pub fn bank_hash(&self, slot: Slot) -> Option<Hash> {
215 self.get(slot).map(|bank| bank.hash())
216 }
217
218 pub fn sharable_root_bank(&self) -> SharableBank {
219 self.root_bank.clone()
220 }
221
222 pub fn root_bank(&self) -> Arc<Bank> {
223 self.root_bank.load()
224 }
225
226 pub fn install_scheduler_pool(&mut self, pool: InstalledSchedulerPoolArc) {
227 info!("Installed new scheduler_pool into bank_forks: {pool:?}");
228 assert!(
229 self.scheduler_pool.replace(pool).is_none(),
230 "Reinstalling scheduler pool isn't supported"
231 );
232 }
233
234 pub fn insert(&mut self, bank: Bank) -> BankWithScheduler {
235 self.insert_with_scheduling_mode(SchedulingMode::BlockVerification, bank)
236 }
237
238 pub fn insert_with_scheduling_mode(
239 &mut self,
240 mode: SchedulingMode,
241 mut bank: Bank,
242 ) -> BankWithScheduler {
243 if self.root.load(Ordering::Relaxed) < self.highest_slot_at_startup {
244 bank.set_check_program_modification_slot(true);
245 }
246
247 let bank = Arc::new(bank);
248 let bank = if let Some(scheduler_pool) = &self.scheduler_pool {
249 Self::install_scheduler_into_bank(scheduler_pool, mode, bank)
250 } else {
251 BankWithScheduler::new_without_scheduler(bank)
252 };
253 let prev = self.banks.insert(bank.slot(), bank.clone_with_scheduler());
254 assert!(prev.is_none());
255 let slot = bank.slot();
256 self.descendants.entry(slot).or_default();
257 for parent in bank.proper_ancestors() {
258 self.descendants.entry(parent).or_default().insert(slot);
259 }
260 bank
261 }
262
263 fn install_scheduler_into_bank(
264 scheduler_pool: &InstalledSchedulerPoolArc,
265 mode: SchedulingMode,
266 bank: Arc<Bank>,
267 ) -> BankWithScheduler {
268 let context = SchedulingContext::new_with_mode(mode, bank.clone());
269 let scheduler = scheduler_pool.take_scheduler(context);
270 let bank_with_scheduler = BankWithScheduler::new(bank, Some(scheduler));
271 if matches!(mode, SchedulingMode::BlockVerification) {
276 scheduler_pool.register_timeout_listener(bank_with_scheduler.create_timeout_listener());
277 }
278 bank_with_scheduler
279 }
280
281 pub fn insert_from_ledger(&mut self, bank: Bank) -> BankWithScheduler {
282 self.highest_slot_at_startup = std::cmp::max(self.highest_slot_at_startup, bank.slot());
283 self.insert(bank)
284 }
285
286 pub fn remove(&mut self, slot: Slot) -> Option<BankWithScheduler> {
287 let bank = self.banks.remove(&slot)?;
288 for parent in bank.proper_ancestors() {
289 let Entry::Occupied(mut entry) = self.descendants.entry(parent) else {
290 panic!("this should not happen!");
291 };
292 entry.get_mut().remove(&slot);
293 if entry.get().is_empty() && !self.banks.contains_key(&parent) {
294 entry.remove_entry();
295 }
296 }
297 let Entry::Occupied(entry) = self.descendants.entry(slot) else {
298 panic!("this should not happen!");
299 };
300 if entry.get().is_empty() {
301 entry.remove_entry();
302 }
303 Some(bank)
304 }
305
306 pub fn highest_slot(&self) -> Slot {
307 self.banks.values().map(|bank| bank.slot()).max().unwrap()
308 }
309
310 pub fn working_bank(&self) -> Arc<Bank> {
311 self[self.highest_slot()].clone()
312 }
313
314 pub fn working_bank_with_scheduler(&self) -> BankWithScheduler {
315 self.banks[&self.highest_slot()].clone_with_scheduler()
316 }
317
318 pub fn register_dumped_slot_subscriber(&mut self, notifier: DumpedSlotSubscription) {
321 self.dumped_slot_subscribers.push(notifier);
322 }
323
324 pub fn dump_slots<'a, I>(&mut self, slots: I) -> (Vec<(Slot, BankId)>, Vec<BankWithScheduler>)
326 where
327 I: Iterator<Item = &'a Slot>,
328 {
329 for subscriber in &self.dumped_slot_subscribers {
333 let mut lock = subscriber.lock().unwrap();
334 *lock = true;
335 }
336
337 slots
338 .map(|slot| {
339 let bank = self
341 .remove(*slot)
342 .expect("BankForks should not have been purged yet");
343 bank_hash_details::write_bank_hash_details_file(&bank)
344 .map_err(|err| {
345 warn!("Unable to write bank hash details file: {err}");
346 })
347 .ok();
348 ((*slot, bank.bank_id()), bank)
349 })
350 .unzip()
351 }
352
353 fn do_set_root_return_metrics(
354 &mut self,
355 root: Slot,
356 snapshot_controller: Option<&SnapshotController>,
357 highest_super_majority_root: Option<Slot>,
358 ) -> Result<(Vec<BankWithScheduler>, SetRootMetrics), SetRootError> {
359 let old_epoch = self.root_bank.load().epoch();
360
361 let root_bank = &self
362 .get(root)
363 .expect("root bank didn't exist in bank_forks");
364
365 self.root.store(root, Ordering::Release);
369 self.root_bank.store(Arc::clone(root_bank));
370
371 let new_epoch = root_bank.epoch();
372 if old_epoch != new_epoch {
373 info!(
374 "Root entering epoch: {new_epoch}, next_epoch_start_slot: {}, epoch_stakes: {:#?}",
375 root_bank
376 .epoch_schedule()
377 .get_first_slot_in_epoch(new_epoch + 1),
378 root_bank
379 .epoch_stakes(new_epoch)
380 .unwrap()
381 .node_id_to_vote_accounts()
382 );
383 info!(
386 "Clearing epoch rewards cache for epoch {old_epoch} after setting root to slot \
387 {root}"
388 );
389 root_bank.clear_epoch_rewards_cache();
390 }
391 let root_tx_count = root_bank
392 .parents()
393 .last()
394 .map(|bank| bank.transaction_count())
395 .unwrap_or(0);
396 let mut banks = vec![root_bank];
398 let parents = root_bank.parents();
399 banks.extend(parents.iter());
400 let total_parent_banks = banks.len();
401 let (is_root_bank_squashed, mut squash_timing, total_snapshot_ms) =
402 if let Some(snapshot_controller) = snapshot_controller {
403 snapshot_controller.handle_new_roots(root, &banks)?
404 } else {
405 (false, SquashTiming::default(), 0)
406 };
407
408 if !is_root_bank_squashed {
409 squash_timing += root_bank.squash();
410 }
411 let new_tx_count = root_bank.transaction_count();
412 let accounts_data_len = root_bank.load_accounts_data_size() as i64;
413 let mut prune_time = Measure::start("set_root::prune");
414 let (removed_banks, prune_slots_ms, prune_remove_ms) =
415 self.prune_non_rooted(root, highest_super_majority_root);
416 prune_time.stop();
417 let dropped_banks_len = removed_banks.len();
418
419 let mut drop_parent_banks_time = Measure::start("set_root::drop_banks");
420 drop(parents);
421 drop_parent_banks_time.stop();
422
423 Ok((
424 removed_banks,
425 SetRootMetrics {
426 timings: SetRootTimings {
427 total_squash_time: squash_timing,
428 total_snapshot_ms: total_snapshot_ms as i64,
429 prune_non_rooted_ms: prune_time.as_ms() as i64,
430 drop_parent_banks_ms: drop_parent_banks_time.as_ms() as i64,
431 prune_slots_ms: prune_slots_ms as i64,
432 prune_remove_ms: prune_remove_ms as i64,
433 },
434 total_parent_banks: total_parent_banks as i64,
435 tx_count: (new_tx_count - root_tx_count) as i64,
436 dropped_banks_len: dropped_banks_len as i64,
437 accounts_data_len,
438 },
439 ))
440 }
441
442 pub fn prune_program_cache(&self, root: Slot) {
443 if let Some(root_bank) = self.banks.get(&root) {
444 root_bank.prune_program_cache(root, root_bank.epoch());
445 }
446 }
447
448 pub fn set_root(
449 &mut self,
450 root: Slot,
451 snapshot_controller: Option<&SnapshotController>,
452 highest_super_majority_root: Option<Slot>,
453 ) -> Result<Vec<BankWithScheduler>, SetRootError> {
454 let program_cache_prune_start = Instant::now();
455 let set_root_start = Instant::now();
456 let (removed_banks, set_root_metrics) = self.do_set_root_return_metrics(
457 root,
458 snapshot_controller,
459 highest_super_majority_root,
460 )?;
461 datapoint_info!(
462 "bank-forks_set_root",
463 (
464 "elapsed_ms",
465 set_root_start.elapsed().as_millis() as usize,
466 i64
467 ),
468 ("slot", root, i64),
469 (
470 "total_parent_banks",
471 set_root_metrics.total_parent_banks,
472 i64
473 ),
474 ("total_banks", self.banks.len(), i64),
475 (
476 "total_squash_cache_ms",
477 set_root_metrics.timings.total_squash_time.squash_cache_ms,
478 i64
479 ),
480 (
481 "total_squash_accounts_ms",
482 set_root_metrics
483 .timings
484 .total_squash_time
485 .squash_accounts_ms,
486 i64
487 ),
488 (
489 "total_squash_accounts_index_ms",
490 set_root_metrics
491 .timings
492 .total_squash_time
493 .squash_accounts_index_ms,
494 i64
495 ),
496 (
497 "total_squash_accounts_cache_ms",
498 set_root_metrics
499 .timings
500 .total_squash_time
501 .squash_accounts_cache_ms,
502 i64
503 ),
504 (
505 "total_squash_accounts_store_ms",
506 set_root_metrics
507 .timings
508 .total_squash_time
509 .squash_accounts_store_ms,
510 i64
511 ),
512 (
513 "total_snapshot_ms",
514 set_root_metrics.timings.total_snapshot_ms,
515 i64
516 ),
517 ("tx_count", set_root_metrics.tx_count, i64),
518 (
519 "prune_non_rooted_ms",
520 set_root_metrics.timings.prune_non_rooted_ms,
521 i64
522 ),
523 (
524 "drop_parent_banks_ms",
525 set_root_metrics.timings.drop_parent_banks_ms,
526 i64
527 ),
528 (
529 "prune_slots_ms",
530 set_root_metrics.timings.prune_slots_ms,
531 i64
532 ),
533 (
534 "prune_remove_ms",
535 set_root_metrics.timings.prune_remove_ms,
536 i64
537 ),
538 (
539 "program_cache_prune_ms",
540 program_cache_prune_start.elapsed().as_millis() as i64,
541 i64
542 ),
543 ("dropped_banks_len", set_root_metrics.dropped_banks_len, i64),
544 ("accounts_data_len", set_root_metrics.accounts_data_len, i64),
545 );
546 Ok(removed_banks)
547 }
548
549 pub fn root(&self) -> Slot {
550 self.root.load(Ordering::Relaxed)
551 }
552
553 pub fn get_atomic_root(&self) -> ReadOnlyAtomicSlot {
555 ReadOnlyAtomicSlot {
556 slot: self.root.clone(),
557 }
558 }
559
560 fn prune_non_rooted(
611 &mut self,
612 root: Slot,
613 highest_super_majority_root: Option<Slot>,
614 ) -> (Vec<BankWithScheduler>, u64, u64) {
615 let mut prune_slots_time = Measure::start("prune_slots");
618 let highest_super_majority_root = highest_super_majority_root.unwrap_or(root);
619 let prune_slots: Vec<_> = self
620 .banks
621 .keys()
622 .copied()
623 .filter(|slot| {
624 let keep = *slot == root
625 || self.descendants[&root].contains(slot)
626 || (*slot < root
627 && *slot >= highest_super_majority_root
628 && self.descendants[slot].contains(&root));
629 !keep
630 })
631 .collect();
632 prune_slots_time.stop();
633
634 let mut prune_remove_time = Measure::start("prune_slots");
635 let removed_banks = prune_slots
636 .into_iter()
637 .filter_map(|slot| self.remove(slot))
638 .collect();
639 prune_remove_time.stop();
640
641 (
642 removed_banks,
643 prune_slots_time.as_ms(),
644 prune_remove_time.as_ms(),
645 )
646 }
647}
648
649impl ForkGraph for BankForks {
650 fn relationship(&self, a: Slot, b: Slot) -> BlockRelation {
651 let known_slot_range = self.root()..=self.highest_slot();
652 if known_slot_range.contains(&a) && known_slot_range.contains(&b) {
653 {
654 (a == b)
655 .then_some(BlockRelation::Equal)
656 .or_else(|| {
657 self.banks.get(&b).and_then(|bank| {
658 bank.ancestors
659 .contains_key(&a)
660 .then_some(BlockRelation::Ancestor)
661 })
662 })
663 .or_else(|| {
664 self.descendants.get(&b).and_then(|slots| {
665 slots.contains(&a).then_some(BlockRelation::Descendant)
666 })
667 })
668 .unwrap_or(BlockRelation::Unrelated)
669 }
670 } else {
671 BlockRelation::Unknown
672 }
673 }
674}
675
676impl Drop for BankForks {
677 fn drop(&mut self) {
678 info!("BankForks::drop(): started...");
679 self.banks.clear();
680
681 if let Some(scheduler_pool) = self.scheduler_pool.take() {
682 scheduler_pool.uninstalled_from_bank_forks();
683 }
684 info!("BankForks::drop(): ...finished");
685 }
686}
687
688#[cfg(test)]
689mod tests {
690 use {
691 super::*,
692 crate::{
693 bank::test_utils::update_vote_account_timestamp,
694 genesis_utils::{
695 create_genesis_config, create_genesis_config_with_leader, GenesisConfigInfo,
696 },
697 },
698 assert_matches::assert_matches,
699 solana_clock::UnixTimestamp,
700 solana_epoch_schedule::EpochSchedule,
701 solana_keypair::Keypair,
702 solana_pubkey::Pubkey,
703 solana_signer::Signer,
704 solana_vote_program::vote_state::BlockTimestamp,
705 };
706
707 #[test]
708 fn test_bank_forks_new_rw_arc_memory_leak() {
709 for _ in 0..1000 {
710 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
711 BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
712 }
713 }
714
715 #[test]
716 fn test_bank_forks_new() {
717 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
718 let bank = Bank::new_for_tests(&genesis_config);
719 let bank_forks = BankForks::new_rw_arc(bank);
720 let mut bank_forks = bank_forks.write().unwrap();
721 let child_bank = Bank::new_from_parent(bank_forks[0].clone(), &Pubkey::default(), 1);
722 child_bank.register_default_tick_for_test();
723 bank_forks.insert(child_bank);
724 assert_eq!(bank_forks[1u64].tick_height(), 1);
725 assert_eq!(bank_forks.working_bank().tick_height(), 1);
726 }
727
728 #[test]
729 fn test_bank_forks_descendants() {
730 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
731 let bank = Bank::new_for_tests(&genesis_config);
732 let bank_forks = BankForks::new_rw_arc(bank);
733 let mut bank_forks = bank_forks.write().unwrap();
734 let bank0 = bank_forks[0].clone();
735 let bank = Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 1);
736 bank_forks.insert(bank);
737 let bank = Bank::new_from_parent(bank0, &Pubkey::default(), 2);
738 bank_forks.insert(bank);
739 let descendants = bank_forks.descendants();
740 let children: HashSet<u64> = [1u64, 2u64].iter().copied().collect();
741 assert_eq!(children, *descendants.get(&0).unwrap());
742 assert!(descendants[&1].is_empty());
743 assert!(descendants[&2].is_empty());
744 }
745
746 #[test]
747 fn test_bank_forks_ancestors() {
748 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
749 let bank = Bank::new_for_tests(&genesis_config);
750 let bank_forks = BankForks::new_rw_arc(bank);
751 let mut bank_forks = bank_forks.write().unwrap();
752 let bank0 = bank_forks[0].clone();
753 let bank = Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 1);
754 bank_forks.insert(bank);
755 let bank = Bank::new_from_parent(bank0, &Pubkey::default(), 2);
756 bank_forks.insert(bank);
757 let ancestors = bank_forks.ancestors();
758 assert!(ancestors[&0].is_empty());
759 let parents: Vec<u64> = ancestors[&1].iter().cloned().collect();
760 assert_eq!(parents, vec![0]);
761 let parents: Vec<u64> = ancestors[&2].iter().cloned().collect();
762 assert_eq!(parents, vec![0]);
763 }
764
765 #[test]
766 fn test_bank_forks_frozen_banks() {
767 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
768 let bank = Bank::new_for_tests(&genesis_config);
769 let bank_forks = BankForks::new_rw_arc(bank);
770 let mut bank_forks = bank_forks.write().unwrap();
771 let bank0 = bank_forks[0].clone();
772 let child_bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
773 bank_forks.insert(child_bank);
774
775 let frozen_slots: HashSet<Slot> = bank_forks
776 .frozen_banks()
777 .map(|(slot, _bank)| slot)
778 .collect();
779 assert!(frozen_slots.contains(&0));
780 assert!(!frozen_slots.contains(&1));
781 }
782
783 #[test]
784 fn test_bank_forks_active_banks() {
785 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
786 let bank = Bank::new_for_tests(&genesis_config);
787 let bank_forks = BankForks::new_rw_arc(bank);
788 let mut bank_forks = bank_forks.write().unwrap();
789 let bank0 = bank_forks[0].clone();
790 let child_bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
791 bank_forks.insert(child_bank);
792 assert_eq!(bank_forks.active_bank_slots(), vec![1]);
793 }
794
795 #[test]
796 fn test_bank_forks_different_set_root() {
797 solana_logger::setup();
798 let leader_keypair = Keypair::new();
799 let GenesisConfigInfo {
800 mut genesis_config,
801 voting_keypair,
802 ..
803 } = create_genesis_config_with_leader(10_000, &leader_keypair.pubkey(), 1_000);
804 let slots_in_epoch = 32;
805 genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
806
807 let bank0 = Bank::new_for_tests(&genesis_config);
808 let bank_forks0 = BankForks::new_rw_arc(bank0);
809 let mut bank_forks0 = bank_forks0.write().unwrap();
810 bank_forks0.set_root(0, None, None).unwrap();
811
812 let bank1 = Bank::new_for_tests(&genesis_config);
813 let bank_forks1 = BankForks::new_rw_arc(bank1);
814 let mut bank_forks1 = bank_forks1.write().unwrap();
815
816 let additional_timestamp_secs = 2;
817
818 let num_slots = slots_in_epoch + 1; for slot in 1..num_slots {
820 let update_timestamp_case = slot == slots_in_epoch;
823
824 let child1 =
825 Bank::new_from_parent(bank_forks0[slot - 1].clone(), &Pubkey::default(), slot);
826 let child2 =
827 Bank::new_from_parent(bank_forks1[slot - 1].clone(), &Pubkey::default(), slot);
828
829 if update_timestamp_case {
830 for child in &[&child1, &child2] {
831 let recent_timestamp: UnixTimestamp = child.unix_timestamp_from_genesis();
832 update_vote_account_timestamp(
833 BlockTimestamp {
834 slot: child.slot(),
835 timestamp: recent_timestamp + additional_timestamp_secs,
836 },
837 child,
838 &voting_keypair.pubkey(),
839 );
840 }
841 }
842
843 bank_forks0.insert(child1);
845 bank_forks0.set_root(slot, None, None).unwrap();
846
847 bank_forks1.insert(child2);
849 }
850 let child1 = &bank_forks0.working_bank();
851 let child2 = &bank_forks1.working_bank();
852
853 child1.freeze();
854 child2.freeze();
855
856 info!("child0.ancestors: {:?}", child1.ancestors);
857 info!("child1.ancestors: {:?}", child2.ancestors);
858 assert_eq!(child1.hash(), child2.hash());
859 }
860
861 fn make_hash_map(data: Vec<(Slot, Vec<Slot>)>) -> HashMap<Slot, HashSet<Slot>> {
862 data.into_iter()
863 .map(|(k, v)| (k, v.into_iter().collect()))
864 .collect()
865 }
866
867 fn extend_bank_forks(bank_forks: Arc<RwLock<BankForks>>, parent_child_pairs: &[(Slot, Slot)]) {
868 for (parent, child) in parent_child_pairs.iter() {
869 let parent: Arc<Bank> = bank_forks.read().unwrap().banks[parent].clone();
870 bank_forks.write().unwrap().insert(Bank::new_from_parent(
871 parent,
872 &Pubkey::default(),
873 *child,
874 ));
875 }
876 }
877
878 #[test]
879 fn test_bank_forks_with_set_root() {
880 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
881 let bank = Bank::new_for_tests(&genesis_config);
882 let bank_forks = BankForks::new_rw_arc(bank);
883
884 let parent_child_pairs = vec![(0, 1), (1, 2), (0, 3), (3, 4)];
885 extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
886
887 assert_eq!(
888 bank_forks.read().unwrap().ancestors(),
889 make_hash_map(vec![
890 (0, vec![]),
891 (1, vec![0]),
892 (2, vec![0, 1]),
893 (3, vec![0]),
894 (4, vec![0, 3]),
895 ])
896 );
897 assert_eq!(
898 bank_forks.read().unwrap().descendants(),
899 make_hash_map(vec![
900 (0, vec![1, 2, 3, 4]),
901 (1, vec![2]),
902 (2, vec![]),
903 (3, vec![4]),
904 (4, vec![]),
905 ])
906 );
907 bank_forks
908 .write()
909 .unwrap()
910 .set_root(
911 2, None, None, )
915 .unwrap();
916 bank_forks.read().unwrap().get(2).unwrap().squash();
917 assert_eq!(
918 bank_forks.read().unwrap().ancestors(),
919 make_hash_map(vec![(2, vec![]),])
920 );
921 assert_eq!(
922 bank_forks.read().unwrap().descendants(),
923 make_hash_map(vec![(0, vec![2]), (1, vec![2]), (2, vec![]),])
924 );
925
926 let parent_child_pairs = vec![(2, 5), (5, 6)];
927 extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
928 assert_eq!(
929 bank_forks.read().unwrap().ancestors(),
930 make_hash_map(vec![(2, vec![]), (5, vec![2]), (6, vec![2, 5])])
931 );
932 assert_eq!(
933 bank_forks.read().unwrap().descendants(),
934 make_hash_map(vec![
935 (0, vec![2]),
936 (1, vec![2]),
937 (2, vec![5, 6]),
938 (5, vec![6]),
939 (6, vec![])
940 ])
941 );
942 }
943
944 #[test]
945 fn test_bank_forks_with_highest_super_majority_root() {
946 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
947 let bank = Bank::new_for_tests(&genesis_config);
948 assert_eq!(bank.slot(), 0);
949 let bank_forks = BankForks::new_rw_arc(bank);
950
951 let parent_child_pairs = vec![(0, 1), (1, 2), (0, 3), (3, 4)];
952 extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
953
954 assert_eq!(
955 bank_forks.read().unwrap().ancestors(),
956 make_hash_map(vec![
957 (0, vec![]),
958 (1, vec![0]),
959 (2, vec![0, 1]),
960 (3, vec![0]),
961 (4, vec![0, 3]),
962 ])
963 );
964 assert_eq!(
965 bank_forks.read().unwrap().descendants(),
966 make_hash_map(vec![
967 (0, vec![1, 2, 3, 4]),
968 (1, vec![2]),
969 (2, vec![]),
970 (3, vec![4]),
971 (4, vec![]),
972 ])
973 );
974 bank_forks
975 .write()
976 .unwrap()
977 .set_root(
978 2,
979 None, Some(1), )
982 .unwrap();
983 bank_forks.read().unwrap().get(2).unwrap().squash();
984 assert_eq!(
985 bank_forks.read().unwrap().ancestors(),
986 make_hash_map(vec![(1, vec![]), (2, vec![]),])
987 );
988 assert_eq!(
989 bank_forks.read().unwrap().descendants(),
990 make_hash_map(vec![(0, vec![1, 2]), (1, vec![2]), (2, vec![]),])
991 );
992
993 let parent_child_pairs = vec![(2, 5), (5, 6)];
994 extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
995 assert_eq!(
996 bank_forks.read().unwrap().ancestors(),
997 make_hash_map(vec![
998 (1, vec![]),
999 (2, vec![]),
1000 (5, vec![2]),
1001 (6, vec![2, 5])
1002 ])
1003 );
1004 assert_eq!(
1005 bank_forks.read().unwrap().descendants(),
1006 make_hash_map(vec![
1007 (0, vec![1, 2]),
1008 (1, vec![2]),
1009 (2, vec![5, 6]),
1010 (5, vec![6]),
1011 (6, vec![])
1012 ])
1013 );
1014 }
1015
1016 #[test]
1017 fn test_fork_graph() {
1018 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
1019 let bank = Bank::new_for_tests(&genesis_config);
1020 let bank_forks = BankForks::new_rw_arc(bank);
1021
1022 let parent_child_pairs = vec![
1023 (0, 1),
1024 (1, 3),
1025 (3, 8),
1026 (0, 2),
1027 (2, 4),
1028 (4, 5),
1029 (5, 10),
1030 (4, 6),
1031 (6, 12),
1032 ];
1033 extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
1034
1035 let mut bank_forks = bank_forks.write().unwrap();
1046 assert_matches!(bank_forks.relationship(0, 3), BlockRelation::Ancestor);
1047 assert_matches!(bank_forks.relationship(0, 10), BlockRelation::Ancestor);
1048 assert_matches!(bank_forks.relationship(0, 12), BlockRelation::Ancestor);
1049 assert_matches!(bank_forks.relationship(1, 3), BlockRelation::Ancestor);
1050 assert_matches!(bank_forks.relationship(2, 10), BlockRelation::Ancestor);
1051 assert_matches!(bank_forks.relationship(2, 12), BlockRelation::Ancestor);
1052 assert_matches!(bank_forks.relationship(4, 10), BlockRelation::Ancestor);
1053 assert_matches!(bank_forks.relationship(4, 12), BlockRelation::Ancestor);
1054 assert_matches!(bank_forks.relationship(6, 10), BlockRelation::Unrelated);
1055 assert_matches!(bank_forks.relationship(5, 12), BlockRelation::Unrelated);
1056 assert_matches!(bank_forks.relationship(6, 12), BlockRelation::Ancestor);
1057
1058 assert_matches!(bank_forks.relationship(6, 2), BlockRelation::Descendant);
1059 assert_matches!(bank_forks.relationship(10, 2), BlockRelation::Descendant);
1060 assert_matches!(bank_forks.relationship(8, 3), BlockRelation::Descendant);
1061 assert_matches!(bank_forks.relationship(6, 3), BlockRelation::Unrelated);
1062 assert_matches!(bank_forks.relationship(12, 2), BlockRelation::Descendant);
1063 assert_matches!(bank_forks.relationship(12, 1), BlockRelation::Unrelated);
1064 assert_matches!(bank_forks.relationship(1, 2), BlockRelation::Unrelated);
1065
1066 assert_matches!(bank_forks.relationship(1, 13), BlockRelation::Unknown);
1067 assert_matches!(bank_forks.relationship(13, 2), BlockRelation::Unknown);
1068 bank_forks
1069 .set_root(
1070 2,
1071 None, Some(1), )
1074 .unwrap();
1075 assert_matches!(bank_forks.relationship(1, 2), BlockRelation::Unknown);
1076 assert_matches!(bank_forks.relationship(2, 0), BlockRelation::Unknown);
1077 }
1078}