1#[cfg(feature = "frozen-abi")]
2use solana_frozen_abi_macro::{frozen_abi, AbiExample, StableAbi, StableAbiSample};
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(
22 api_digest = "GvUzgtcxhKVVxPAjSntXGPqjLZK5ovgZzCiUP1tDpB9q",
23 abi_digest = "6kXER3mQxF3R1Th74tQFGfYUWJfBakNZZVyU4rTrNEek",
24 abi_serializer = ["bincode", "wincode"]
25 ),
26 derive(AbiExample, StableAbi, StableAbiSample)
27)]
28#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
29#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
30#[derive(Default, Debug, PartialEq, Eq, Clone)]
31pub struct Vote {
32 pub slots: Vec<Slot>,
34 pub hash: Hash,
36 pub timestamp: Option<UnixTimestamp>,
38}
39
40impl Vote {
41 pub fn new(slots: Vec<Slot>, hash: Hash) -> Self {
42 Self {
43 slots,
44 hash,
45 timestamp: None,
46 }
47 }
48
49 pub fn last_voted_slot(&self) -> Option<Slot> {
50 self.slots.last().copied()
51 }
52}
53
54#[cfg_attr(
55 feature = "frozen-abi",
56 frozen_abi(
57 api_digest = "CxyuwbaEdzP7jDCZyxjgQvLGXadBUZF3LoUvbSpQ6tYN",
58 abi_digest = "VRLZyFD5255zgCbMPBFExQyw2wyY41U6h4yCe5oT9tR",
59 abi_serializer = ["bincode", "wincode"]
60 ),
61 derive(AbiExample, StableAbi, StableAbiSample)
62)]
63#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
64#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
65#[derive(Default, Debug, PartialEq, Eq, Clone)]
66pub struct VoteStateUpdate {
67 #[cfg_attr(
69 feature = "frozen-abi",
70 stable_abi_sample(with = "super::sampling::sample_lockouts(rng)")
71 )]
72 pub lockouts: VecDeque<Lockout>,
73 #[cfg_attr(
75 feature = "frozen-abi",
76 stable_abi_sample(with = "super::sampling::sample_root(rng)")
77 )]
78 pub root: Option<Slot>,
79 pub hash: Hash,
81 pub timestamp: Option<UnixTimestamp>,
83}
84
85impl From<Vec<(Slot, u32)>> for VoteStateUpdate {
86 fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
87 let lockouts: VecDeque<Lockout> = recent_slots
88 .into_iter()
89 .map(|(slot, confirmation_count)| {
90 Lockout::new_with_confirmation_count(slot, confirmation_count)
91 })
92 .collect();
93 Self {
94 lockouts,
95 root: None,
96 hash: Hash::default(),
97 timestamp: None,
98 }
99 }
100}
101
102impl VoteStateUpdate {
103 pub fn new(lockouts: VecDeque<Lockout>, root: Option<Slot>, hash: Hash) -> Self {
104 Self {
105 lockouts,
106 root,
107 hash,
108 timestamp: None,
109 }
110 }
111
112 pub fn slots(&self) -> Vec<Slot> {
113 self.lockouts.iter().map(|lockout| lockout.slot()).collect()
114 }
115
116 pub fn last_voted_slot(&self) -> Option<Slot> {
117 self.lockouts.back().map(|l| l.slot())
118 }
119}
120
121#[cfg_attr(
122 feature = "frozen-abi",
123 frozen_abi(
124 api_digest = "6UDiQMH4wbNwkMHosPMtekMYu2Qa6CHPZ2ymK4mc6FGu",
125 abi_digest = "FUbrVcYe9LvPfr6PEk3E27YybVodHTfgZ7SnVzi3bR7",
126 abi_serializer = ["bincode", "wincode"]
127 ),
128 derive(AbiExample, StableAbi, StableAbiSample)
129)]
130#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
131#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
132#[derive(Default, Debug, PartialEq, Eq, Clone)]
133pub struct TowerSync {
134 #[cfg_attr(
136 feature = "frozen-abi",
137 stable_abi_sample(with = "super::sampling::sample_lockouts(rng)")
138 )]
139 pub lockouts: VecDeque<Lockout>,
140 #[cfg_attr(
142 feature = "frozen-abi",
143 stable_abi_sample(with = "super::sampling::sample_root(rng)")
144 )]
145 pub root: Option<Slot>,
146 pub hash: Hash,
148 pub timestamp: Option<UnixTimestamp>,
150 pub block_id: Hash,
154}
155
156impl From<Vec<(Slot, u32)>> for TowerSync {
157 fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
158 let lockouts: VecDeque<Lockout> = recent_slots
159 .into_iter()
160 .map(|(slot, confirmation_count)| {
161 Lockout::new_with_confirmation_count(slot, confirmation_count)
162 })
163 .collect();
164 Self {
165 lockouts,
166 root: None,
167 hash: Hash::default(),
168 timestamp: None,
169 block_id: Hash::default(),
170 }
171 }
172}
173
174impl TowerSync {
175 pub fn new(
176 lockouts: VecDeque<Lockout>,
177 root: Option<Slot>,
178 hash: Hash,
179 block_id: Hash,
180 ) -> Self {
181 Self {
182 lockouts,
183 root,
184 hash,
185 timestamp: None,
186 block_id,
187 }
188 }
189
190 pub fn new_from_slot(slot: Slot, hash: Hash) -> Self {
194 let lowest_slot = slot
195 .saturating_add(1)
196 .saturating_sub(MAX_LOCKOUT_HISTORY as u64);
197 let slots: Vec<_> = (lowest_slot..slot.saturating_add(1)).collect();
198 Self::new_from_slots(
199 slots,
200 hash,
201 (lowest_slot > 0).then(|| lowest_slot.saturating_sub(1)),
202 )
203 }
204
205 pub fn new_from_slots(slots: Vec<Slot>, hash: Hash, root: Option<Slot>) -> Self {
207 let lockouts: VecDeque<Lockout> = slots
208 .into_iter()
209 .rev()
210 .enumerate()
211 .map(|(cc, s)| Lockout::new_with_confirmation_count(s, cc.saturating_add(1) as u32))
212 .rev()
213 .collect();
214 Self {
215 lockouts,
216 hash,
217 root,
218 timestamp: None,
219 block_id: Hash::default(),
220 }
221 }
222
223 pub fn slots(&self) -> Vec<Slot> {
224 self.lockouts.iter().map(|lockout| lockout.slot()).collect()
225 }
226
227 pub fn last_voted_slot(&self) -> Option<Slot> {
228 self.lockouts.back().map(|l| l.slot())
229 }
230}
231
232#[cfg_attr(feature = "frozen-abi", derive(StableAbi, StableAbiSample))]
233#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
234#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
235#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
236pub struct VoteInit {
237 pub node_pubkey: Pubkey,
238 pub authorized_voter: Pubkey,
239 pub authorized_withdrawer: Pubkey,
240 pub commission: u8,
241}
242
243#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
244#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
245#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
246#[cfg_attr(feature = "frozen-abi", derive(StableAbi, StableAbiSample))]
247#[derive(Debug, PartialEq, Eq, Clone, Copy)]
248pub struct VoteInitV2 {
249 pub node_pubkey: Pubkey,
250 pub authorized_voter: Pubkey,
251 #[cfg_attr(
252 feature = "serde",
253 serde_as(as = "[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]")
254 )]
255 pub authorized_voter_bls_pubkey: [u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
256 #[cfg_attr(
257 feature = "serde",
258 serde_as(as = "[_; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE]")
259 )]
260 pub authorized_voter_bls_proof_of_possession: [u8; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
261 pub authorized_withdrawer: Pubkey,
262 pub inflation_rewards_commission_bps: u16,
263 pub block_revenue_commission_bps: u16,
264}
265
266impl Default for VoteInitV2 {
267 fn default() -> Self {
268 Self {
269 node_pubkey: Pubkey::default(),
270 authorized_voter: Pubkey::default(),
271 authorized_voter_bls_pubkey: [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
272 authorized_voter_bls_proof_of_possession: [0u8;
273 BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
274 authorized_withdrawer: Pubkey::default(),
275 inflation_rewards_commission_bps: 0,
276 block_revenue_commission_bps: 0,
277 }
278 }
279}
280
281#[cfg_attr(feature = "serde", cfg_eval::cfg_eval, serde_as)]
282#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
283#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
284#[cfg_attr(feature = "frozen-abi", derive(StableAbi, StableAbiSample))]
285#[derive(Debug, PartialEq, Eq, Clone, Copy)]
286pub struct VoterWithBLSArgs {
287 #[cfg_attr(
288 feature = "serde",
289 serde_as(as = "[_; BLS_PUBLIC_KEY_COMPRESSED_SIZE]")
290 )]
291 pub bls_pubkey: [u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
292 #[cfg_attr(
293 feature = "serde",
294 serde_as(as = "[_; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE]")
295 )]
296 pub bls_proof_of_possession: [u8; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
297}
298
299impl Default for VoterWithBLSArgs {
300 fn default() -> Self {
301 Self {
302 bls_pubkey: [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE],
303 bls_proof_of_possession: [0u8; BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE],
304 }
305 }
306}
307
308#[cfg_attr(feature = "frozen-abi", derive(StableAbi, StableAbiSample))]
309#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
310#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
311#[derive(Debug, PartialEq, Eq, Clone, Copy)]
312pub enum VoteAuthorize {
313 Voter,
314 Withdrawer,
315 VoterWithBLS(VoterWithBLSArgs),
316}
317
318#[cfg_attr(feature = "frozen-abi", derive(StableAbi, StableAbiSample))]
319#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
320#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
321#[derive(Debug, PartialEq, Eq, Clone)]
322pub struct VoteAuthorizeWithSeedArgs {
323 pub authorization_type: VoteAuthorize,
324 pub current_authority_derived_key_owner: Pubkey,
325 pub current_authority_derived_key_seed: String,
326 pub new_authority: Pubkey,
327}
328
329#[cfg_attr(feature = "frozen-abi", derive(StableAbi, StableAbiSample))]
330#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
331#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
332#[derive(Debug, PartialEq, Eq, Clone)]
333pub struct VoteAuthorizeCheckedWithSeedArgs {
334 pub authorization_type: VoteAuthorize,
335 pub current_authority_derived_key_owner: Pubkey,
336 pub current_authority_derived_key_seed: String,
337}