1use {
4 crate::{
5 accounts_background_service::{AbsRequestSender, SnapshotRequest},
6 bank::Bank,
7 snapshot_config::SnapshotConfig,
8 },
9 log::*,
10 safecoin_measure::measure::Measure,
11 solana_sdk::{clock::Slot, hash::Hash, timing},
12 std::{
13 collections::{hash_map::Entry, HashMap, HashSet},
14 ops::Index,
15 sync::{atomic::AtomicBool, Arc},
16 time::Instant,
17 },
18};
19
20pub const MAX_ROOT_DISTANCE_FOR_VOTE_ONLY: Slot = 400;
21
22#[derive(Debug, Default, Copy, Clone)]
23struct SetRootMetrics {
24 timings: SetRootTimings,
25 total_parent_banks: i64,
26 tx_count: i64,
27 dropped_banks_len: i64,
28 accounts_data_len: i64,
29}
30
31#[derive(Debug, Default, Copy, Clone)]
32struct SetRootTimings {
33 total_squash_cache_ms: i64,
34 total_squash_accounts_ms: i64,
35 total_squash_accounts_index_ms: i64,
36 total_squash_accounts_cache_ms: i64,
37 total_squash_accounts_store_ms: i64,
38 total_snapshot_ms: i64,
39 prune_non_rooted_ms: i64,
40 drop_parent_banks_ms: i64,
41 prune_slots_ms: i64,
42 prune_remove_ms: i64,
43}
44
45pub struct BankForks {
46 banks: HashMap<Slot, Arc<Bank>>,
47 descendants: HashMap<Slot, HashSet<Slot>>,
48 root: Slot,
49 pub snapshot_config: Option<SnapshotConfig>,
50
51 pub accounts_hash_interval_slots: Slot,
52 last_accounts_hash_slot: Slot,
53 in_vote_only_mode: Arc<AtomicBool>,
54}
55
56impl Index<u64> for BankForks {
57 type Output = Arc<Bank>;
58 fn index(&self, bank_slot: Slot) -> &Self::Output {
59 &self.banks[&bank_slot]
60 }
61}
62
63impl BankForks {
64 pub fn new(bank: Bank) -> Self {
65 let root = bank.slot();
66 Self::new_from_banks(&[Arc::new(bank)], root)
67 }
68
69 pub fn banks(&self) -> HashMap<Slot, Arc<Bank>> {
70 self.banks.clone()
71 }
72
73 pub fn get_vote_only_mode_signal(&self) -> Arc<AtomicBool> {
74 self.in_vote_only_mode.clone()
75 }
76
77 pub fn len(&self) -> usize {
78 self.banks.len()
79 }
80
81 pub fn is_empty(&self) -> bool {
82 self.banks.is_empty()
83 }
84
85 pub fn ancestors(&self) -> HashMap<Slot, HashSet<Slot>> {
87 let root = self.root;
88 self.banks
89 .iter()
90 .map(|(slot, bank)| {
91 let ancestors = bank.proper_ancestors().filter(|k| *k >= root);
92 (*slot, ancestors.collect())
93 })
94 .collect()
95 }
96
97 pub fn descendants(&self) -> HashMap<Slot, HashSet<Slot>> {
99 self.descendants.clone()
100 }
101
102 pub fn frozen_banks(&self) -> HashMap<Slot, Arc<Bank>> {
103 self.banks
104 .iter()
105 .filter(|(_, b)| b.is_frozen())
106 .map(|(k, b)| (*k, b.clone()))
107 .collect()
108 }
109
110 pub fn active_bank_slots(&self) -> Vec<Slot> {
111 self.banks
112 .iter()
113 .filter(|(_, v)| !v.is_frozen())
114 .map(|(k, _v)| *k)
115 .collect()
116 }
117
118 pub fn get(&self, bank_slot: Slot) -> Option<Arc<Bank>> {
119 self.banks.get(&bank_slot).cloned()
120 }
121
122 pub fn get_with_checked_hash(
123 &self,
124 (bank_slot, expected_hash): (Slot, Hash),
125 ) -> Option<Arc<Bank>> {
126 let maybe_bank = self.get(bank_slot);
127 if let Some(bank) = &maybe_bank {
128 assert_eq!(bank.hash(), expected_hash);
129 }
130 maybe_bank
131 }
132
133 pub fn bank_hash(&self, slot: Slot) -> Option<Hash> {
134 self.get(slot).map(|bank| bank.hash())
135 }
136
137 pub fn root_bank(&self) -> Arc<Bank> {
138 self[self.root()].clone()
139 }
140
141 pub fn new_from_banks(initial_forks: &[Arc<Bank>], root: Slot) -> Self {
142 let mut banks = HashMap::new();
143
144 for bank in initial_forks {
146 banks.insert(bank.slot(), bank.clone());
147 let parents = bank.parents();
148 for parent in parents {
149 if banks.insert(parent.slot(), parent.clone()).is_some() {
150 break;
152 }
153 }
154 }
155 let mut descendants = HashMap::<_, HashSet<_>>::new();
156 for (slot, bank) in &banks {
157 descendants.entry(*slot).or_default();
158 for parent in bank.proper_ancestors() {
159 descendants.entry(parent).or_default().insert(*slot);
160 }
161 }
162 Self {
163 root,
164 banks,
165 descendants,
166 snapshot_config: None,
167 accounts_hash_interval_slots: std::u64::MAX,
168 last_accounts_hash_slot: root,
169 in_vote_only_mode: Arc::new(AtomicBool::new(false)),
170 }
171 }
172
173 pub fn insert(&mut self, bank: Bank) -> Arc<Bank> {
174 let bank = Arc::new(bank);
175 let prev = self.banks.insert(bank.slot(), bank.clone());
176 assert!(prev.is_none());
177 let slot = bank.slot();
178 self.descendants.entry(slot).or_default();
179 for parent in bank.proper_ancestors() {
180 self.descendants.entry(parent).or_default().insert(slot);
181 }
182 bank
183 }
184
185 pub fn remove(&mut self, slot: Slot) -> Option<Arc<Bank>> {
186 let bank = self.banks.remove(&slot)?;
187 for parent in bank.proper_ancestors() {
188 let mut entry = match self.descendants.entry(parent) {
189 Entry::Vacant(_) => panic!("this should not happen!"),
190 Entry::Occupied(entry) => entry,
191 };
192 entry.get_mut().remove(&slot);
193 if entry.get().is_empty() && !self.banks.contains_key(&parent) {
194 entry.remove_entry();
195 }
196 }
197 let entry = match self.descendants.entry(slot) {
198 Entry::Vacant(_) => panic!("this should not happen!"),
199 Entry::Occupied(entry) => entry,
200 };
201 if entry.get().is_empty() {
202 entry.remove_entry();
203 }
204 Some(bank)
205 }
206
207 pub fn highest_slot(&self) -> Slot {
208 self.banks.values().map(|bank| bank.slot()).max().unwrap()
209 }
210
211 pub fn working_bank(&self) -> Arc<Bank> {
212 self[self.highest_slot()].clone()
213 }
214
215 fn do_set_root_return_metrics(
216 &mut self,
217 root: Slot,
218 accounts_background_request_sender: &AbsRequestSender,
219 highest_confirmed_root: Option<Slot>,
220 ) -> (Vec<Arc<Bank>>, SetRootMetrics) {
221 let old_epoch = self.root_bank().epoch();
222 self.root = root;
223 let root_bank = self
224 .banks
225 .get(&root)
226 .expect("root bank didn't exist in bank_forks");
227 let new_epoch = root_bank.epoch();
228 if old_epoch != new_epoch {
229 info!(
230 "Root entering
231 epoch: {},
232 next_epoch_start_slot: {},
233 epoch_stakes: {:#?}",
234 new_epoch,
235 root_bank
236 .epoch_schedule()
237 .get_first_slot_in_epoch(new_epoch + 1),
238 root_bank
239 .epoch_stakes(new_epoch)
240 .unwrap()
241 .node_id_to_vote_accounts()
242 );
243 }
244 let root_tx_count = root_bank
245 .parents()
246 .last()
247 .map(|bank| bank.transaction_count())
248 .unwrap_or(0);
249 let mut is_root_bank_squashed = false;
251 let mut banks = vec![root_bank];
252 let parents = root_bank.parents();
253 banks.extend(parents.iter());
254 let total_parent_banks = banks.len();
255 let mut total_squash_accounts_ms = 0;
256 let mut total_squash_accounts_index_ms = 0;
257 let mut total_squash_accounts_cache_ms = 0;
258 let mut total_squash_accounts_store_ms = 0;
259 let mut total_squash_cache_ms = 0;
260 let mut total_snapshot_ms = 0;
261 for bank in banks.iter() {
262 let bank_slot = bank.slot();
263 if bank.block_height() % self.accounts_hash_interval_slots == 0
264 && bank_slot > self.last_accounts_hash_slot
265 {
266 self.last_accounts_hash_slot = bank_slot;
267 let squash_timing = bank.squash();
268 total_squash_accounts_ms += squash_timing.squash_accounts_ms as i64;
269 total_squash_accounts_index_ms += squash_timing.squash_accounts_index_ms as i64;
270 total_squash_accounts_cache_ms += squash_timing.squash_accounts_cache_ms as i64;
271 total_squash_accounts_store_ms += squash_timing.squash_accounts_store_ms as i64;
272 total_squash_cache_ms += squash_timing.squash_cache_ms as i64;
273 is_root_bank_squashed = bank_slot == root;
274
275 let mut snapshot_time = Measure::start("squash::snapshot_time");
276 if self.snapshot_config.is_some()
277 && accounts_background_request_sender.is_snapshot_creation_enabled()
278 {
279 let snapshot_root_bank = self.root_bank();
280 let root_slot = snapshot_root_bank.slot();
281 if snapshot_root_bank.is_startup_verification_complete() {
282 let status_cache_slot_deltas = snapshot_root_bank
285 .status_cache
286 .read()
287 .unwrap()
288 .root_slot_deltas();
289 if let Err(e) = accounts_background_request_sender.send_snapshot_request(
290 SnapshotRequest {
291 snapshot_root_bank,
292 status_cache_slot_deltas,
293 },
294 ) {
295 warn!(
296 "Error sending snapshot request for bank: {}, err: {:?}",
297 root_slot, e
298 );
299 }
300 } else {
301 info!("Not sending snapshot request for bank: {}, startup verification is incomplete", root_slot);
302 }
303 }
304 snapshot_time.stop();
305 total_snapshot_ms += snapshot_time.as_ms() as i64;
306 break;
307 }
308 }
309 if !is_root_bank_squashed {
310 let squash_timing = root_bank.squash();
311 total_squash_accounts_ms += squash_timing.squash_accounts_ms as i64;
312 total_squash_accounts_index_ms += squash_timing.squash_accounts_index_ms as i64;
313 total_squash_accounts_cache_ms += squash_timing.squash_accounts_cache_ms as i64;
314 total_squash_accounts_store_ms += squash_timing.squash_accounts_store_ms as i64;
315 total_squash_cache_ms += squash_timing.squash_cache_ms as i64;
316 }
317 let new_tx_count = root_bank.transaction_count();
318 let accounts_data_len = root_bank.load_accounts_data_size() as i64;
319 let mut prune_time = Measure::start("set_root::prune");
320 let (removed_banks, prune_slots_ms, prune_remove_ms) =
321 self.prune_non_rooted(root, highest_confirmed_root);
322 prune_time.stop();
323 let dropped_banks_len = removed_banks.len();
324
325 let mut drop_parent_banks_time = Measure::start("set_root::drop_banks");
326 drop(parents);
327 drop_parent_banks_time.stop();
328
329 (
330 removed_banks,
331 SetRootMetrics {
332 timings: SetRootTimings {
333 total_squash_cache_ms,
334 total_squash_accounts_ms,
335 total_squash_accounts_index_ms,
336 total_squash_accounts_cache_ms,
337 total_squash_accounts_store_ms,
338 total_snapshot_ms,
339 prune_non_rooted_ms: prune_time.as_ms() as i64,
340 drop_parent_banks_ms: drop_parent_banks_time.as_ms() as i64,
341 prune_slots_ms: prune_slots_ms as i64,
342 prune_remove_ms: prune_remove_ms as i64,
343 },
344 total_parent_banks: total_parent_banks as i64,
345 tx_count: (new_tx_count - root_tx_count) as i64,
346 dropped_banks_len: dropped_banks_len as i64,
347 accounts_data_len,
348 },
349 )
350 }
351
352 pub fn set_root(
353 &mut self,
354 root: Slot,
355 accounts_background_request_sender: &AbsRequestSender,
356 highest_confirmed_root: Option<Slot>,
357 ) -> Vec<Arc<Bank>> {
358 let set_root_start = Instant::now();
359 let (removed_banks, set_root_metrics) = self.do_set_root_return_metrics(
360 root,
361 accounts_background_request_sender,
362 highest_confirmed_root,
363 );
364 datapoint_info!(
365 "bank-forks_set_root",
366 (
367 "elapsed_ms",
368 timing::duration_as_ms(&set_root_start.elapsed()) as usize,
369 i64
370 ),
371 ("slot", root, i64),
372 (
373 "total_parent_banks",
374 set_root_metrics.total_parent_banks,
375 i64
376 ),
377 ("total_banks", self.banks.len(), i64),
378 (
379 "total_squash_cache_ms",
380 set_root_metrics.timings.total_squash_cache_ms,
381 i64
382 ),
383 (
384 "total_squash_accounts_ms",
385 set_root_metrics.timings.total_squash_accounts_ms,
386 i64
387 ),
388 (
389 "total_squash_accounts_index_ms",
390 set_root_metrics.timings.total_squash_accounts_index_ms,
391 i64
392 ),
393 (
394 "total_squash_accounts_cache_ms",
395 set_root_metrics.timings.total_squash_accounts_cache_ms,
396 i64
397 ),
398 (
399 "total_squash_accounts_store_ms",
400 set_root_metrics.timings.total_squash_accounts_store_ms,
401 i64
402 ),
403 (
404 "total_snapshot_ms",
405 set_root_metrics.timings.total_snapshot_ms,
406 i64
407 ),
408 ("tx_count", set_root_metrics.tx_count, i64),
409 (
410 "prune_non_rooted_ms",
411 set_root_metrics.timings.prune_non_rooted_ms,
412 i64
413 ),
414 (
415 "drop_parent_banks_ms",
416 set_root_metrics.timings.drop_parent_banks_ms,
417 i64
418 ),
419 (
420 "prune_slots_ms",
421 set_root_metrics.timings.prune_slots_ms,
422 i64
423 ),
424 (
425 "prune_remove_ms",
426 set_root_metrics.timings.prune_remove_ms,
427 i64
428 ),
429 ("dropped_banks_len", set_root_metrics.dropped_banks_len, i64),
430 ("accounts_data_len", set_root_metrics.accounts_data_len, i64),
431 );
432 removed_banks
433 }
434
435 pub fn root(&self) -> Slot {
436 self.root
437 }
438
439 fn prune_non_rooted(
490 &mut self,
491 root: Slot,
492 highest_confirmed_root: Option<Slot>,
493 ) -> (Vec<Arc<Bank>>, u64, u64) {
494 #![allow(clippy::needless_collect)]
498 let mut prune_slots_time = Measure::start("prune_slots");
499 let highest_confirmed_root = highest_confirmed_root.unwrap_or(root);
500 let prune_slots: Vec<_> = self
501 .banks
502 .keys()
503 .copied()
504 .filter(|slot| {
505 let keep = *slot == root
506 || self.descendants[&root].contains(slot)
507 || (*slot < root
508 && *slot >= highest_confirmed_root
509 && self.descendants[slot].contains(&root));
510 !keep
511 })
512 .collect();
513 prune_slots_time.stop();
514
515 let mut prune_remove_time = Measure::start("prune_slots");
516 let removed_banks = prune_slots
517 .into_iter()
518 .filter_map(|slot| self.remove(slot))
519 .collect();
520 prune_remove_time.stop();
521
522 (
523 removed_banks,
524 prune_slots_time.as_ms(),
525 prune_remove_time.as_ms(),
526 )
527 }
528
529 pub fn set_snapshot_config(&mut self, snapshot_config: Option<SnapshotConfig>) {
530 self.snapshot_config = snapshot_config;
531 }
532
533 pub fn set_accounts_hash_interval_slots(&mut self, accounts_interval_slots: u64) {
534 self.accounts_hash_interval_slots = accounts_interval_slots;
535 }
536}
537
538#[cfg(test)]
539mod tests {
540 use {
541 super::*,
542 crate::{
543 bank::tests::update_vote_account_timestamp,
544 genesis_utils::{
545 create_genesis_config, create_genesis_config_with_leader, GenesisConfigInfo,
546 },
547 },
548 solana_sdk::{
549 clock::UnixTimestamp,
550 hash::Hash,
551 pubkey::Pubkey,
552 signature::{Keypair, Signer},
553 sysvar::epoch_schedule::EpochSchedule,
554 },
555 solana_vote_program::vote_state::BlockTimestamp,
556 };
557
558 #[test]
559 fn test_bank_forks_new() {
560 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
561 let bank = Bank::new_for_tests(&genesis_config);
562 let mut bank_forks = BankForks::new(bank);
563 let child_bank = Bank::new_from_parent(&bank_forks[0u64], &Pubkey::default(), 1);
564 child_bank.register_tick(&Hash::default());
565 bank_forks.insert(child_bank);
566 assert_eq!(bank_forks[1u64].tick_height(), 1);
567 assert_eq!(bank_forks.working_bank().tick_height(), 1);
568 }
569
570 #[test]
571 fn test_bank_forks_new_from_banks() {
572 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
573 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
574 let child_bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 1));
575
576 let bank_forks = BankForks::new_from_banks(&[bank.clone(), child_bank.clone()], 0);
577 assert_eq!(bank_forks.root(), 0);
578 assert_eq!(bank_forks.working_bank().slot(), 1);
579
580 let bank_forks = BankForks::new_from_banks(&[child_bank, bank], 0);
581 assert_eq!(bank_forks.root(), 0);
582 assert_eq!(bank_forks.working_bank().slot(), 1);
583 }
584
585 #[test]
586 fn test_bank_forks_descendants() {
587 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
588 let bank = Bank::new_for_tests(&genesis_config);
589 let mut bank_forks = BankForks::new(bank);
590 let bank0 = bank_forks[0].clone();
591 let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
592 bank_forks.insert(bank);
593 let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
594 bank_forks.insert(bank);
595 let descendants = bank_forks.descendants();
596 let children: HashSet<u64> = [1u64, 2u64].iter().copied().collect();
597 assert_eq!(children, *descendants.get(&0).unwrap());
598 assert!(descendants[&1].is_empty());
599 assert!(descendants[&2].is_empty());
600 }
601
602 #[test]
603 fn test_bank_forks_ancestors() {
604 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
605 let bank = Bank::new_for_tests(&genesis_config);
606 let mut bank_forks = BankForks::new(bank);
607 let bank0 = bank_forks[0].clone();
608 let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
609 bank_forks.insert(bank);
610 let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
611 bank_forks.insert(bank);
612 let ancestors = bank_forks.ancestors();
613 assert!(ancestors[&0].is_empty());
614 let parents: Vec<u64> = ancestors[&1].iter().cloned().collect();
615 assert_eq!(parents, vec![0]);
616 let parents: Vec<u64> = ancestors[&2].iter().cloned().collect();
617 assert_eq!(parents, vec![0]);
618 }
619
620 #[test]
621 fn test_bank_forks_frozen_banks() {
622 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
623 let bank = Bank::new_for_tests(&genesis_config);
624 let mut bank_forks = BankForks::new(bank);
625 let child_bank = Bank::new_from_parent(&bank_forks[0u64], &Pubkey::default(), 1);
626 bank_forks.insert(child_bank);
627 assert!(bank_forks.frozen_banks().get(&0).is_some());
628 assert!(bank_forks.frozen_banks().get(&1).is_none());
629 }
630
631 #[test]
632 fn test_bank_forks_active_banks() {
633 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
634 let bank = Bank::new_for_tests(&genesis_config);
635 let mut bank_forks = BankForks::new(bank);
636 let child_bank = Bank::new_from_parent(&bank_forks[0u64], &Pubkey::default(), 1);
637 bank_forks.insert(child_bank);
638 assert_eq!(bank_forks.active_bank_slots(), vec![1]);
639 }
640
641 #[test]
642 fn test_bank_forks_different_set_root() {
643 solana_logger::setup();
644 let leader_keypair = Keypair::new();
645 let GenesisConfigInfo {
646 mut genesis_config,
647 voting_keypair,
648 ..
649 } = create_genesis_config_with_leader(10_000, &leader_keypair.pubkey(), 1_000);
650 let slots_in_epoch = 32;
651 genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
652
653 let bank0 = Bank::new_for_tests(&genesis_config);
654 let mut bank_forks0 = BankForks::new(bank0);
655 bank_forks0.set_root(0, &AbsRequestSender::default(), None);
656
657 let bank1 = Bank::new_for_tests(&genesis_config);
658 let mut bank_forks1 = BankForks::new(bank1);
659
660 let additional_timestamp_secs = 2;
661
662 let num_slots = slots_in_epoch + 1; for slot in 1..num_slots {
664 let update_timestamp_case = slot == slots_in_epoch;
667
668 let child1 = Bank::new_from_parent(&bank_forks0[slot - 1], &Pubkey::default(), slot);
669 let child2 = Bank::new_from_parent(&bank_forks1[slot - 1], &Pubkey::default(), slot);
670
671 if update_timestamp_case {
672 for child in &[&child1, &child2] {
673 let recent_timestamp: UnixTimestamp = child.unix_timestamp_from_genesis();
674 update_vote_account_timestamp(
675 BlockTimestamp {
676 slot: child.slot(),
677 timestamp: recent_timestamp + additional_timestamp_secs,
678 },
679 child,
680 &voting_keypair.pubkey(),
681 );
682 }
683 }
684
685 bank_forks0.insert(child1);
687 bank_forks0.set_root(slot, &AbsRequestSender::default(), None);
688
689 bank_forks1.insert(child2);
691 }
692 let child1 = &bank_forks0.working_bank();
693 let child2 = &bank_forks1.working_bank();
694
695 child1.freeze();
696 child2.freeze();
697
698 info!("child0.ancestors: {:?}", child1.ancestors);
699 info!("child1.ancestors: {:?}", child2.ancestors);
700 assert_eq!(child1.hash(), child2.hash());
701 }
702
703 fn make_hash_map(data: Vec<(Slot, Vec<Slot>)>) -> HashMap<Slot, HashSet<Slot>> {
704 data.into_iter()
705 .map(|(k, v)| (k, v.into_iter().collect()))
706 .collect()
707 }
708
709 #[test]
710 fn test_bank_forks_with_set_root() {
711 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
712 let mut banks = vec![Arc::new(Bank::new_for_tests(&genesis_config))];
713 assert_eq!(banks[0].slot(), 0);
714 let mut bank_forks = BankForks::new_from_banks(&banks, 0);
715 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[0], &Pubkey::default(), 1)));
716 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[1], &Pubkey::default(), 2)));
717 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[0], &Pubkey::default(), 3)));
718 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[3], &Pubkey::default(), 4)));
719 assert_eq!(
720 bank_forks.ancestors(),
721 make_hash_map(vec![
722 (0, vec![]),
723 (1, vec![0]),
724 (2, vec![0, 1]),
725 (3, vec![0]),
726 (4, vec![0, 3]),
727 ])
728 );
729 assert_eq!(
730 bank_forks.descendants(),
731 make_hash_map(vec![
732 (0, vec![1, 2, 3, 4]),
733 (1, vec![2]),
734 (2, vec![]),
735 (3, vec![4]),
736 (4, vec![]),
737 ])
738 );
739 bank_forks.set_root(
740 2,
741 &AbsRequestSender::default(),
742 None, );
744 banks[2].squash();
745 assert_eq!(bank_forks.ancestors(), make_hash_map(vec![(2, vec![]),]));
746 assert_eq!(
747 bank_forks.descendants(),
748 make_hash_map(vec![(0, vec![2]), (1, vec![2]), (2, vec![]),])
749 );
750 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[2], &Pubkey::default(), 5)));
751 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[5], &Pubkey::default(), 6)));
752 assert_eq!(
753 bank_forks.ancestors(),
754 make_hash_map(vec![(2, vec![]), (5, vec![2]), (6, vec![2, 5])])
755 );
756 assert_eq!(
757 bank_forks.descendants(),
758 make_hash_map(vec![
759 (0, vec![2]),
760 (1, vec![2]),
761 (2, vec![5, 6]),
762 (5, vec![6]),
763 (6, vec![])
764 ])
765 );
766 }
767
768 #[test]
769 fn test_bank_forks_with_highest_confirmed_root() {
770 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
771 let mut banks = vec![Arc::new(Bank::new_for_tests(&genesis_config))];
772 assert_eq!(banks[0].slot(), 0);
773 let mut bank_forks = BankForks::new_from_banks(&banks, 0);
774 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[0], &Pubkey::default(), 1)));
775 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[1], &Pubkey::default(), 2)));
776 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[0], &Pubkey::default(), 3)));
777 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[3], &Pubkey::default(), 4)));
778 assert_eq!(
779 bank_forks.ancestors(),
780 make_hash_map(vec![
781 (0, vec![]),
782 (1, vec![0]),
783 (2, vec![0, 1]),
784 (3, vec![0]),
785 (4, vec![0, 3]),
786 ])
787 );
788 assert_eq!(
789 bank_forks.descendants(),
790 make_hash_map(vec![
791 (0, vec![1, 2, 3, 4]),
792 (1, vec![2]),
793 (2, vec![]),
794 (3, vec![4]),
795 (4, vec![]),
796 ])
797 );
798 bank_forks.set_root(
799 2,
800 &AbsRequestSender::default(),
801 Some(1), );
803 banks[2].squash();
804 assert_eq!(
805 bank_forks.ancestors(),
806 make_hash_map(vec![(1, vec![]), (2, vec![]),])
807 );
808 assert_eq!(
809 bank_forks.descendants(),
810 make_hash_map(vec![(0, vec![1, 2]), (1, vec![2]), (2, vec![]),])
811 );
812 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[2], &Pubkey::default(), 5)));
813 banks.push(bank_forks.insert(Bank::new_from_parent(&banks[5], &Pubkey::default(), 6)));
814 assert_eq!(
815 bank_forks.ancestors(),
816 make_hash_map(vec![
817 (1, vec![]),
818 (2, vec![]),
819 (5, vec![2]),
820 (6, vec![2, 5])
821 ])
822 );
823 assert_eq!(
824 bank_forks.descendants(),
825 make_hash_map(vec![
826 (0, vec![1, 2]),
827 (1, vec![2]),
828 (2, vec![5, 6]),
829 (5, vec![6]),
830 (6, vec![])
831 ])
832 );
833 }
834}