solana_vote_interface/state/
vote_state_versions.rs

1#[cfg(test)]
2use arbitrary::{Arbitrary, Unstructured};
3use {
4    crate::{
5        authorized_voters::AuthorizedVoters,
6        state::{
7            vote_state_0_23_5::VoteState0_23_5, vote_state_1_14_11::VoteState1_14_11, CircBuf,
8            LandedVote, Lockout, VoteState,
9        },
10    },
11    solana_pubkey::Pubkey,
12    std::collections::VecDeque,
13};
14
15#[cfg_attr(
16    feature = "serde",
17    derive(serde_derive::Deserialize, serde_derive::Serialize)
18)]
19#[derive(Debug, PartialEq, Eq, Clone)]
20pub enum VoteStateVersions {
21    V0_23_5(Box<VoteState0_23_5>),
22    V1_14_11(Box<VoteState1_14_11>),
23    Current(Box<VoteState>),
24}
25
26impl VoteStateVersions {
27    pub fn new_current(vote_state: VoteState) -> Self {
28        Self::Current(Box::new(vote_state))
29    }
30
31    pub fn convert_to_current(self) -> VoteState {
32        match self {
33            VoteStateVersions::V0_23_5(state) => {
34                let authorized_voters =
35                    AuthorizedVoters::new(state.authorized_voter_epoch, state.authorized_voter);
36
37                VoteState {
38                    node_pubkey: state.node_pubkey,
39
40                    authorized_withdrawer: state.authorized_withdrawer,
41
42                    commission: state.commission,
43
44                    votes: Self::landed_votes_from_lockouts(state.votes),
45
46                    root_slot: state.root_slot,
47
48                    authorized_voters,
49
50                    prior_voters: CircBuf::default(),
51
52                    epoch_credits: state.epoch_credits.clone(),
53
54                    last_timestamp: state.last_timestamp.clone(),
55                }
56            }
57
58            VoteStateVersions::V1_14_11(state) => VoteState {
59                node_pubkey: state.node_pubkey,
60                authorized_withdrawer: state.authorized_withdrawer,
61                commission: state.commission,
62
63                votes: Self::landed_votes_from_lockouts(state.votes),
64
65                root_slot: state.root_slot,
66
67                authorized_voters: state.authorized_voters.clone(),
68
69                prior_voters: state.prior_voters,
70
71                epoch_credits: state.epoch_credits,
72
73                last_timestamp: state.last_timestamp,
74            },
75
76            VoteStateVersions::Current(state) => *state,
77        }
78    }
79
80    fn landed_votes_from_lockouts(lockouts: VecDeque<Lockout>) -> VecDeque<LandedVote> {
81        lockouts.into_iter().map(|lockout| lockout.into()).collect()
82    }
83
84    pub fn is_uninitialized(&self) -> bool {
85        match self {
86            VoteStateVersions::V0_23_5(vote_state) => {
87                vote_state.authorized_voter == Pubkey::default()
88            }
89
90            VoteStateVersions::V1_14_11(vote_state) => vote_state.authorized_voters.is_empty(),
91
92            VoteStateVersions::Current(vote_state) => vote_state.authorized_voters.is_empty(),
93        }
94    }
95
96    pub fn vote_state_size_of(is_current: bool) -> usize {
97        if is_current {
98            VoteState::size_of()
99        } else {
100            VoteState1_14_11::size_of()
101        }
102    }
103
104    pub fn is_correct_size_and_initialized(data: &[u8]) -> bool {
105        VoteState::is_correct_size_and_initialized(data)
106            || VoteState1_14_11::is_correct_size_and_initialized(data)
107    }
108}
109
110#[cfg(test)]
111impl Arbitrary<'_> for VoteStateVersions {
112    fn arbitrary(u: &mut Unstructured<'_>) -> arbitrary::Result<Self> {
113        let variant = u.choose_index(2)?;
114        match variant {
115            0 => Ok(Self::Current(Box::new(VoteState::arbitrary(u)?))),
116            1 => Ok(Self::V1_14_11(Box::new(VoteState1_14_11::arbitrary(u)?))),
117            _ => unreachable!(),
118        }
119    }
120}