solana_program/vote/state/
vote_state_1_14_11.rs

1use super::*;
2#[cfg(test)]
3use arbitrary::Arbitrary;
4
5// Offset used for VoteState version 1_14_11
6const DEFAULT_PRIOR_VOTERS_OFFSET: usize = 82;
7
8#[cfg_attr(
9    feature = "frozen-abi",
10    frozen_abi(digest = "64duaG8iUgwmgMM9y1Pdi8S9jBGoPcjS5HrE8RRfsxJJ"),
11    derive(AbiExample)
12)]
13#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone)]
14#[cfg_attr(test, derive(Arbitrary))]
15pub struct VoteState1_14_11 {
16    /// the node that votes in this account
17    pub node_pubkey: Pubkey,
18
19    /// the signer for withdrawals
20    pub authorized_withdrawer: Pubkey,
21    /// percentage (0-100) that represents what part of a rewards
22    ///  payout should be given to this VoteAccount
23    pub commission: u8,
24
25    pub votes: VecDeque<Lockout>,
26
27    // This usually the last Lockout which was popped from self.votes.
28    // However, it can be arbitrary slot, when being used inside Tower
29    pub root_slot: Option<Slot>,
30
31    /// the signer for vote transactions
32    pub authorized_voters: AuthorizedVoters,
33
34    /// history of prior authorized voters and the epochs for which
35    /// they were set, the bottom end of the range is inclusive,
36    /// the top of the range is exclusive
37    pub prior_voters: CircBuf<(Pubkey, Epoch, Epoch)>,
38
39    /// history of how many credits earned by the end of each epoch
40    ///  each tuple is (Epoch, credits, prev_credits)
41    pub epoch_credits: Vec<(Epoch, u64, u64)>,
42
43    /// most recent timestamp submitted with a vote
44    pub last_timestamp: BlockTimestamp,
45}
46
47impl VoteState1_14_11 {
48    pub fn get_rent_exempt_reserve(rent: &Rent) -> u64 {
49        rent.minimum_balance(Self::size_of())
50    }
51
52    /// Upper limit on the size of the Vote State
53    /// when votes.len() is MAX_LOCKOUT_HISTORY.
54    pub fn size_of() -> usize {
55        3731 // see test_vote_state_size_of
56    }
57
58    pub fn is_correct_size_and_initialized(data: &[u8]) -> bool {
59        const VERSION_OFFSET: usize = 4;
60        const DEFAULT_PRIOR_VOTERS_END: usize = VERSION_OFFSET + DEFAULT_PRIOR_VOTERS_OFFSET;
61        data.len() == VoteState1_14_11::size_of()
62            && data[VERSION_OFFSET..DEFAULT_PRIOR_VOTERS_END] != [0; DEFAULT_PRIOR_VOTERS_OFFSET]
63    }
64}
65
66impl From<VoteState> for VoteState1_14_11 {
67    fn from(vote_state: VoteState) -> Self {
68        Self {
69            node_pubkey: vote_state.node_pubkey,
70            authorized_withdrawer: vote_state.authorized_withdrawer,
71            commission: vote_state.commission,
72            votes: vote_state
73                .votes
74                .into_iter()
75                .map(|landed_vote| landed_vote.into())
76                .collect(),
77            root_slot: vote_state.root_slot,
78            authorized_voters: vote_state.authorized_voters,
79            prior_voters: vote_state.prior_voters,
80            epoch_credits: vote_state.epoch_credits,
81            last_timestamp: vote_state.last_timestamp,
82        }
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_vote_deserialize_1_14_11() {
92        // base case
93        let target_vote_state = VoteState1_14_11::default();
94        let target_vote_state_versions = VoteStateVersions::V1_14_11(Box::new(target_vote_state));
95        let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
96
97        let mut test_vote_state = MaybeUninit::uninit();
98        VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
99        let test_vote_state = unsafe { test_vote_state.assume_init() };
100
101        assert_eq!(
102            target_vote_state_versions.convert_to_current(),
103            test_vote_state
104        );
105
106        // variant
107        // provide 4x the minimum struct size in bytes to ensure we typically touch every field
108        let struct_bytes_x4 = std::mem::size_of::<VoteState1_14_11>() * 4;
109        for _ in 0..1000 {
110            let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
111            let mut unstructured = Unstructured::new(&raw_data);
112
113            let arbitrary_vote_state = VoteState1_14_11::arbitrary(&mut unstructured).unwrap();
114            let target_vote_state_versions =
115                VoteStateVersions::V1_14_11(Box::new(arbitrary_vote_state));
116
117            let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
118            let target_vote_state = target_vote_state_versions.convert_to_current();
119
120            let mut test_vote_state = MaybeUninit::uninit();
121            VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
122            let test_vote_state = unsafe { test_vote_state.assume_init() };
123
124            assert_eq!(target_vote_state, test_vote_state);
125        }
126    }
127}