solana_program/vote/
authorized_voters.rs

1#[cfg(test)]
2use arbitrary::Arbitrary;
3use {
4    crate::pubkey::Pubkey,
5    serde_derive::{Deserialize, Serialize},
6    solana_clock::Epoch,
7    std::collections::BTreeMap,
8};
9
10#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
11#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)]
12#[cfg_attr(test, derive(Arbitrary))]
13pub struct AuthorizedVoters {
14    authorized_voters: BTreeMap<Epoch, Pubkey>,
15}
16
17impl AuthorizedVoters {
18    pub fn new(epoch: Epoch, pubkey: Pubkey) -> Self {
19        let mut authorized_voters = BTreeMap::new();
20        authorized_voters.insert(epoch, pubkey);
21        Self { authorized_voters }
22    }
23
24    pub fn get_authorized_voter(&self, epoch: Epoch) -> Option<Pubkey> {
25        self.get_or_calculate_authorized_voter_for_epoch(epoch)
26            .map(|(pubkey, _)| pubkey)
27    }
28
29    pub fn get_and_cache_authorized_voter_for_epoch(&mut self, epoch: Epoch) -> Option<Pubkey> {
30        let res = self.get_or_calculate_authorized_voter_for_epoch(epoch);
31
32        res.map(|(pubkey, existed)| {
33            if !existed {
34                self.authorized_voters.insert(epoch, pubkey);
35            }
36            pubkey
37        })
38    }
39
40    pub fn insert(&mut self, epoch: Epoch, authorized_voter: Pubkey) {
41        self.authorized_voters.insert(epoch, authorized_voter);
42    }
43
44    pub fn purge_authorized_voters(&mut self, current_epoch: Epoch) -> bool {
45        // Iterate through the keys in order, filtering out the ones
46        // less than the current epoch
47        let expired_keys: Vec<_> = self
48            .authorized_voters
49            .range(0..current_epoch)
50            .map(|(authorized_epoch, _)| *authorized_epoch)
51            .collect();
52
53        for key in expired_keys {
54            self.authorized_voters.remove(&key);
55        }
56
57        // Have to uphold this invariant b/c this is
58        // 1) The check for whether the vote state is initialized
59        // 2) How future authorized voters for uninitialized epochs are set
60        //    by this function
61        assert!(!self.authorized_voters.is_empty());
62        true
63    }
64
65    pub fn is_empty(&self) -> bool {
66        self.authorized_voters.is_empty()
67    }
68
69    pub fn first(&self) -> Option<(&u64, &Pubkey)> {
70        self.authorized_voters.iter().next()
71    }
72
73    pub fn last(&self) -> Option<(&u64, &Pubkey)> {
74        self.authorized_voters.iter().next_back()
75    }
76
77    pub fn len(&self) -> usize {
78        self.authorized_voters.len()
79    }
80
81    pub fn contains(&self, epoch: Epoch) -> bool {
82        self.authorized_voters.contains_key(&epoch)
83    }
84
85    pub fn iter(&self) -> std::collections::btree_map::Iter<Epoch, Pubkey> {
86        self.authorized_voters.iter()
87    }
88
89    // Returns the authorized voter at the given epoch if the epoch is >= the
90    // current epoch, and a bool indicating whether the entry for this epoch
91    // exists in the self.authorized_voter map
92    fn get_or_calculate_authorized_voter_for_epoch(&self, epoch: Epoch) -> Option<(Pubkey, bool)> {
93        let res = self.authorized_voters.get(&epoch);
94        if res.is_none() {
95            // If no authorized voter has been set yet for this epoch,
96            // this must mean the authorized voter remains unchanged
97            // from the latest epoch before this one
98            let res = self.authorized_voters.range(0..epoch).next_back();
99
100            /*
101            if res.is_none() {
102                warn!(
103                    "Tried to query for the authorized voter of an epoch earlier
104                    than the current epoch. Earlier epochs have been purged"
105                );
106            }
107            */
108
109            res.map(|(_, pubkey)| (*pubkey, false))
110        } else {
111            res.map(|pubkey| (*pubkey, true))
112        }
113    }
114}