1#[cfg(feature = "frozen-abi")]
2use solana_frozen_abi_macro::{frozen_abi, AbiExample};
3use {
4 crate::state::{
5 Lockout, BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE, BLS_PUBLIC_KEY_COMPRESSED_SIZE,
6 MAX_LOCKOUT_HISTORY,
7 },
8 solana_clock::{Slot, UnixTimestamp},
9 solana_hash::Hash,
10 solana_pubkey::Pubkey,
11 std::{collections::VecDeque, fmt::Debug},
12};
13#[cfg(feature = "serde")]
14use {
15 serde_derive::{Deserialize, Serialize},
16 serde_with::serde_as,
17};
18
19#[cfg_attr(
20 feature = "frozen-abi",
21 frozen_abi(digest = "GvUzgtcxhKVVxPAjSntXGPqjLZK5ovgZzCiUP1tDpB9q"),
22 derive(AbiExample)
23)]
24#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
25#[derive(Default, Debug, PartialEq, Eq, Clone)]
26pub struct Vote {
27 pub slots: Vec<Slot>,
29 pub hash: Hash,
31 pub timestamp: Option<UnixTimestamp>,
33}
34
35impl Vote {
36 pub fn new(slots: Vec<Slot>, hash: Hash) -> Self {
37 Self {
38 slots,
39 hash,
40 timestamp: None,
41 }
42 }
43
44 pub fn last_voted_slot(&self) -> Option<Slot> {
45 self.slots.last().copied()
46 }
47}
48
49#[cfg_attr(
50 feature = "frozen-abi",
51 frozen_abi(digest = "CxyuwbaEdzP7jDCZyxjgQvLGXadBUZF3LoUvbSpQ6tYN"),
52 derive(AbiExample)
53)]
54#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
55#[derive(Default, Debug, PartialEq, Eq, Clone)]
56pub struct VoteStateUpdate {
57 pub lockouts: VecDeque<Lockout>,
59 pub root: Option<Slot>,
61 pub hash: Hash,
63 pub timestamp: Option<UnixTimestamp>,
65}
66
67impl From<Vec<(Slot, u32)>> for VoteStateUpdate {
68 fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
69 let lockouts: VecDeque<Lockout> = recent_slots
70 .into_iter()
71 .map(|(slot, confirmation_count)| {
72 Lockout::new_with_confirmation_count(slot, confirmation_count)
73 })
74 .collect();
75 Self {
76 lockouts,
77 root: None,
78 hash: Hash::default(),
79 timestamp: None,
80 }
81 }
82}
83
84impl VoteStateUpdate {
85 pub fn new(lockouts: VecDeque<Lockout>, root: Option<Slot>, hash: Hash) -> Self {
86 Self {
87 lockouts,
88 root,
89 hash,
90 timestamp: None,
91 }
92 }
93
94 pub fn slots(&self) -> Vec<Slot> {
95 self.lockouts.iter().map(|lockout| lockout.slot()).collect()
96 }
97
98 pub fn last_voted_slot(&self) -> Option<Slot> {
99 self.lockouts.back().map(|l| l.slot())
100 }
101}
102
103#[cfg_attr(
104 feature = "frozen-abi",
105 frozen_abi(digest = "6UDiQMH4wbNwkMHosPMtekMYu2Qa6CHPZ2ymK4mc6FGu"),
106 derive(AbiExample)
107)]
108#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
109#[derive(Default, Debug, PartialEq, Eq, Clone)]
110pub struct TowerSync {
111 pub lockouts: VecDeque<Lockout>,
113 pub root: Option<Slot>,
115 pub hash: Hash,
117 pub timestamp: Option<UnixTimestamp>,
119 pub block_id: Hash,
123}
124
125impl From<Vec<(Slot, u32)>> for TowerSync {
126 fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
127 let lockouts: VecDeque<Lockout> = recent_slots
128 .into_iter()
129 .map(|(slot, confirmation_count)| {
130 Lockout::new_with_confirmation_count(slot, confirmation_count)
131 })
132 .collect();
133 Self {
134 lockouts,
135 root: None,
136 hash: Hash::default(),
137 timestamp: None,
138 block_id: Hash::default(),
139 }
140 }
141}
142
143impl TowerSync {
144 pub fn new(
145 lockouts: VecDeque<Lockout>,
146 root: Option<Slot>,
147 hash: Hash,
148 block_id: Hash,
149 ) -> Self {
150 Self {
151 lockouts,
152 root,
153 hash,
154 timestamp: None,
155 block_id,
156 }
157 }
158
159 pub fn new_from_slot(slot: Slot, hash: Hash) -> Self {
163 let lowest_slot = slot
164 .saturating_add(1)
165 .saturating_sub(MAX_LOCKOUT_HISTORY as u64);
166 let slots: Vec<_> = (lowest_slot..slot.saturating_add(1)).collect();
167 Self::new_from_slots(
168 slots,
169 hash,
170 (lowest_slot > 0).then(|| lowest_slot.saturating_sub(1)),
171 )
172 }
173
174 pub fn new_from_slots(slots: Vec<Slot>, hash: Hash, root: Option<Slot>) -> Self {
176 let lockouts: VecDeque<Lockout> = slots
177 .into_iter()
178 .rev()
179 .enumerate()
180 .map(|(cc, s)| Lockout::new_with_confirmation_count(s, cc.saturating_add(1) as u32))
181 .rev()
182 .collect();
183 Self {
184 lockouts,
185 hash,
186 root,
187 timestamp: None,
188 block_id: Hash::default(),
189 }
190 }
191
192 pub fn slots(&self) -> Vec<Slot> {
193 self.lockouts.iter().map(|lockout| lockout.slot()).collect()
194 }
195
196 pub fn last_voted_slot(&self) -> Option<Slot> {
197 self.lockouts.back().map(|l| l.slot())
198 }
199}
200
201#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
202#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
203pub struct VoteInit {
204 pub node_pubkey: Pubkey,
205 pub authorized_voter: Pubkey,
206 pub authorized_withdrawer: Pubkey,
207 pub commission: u8,
208}
209
210#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
211#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
212#[derive(Debug, PartialEq, Eq, Clone, Copy)]
213pub struct VoteInitV2 {
214 pub node_pubkey: Pubkey,
215 pub authorized_voter: Pubkey,
216 #[cfg_attr(
217 feature = "serde",
218 serde_as(as = "[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]")
219 )]
220 pub authorized_voter_bls_pubkey: [u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
221 #[cfg_attr(
222 feature = "serde",
223 serde_as(as = "[_; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE]")
224 )]
225 pub authorized_voter_bls_proof_of_possession: [u8; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
226 pub authorized_withdrawer: Pubkey,
227 pub inflation_rewards_commission_bps: u16,
228 pub block_revenue_commission_bps: u16,
229}
230
231impl Default for VoteInitV2 {
232 fn default() -> Self {
233 Self {
234 node_pubkey: Pubkey::default(),
235 authorized_voter: Pubkey::default(),
236 authorized_voter_bls_pubkey: [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
237 authorized_voter_bls_proof_of_possession: [0u8;
238 BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
239 authorized_withdrawer: Pubkey::default(),
240 inflation_rewards_commission_bps: 0,
241 block_revenue_commission_bps: 0,
242 }
243 }
244}
245
246#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
247#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
248#[derive(Debug, PartialEq, Eq, Clone, Copy)]
249pub struct VoterWithBLSArgs {
250 #[cfg_attr(
251 feature = "serde",
252 serde_as(as = "[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]")
253 )]
254 pub bls_pubkey: [u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
255 #[cfg_attr(
256 feature = "serde",
257 serde_as(as = "[_; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE]")
258 )]
259 pub bls_proof_of_possession: [u8; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
260}
261
262impl Default for VoterWithBLSArgs {
263 fn default() -> Self {
264 Self {
265 bls_pubkey: [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
266 bls_proof_of_possession: [0u8; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
267 }
268 }
269}
270
271#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
272#[derive(Debug, PartialEq, Eq, Clone, Copy)]
273pub enum VoteAuthorize {
274 Voter,
275 Withdrawer,
276 VoterWithBLS(VoterWithBLSArgs),
277}
278
279#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
280#[derive(Debug, PartialEq, Eq, Clone)]
281pub struct VoteAuthorizeWithSeedArgs {
282 pub authorization_type: VoteAuthorize,
283 pub current_authority_derived_key_owner: Pubkey,
284 pub current_authority_derived_key_seed: String,
285 pub new_authority: Pubkey,
286}
287
288#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
289#[derive(Debug, PartialEq, Eq, Clone)]
290pub struct VoteAuthorizeCheckedWithSeedArgs {
291 pub authorization_type: VoteAuthorize,
292 pub current_authority_derived_key_owner: Pubkey,
293 pub current_authority_derived_key_seed: String,
294}