1use {
2 itertools::Itertools,
3 serde::{
4 de::{MapAccess, Visitor},
5 ser::{Serialize, Serializer},
6 },
7 solana_account::{AccountSharedData, ReadableAccount},
8 solana_instruction::error::InstructionError,
9 solana_pubkey::Pubkey,
10 solana_vote_interface::state::VoteState,
11 std::{
12 cmp::Ordering,
13 collections::{hash_map::Entry, HashMap},
14 fmt,
15 iter::FromIterator,
16 mem::{self, MaybeUninit},
17 ptr::addr_of_mut,
18 sync::{Arc, OnceLock},
19 },
20 thiserror::Error,
21};
22
23#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
24#[derive(Clone, Debug, PartialEq)]
25pub struct VoteAccount(Arc<VoteAccountInner>);
26
27#[derive(Debug, Error)]
28pub enum Error {
29 #[error(transparent)]
30 InstructionError(#[from] InstructionError),
31 #[error("Invalid vote account owner: {0}")]
32 InvalidOwner(Pubkey),
33}
34
35#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
36#[derive(Debug)]
37struct VoteAccountInner {
38 account: AccountSharedData,
39 vote_state: VoteState,
40}
41
42pub type VoteAccountsHashMap = HashMap<Pubkey, (u64, VoteAccount)>;
43#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
44#[derive(Debug, Serialize, Deserialize)]
45pub struct VoteAccounts {
46 #[serde(deserialize_with = "deserialize_accounts_hash_map")]
47 vote_accounts: Arc<VoteAccountsHashMap>,
48 #[serde(skip)]
50 staked_nodes: OnceLock<
51 Arc<
52 HashMap<
53 Pubkey, u64, >,
56 >,
57 >,
58}
59
60impl Clone for VoteAccounts {
61 fn clone(&self) -> Self {
62 Self {
63 vote_accounts: Arc::clone(&self.vote_accounts),
64 staked_nodes: OnceLock::new(),
69 }
70 }
71}
72
73impl VoteAccount {
74 pub fn account(&self) -> &AccountSharedData {
75 &self.0.account
76 }
77
78 pub fn lamports(&self) -> u64 {
79 self.0.account.lamports()
80 }
81
82 pub fn owner(&self) -> &Pubkey {
83 self.0.account.owner()
84 }
85
86 pub fn vote_state(&self) -> &VoteState {
87 &self.0.vote_state
88 }
89
90 pub fn node_pubkey(&self) -> &Pubkey {
92 &self.0.vote_state.node_pubkey
93 }
94
95 #[cfg(feature = "dev-context-only-utils")]
96 pub fn new_random() -> VoteAccount {
97 use {
98 rand::Rng as _,
99 solana_clock::Clock,
100 solana_vote_interface::state::{VoteInit, VoteStateVersions},
101 };
102
103 let mut rng = rand::thread_rng();
104
105 let vote_init = VoteInit {
106 node_pubkey: Pubkey::new_unique(),
107 authorized_voter: Pubkey::new_unique(),
108 authorized_withdrawer: Pubkey::new_unique(),
109 commission: rng.gen(),
110 };
111 let clock = Clock {
112 slot: rng.gen(),
113 epoch_start_timestamp: rng.gen(),
114 epoch: rng.gen(),
115 leader_schedule_epoch: rng.gen(),
116 unix_timestamp: rng.gen(),
117 };
118 let vote_state = VoteState::new(&vote_init, &clock);
119 let account = AccountSharedData::new_data(
120 rng.gen(), &VoteStateVersions::new_current(vote_state.clone()),
122 &solana_sdk_ids::vote::id(), )
124 .unwrap();
125
126 VoteAccount::try_from(account).unwrap()
127 }
128}
129
130impl VoteAccounts {
131 pub fn len(&self) -> usize {
132 self.vote_accounts.len()
133 }
134
135 pub fn is_empty(&self) -> bool {
136 self.vote_accounts.is_empty()
137 }
138
139 pub fn staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
140 self.staked_nodes
141 .get_or_init(|| {
142 Arc::new(
143 self.vote_accounts
144 .values()
145 .filter(|(stake, _)| *stake != 0u64)
146 .map(|(stake, vote_account)| (*vote_account.node_pubkey(), stake))
147 .into_grouping_map()
148 .aggregate(|acc, _node_pubkey, stake| {
149 Some(acc.unwrap_or_default() + stake)
150 }),
151 )
152 })
153 .clone()
154 }
155
156 pub fn get(&self, pubkey: &Pubkey) -> Option<&VoteAccount> {
157 let (_stake, vote_account) = self.vote_accounts.get(pubkey)?;
158 Some(vote_account)
159 }
160
161 pub fn get_delegated_stake(&self, pubkey: &Pubkey) -> u64 {
162 self.vote_accounts
163 .get(pubkey)
164 .map(|(stake, _vote_account)| *stake)
165 .unwrap_or_default()
166 }
167
168 pub fn iter(&self) -> impl Iterator<Item = (&Pubkey, &VoteAccount)> {
169 self.vote_accounts
170 .iter()
171 .map(|(vote_pubkey, (_stake, vote_account))| (vote_pubkey, vote_account))
172 }
173
174 pub fn delegated_stakes(&self) -> impl Iterator<Item = (&Pubkey, u64)> {
175 self.vote_accounts
176 .iter()
177 .map(|(vote_pubkey, (stake, _vote_account))| (vote_pubkey, *stake))
178 }
179
180 pub fn find_max_by_delegated_stake(&self) -> Option<&VoteAccount> {
181 let key = |(_pubkey, (stake, _vote_account)): &(_, &(u64, _))| *stake;
182 let (_pubkey, (_stake, vote_account)) = self.vote_accounts.iter().max_by_key(key)?;
183 Some(vote_account)
184 }
185
186 pub fn insert(
187 &mut self,
188 pubkey: Pubkey,
189 new_vote_account: VoteAccount,
190 calculate_stake: impl FnOnce() -> u64,
191 ) -> Option<VoteAccount> {
192 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
193 match vote_accounts.entry(pubkey) {
194 Entry::Occupied(mut entry) => {
195 let (stake, old_vote_account) = entry.get_mut();
197
198 if let Some(staked_nodes) = self.staked_nodes.get_mut() {
199 let old_node_pubkey = old_vote_account.node_pubkey();
200 let new_node_pubkey = new_vote_account.node_pubkey();
201 if new_node_pubkey != old_node_pubkey {
202 Self::do_sub_node_stake(staked_nodes, *stake, old_node_pubkey);
205 Self::do_add_node_stake(staked_nodes, *stake, *new_node_pubkey);
206 }
207 }
208
209 Some(mem::replace(old_vote_account, new_vote_account))
211 }
212 Entry::Vacant(entry) => {
213 let (stake, vote_account) = entry.insert((calculate_stake(), new_vote_account));
215 if let Some(staked_nodes) = self.staked_nodes.get_mut() {
216 Self::do_add_node_stake(staked_nodes, *stake, *vote_account.node_pubkey());
217 }
218 None
219 }
220 }
221 }
222
223 pub fn remove(&mut self, pubkey: &Pubkey) -> Option<(u64, VoteAccount)> {
224 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
225 let entry = vote_accounts.remove(pubkey);
226 if let Some((stake, ref vote_account)) = entry {
227 self.sub_node_stake(stake, vote_account);
228 }
229 entry
230 }
231
232 pub fn add_stake(&mut self, pubkey: &Pubkey, delta: u64) {
233 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
234 if let Some((stake, vote_account)) = vote_accounts.get_mut(pubkey) {
235 *stake += delta;
236 let vote_account = vote_account.clone();
237 self.add_node_stake(delta, &vote_account);
238 }
239 }
240
241 pub fn sub_stake(&mut self, pubkey: &Pubkey, delta: u64) {
242 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
243 if let Some((stake, vote_account)) = vote_accounts.get_mut(pubkey) {
244 *stake = stake
245 .checked_sub(delta)
246 .expect("subtraction value exceeds account's stake");
247 let vote_account = vote_account.clone();
248 self.sub_node_stake(delta, &vote_account);
249 }
250 }
251
252 fn add_node_stake(&mut self, stake: u64, vote_account: &VoteAccount) {
253 let Some(staked_nodes) = self.staked_nodes.get_mut() else {
254 return;
255 };
256
257 VoteAccounts::do_add_node_stake(staked_nodes, stake, *vote_account.node_pubkey());
258 }
259
260 fn do_add_node_stake(
261 staked_nodes: &mut Arc<HashMap<Pubkey, u64>>,
262 stake: u64,
263 node_pubkey: Pubkey,
264 ) {
265 if stake == 0u64 {
266 return;
267 }
268
269 Arc::make_mut(staked_nodes)
270 .entry(node_pubkey)
271 .and_modify(|s| *s += stake)
272 .or_insert(stake);
273 }
274
275 fn sub_node_stake(&mut self, stake: u64, vote_account: &VoteAccount) {
276 let Some(staked_nodes) = self.staked_nodes.get_mut() else {
277 return;
278 };
279
280 VoteAccounts::do_sub_node_stake(staked_nodes, stake, vote_account.node_pubkey());
281 }
282
283 fn do_sub_node_stake(
284 staked_nodes: &mut Arc<HashMap<Pubkey, u64>>,
285 stake: u64,
286 node_pubkey: &Pubkey,
287 ) {
288 if stake == 0u64 {
289 return;
290 }
291
292 let staked_nodes = Arc::make_mut(staked_nodes);
293 let current_stake = staked_nodes
294 .get_mut(node_pubkey)
295 .expect("this should not happen");
296 match (*current_stake).cmp(&stake) {
297 Ordering::Less => panic!("subtraction value exceeds node's stake"),
298 Ordering::Equal => {
299 staked_nodes.remove(node_pubkey);
300 }
301 Ordering::Greater => *current_stake -= stake,
302 }
303 }
304}
305
306impl Serialize for VoteAccount {
307 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
308 where
309 S: Serializer,
310 {
311 self.0.account.serialize(serializer)
312 }
313}
314
315impl From<VoteAccount> for AccountSharedData {
316 fn from(account: VoteAccount) -> Self {
317 account.0.account.clone()
318 }
319}
320
321impl TryFrom<AccountSharedData> for VoteAccount {
322 type Error = Error;
323 fn try_from(account: AccountSharedData) -> Result<Self, Self::Error> {
324 if !solana_sdk_ids::vote::check_id(account.owner()) {
325 return Err(Error::InvalidOwner(*account.owner()));
326 }
327
328 let mut inner = Arc::new(MaybeUninit::<VoteAccountInner>::uninit());
330 let inner_ptr = Arc::get_mut(&mut inner)
331 .expect("we're the only ref")
332 .as_mut_ptr();
333
334 unsafe {
340 let vote_state = addr_of_mut!((*inner_ptr).vote_state);
341 let vote_state = &mut *(vote_state as *mut MaybeUninit<VoteState>);
347
348 if let Err(e) = VoteState::deserialize_into_uninit(account.data(), vote_state) {
350 return Err(e.into());
356 }
357
358 addr_of_mut!((*inner_ptr).account).write(account);
360
361 Ok(VoteAccount(mem::transmute::<
365 Arc<MaybeUninit<VoteAccountInner>>,
366 Arc<VoteAccountInner>,
367 >(inner)))
368 }
369 }
370}
371
372impl PartialEq<VoteAccountInner> for VoteAccountInner {
373 fn eq(&self, other: &Self) -> bool {
374 let Self {
375 account,
376 vote_state: _,
377 } = self;
378 account == &other.account
379 }
380}
381
382impl Default for VoteAccounts {
383 fn default() -> Self {
384 Self {
385 vote_accounts: Arc::default(),
386 staked_nodes: OnceLock::new(),
387 }
388 }
389}
390
391impl PartialEq<VoteAccounts> for VoteAccounts {
392 fn eq(&self, other: &Self) -> bool {
393 let Self {
394 vote_accounts,
395 staked_nodes: _,
396 } = self;
397 vote_accounts == &other.vote_accounts
398 }
399}
400
401impl From<Arc<VoteAccountsHashMap>> for VoteAccounts {
402 fn from(vote_accounts: Arc<VoteAccountsHashMap>) -> Self {
403 Self {
404 vote_accounts,
405 staked_nodes: OnceLock::new(),
406 }
407 }
408}
409
410impl AsRef<VoteAccountsHashMap> for VoteAccounts {
411 fn as_ref(&self) -> &VoteAccountsHashMap {
412 &self.vote_accounts
413 }
414}
415
416impl From<&VoteAccounts> for Arc<VoteAccountsHashMap> {
417 fn from(vote_accounts: &VoteAccounts) -> Self {
418 Arc::clone(&vote_accounts.vote_accounts)
419 }
420}
421
422impl FromIterator<(Pubkey, (u64, VoteAccount))> for VoteAccounts {
423 fn from_iter<I>(iter: I) -> Self
424 where
425 I: IntoIterator<Item = (Pubkey, (u64, VoteAccount))>,
426 {
427 Self::from(Arc::new(HashMap::from_iter(iter)))
428 }
429}
430
431fn deserialize_accounts_hash_map<'de, D>(
438 deserializer: D,
439) -> Result<Arc<VoteAccountsHashMap>, D::Error>
440where
441 D: serde::Deserializer<'de>,
442{
443 struct VoteAccountsVisitor;
444
445 impl<'de> Visitor<'de> for VoteAccountsVisitor {
446 type Value = Arc<VoteAccountsHashMap>;
447
448 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
449 formatter.write_str("a map of vote accounts")
450 }
451
452 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
453 where
454 M: MapAccess<'de>,
455 {
456 let mut accounts = HashMap::new();
457
458 while let Some((pubkey, (stake, account))) =
459 access.next_entry::<Pubkey, (u64, AccountSharedData)>()?
460 {
461 match VoteAccount::try_from(account) {
462 Ok(vote_account) => {
463 accounts.insert(pubkey, (stake, vote_account));
464 }
465 Err(e) => {
466 log::warn!("failed to deserialize vote account: {e}");
467 }
468 }
469 }
470
471 Ok(Arc::new(accounts))
472 }
473 }
474
475 deserializer.deserialize_map(VoteAccountsVisitor)
476}
477
478#[cfg(test)]
479mod tests {
480 use {
481 super::*,
482 bincode::Options,
483 rand::Rng,
484 solana_account::WritableAccount,
485 solana_clock::Clock,
486 solana_pubkey::Pubkey,
487 solana_vote_interface::state::{VoteInit, VoteStateVersions},
488 std::iter::repeat_with,
489 };
490
491 fn new_rand_vote_account<R: Rng>(
492 rng: &mut R,
493 node_pubkey: Option<Pubkey>,
494 ) -> (AccountSharedData, VoteState) {
495 let vote_init = VoteInit {
496 node_pubkey: node_pubkey.unwrap_or_else(Pubkey::new_unique),
497 authorized_voter: Pubkey::new_unique(),
498 authorized_withdrawer: Pubkey::new_unique(),
499 commission: rng.gen(),
500 };
501 let clock = Clock {
502 slot: rng.gen(),
503 epoch_start_timestamp: rng.gen(),
504 epoch: rng.gen(),
505 leader_schedule_epoch: rng.gen(),
506 unix_timestamp: rng.gen(),
507 };
508 let vote_state = VoteState::new(&vote_init, &clock);
509 let account = AccountSharedData::new_data(
510 rng.gen(), &VoteStateVersions::new_current(vote_state.clone()),
512 &solana_sdk_ids::vote::id(), )
514 .unwrap();
515 (account, vote_state)
516 }
517
518 fn new_rand_vote_accounts<R: Rng>(
519 rng: &mut R,
520 num_nodes: usize,
521 ) -> impl Iterator<Item = (Pubkey, (u64, VoteAccount))> + '_ {
522 let nodes: Vec<_> = repeat_with(Pubkey::new_unique).take(num_nodes).collect();
523 repeat_with(move || {
524 let node = nodes[rng.gen_range(0..nodes.len())];
525 let (account, _) = new_rand_vote_account(rng, Some(node));
526 let stake = rng.gen_range(0..997);
527 let vote_account = VoteAccount::try_from(account).unwrap();
528 (Pubkey::new_unique(), (stake, vote_account))
529 })
530 }
531
532 fn staked_nodes<'a, I>(vote_accounts: I) -> HashMap<Pubkey, u64>
533 where
534 I: IntoIterator<Item = &'a (Pubkey, (u64, VoteAccount))>,
535 {
536 let mut staked_nodes = HashMap::new();
537 for (_, (stake, vote_account)) in vote_accounts
538 .into_iter()
539 .filter(|(_, (stake, _))| *stake != 0)
540 {
541 staked_nodes
542 .entry(*vote_account.node_pubkey())
543 .and_modify(|s| *s += *stake)
544 .or_insert(*stake);
545 }
546 staked_nodes
547 }
548
549 #[test]
550 fn test_vote_account_try_from() {
551 let mut rng = rand::thread_rng();
552 let (account, vote_state) = new_rand_vote_account(&mut rng, None);
553 let lamports = account.lamports();
554 let vote_account = VoteAccount::try_from(account.clone()).unwrap();
555 assert_eq!(lamports, vote_account.lamports());
556 assert_eq!(vote_state, *vote_account.vote_state());
557 assert_eq!(&account, vote_account.account());
558 }
559
560 #[test]
561 #[should_panic(expected = "InvalidOwner")]
562 fn test_vote_account_try_from_invalid_owner() {
563 let mut rng = rand::thread_rng();
564 let (mut account, _) = new_rand_vote_account(&mut rng, None);
565 account.set_owner(Pubkey::new_unique());
566 VoteAccount::try_from(account).unwrap();
567 }
568
569 #[test]
570 #[should_panic(expected = "InvalidAccountData")]
571 fn test_vote_account_try_from_invalid_account() {
572 let mut account = AccountSharedData::default();
573 account.set_owner(solana_sdk_ids::vote::id());
574 VoteAccount::try_from(account).unwrap();
575 }
576
577 #[test]
578 fn test_vote_account_serialize() {
579 let mut rng = rand::thread_rng();
580 let (account, vote_state) = new_rand_vote_account(&mut rng, None);
581 let vote_account = VoteAccount::try_from(account.clone()).unwrap();
582 assert_eq!(vote_state, *vote_account.vote_state());
583 assert_eq!(
585 bincode::serialize(&account).unwrap(),
586 bincode::serialize(&vote_account).unwrap()
587 );
588 }
589
590 #[test]
591 fn test_vote_accounts_serialize() {
592 let mut rng = rand::thread_rng();
593 let vote_accounts_hash_map: VoteAccountsHashMap =
594 new_rand_vote_accounts(&mut rng, 64).take(1024).collect();
595 let vote_accounts = VoteAccounts::from(Arc::new(vote_accounts_hash_map.clone()));
596 assert!(vote_accounts.staked_nodes().len() > 32);
597 assert_eq!(
598 bincode::serialize(&vote_accounts).unwrap(),
599 bincode::serialize(&vote_accounts_hash_map).unwrap(),
600 );
601 assert_eq!(
602 bincode::options().serialize(&vote_accounts).unwrap(),
603 bincode::options()
604 .serialize(&vote_accounts_hash_map)
605 .unwrap(),
606 )
607 }
608
609 #[test]
610 fn test_vote_accounts_deserialize() {
611 let mut rng = rand::thread_rng();
612 let vote_accounts_hash_map: VoteAccountsHashMap =
613 new_rand_vote_accounts(&mut rng, 64).take(1024).collect();
614 let data = bincode::serialize(&vote_accounts_hash_map).unwrap();
615 let vote_accounts: VoteAccounts = bincode::deserialize(&data).unwrap();
616 assert!(vote_accounts.staked_nodes().len() > 32);
617 assert_eq!(*vote_accounts.vote_accounts, vote_accounts_hash_map);
618 let data = bincode::options()
619 .serialize(&vote_accounts_hash_map)
620 .unwrap();
621 let vote_accounts: VoteAccounts = bincode::options().deserialize(&data).unwrap();
622 assert_eq!(*vote_accounts.vote_accounts, vote_accounts_hash_map);
623 }
624
625 #[test]
626 fn test_vote_accounts_deserialize_invalid_account() {
627 let mut rng = rand::thread_rng();
628 let mut vote_accounts_hash_map = HashMap::<Pubkey, (u64, AccountSharedData)>::new();
631
632 let (valid_account, _) = new_rand_vote_account(&mut rng, None);
633 vote_accounts_hash_map.insert(Pubkey::new_unique(), (0xAA, valid_account.clone()));
634
635 let invalid_account_data =
637 AccountSharedData::new_data(42, &vec![0xFF; 42], &solana_sdk_ids::vote::id()).unwrap();
638 vote_accounts_hash_map.insert(Pubkey::new_unique(), (0xBB, invalid_account_data));
639
640 let invalid_account_key =
642 AccountSharedData::new_data(42, &valid_account.data().to_vec(), &Pubkey::new_unique())
643 .unwrap();
644 vote_accounts_hash_map.insert(Pubkey::new_unique(), (0xCC, invalid_account_key));
645
646 let data = bincode::serialize(&vote_accounts_hash_map).unwrap();
647 let options = bincode::options()
648 .with_fixint_encoding()
649 .allow_trailing_bytes();
650 let mut deserializer = bincode::de::Deserializer::from_slice(&data, options);
651 let vote_accounts = deserialize_accounts_hash_map(&mut deserializer).unwrap();
652
653 assert_eq!(vote_accounts.len(), 1);
654 let (stake, _account) = vote_accounts.values().next().unwrap();
655 assert_eq!(*stake, 0xAA);
656 }
657
658 #[test]
659 fn test_staked_nodes() {
660 let mut rng = rand::thread_rng();
661 let mut accounts: Vec<_> = new_rand_vote_accounts(&mut rng, 64).take(1024).collect();
662 let mut vote_accounts = VoteAccounts::default();
663 for (k, (pubkey, (stake, vote_account))) in accounts.iter().enumerate() {
665 vote_accounts.insert(*pubkey, vote_account.clone(), || *stake);
666 if (k + 1) % 128 == 0 {
667 assert_eq!(
668 staked_nodes(&accounts[..k + 1]),
669 *vote_accounts.staked_nodes()
670 );
671 }
672 }
673 for k in 0..256 {
675 let index = rng.gen_range(0..accounts.len());
676 let (pubkey, (_, _)) = accounts.swap_remove(index);
677 vote_accounts.remove(&pubkey);
678 if (k + 1) % 32 == 0 {
679 assert_eq!(staked_nodes(&accounts), *vote_accounts.staked_nodes());
680 }
681 }
682 for k in 0..2048 {
684 let index = rng.gen_range(0..accounts.len());
685 let (pubkey, (stake, _)) = &mut accounts[index];
686 let new_stake = rng.gen_range(0..997);
687 if new_stake < *stake {
688 vote_accounts.sub_stake(pubkey, *stake - new_stake);
689 } else {
690 vote_accounts.add_stake(pubkey, new_stake - *stake);
691 }
692 *stake = new_stake;
693 if (k + 1) % 128 == 0 {
694 assert_eq!(staked_nodes(&accounts), *vote_accounts.staked_nodes());
695 }
696 }
697 while !accounts.is_empty() {
699 let index = rng.gen_range(0..accounts.len());
700 let (pubkey, (_, _)) = accounts.swap_remove(index);
701 vote_accounts.remove(&pubkey);
702 if accounts.len() % 32 == 0 {
703 assert_eq!(staked_nodes(&accounts), *vote_accounts.staked_nodes());
704 }
705 }
706 assert!(vote_accounts.staked_nodes.get().unwrap().is_empty());
707 }
708
709 #[test]
710 fn test_staked_nodes_update() {
711 let mut vote_accounts = VoteAccounts::default();
712
713 let mut rng = rand::thread_rng();
714 let pubkey = Pubkey::new_unique();
715 let node_pubkey = Pubkey::new_unique();
716 let (account1, _) = new_rand_vote_account(&mut rng, Some(node_pubkey));
717 let vote_account1 = VoteAccount::try_from(account1).unwrap();
718
719 let ret = vote_accounts.insert(pubkey, vote_account1.clone(), || 42);
721 assert_eq!(ret, None);
722 assert_eq!(vote_accounts.get_delegated_stake(&pubkey), 42);
723 assert_eq!(vote_accounts.staked_nodes().get(&node_pubkey), Some(&42));
724
725 let ret = vote_accounts.insert(pubkey, vote_account1.clone(), || {
727 panic!("should not be called")
728 });
729 assert_eq!(ret, Some(vote_account1.clone()));
730 assert_eq!(vote_accounts.get(&pubkey), Some(&vote_account1));
731 assert_eq!(vote_accounts.get_delegated_stake(&pubkey), 42);
733 assert_eq!(vote_accounts.staked_nodes().get(&node_pubkey), Some(&42));
734
735 let (account2, _) = new_rand_vote_account(&mut rng, Some(node_pubkey));
737 let vote_account2 = VoteAccount::try_from(account2).unwrap();
738 let ret = vote_accounts.insert(pubkey, vote_account2.clone(), || {
739 panic!("should not be called")
740 });
741 assert_eq!(ret, Some(vote_account1.clone()));
742 assert_eq!(vote_accounts.get(&pubkey), Some(&vote_account2));
743 assert_eq!(vote_accounts.get_delegated_stake(&pubkey), 42);
745 assert_eq!(vote_accounts.staked_nodes().get(&node_pubkey), Some(&42));
746
747 let new_node_pubkey = Pubkey::new_unique();
749 let (account3, _) = new_rand_vote_account(&mut rng, Some(new_node_pubkey));
750 let vote_account3 = VoteAccount::try_from(account3).unwrap();
751 let ret = vote_accounts.insert(pubkey, vote_account3.clone(), || {
752 panic!("should not be called")
753 });
754 assert_eq!(ret, Some(vote_account2.clone()));
755 assert_eq!(vote_accounts.staked_nodes().get(&node_pubkey), None);
756 assert_eq!(
757 vote_accounts.staked_nodes().get(&new_node_pubkey),
758 Some(&42)
759 );
760 }
761
762 #[test]
763 fn test_staked_nodes_zero_stake() {
764 let mut vote_accounts = VoteAccounts::default();
765
766 let mut rng = rand::thread_rng();
767 let pubkey = Pubkey::new_unique();
768 let node_pubkey = Pubkey::new_unique();
769 let (account1, _) = new_rand_vote_account(&mut rng, Some(node_pubkey));
770 let vote_account1 = VoteAccount::try_from(account1).unwrap();
771
772 assert!(vote_accounts.staked_nodes().is_empty());
774 let ret = vote_accounts.insert(pubkey, vote_account1.clone(), || 0);
775 assert_eq!(ret, None);
776 assert_eq!(vote_accounts.get_delegated_stake(&pubkey), 0);
777 assert_eq!(vote_accounts.staked_nodes().get(&node_pubkey), None);
779
780 let new_node_pubkey = Pubkey::new_unique();
782 let (account2, _) = new_rand_vote_account(&mut rng, Some(new_node_pubkey));
783 let vote_account2 = VoteAccount::try_from(account2).unwrap();
784 let ret = vote_accounts.insert(pubkey, vote_account2.clone(), || {
785 panic!("should not be called")
786 });
787 assert_eq!(ret, Some(vote_account1));
788 assert_eq!(vote_accounts.get_delegated_stake(&pubkey), 0);
789 assert_eq!(vote_accounts.staked_nodes().get(&node_pubkey), None);
790 assert_eq!(vote_accounts.staked_nodes().get(&new_node_pubkey), None);
791 }
792
793 #[test]
795 fn test_staked_nodes_cow() {
796 let mut rng = rand::thread_rng();
797 let mut accounts = new_rand_vote_accounts(&mut rng, 64);
798 let mut vote_accounts = VoteAccounts::default();
800 for (pubkey, (stake, vote_account)) in (&mut accounts).take(1024) {
801 vote_accounts.insert(pubkey, vote_account, || stake);
802 }
803 let staked_nodes = vote_accounts.staked_nodes();
804 let (pubkey, (more_stake, vote_account)) =
805 accounts.find(|(_, (stake, _))| *stake != 0).unwrap();
806 let node_pubkey = *vote_account.node_pubkey();
807 vote_accounts.insert(pubkey, vote_account, || more_stake);
808 assert_ne!(staked_nodes, vote_accounts.staked_nodes());
809 assert_eq!(
810 vote_accounts.staked_nodes()[&node_pubkey],
811 more_stake + staked_nodes.get(&node_pubkey).copied().unwrap_or_default()
812 );
813 for (pubkey, stake) in vote_accounts.staked_nodes().iter() {
814 if pubkey != &node_pubkey {
815 assert_eq!(*stake, staked_nodes[pubkey]);
816 } else {
817 assert_eq!(
818 *stake,
819 more_stake + staked_nodes.get(pubkey).copied().unwrap_or_default()
820 );
821 }
822 }
823 }
824
825 #[test]
827 fn test_vote_accounts_cow() {
828 let mut rng = rand::thread_rng();
829 let mut accounts = new_rand_vote_accounts(&mut rng, 64);
830 let mut vote_accounts = VoteAccounts::default();
832 for (pubkey, (stake, vote_account)) in (&mut accounts).take(1024) {
833 vote_accounts.insert(pubkey, vote_account, || stake);
834 }
835 let vote_accounts_hashmap = Arc::<VoteAccountsHashMap>::from(&vote_accounts);
836 assert_eq!(vote_accounts_hashmap, vote_accounts.vote_accounts);
837 assert!(Arc::ptr_eq(
838 &vote_accounts_hashmap,
839 &vote_accounts.vote_accounts
840 ));
841 let (pubkey, (more_stake, vote_account)) =
842 accounts.find(|(_, (stake, _))| *stake != 0).unwrap();
843 vote_accounts.insert(pubkey, vote_account.clone(), || more_stake);
844 assert!(!Arc::ptr_eq(
845 &vote_accounts_hashmap,
846 &vote_accounts.vote_accounts
847 ));
848 assert_ne!(vote_accounts_hashmap, vote_accounts.vote_accounts);
849 let other = (more_stake, vote_account);
850 for (pk, value) in vote_accounts.vote_accounts.iter() {
851 if *pk != pubkey {
852 assert_eq!(value, &vote_accounts_hashmap[pk]);
853 } else {
854 assert_eq!(value, &other);
855 }
856 }
857 }
858}