atlas_vote_interface/state/
vote_state_1_14_11.rs

1use super::*;
2#[cfg(feature = "dev-context-only-utils")]
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    atlas_frozen_abi_macro::frozen_abi(digest = "2rjXSWaNeAdoUNJDC5otC7NPR1qXHvLMuAs5faE4DPEt"),
11    derive(atlas_frozen_abi_macro::AbiExample)
12)]
13#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
14#[derive(Debug, Default, PartialEq, Eq, Clone)]
15#[cfg_attr(feature = "dev-context-only-utils", derive(Arbitrary))]
16pub struct VoteState1_14_11 {
17    /// the node that votes in this account
18    pub node_pubkey: Pubkey,
19
20    /// the signer for withdrawals
21    pub authorized_withdrawer: Pubkey,
22    /// percentage (0-100) that represents what part of a rewards
23    ///  payout should be given to this VoteAccount
24    pub commission: u8,
25
26    pub votes: VecDeque<Lockout>,
27
28    // This usually the last Lockout which was popped from self.votes.
29    // However, it can be arbitrary slot, when being used inside Tower
30    pub root_slot: Option<Slot>,
31
32    /// the signer for vote transactions
33    pub authorized_voters: AuthorizedVoters,
34
35    /// history of prior authorized voters and the epochs for which
36    /// they were set, the bottom end of the range is inclusive,
37    /// the top of the range is exclusive
38    pub prior_voters: CircBuf<(Pubkey, Epoch, Epoch)>,
39
40    /// history of how many credits earned by the end of each epoch
41    ///  each tuple is (Epoch, credits, prev_credits)
42    pub epoch_credits: Vec<(Epoch, u64, u64)>,
43
44    /// most recent timestamp submitted with a vote
45    pub last_timestamp: BlockTimestamp,
46}
47
48impl VoteState1_14_11 {
49    pub fn get_rent_exempt_reserve(rent: &Rent) -> u64 {
50        rent.minimum_balance(Self::size_of())
51    }
52
53    /// Upper limit on the size of the Vote State
54    /// when votes.len() is MAX_LOCKOUT_HISTORY.
55    pub fn size_of() -> usize {
56        3731 // see test_vote_state_size_of
57    }
58
59    pub fn is_uninitialized(&self) -> bool {
60        self.authorized_voters.is_empty()
61    }
62
63    pub fn is_correct_size_and_initialized(data: &[u8]) -> bool {
64        const VERSION_OFFSET: usize = 4;
65        const DEFAULT_PRIOR_VOTERS_END: usize = VERSION_OFFSET + DEFAULT_PRIOR_VOTERS_OFFSET;
66        data.len() == VoteState1_14_11::size_of()
67            && data[VERSION_OFFSET..DEFAULT_PRIOR_VOTERS_END] != [0; DEFAULT_PRIOR_VOTERS_OFFSET]
68    }
69}
70
71impl From<VoteStateV3> for VoteState1_14_11 {
72    fn from(vote_state: VoteStateV3) -> Self {
73        Self {
74            node_pubkey: vote_state.node_pubkey,
75            authorized_withdrawer: vote_state.authorized_withdrawer,
76            commission: vote_state.commission,
77            votes: vote_state
78                .votes
79                .into_iter()
80                .map(|landed_vote| landed_vote.into())
81                .collect(),
82            root_slot: vote_state.root_slot,
83            authorized_voters: vote_state.authorized_voters,
84            prior_voters: vote_state.prior_voters,
85            epoch_credits: vote_state.epoch_credits,
86            last_timestamp: vote_state.last_timestamp,
87        }
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use {super::*, core::mem::MaybeUninit};
94
95    #[test]
96    fn test_vote_deserialize_1_14_11() {
97        // base case
98        let target_vote_state = VoteState1_14_11::default();
99        let target_vote_state_versions = VoteStateVersions::V1_14_11(Box::new(target_vote_state));
100        let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
101
102        // v3
103        let mut test_vote_state_v3 = MaybeUninit::uninit();
104        VoteStateV3::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state_v3).unwrap();
105        let test_vote_state = unsafe { test_vote_state_v3.assume_init() };
106
107        assert_eq!(
108            target_vote_state_versions
109                .clone()
110                .try_convert_to_v3()
111                .unwrap(),
112            test_vote_state
113        );
114
115        // v4
116        let vote_pubkey = Pubkey::new_unique();
117        let mut test_vote_state_v4 = MaybeUninit::uninit();
118        VoteStateV4::deserialize_into_uninit(
119            &vote_state_buf,
120            &mut test_vote_state_v4,
121            &vote_pubkey,
122        )
123        .unwrap();
124        let test_vote_state = unsafe { test_vote_state_v4.assume_init() };
125
126        assert_eq!(
127            target_vote_state_versions
128                .try_convert_to_v4(&vote_pubkey)
129                .unwrap(),
130            test_vote_state
131        );
132
133        // variant
134        // provide 4x the minimum struct size in bytes to ensure we typically touch every field
135        let struct_bytes_x4 = std::mem::size_of::<VoteState1_14_11>() * 4;
136        for _ in 0..1000 {
137            let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
138            let mut unstructured = Unstructured::new(&raw_data);
139
140            let arbitrary_vote_state = VoteState1_14_11::arbitrary(&mut unstructured).unwrap();
141            let target_vote_state_versions =
142                VoteStateVersions::V1_14_11(Box::new(arbitrary_vote_state));
143
144            // v3
145            let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
146            let target_vote_state_v3 = target_vote_state_versions
147                .clone()
148                .try_convert_to_v3()
149                .unwrap();
150
151            let mut test_vote_state_v3 = MaybeUninit::uninit();
152            VoteStateV3::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state_v3).unwrap();
153            let test_vote_state = unsafe { test_vote_state_v3.assume_init() };
154
155            assert_eq!(target_vote_state_v3, test_vote_state);
156
157            // v4
158            let vote_pubkey = Pubkey::new_unique();
159            let target_vote_state_v4 = target_vote_state_versions
160                .try_convert_to_v4(&vote_pubkey)
161                .unwrap();
162
163            let mut test_vote_state_v4 = MaybeUninit::uninit();
164            VoteStateV4::deserialize_into_uninit(
165                &vote_state_buf,
166                &mut test_vote_state_v4,
167                &vote_pubkey,
168            )
169            .unwrap();
170            let test_vote_state = unsafe { test_vote_state_v4.assume_init() };
171
172            assert_eq!(target_vote_state_v4, test_vote_state);
173        }
174    }
175}