atlas_vote_interface/state/
vote_state_v4.rs1#[cfg(feature = "bincode")]
2use super::VoteStateVersions;
3#[cfg(feature = "dev-context-only-utils")]
4use arbitrary::Arbitrary;
5#[cfg(feature = "serde")]
6use serde_derive::{Deserialize, Serialize};
7#[cfg(feature = "serde")]
8use serde_with::serde_as;
9#[cfg(feature = "frozen-abi")]
10use atlas_frozen_abi_macro::{frozen_abi, AbiExample};
11#[cfg(any(target_os = "atlas", feature = "bincode"))]
12use atlas_instruction::error::InstructionError;
13use {
14 super::{BlockTimestamp, LandedVote, BLS_PUBLIC_KEY_COMPRESSED_SIZE},
15 crate::authorized_voters::AuthorizedVoters,
16 atlas_clock::{Epoch, Slot},
17 atlas_pubkey::Pubkey,
18 std::{collections::VecDeque, fmt::Debug},
19};
20
21#[cfg_attr(
22 feature = "frozen-abi",
23 frozen_abi(digest = "2H9WgTh7LgdnpinvEwxzP3HF6SDuKp6qdwFmJk9jHDRP"),
24 derive(AbiExample)
25)]
26#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
27#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
28#[derive(Debug, Default, PartialEq, Eq, Clone)]
29#[cfg_attr(feature = "dev-context-only-utils", derive(Arbitrary))]
30pub struct VoteStateV4 {
31 pub node_pubkey: Pubkey,
33 pub authorized_withdrawer: Pubkey,
35
36 pub inflation_rewards_collector: Pubkey,
38 pub block_revenue_collector: Pubkey,
40
41 pub inflation_rewards_commission_bps: u16,
44 pub block_revenue_commission_bps: u16,
47
48 pub pending_delegator_rewards: u64,
50
51 #[cfg_attr(
53 feature = "serde",
54 serde_as(as = "Option<[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]>")
55 )]
56 pub bls_pubkey_compressed: Option<[u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE]>,
57
58 pub votes: VecDeque<LandedVote>,
59 pub root_slot: Option<Slot>,
60
61 pub authorized_voters: AuthorizedVoters,
64
65 pub epoch_credits: Vec<(Epoch, u64, u64)>,
68
69 pub last_timestamp: BlockTimestamp,
71}
72
73impl VoteStateV4 {
74 pub const fn size_of() -> usize {
77 3762 }
79
80 #[cfg(any(target_os = "atlas", feature = "bincode"))]
81 pub fn deserialize(input: &[u8], vote_pubkey: &Pubkey) -> Result<Self, InstructionError> {
82 let mut vote_state = Self::default();
83 Self::deserialize_into(input, &mut vote_state, vote_pubkey)?;
84 Ok(vote_state)
85 }
86
87 #[cfg(any(target_os = "atlas", feature = "bincode"))]
95 pub fn deserialize_into(
96 input: &[u8],
97 vote_state: &mut VoteStateV4,
98 vote_pubkey: &Pubkey,
99 ) -> Result<(), InstructionError> {
100 use super::vote_state_deserialize;
101 vote_state_deserialize::deserialize_into(input, vote_state, |input, vote_state| {
102 Self::deserialize_into_ptr(input, vote_state, vote_pubkey)
103 })
104 }
105
106 #[cfg(any(target_os = "atlas", feature = "bincode"))]
118 pub fn deserialize_into_uninit(
119 input: &[u8],
120 vote_state: &mut std::mem::MaybeUninit<VoteStateV4>,
121 vote_pubkey: &Pubkey,
122 ) -> Result<(), InstructionError> {
123 Self::deserialize_into_ptr(input, vote_state.as_mut_ptr(), vote_pubkey)
124 }
125
126 #[cfg(any(target_os = "atlas", feature = "bincode"))]
127 fn deserialize_into_ptr(
128 input: &[u8],
129 vote_state: *mut VoteStateV4,
130 vote_pubkey: &Pubkey,
131 ) -> Result<(), InstructionError> {
132 use super::vote_state_deserialize::{deserialize_vote_state_into_v4, SourceVersion};
133
134 let mut cursor = std::io::Cursor::new(input);
135
136 let variant = atlas_serialize_utils::cursor::read_u32(&mut cursor)?;
137 match variant {
138 0 => {
142 #[cfg(not(target_os = "atlas"))]
143 {
144 unsafe {
150 vote_state.write(
151 bincode::deserialize::<VoteStateVersions>(input)
152 .map_err(|_| InstructionError::InvalidAccountData)
153 .and_then(|versioned| versioned.try_convert_to_v4(vote_pubkey))?,
154 );
155 }
156 Ok(())
157 }
158 #[cfg(target_os = "atlas")]
159 Err(InstructionError::InvalidAccountData)
160 }
161 1 => deserialize_vote_state_into_v4(
163 &mut cursor,
164 vote_state,
165 SourceVersion::V1_14_11 { vote_pubkey },
166 ),
167 2 => deserialize_vote_state_into_v4(
169 &mut cursor,
170 vote_state,
171 SourceVersion::V3 { vote_pubkey },
172 ),
173 3 => deserialize_vote_state_into_v4(&mut cursor, vote_state, SourceVersion::V4),
175 _ => Err(InstructionError::InvalidAccountData),
176 }?;
177
178 Ok(())
179 }
180
181 #[cfg(feature = "bincode")]
182 pub fn serialize(
183 versioned: &VoteStateVersions,
184 output: &mut [u8],
185 ) -> Result<(), InstructionError> {
186 bincode::serialize_into(output, versioned).map_err(|err| match *err {
187 bincode::ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall,
188 _ => InstructionError::GenericError,
189 })
190 }
191
192 pub fn is_correct_size_and_initialized(data: &[u8]) -> bool {
193 data.len() == VoteStateV4::size_of() && data[..4] == [3, 0, 0, 0] }
196
197 #[cfg(test)]
198 pub(crate) fn get_max_sized_vote_state() -> Self {
199 use super::{MAX_EPOCH_CREDITS_HISTORY, MAX_LOCKOUT_HISTORY};
200
201 const MAX_AUTHORIZED_VOTERS: usize = 4;
203
204 let mut authorized_voters = AuthorizedVoters::default();
205 for i in 0..MAX_AUTHORIZED_VOTERS as u64 {
206 authorized_voters.insert(i, Pubkey::new_unique());
207 }
208
209 Self {
210 votes: VecDeque::from(vec![LandedVote::default(); MAX_LOCKOUT_HISTORY]),
211 root_slot: Some(u64::MAX),
212 epoch_credits: vec![(0, 0, 0); MAX_EPOCH_CREDITS_HISTORY],
213 authorized_voters,
214 ..Self::default()
215 }
216 }
217}