1#[cfg(feature = "dev-context-only-utils")]
4use arbitrary::Arbitrary;
5#[cfg(test)]
6use arbitrary::Unstructured;
7#[cfg(feature = "serde")]
8use serde_derive::{Deserialize, Serialize};
9#[cfg(feature = "frozen-abi")]
10use atlas_frozen_abi_macro::AbiExample;
11use {
12 crate::authorized_voters::AuthorizedVoters,
13 atlas_clock::{Epoch, Slot, UnixTimestamp},
14 atlas_pubkey::Pubkey,
15 atlas_rent::Rent,
16 std::{collections::VecDeque, fmt::Debug},
17};
18
19mod vote_state_0_23_5;
20pub mod vote_state_1_14_11;
21pub use vote_state_1_14_11::*;
22pub mod vote_state_versions;
23pub use vote_state_versions::*;
24pub mod vote_state_v3;
25pub use vote_state_v3::VoteStateV3;
26pub mod vote_state_v4;
27pub use vote_state_v4::VoteStateV4;
28mod vote_instruction_data;
29pub use vote_instruction_data::*;
30#[cfg(any(target_os = "atlas", feature = "bincode"))]
31pub(crate) mod vote_state_deserialize;
32
33pub const BLS_PUBLIC_KEY_COMPRESSED_SIZE: usize = 48;
35
36pub const BLS_PROOF_OF_POSSESSION_COMPRESSED_SIZE: usize = 96;
38
39pub const MAX_LOCKOUT_HISTORY: usize = 31;
41pub const INITIAL_LOCKOUT: usize = 2;
42
43pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64;
45
46const DEFAULT_PRIOR_VOTERS_OFFSET: usize = 114;
48
49pub const VOTE_CREDITS_GRACE_SLOTS: u8 = 2;
51
52pub const VOTE_CREDITS_MAXIMUM_PER_SLOT: u8 = 16;
54
55#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
56#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
57#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
58#[cfg_attr(feature = "dev-context-only-utils", derive(Arbitrary))]
59pub struct Lockout {
60 slot: Slot,
61 confirmation_count: u32,
62}
63
64impl Lockout {
65 pub fn new(slot: Slot) -> Self {
66 Self::new_with_confirmation_count(slot, 1)
67 }
68
69 pub fn new_with_confirmation_count(slot: Slot, confirmation_count: u32) -> Self {
70 Self {
71 slot,
72 confirmation_count,
73 }
74 }
75
76 pub fn lockout(&self) -> u64 {
78 (INITIAL_LOCKOUT as u64).wrapping_pow(std::cmp::min(
79 self.confirmation_count(),
80 MAX_LOCKOUT_HISTORY as u32,
81 ))
82 }
83
84 pub fn last_locked_out_slot(&self) -> Slot {
88 self.slot.saturating_add(self.lockout())
89 }
90
91 pub fn is_locked_out_at_slot(&self, slot: Slot) -> bool {
92 self.last_locked_out_slot() >= slot
93 }
94
95 pub fn slot(&self) -> Slot {
96 self.slot
97 }
98
99 pub fn confirmation_count(&self) -> u32 {
100 self.confirmation_count
101 }
102
103 pub fn increase_confirmation_count(&mut self, by: u32) {
104 self.confirmation_count = self.confirmation_count.saturating_add(by)
105 }
106}
107
108#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
109#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
110#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
111#[cfg_attr(feature = "dev-context-only-utils", derive(Arbitrary))]
112pub struct LandedVote {
113 pub latency: u8,
117 pub lockout: Lockout,
118}
119
120impl LandedVote {
121 pub fn slot(&self) -> Slot {
122 self.lockout.slot
123 }
124
125 pub fn confirmation_count(&self) -> u32 {
126 self.lockout.confirmation_count
127 }
128}
129
130impl From<LandedVote> for Lockout {
131 fn from(landed_vote: LandedVote) -> Self {
132 landed_vote.lockout
133 }
134}
135
136impl From<Lockout> for LandedVote {
137 fn from(lockout: Lockout) -> Self {
138 Self {
139 latency: 0,
140 lockout,
141 }
142 }
143}
144
145#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
146#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
147#[derive(Debug, Default, PartialEq, Eq, Clone)]
148#[cfg_attr(feature = "dev-context-only-utils", derive(Arbitrary))]
149pub struct BlockTimestamp {
150 pub slot: Slot,
151 pub timestamp: UnixTimestamp,
152}
153
154const MAX_ITEMS: usize = 32;
156
157#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
158#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
159#[derive(Debug, PartialEq, Eq, Clone)]
160#[cfg_attr(feature = "dev-context-only-utils", derive(Arbitrary))]
161pub struct CircBuf<I> {
162 buf: [I; MAX_ITEMS],
163 idx: usize,
165 is_empty: bool,
166}
167
168impl<I: Default + Copy> Default for CircBuf<I> {
169 fn default() -> Self {
170 Self {
171 buf: [I::default(); MAX_ITEMS],
172 idx: MAX_ITEMS
173 .checked_sub(1)
174 .expect("`MAX_ITEMS` should be positive"),
175 is_empty: true,
176 }
177 }
178}
179
180impl<I> CircBuf<I> {
181 pub fn append(&mut self, item: I) {
182 self.idx = self
184 .idx
185 .checked_add(1)
186 .and_then(|idx| idx.checked_rem(MAX_ITEMS))
187 .expect("`self.idx` should be < `MAX_ITEMS` which should be non-zero");
188
189 self.buf[self.idx] = item;
190 self.is_empty = false;
191 }
192
193 pub fn buf(&self) -> &[I; MAX_ITEMS] {
194 &self.buf
195 }
196
197 pub fn last(&self) -> Option<&I> {
198 if !self.is_empty {
199 self.buf.get(self.idx)
200 } else {
201 None
202 }
203 }
204}
205
206#[cfg(feature = "serde")]
207pub mod serde_compact_vote_state_update {
208 use {
209 super::*,
210 crate::state::Lockout,
211 serde::{Deserialize, Deserializer, Serialize, Serializer},
212 atlas_hash::Hash,
213 atlas_serde_varint as serde_varint, atlas_short_vec as short_vec,
214 };
215
216 #[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
217 #[derive(serde_derive::Deserialize, serde_derive::Serialize)]
218 struct LockoutOffset {
219 #[serde(with = "serde_varint")]
220 offset: Slot,
221 confirmation_count: u8,
222 }
223
224 #[derive(serde_derive::Deserialize, serde_derive::Serialize)]
225 struct CompactVoteStateUpdate {
226 root: Slot,
227 #[serde(with = "short_vec")]
228 lockout_offsets: Vec<LockoutOffset>,
229 hash: Hash,
230 timestamp: Option<UnixTimestamp>,
231 }
232
233 pub fn serialize<S>(
234 vote_state_update: &VoteStateUpdate,
235 serializer: S,
236 ) -> Result<S::Ok, S::Error>
237 where
238 S: Serializer,
239 {
240 let lockout_offsets = vote_state_update.lockouts.iter().scan(
241 vote_state_update.root.unwrap_or_default(),
242 |slot, lockout| {
243 let Some(offset) = lockout.slot().checked_sub(*slot) else {
244 return Some(Err(serde::ser::Error::custom("Invalid vote lockout")));
245 };
246 let Ok(confirmation_count) = u8::try_from(lockout.confirmation_count()) else {
247 return Some(Err(serde::ser::Error::custom("Invalid confirmation count")));
248 };
249 let lockout_offset = LockoutOffset {
250 offset,
251 confirmation_count,
252 };
253 *slot = lockout.slot();
254 Some(Ok(lockout_offset))
255 },
256 );
257 let compact_vote_state_update = CompactVoteStateUpdate {
258 root: vote_state_update.root.unwrap_or(Slot::MAX),
259 lockout_offsets: lockout_offsets.collect::<Result<_, _>>()?,
260 hash: Hash::new_from_array(vote_state_update.hash.to_bytes()),
261 timestamp: vote_state_update.timestamp,
262 };
263 compact_vote_state_update.serialize(serializer)
264 }
265
266 pub fn deserialize<'de, D>(deserializer: D) -> Result<VoteStateUpdate, D::Error>
267 where
268 D: Deserializer<'de>,
269 {
270 let CompactVoteStateUpdate {
271 root,
272 lockout_offsets,
273 hash,
274 timestamp,
275 } = CompactVoteStateUpdate::deserialize(deserializer)?;
276 let root = (root != Slot::MAX).then_some(root);
277 let lockouts =
278 lockout_offsets
279 .iter()
280 .scan(root.unwrap_or_default(), |slot, lockout_offset| {
281 *slot = match slot.checked_add(lockout_offset.offset) {
282 None => {
283 return Some(Err(serde::de::Error::custom("Invalid lockout offset")))
284 }
285 Some(slot) => slot,
286 };
287 let lockout = Lockout::new_with_confirmation_count(
288 *slot,
289 u32::from(lockout_offset.confirmation_count),
290 );
291 Some(Ok(lockout))
292 });
293 Ok(VoteStateUpdate {
294 root,
295 lockouts: lockouts.collect::<Result<_, _>>()?,
296 hash,
297 timestamp,
298 })
299 }
300}
301
302#[cfg(feature = "serde")]
303pub mod serde_tower_sync {
304 use {
305 super::*,
306 crate::state::Lockout,
307 serde::{Deserialize, Deserializer, Serialize, Serializer},
308 atlas_hash::Hash,
309 atlas_serde_varint as serde_varint, atlas_short_vec as short_vec,
310 };
311
312 #[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
313 #[derive(serde_derive::Deserialize, serde_derive::Serialize)]
314 struct LockoutOffset {
315 #[serde(with = "serde_varint")]
316 offset: Slot,
317 confirmation_count: u8,
318 }
319
320 #[derive(serde_derive::Deserialize, serde_derive::Serialize)]
321 struct CompactTowerSync {
322 root: Slot,
323 #[serde(with = "short_vec")]
324 lockout_offsets: Vec<LockoutOffset>,
325 hash: Hash,
326 timestamp: Option<UnixTimestamp>,
327 block_id: Hash,
328 }
329
330 pub fn serialize<S>(tower_sync: &TowerSync, serializer: S) -> Result<S::Ok, S::Error>
331 where
332 S: Serializer,
333 {
334 let lockout_offsets = tower_sync.lockouts.iter().scan(
335 tower_sync.root.unwrap_or_default(),
336 |slot, lockout| {
337 let Some(offset) = lockout.slot().checked_sub(*slot) else {
338 return Some(Err(serde::ser::Error::custom("Invalid vote lockout")));
339 };
340 let Ok(confirmation_count) = u8::try_from(lockout.confirmation_count()) else {
341 return Some(Err(serde::ser::Error::custom("Invalid confirmation count")));
342 };
343 let lockout_offset = LockoutOffset {
344 offset,
345 confirmation_count,
346 };
347 *slot = lockout.slot();
348 Some(Ok(lockout_offset))
349 },
350 );
351 let compact_tower_sync = CompactTowerSync {
352 root: tower_sync.root.unwrap_or(Slot::MAX),
353 lockout_offsets: lockout_offsets.collect::<Result<_, _>>()?,
354 hash: Hash::new_from_array(tower_sync.hash.to_bytes()),
355 timestamp: tower_sync.timestamp,
356 block_id: Hash::new_from_array(tower_sync.block_id.to_bytes()),
357 };
358 compact_tower_sync.serialize(serializer)
359 }
360
361 pub fn deserialize<'de, D>(deserializer: D) -> Result<TowerSync, D::Error>
362 where
363 D: Deserializer<'de>,
364 {
365 let CompactTowerSync {
366 root,
367 lockout_offsets,
368 hash,
369 timestamp,
370 block_id,
371 } = CompactTowerSync::deserialize(deserializer)?;
372 let root = (root != Slot::MAX).then_some(root);
373 let lockouts =
374 lockout_offsets
375 .iter()
376 .scan(root.unwrap_or_default(), |slot, lockout_offset| {
377 *slot = match slot.checked_add(lockout_offset.offset) {
378 None => {
379 return Some(Err(serde::de::Error::custom("Invalid lockout offset")))
380 }
381 Some(slot) => slot,
382 };
383 let lockout = Lockout::new_with_confirmation_count(
384 *slot,
385 u32::from(lockout_offset.confirmation_count),
386 );
387 Some(Ok(lockout))
388 });
389 Ok(TowerSync {
390 root,
391 lockouts: lockouts.collect::<Result<_, _>>()?,
392 hash,
393 timestamp,
394 block_id,
395 })
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use {
402 super::*, crate::state::vote_state_0_23_5::VoteState0_23_5, bincode::serialized_size,
403 core::mem::MaybeUninit, itertools::Itertools, rand::Rng, atlas_clock::Clock,
404 atlas_hash::Hash, atlas_instruction::error::InstructionError,
405 };
406
407 fn create_test_vote_state_v4(node_pubkey: Pubkey, root_slot: Slot) -> VoteStateV4 {
409 let votes = (1..32)
410 .map(|x| LandedVote {
411 latency: 0,
412 lockout: Lockout::new_with_confirmation_count(
413 u64::from(x).saturating_add(root_slot),
414 32_u32.saturating_sub(x),
415 ),
416 })
417 .collect();
418 VoteStateV4 {
419 node_pubkey,
420 root_slot: Some(root_slot),
421 votes,
422 ..VoteStateV4::default()
423 }
424 }
425
426 #[test]
427 fn test_vote_serialize_v3() {
428 let mut buffer: Vec<u8> = vec![0; VoteStateV3::size_of()];
429 let mut vote_state = VoteStateV3::default();
430 vote_state
431 .votes
432 .resize(MAX_LOCKOUT_HISTORY, LandedVote::default());
433 vote_state.root_slot = Some(1);
434 let versioned = VoteStateVersions::new_v3(vote_state);
435 assert!(VoteStateV3::serialize(&versioned, &mut buffer[0..4]).is_err());
436 VoteStateV3::serialize(&versioned, &mut buffer).unwrap();
437 assert_eq!(
438 VoteStateV3::deserialize(&buffer).unwrap(),
439 versioned.try_convert_to_v3().unwrap()
440 );
441 }
442
443 #[test]
444 fn test_vote_serialize_v4() {
445 let vote_pubkey_for_deserialize = Pubkey::new_unique();
448 let vote_pubkey_for_convert = Pubkey::new_unique();
449
450 let mut buffer: Vec<u8> = vec![0; VoteStateV4::size_of()];
451 let mut vote_state = VoteStateV4::default();
452 vote_state
453 .votes
454 .resize(MAX_LOCKOUT_HISTORY, LandedVote::default());
455 vote_state.root_slot = Some(1);
456 let versioned = VoteStateVersions::new_v4(vote_state);
457 assert!(VoteStateV4::serialize(&versioned, &mut buffer[0..4]).is_err());
458 VoteStateV4::serialize(&versioned, &mut buffer).unwrap();
459 assert_eq!(
460 VoteStateV4::deserialize(&buffer, &vote_pubkey_for_deserialize).unwrap(),
461 versioned
462 .try_convert_to_v4(&vote_pubkey_for_convert)
463 .unwrap()
464 );
465 }
466
467 #[test]
468 fn test_vote_deserialize_into_v3() {
469 let target_vote_state = VoteStateV3::default();
471 let vote_state_buf =
472 bincode::serialize(&VoteStateVersions::new_v3(target_vote_state.clone())).unwrap();
473
474 let mut test_vote_state = VoteStateV3::default();
475 VoteStateV3::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
476
477 assert_eq!(target_vote_state, test_vote_state);
478
479 let struct_bytes_x4 = std::mem::size_of::<VoteStateV3>() * 4;
482 for _ in 0..1000 {
483 let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
484 let mut unstructured = Unstructured::new(&raw_data);
485
486 let target_vote_state_versions =
487 VoteStateVersions::arbitrary(&mut unstructured).unwrap();
488 let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
489
490 if let Ok(target_vote_state) = target_vote_state_versions.try_convert_to_v3() {
492 let mut test_vote_state = VoteStateV3::default();
493 VoteStateV3::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
494
495 assert_eq!(target_vote_state, test_vote_state);
496 }
497 }
498 }
499
500 #[test]
501 fn test_vote_deserialize_into_v4() {
502 let vote_pubkey = Pubkey::new_unique();
503
504 let target_vote_state = VoteStateV4::default();
506 let vote_state_buf =
507 bincode::serialize(&VoteStateVersions::new_v4(target_vote_state.clone())).unwrap();
508
509 let mut test_vote_state = VoteStateV4::default();
510 VoteStateV4::deserialize_into(&vote_state_buf, &mut test_vote_state, &vote_pubkey).unwrap();
511
512 assert_eq!(target_vote_state, test_vote_state);
513
514 let struct_bytes_x4 = std::mem::size_of::<VoteStateV4>() * 4;
517 for _ in 0..1000 {
518 let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
519 let mut unstructured = Unstructured::new(&raw_data);
520
521 let target_vote_state_versions =
522 VoteStateVersions::arbitrary(&mut unstructured).unwrap();
523 let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
524 let target_vote_state = target_vote_state_versions
525 .try_convert_to_v4(&vote_pubkey)
526 .unwrap();
527
528 let mut test_vote_state = VoteStateV4::default();
529 VoteStateV4::deserialize_into(&vote_state_buf, &mut test_vote_state, &vote_pubkey)
530 .unwrap();
531
532 assert_eq!(target_vote_state, test_vote_state);
533 }
534 }
535
536 #[test]
537 fn test_vote_deserialize_into_error_v3() {
538 let target_vote_state = VoteStateV3::new_rand_for_tests(Pubkey::new_unique(), 42);
539 let mut vote_state_buf =
540 bincode::serialize(&VoteStateVersions::new_v3(target_vote_state.clone())).unwrap();
541 let len = vote_state_buf.len();
542 vote_state_buf.truncate(len - 1);
543
544 let mut test_vote_state = VoteStateV3::default();
545 VoteStateV3::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap_err();
546 assert_eq!(test_vote_state, VoteStateV3::default());
547 }
548
549 #[test]
550 fn test_vote_deserialize_into_error_v4() {
551 let vote_pubkey = Pubkey::new_unique();
552
553 let target_vote_state = create_test_vote_state_v4(Pubkey::new_unique(), 42);
554 let mut vote_state_buf =
555 bincode::serialize(&VoteStateVersions::new_v4(target_vote_state.clone())).unwrap();
556 let len = vote_state_buf.len();
557 vote_state_buf.truncate(len - 1);
558
559 let mut test_vote_state = VoteStateV4::default();
560 VoteStateV4::deserialize_into(&vote_state_buf, &mut test_vote_state, &vote_pubkey)
561 .unwrap_err();
562 assert_eq!(test_vote_state, VoteStateV4::default());
563 }
564
565 #[test]
566 fn test_vote_deserialize_into_uninit_v3() {
567 let target_vote_state = VoteStateV3::default();
569 let vote_state_buf =
570 bincode::serialize(&VoteStateVersions::new_v3(target_vote_state.clone())).unwrap();
571
572 let mut test_vote_state = MaybeUninit::uninit();
573 VoteStateV3::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
574 let test_vote_state = unsafe { test_vote_state.assume_init() };
575
576 assert_eq!(target_vote_state, test_vote_state);
577
578 let struct_bytes_x4 = std::mem::size_of::<VoteStateV3>() * 4;
581 for _ in 0..1000 {
582 let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
583 let mut unstructured = Unstructured::new(&raw_data);
584
585 let target_vote_state_versions =
586 VoteStateVersions::arbitrary(&mut unstructured).unwrap();
587 let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
588
589 if let Ok(target_vote_state) = target_vote_state_versions.try_convert_to_v3() {
591 let mut test_vote_state = MaybeUninit::uninit();
592 VoteStateV3::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state)
593 .unwrap();
594 let test_vote_state = unsafe { test_vote_state.assume_init() };
595
596 assert_eq!(target_vote_state, test_vote_state);
597 }
598 }
599 }
600
601 #[test]
602 fn test_vote_deserialize_into_uninit_v4() {
603 let vote_pubkey = Pubkey::new_unique();
604
605 let target_vote_state = VoteStateV4::default();
607 let vote_state_buf =
608 bincode::serialize(&VoteStateVersions::new_v4(target_vote_state.clone())).unwrap();
609
610 let mut test_vote_state = MaybeUninit::uninit();
611 VoteStateV4::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state, &vote_pubkey)
612 .unwrap();
613 let test_vote_state = unsafe { test_vote_state.assume_init() };
614
615 assert_eq!(target_vote_state, test_vote_state);
616
617 let struct_bytes_x4 = std::mem::size_of::<VoteStateV4>() * 4;
620 for _ in 0..1000 {
621 let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
622 let mut unstructured = Unstructured::new(&raw_data);
623
624 let target_vote_state_versions =
625 VoteStateVersions::arbitrary(&mut unstructured).unwrap();
626 let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();
627 let target_vote_state = target_vote_state_versions
628 .try_convert_to_v4(&Pubkey::default())
629 .unwrap();
630
631 let mut test_vote_state = MaybeUninit::uninit();
632 VoteStateV4::deserialize_into_uninit(
633 &vote_state_buf,
634 &mut test_vote_state,
635 &Pubkey::default(),
636 )
637 .unwrap();
638 let test_vote_state = unsafe { test_vote_state.assume_init() };
639
640 assert_eq!(target_vote_state, test_vote_state);
641 }
642 }
643
644 #[test]
645 fn test_vote_deserialize_into_uninit_nopanic_v3() {
646 let mut test_vote_state = MaybeUninit::uninit();
648 let e = VoteStateV3::deserialize_into_uninit(&[], &mut test_vote_state).unwrap_err();
649 assert_eq!(e, InstructionError::InvalidAccountData);
650
651 let serialized_len_x4 = serialized_size(&VoteStateV3::default()).unwrap() * 4;
653 let mut rng = rand::thread_rng();
654 for _ in 0..1000 {
655 let raw_data_length = rng.gen_range(1..serialized_len_x4);
656 let mut raw_data: Vec<u8> = (0..raw_data_length).map(|_| rng.gen::<u8>()).collect();
657
658 if raw_data_length >= 4 && rng.gen::<bool>() {
660 let tag = rng.gen::<u8>() % 4;
661 raw_data[0] = tag;
662 raw_data[1] = 0;
663 raw_data[2] = 0;
664 raw_data[3] = 0;
665 }
666
667 let mut test_vote_state = MaybeUninit::uninit();
670 let test_res = VoteStateV3::deserialize_into_uninit(&raw_data, &mut test_vote_state);
671
672 let bincode_res = bincode::deserialize::<VoteStateVersions>(&raw_data)
674 .map_err(|_| InstructionError::InvalidAccountData)
675 .and_then(|versioned| versioned.try_convert_to_v3());
676
677 if test_res.is_err() {
678 assert!(bincode_res.is_err());
679 } else {
680 let test_vote_state = unsafe { test_vote_state.assume_init() };
681 assert_eq!(test_vote_state, bincode_res.unwrap());
682 }
683 }
684 }
685
686 #[test]
687 fn test_vote_deserialize_into_uninit_nopanic_v4() {
688 let vote_pubkey = Pubkey::new_unique();
689
690 let mut test_vote_state = MaybeUninit::uninit();
692 let e = VoteStateV4::deserialize_into_uninit(&[], &mut test_vote_state, &vote_pubkey)
693 .unwrap_err();
694 assert_eq!(e, InstructionError::InvalidAccountData);
695
696 let serialized_len_x4 = serialized_size(&VoteStateV4::default()).unwrap() * 4;
698 let mut rng = rand::thread_rng();
699 for _ in 0..1000 {
700 let raw_data_length = rng.gen_range(1..serialized_len_x4);
701 let mut raw_data: Vec<u8> = (0..raw_data_length).map(|_| rng.gen::<u8>()).collect();
702
703 if raw_data_length >= 4 && rng.gen::<bool>() {
705 let tag = rng.gen::<u8>() % 4;
706 raw_data[0] = tag;
707 raw_data[1] = 0;
708 raw_data[2] = 0;
709 raw_data[3] = 0;
710 }
711
712 let mut test_vote_state = MaybeUninit::uninit();
715 let test_res =
716 VoteStateV4::deserialize_into_uninit(&raw_data, &mut test_vote_state, &vote_pubkey);
717 let bincode_res = bincode::deserialize::<VoteStateVersions>(&raw_data)
718 .map(|versioned| versioned.try_convert_to_v4(&vote_pubkey).unwrap());
719
720 if test_res.is_err() {
721 assert!(bincode_res.is_err());
722 } else {
723 let test_vote_state = unsafe { test_vote_state.assume_init() };
724 assert_eq!(test_vote_state, bincode_res.unwrap());
725 }
726 }
727 }
728
729 #[test]
730 fn test_vote_deserialize_into_uninit_ill_sized_v3() {
731 let struct_bytes_x4 = std::mem::size_of::<VoteStateV3>() * 4;
733 for _ in 0..1000 {
734 let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
735 let mut unstructured = Unstructured::new(&raw_data);
736
737 let original_vote_state_versions =
738 VoteStateVersions::arbitrary(&mut unstructured).unwrap();
739 let original_buf = bincode::serialize(&original_vote_state_versions).unwrap();
740
741 if !matches!(original_vote_state_versions, VoteStateVersions::V4(_)) {
743 let mut truncated_buf = original_buf.clone();
744 let mut expanded_buf = original_buf.clone();
745
746 truncated_buf.resize(original_buf.len() - 8, 0);
747 expanded_buf.resize(original_buf.len() + 8, 0);
748
749 let mut test_vote_state = MaybeUninit::uninit();
751 let test_res =
752 VoteStateV3::deserialize_into_uninit(&truncated_buf, &mut test_vote_state);
753 let bincode_res = bincode::deserialize::<VoteStateVersions>(&truncated_buf)
756 .map_err(|_| InstructionError::InvalidAccountData)
757 .and_then(|versioned| versioned.try_convert_to_v3());
758
759 assert!(test_res.is_err());
760 assert!(bincode_res.is_err());
761
762 let mut test_vote_state = MaybeUninit::uninit();
764 VoteStateV3::deserialize_into_uninit(&expanded_buf, &mut test_vote_state).unwrap();
765 let bincode_res = bincode::deserialize::<VoteStateVersions>(&expanded_buf)
768 .map_err(|_| InstructionError::InvalidAccountData)
769 .and_then(|versioned| versioned.try_convert_to_v3());
770
771 let test_vote_state = unsafe { test_vote_state.assume_init() };
772 assert_eq!(test_vote_state, bincode_res.unwrap());
773 }
774 }
775 }
776
777 #[test]
778 fn test_vote_deserialize_into_uninit_ill_sized_v4() {
779 let vote_pubkey = Pubkey::new_unique();
780
781 let struct_bytes_x4 = std::mem::size_of::<VoteStateV4>() * 4;
783 for _ in 0..1000 {
784 let raw_data: Vec<u8> = (0..struct_bytes_x4).map(|_| rand::random::<u8>()).collect();
785 let mut unstructured = Unstructured::new(&raw_data);
786
787 let original_vote_state_versions =
788 VoteStateVersions::arbitrary(&mut unstructured).unwrap();
789 let original_buf = bincode::serialize(&original_vote_state_versions).unwrap();
790
791 let mut truncated_buf = original_buf.clone();
792 let mut expanded_buf = original_buf.clone();
793
794 truncated_buf.resize(original_buf.len() - 8, 0);
795 expanded_buf.resize(original_buf.len() + 8, 0);
796
797 let mut test_vote_state = MaybeUninit::uninit();
799 let test_res = VoteStateV4::deserialize_into_uninit(
800 &truncated_buf,
801 &mut test_vote_state,
802 &vote_pubkey,
803 );
804 let bincode_res = bincode::deserialize::<VoteStateVersions>(&truncated_buf)
805 .map(|versioned| versioned.try_convert_to_v4(&vote_pubkey).unwrap());
806
807 assert!(test_res.is_err());
808 assert!(bincode_res.is_err());
809
810 let mut test_vote_state = MaybeUninit::uninit();
812 VoteStateV4::deserialize_into_uninit(&expanded_buf, &mut test_vote_state, &vote_pubkey)
813 .unwrap();
814 let bincode_res = bincode::deserialize::<VoteStateVersions>(&expanded_buf)
815 .map(|versioned| versioned.try_convert_to_v4(&vote_pubkey).unwrap());
816
817 let test_vote_state = unsafe { test_vote_state.assume_init() };
818 assert_eq!(test_vote_state, bincode_res.unwrap());
819 }
820 }
821
822 #[test]
823 fn test_vote_state_v3_size_of() {
824 let vote_state = VoteStateV3::get_max_sized_vote_state();
825 let vote_state = VoteStateVersions::new_v3(vote_state);
826 let size = serialized_size(&vote_state).unwrap();
827 assert_eq!(VoteStateV3::size_of() as u64, size);
828 }
829
830 #[test]
831 fn test_vote_state_v4_size_of() {
832 let vote_state = VoteStateV4::get_max_sized_vote_state();
833 let vote_state = VoteStateVersions::new_v4(vote_state);
834 let size = serialized_size(&vote_state).unwrap();
835 assert!(size < VoteStateV4::size_of() as u64); }
837
838 #[test]
839 fn test_default_vote_state_is_uninitialized() {
840 assert!(VoteStateVersions::new_v3(VoteStateV3::default()).is_uninitialized());
844 }
845
846 #[test]
847 fn test_is_correct_size_and_initialized() {
848 let mut vote_account_data = vec![0; VoteStateV3::size_of()];
850 assert!(!VoteStateVersions::is_correct_size_and_initialized(
851 &vote_account_data
852 ));
853
854 let default_account_state = VoteStateVersions::new_v3(VoteStateV3::default());
856 VoteStateV3::serialize(&default_account_state, &mut vote_account_data).unwrap();
857 assert!(!VoteStateVersions::is_correct_size_and_initialized(
858 &vote_account_data
859 ));
860
861 let short_data = vec![1; DEFAULT_PRIOR_VOTERS_OFFSET];
863 assert!(!VoteStateVersions::is_correct_size_and_initialized(
864 &short_data
865 ));
866
867 let mut large_vote_data = vec![1; 2 * VoteStateV3::size_of()];
869 let default_account_state = VoteStateVersions::new_v3(VoteStateV3::default());
870 VoteStateV3::serialize(&default_account_state, &mut large_vote_data).unwrap();
871 assert!(!VoteStateVersions::is_correct_size_and_initialized(
872 &vote_account_data
873 ));
874
875 let vote_state = VoteStateV3::new(
877 &VoteInit {
878 node_pubkey: Pubkey::new_unique(),
879 authorized_voter: Pubkey::new_unique(),
880 authorized_withdrawer: Pubkey::new_unique(),
881 commission: 0,
882 },
883 &Clock::default(),
884 );
885 let account_state = VoteStateVersions::new_v3(vote_state.clone());
886 VoteStateV3::serialize(&account_state, &mut vote_account_data).unwrap();
887 assert!(VoteStateVersions::is_correct_size_and_initialized(
888 &vote_account_data
889 ));
890
891 let old_vote_state = VoteState1_14_11::from(vote_state);
893 let account_state = VoteStateVersions::V1_14_11(Box::new(old_vote_state));
894 let mut vote_account_data = vec![0; VoteState1_14_11::size_of()];
895 VoteStateV3::serialize(&account_state, &mut vote_account_data).unwrap();
896 assert!(VoteStateVersions::is_correct_size_and_initialized(
897 &vote_account_data
898 ));
899 }
900
901 #[test]
902 fn test_minimum_balance() {
903 let rent = atlas_rent::Rent::default();
904 let minimum_balance = rent.minimum_balance(VoteStateV3::size_of());
905 assert!(minimum_balance as f64 / 10f64.powf(9.0) < 0.04)
907 }
908
909 #[test]
910 fn test_serde_compact_vote_state_update() {
911 let mut rng = rand::thread_rng();
912 for _ in 0..5000 {
913 run_serde_compact_vote_state_update(&mut rng);
914 }
915 }
916
917 fn run_serde_compact_vote_state_update<R: Rng>(rng: &mut R) {
918 let lockouts: VecDeque<_> = std::iter::repeat_with(|| {
919 let slot = 149_303_885_u64.saturating_add(rng.gen_range(0..10_000));
920 let confirmation_count = rng.gen_range(0..33);
921 Lockout::new_with_confirmation_count(slot, confirmation_count)
922 })
923 .take(32)
924 .sorted_by_key(|lockout| lockout.slot())
925 .collect();
926 let root = rng.gen_ratio(1, 2).then(|| {
927 lockouts[0]
928 .slot()
929 .checked_sub(rng.gen_range(0..1_000))
930 .expect("All slots should be greater than 1_000")
931 });
932 let timestamp = rng.gen_ratio(1, 2).then(|| rng.gen());
933 let hash = Hash::from(rng.gen::<[u8; 32]>());
934 let vote_state_update = VoteStateUpdate {
935 lockouts,
936 root,
937 hash,
938 timestamp,
939 };
940 #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
941 enum VoteInstruction {
942 #[serde(with = "serde_compact_vote_state_update")]
943 UpdateVoteState(VoteStateUpdate),
944 UpdateVoteStateSwitch(
945 #[serde(with = "serde_compact_vote_state_update")] VoteStateUpdate,
946 Hash,
947 ),
948 }
949 let vote = VoteInstruction::UpdateVoteState(vote_state_update.clone());
950 let bytes = bincode::serialize(&vote).unwrap();
951 assert_eq!(vote, bincode::deserialize(&bytes).unwrap());
952 let hash = Hash::from(rng.gen::<[u8; 32]>());
953 let vote = VoteInstruction::UpdateVoteStateSwitch(vote_state_update, hash);
954 let bytes = bincode::serialize(&vote).unwrap();
955 assert_eq!(vote, bincode::deserialize(&bytes).unwrap());
956 }
957
958 #[test]
959 fn test_circbuf_oob() {
960 let data: &[u8] = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00];
962 let circ_buf: CircBuf<()> = bincode::deserialize(data).unwrap();
963 assert_eq!(circ_buf.last(), None);
964 }
965
966 #[test]
967 fn test_vote_state_v4_bls_pubkey_compressed() {
968 let vote_pubkey = Pubkey::new_unique();
969
970 let run_test = |start, expected| {
971 let versioned = VoteStateVersions::new_v4(start);
972 let serialized = bincode::serialize(&versioned).unwrap();
973 let deserialized = VoteStateV4::deserialize(&serialized, &vote_pubkey).unwrap();
974 assert_eq!(deserialized.bls_pubkey_compressed, expected);
975 };
976
977 let vote_state_none = VoteStateV4::default();
979 assert_eq!(vote_state_none.bls_pubkey_compressed, None);
980 run_test(vote_state_none, None);
981
982 let test_bls_key = [42u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE];
984 let vote_state_some = VoteStateV4 {
985 bls_pubkey_compressed: Some(test_bls_key),
986 ..VoteStateV4::default()
987 };
988 assert_eq!(vote_state_some.bls_pubkey_compressed, Some(test_bls_key));
989 run_test(vote_state_some, Some(test_bls_key));
990 }
991
992 #[test]
993 fn test_vote_state_version_conversion_bls_pubkey() {
994 let vote_pubkey = Pubkey::new_unique();
995
996 let v0_23_5_state = VoteState0_23_5::default();
998 let v0_23_5_versioned = VoteStateVersions::V0_23_5(Box::new(v0_23_5_state));
999
1000 let v1_14_11_state = VoteState1_14_11::default();
1001 let v1_14_11_versioned = VoteStateVersions::V1_14_11(Box::new(v1_14_11_state));
1002
1003 let v3_state = VoteStateV3::default();
1004 let v3_versioned = VoteStateVersions::V3(Box::new(v3_state));
1005
1006 for versioned in [v0_23_5_versioned, v1_14_11_versioned, v3_versioned] {
1007 let converted = versioned.try_convert_to_v4(&vote_pubkey).unwrap();
1008 assert_eq!(converted.bls_pubkey_compressed, None);
1009 }
1010
1011 let test_bls_key = [128u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE];
1013 let v4_state = VoteStateV4 {
1014 bls_pubkey_compressed: Some(test_bls_key),
1015 ..VoteStateV4::default()
1016 };
1017 let v4_versioned = VoteStateVersions::V4(Box::new(v4_state));
1018 let converted = v4_versioned.try_convert_to_v4(&vote_pubkey).unwrap();
1019 assert_eq!(converted.bls_pubkey_compressed, Some(test_bls_key));
1020 }
1021}