Skip to main content

arch_program/vote/
state.rs

1use std::collections::BTreeMap;
2
3use crate::pubkey::Pubkey;
4
5#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
6pub struct VoteInit {
7    node_pubkey: Pubkey,
8    node_pubkey_parity_even: bool,
9    authority: Pubkey,
10    commission: u8,
11}
12
13impl VoteInit {
14    pub fn new(
15        node_pubkey: Pubkey,
16        node_pubkey_parity_even: bool,
17        authority: Pubkey,
18        commission: u8,
19    ) -> Self {
20        Self {
21            node_pubkey,
22            node_pubkey_parity_even,
23            authority,
24            commission,
25        }
26    }
27
28    pub const fn size_of() -> usize {
29        32 + 1 + 32 + 32 + 1
30    }
31}
32
33#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
34pub struct VoteState {
35    /// the node that votes in this account
36    pub node_pubkey: Pubkey,
37
38    /// If the public key parity if even/odd.
39    pub node_pubkey_parity_even: bool,
40
41    /// the signer for withdrawals
42    pub authority: Pubkey,
43
44    /// percentage (0-100) that represents what part of a rewards
45    ///  payout should be given to this VoteAccount
46    pub commission: u8,
47}
48
49impl VoteState {
50    pub fn new(vote_init: &VoteInit) -> Self {
51        Self {
52            node_pubkey: vote_init.node_pubkey,
53            node_pubkey_parity_even: vote_init.node_pubkey_parity_even,
54            authority: vote_init.authority,
55            commission: vote_init.commission,
56        }
57    }
58
59    pub const fn size_of_new() -> usize {
60        32 + 1 + 32 + 1
61    }
62
63    pub fn serialize(&self) -> Vec<u8> {
64        bincode::serialize(self).unwrap()
65    }
66
67    pub fn deserialize(data: &[u8]) -> Self {
68        bincode::deserialize(data).unwrap()
69    }
70
71    /// Returns the node public key in compressed format.
72    pub fn node_pubkey_serialized(&self) -> [u8; 33] {
73        let mut ret = [0_u8; 33];
74        if self.node_pubkey_parity_even {
75            ret[0] = 0x02;
76        } else {
77            ret[0] = 0x03;
78        }
79        ret[1..].copy_from_slice(&self.node_pubkey.serialize()[..]);
80        ret
81    }
82}
83
84#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)]
85pub struct AuthorizedVoters {
86    authorized_voters: BTreeMap<u64, Pubkey>,
87}
88
89impl AuthorizedVoters {
90    pub fn new(epoch: u64, pubkey: Pubkey) -> Self {
91        let mut authorized_voters = BTreeMap::new();
92        authorized_voters.insert(epoch, pubkey);
93        Self { authorized_voters }
94    }
95
96    pub fn get_authorized_voter(&self, epoch: u64) -> Option<Pubkey> {
97        self.get_or_calculate_authorized_voter_for_epoch(epoch)
98            .map(|(pubkey, _)| pubkey)
99    }
100
101    pub fn get_and_cache_authorized_voter_for_epoch(&mut self, epoch: u64) -> Option<Pubkey> {
102        let res = self.get_or_calculate_authorized_voter_for_epoch(epoch);
103
104        res.map(|(pubkey, existed)| {
105            if !existed {
106                self.authorized_voters.insert(epoch, pubkey);
107            }
108            pubkey
109        })
110    }
111
112    pub fn insert(&mut self, epoch: u64, authorized_voter: Pubkey) {
113        self.authorized_voters.insert(epoch, authorized_voter);
114    }
115
116    pub fn purge_authorized_voters(&mut self, current_epoch: u64) -> bool {
117        // Iterate through the keys in order, filtering out the ones
118        // less than the current epoch
119        let expired_keys: Vec<_> = self
120            .authorized_voters
121            .range(0..current_epoch)
122            .map(|(authorized_epoch, _)| *authorized_epoch)
123            .collect();
124
125        for key in expired_keys {
126            self.authorized_voters.remove(&key);
127        }
128
129        // Have to uphold this invariant b/c this is
130        // 1) The check for whether the vote state is initialized
131        // 2) How future authorized voters for uninitialized epochs are set
132        //    by this function
133        assert!(!self.authorized_voters.is_empty());
134        true
135    }
136
137    pub fn is_empty(&self) -> bool {
138        self.authorized_voters.is_empty()
139    }
140
141    pub fn first(&self) -> Option<(&u64, &Pubkey)> {
142        self.authorized_voters.iter().next()
143    }
144
145    pub fn last(&self) -> Option<(&u64, &Pubkey)> {
146        self.authorized_voters.iter().next_back()
147    }
148
149    pub fn len(&self) -> usize {
150        self.authorized_voters.len()
151    }
152
153    pub fn contains(&self, epoch: u64) -> bool {
154        self.authorized_voters.contains_key(&epoch)
155    }
156
157    pub fn iter(&self) -> std::collections::btree_map::Iter<'_, u64, Pubkey> {
158        self.authorized_voters.iter()
159    }
160
161    // Returns the authorized voter at the given epoch if the epoch is >= the
162    // current epoch, and a bool indicating whether the entry for this epoch
163    // exists in the self.authorized_voter map
164    fn get_or_calculate_authorized_voter_for_epoch(&self, epoch: u64) -> Option<(Pubkey, bool)> {
165        let res = self.authorized_voters.get(&epoch);
166        if res.is_none() {
167            // If no authorized voter has been set yet for this epoch,
168            // this must mean the authorized voter remains unchanged
169            // from the latest epoch before this one
170            let res = self.authorized_voters.range(0..epoch).next_back();
171
172            /*
173            if res.is_none() {
174                warn!(
175                    "Tried to query for the authorized voter of an epoch earlier
176                    than the current epoch. Earlier epochs have been purged"
177                );
178            }
179            */
180
181            res.map(|(_, pubkey)| (*pubkey, false))
182        } else {
183            res.map(|pubkey| (*pubkey, true))
184        }
185    }
186}