solana_runtime/
bank_forks.rs

1//! The `bank_forks` module implements BankForks a DAG of checkpointed Banks
2
3use {
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    /// Create a map of bank slot id to the set of ancestors for the bank slot.
86    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    /// Create a map of bank slot id to the set of all of its descendants
98    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        // Iterate through the heads of all the different forks
145        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                    // All ancestors have already been inserted by another fork
151                    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        // Calculate the accounts hash at a fixed interval
250        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                        // Save off the status cache because these may get pruned if another
283                        // `set_root()` is called before the snapshots package can be generated
284                        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    /// After setting a new root, prune the banks that are no longer on rooted paths
440    ///
441    /// Given the following banks and slots...
442    ///
443    /// ```text
444    /// slot 6                   * (G)
445    ///                         /
446    /// slot 5        (F)  *   /
447    ///                    |  /
448    /// slot 4    (E) *    | /
449    ///               |    |/
450    /// slot 3        |    * (D) <-- root, from set_root()
451    ///               |    |
452    /// slot 2    (C) *    |
453    ///                \   |
454    /// slot 1          \  * (B)
455    ///                  \ |
456    /// slot 0             * (A)  <-- highest confirmed root [1]
457    /// ```
458    ///
459    /// ...where (D) is set as root, clean up (C) and (E), since they are not rooted.
460    ///
461    /// (A) is kept because it is greater-than-or-equal-to the highest confirmed root, and (D) is
462    ///     one of its descendants
463    /// (B) is kept for the same reason as (A)
464    /// (C) is pruned since it is a lower slot than (D), but (D) is _not_ one of its descendants
465    /// (D) is kept since it is the root
466    /// (E) is pruned since it is not a descendant of (D)
467    /// (F) is kept since it is a descendant of (D)
468    /// (G) is kept for the same reason as (F)
469    ///
470    /// and in table form...
471    ///
472    /// ```text
473    ///       |          |  is root a  | is a descendant ||
474    ///  slot | is root? | descendant? |    of root?     || keep?
475    /// ------+----------+-------------+-----------------++-------
476    ///   (A) |     N    |      Y      |        N        ||   Y
477    ///   (B) |     N    |      Y      |        N        ||   Y
478    ///   (C) |     N    |      N      |        N        ||   N
479    ///   (D) |     Y    |      N      |        N        ||   Y
480    ///   (E) |     N    |      N      |        N        ||   N
481    ///   (F) |     N    |      N      |        Y        ||   Y
482    ///   (G) |     N    |      N      |        Y        ||   Y
483    /// ```
484    ///
485    /// [1] RPC has the concept of commitment level, which is based on the highest confirmed root,
486    /// i.e. the cluster-confirmed root.  This commitment is stronger than the local node's root.
487    /// So (A) and (B) are kept to facilitate RPC at different commitment levels.  Everything below
488    /// the highest confirmed root can be pruned.
489    fn prune_non_rooted(
490        &mut self,
491        root: Slot,
492        highest_confirmed_root: Option<Slot>,
493    ) -> (Vec<Arc<Bank>>, u64, u64) {
494        // Clippy doesn't like separating the two collects below,
495        // but we want to collect timing separately, and the 2nd requires
496        // a unique borrow to self which is already borrowed by self.banks
497        #![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; // Advance past first epoch boundary
663        for slot in 1..num_slots {
664            // Just after the epoch boundary, timestamp a vote that will shift
665            // Clock::unix_timestamp from Bank::unix_timestamp_from_genesis()
666            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            // Set root in bank_forks0 to truncate the ancestor history
686            bank_forks0.insert(child1);
687            bank_forks0.set_root(slot, &AbsRequestSender::default(), None);
688
689            // Don't set root in bank_forks1 to keep the ancestor history
690            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, // highest confirmed root
743        );
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), // highest confirmed root
802        );
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}