1use {
2 itertools::Itertools,
3 serde::de::{Deserialize, Deserializer},
4 serde::ser::{Serialize, Serializer},
5 gemachain_sdk::{
6 account::Account, account::AccountSharedData, instruction::InstructionError, pubkey::Pubkey,
7 },
8 gemachain_vote_program::vote_state::VoteState,
9 std::{
10 cmp::Ordering,
11 collections::{hash_map::Entry, HashMap},
12 iter::FromIterator,
13 sync::{Arc, Once, RwLock, RwLockReadGuard},
14 },
15};
16
17const INVALID_VOTE_STATE: Result<VoteState, InstructionError> =
20 Err(InstructionError::InvalidAccountData);
21
22#[derive(Clone, Debug, Default, PartialEq, AbiExample)]
23pub struct VoteAccount(Arc<VoteAccountInner>);
24
25#[derive(Debug, AbiExample)]
26struct VoteAccountInner {
27 account: Account,
28 vote_state: RwLock<Result<VoteState, InstructionError>>,
29 vote_state_once: Once,
30}
31
32#[derive(Debug, AbiExample)]
33pub struct VoteAccounts {
34 vote_accounts: Arc<HashMap<Pubkey, (u64, VoteAccount)>>,
35 staked_nodes: RwLock<
38 Arc<
39 HashMap<
40 Pubkey, u64, >,
43 >,
44 >,
45 staked_nodes_once: Once,
46}
47
48impl VoteAccount {
49 pub(crate) fn carats(&self) -> u64 {
50 self.0.account.carats
51 }
52
53 pub fn vote_state(&self) -> RwLockReadGuard<Result<VoteState, InstructionError>> {
54 let inner = &self.0;
55 inner.vote_state_once.call_once(|| {
56 let vote_state = VoteState::deserialize(&inner.account.data);
57 *inner.vote_state.write().unwrap() = vote_state;
58 });
59 inner.vote_state.read().unwrap()
60 }
61
62 fn node_pubkey(&self) -> Option<Pubkey> {
64 Some(self.vote_state().as_ref().ok()?.node_pubkey)
65 }
66}
67
68impl VoteAccounts {
69 pub fn staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
70 self.staked_nodes_once.call_once(|| {
71 let staked_nodes = self
72 .vote_accounts
73 .values()
74 .filter(|(stake, _)| *stake != 0)
75 .filter_map(|(stake, vote_account)| {
76 let node_pubkey = vote_account.node_pubkey()?;
77 Some((node_pubkey, stake))
78 })
79 .into_grouping_map()
80 .aggregate(|acc, _node_pubkey, stake| Some(acc.unwrap_or_default() + stake));
81 *self.staked_nodes.write().unwrap() = Arc::new(staked_nodes)
82 });
83 self.staked_nodes.read().unwrap().clone()
84 }
85
86 pub fn get(&self, pubkey: &Pubkey) -> Option<&(u64, VoteAccount)> {
87 self.vote_accounts.get(pubkey)
88 }
89
90 pub(crate) fn iter(&self) -> impl Iterator<Item = (&Pubkey, &(u64, VoteAccount))> {
91 self.vote_accounts.iter()
92 }
93
94 pub(crate) fn insert(&mut self, pubkey: Pubkey, (stake, vote_account): (u64, VoteAccount)) {
95 self.add_node_stake(stake, &vote_account);
96 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
97 if let Some((stake, vote_account)) = vote_accounts.insert(pubkey, (stake, vote_account)) {
98 self.sub_node_stake(stake, &vote_account);
99 }
100 }
101
102 pub(crate) fn remove(&mut self, pubkey: &Pubkey) -> Option<(u64, VoteAccount)> {
103 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
104 let entry = vote_accounts.remove(pubkey);
105 if let Some((stake, ref vote_account)) = entry {
106 self.sub_node_stake(stake, vote_account);
107 }
108 entry
109 }
110
111 pub(crate) fn add_stake(&mut self, pubkey: &Pubkey, delta: u64) {
112 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
113 if let Some((stake, vote_account)) = vote_accounts.get_mut(pubkey) {
114 *stake += delta;
115 let vote_account = vote_account.clone();
116 self.add_node_stake(delta, &vote_account);
117 }
118 }
119
120 pub(crate) fn sub_stake(&mut self, pubkey: &Pubkey, delta: u64) {
121 let vote_accounts = Arc::make_mut(&mut self.vote_accounts);
122 if let Some((stake, vote_account)) = vote_accounts.get_mut(pubkey) {
123 *stake = stake
124 .checked_sub(delta)
125 .expect("subtraction value exceeds account's stake");
126 let vote_account = vote_account.clone();
127 self.sub_node_stake(delta, &vote_account);
128 }
129 }
130
131 fn add_node_stake(&mut self, stake: u64, vote_account: &VoteAccount) {
132 if stake != 0 && self.staked_nodes_once.is_completed() {
133 if let Some(node_pubkey) = vote_account.node_pubkey() {
134 let mut staked_nodes = self.staked_nodes.write().unwrap();
135 let staked_nodes = Arc::make_mut(&mut staked_nodes);
136 staked_nodes
137 .entry(node_pubkey)
138 .and_modify(|s| *s += stake)
139 .or_insert(stake);
140 }
141 }
142 }
143
144 fn sub_node_stake(&mut self, stake: u64, vote_account: &VoteAccount) {
145 if stake != 0 && self.staked_nodes_once.is_completed() {
146 if let Some(node_pubkey) = vote_account.node_pubkey() {
147 let mut staked_nodes = self.staked_nodes.write().unwrap();
148 let staked_nodes = Arc::make_mut(&mut staked_nodes);
149 match staked_nodes.entry(node_pubkey) {
150 Entry::Vacant(_) => panic!("this should not happen!"),
151 Entry::Occupied(mut entry) => match entry.get().cmp(&stake) {
152 Ordering::Less => panic!("subtraction value exceeds node's stake"),
153 Ordering::Equal => {
154 entry.remove_entry();
155 }
156 Ordering::Greater => *entry.get_mut() -= stake,
157 },
158 }
159 }
160 }
161 }
162}
163
164impl Serialize for VoteAccount {
165 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
166 where
167 S: Serializer,
168 {
169 self.0.account.serialize(serializer)
170 }
171}
172
173impl<'de> Deserialize<'de> for VoteAccount {
174 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
175 where
176 D: Deserializer<'de>,
177 {
178 let account = Account::deserialize(deserializer)?;
179 Ok(Self::from(account))
180 }
181}
182
183impl From<AccountSharedData> for VoteAccount {
184 fn from(account: AccountSharedData) -> Self {
185 Self(Arc::new(VoteAccountInner::from(account)))
186 }
187}
188
189impl From<Account> for VoteAccount {
190 fn from(account: Account) -> Self {
191 Self(Arc::new(VoteAccountInner::from(account)))
192 }
193}
194
195impl From<AccountSharedData> for VoteAccountInner {
196 fn from(account: AccountSharedData) -> Self {
197 Self::from(Account::from(account))
198 }
199}
200
201impl From<Account> for VoteAccountInner {
202 fn from(account: Account) -> Self {
203 Self {
204 account,
205 vote_state: RwLock::new(INVALID_VOTE_STATE),
206 vote_state_once: Once::new(),
207 }
208 }
209}
210
211impl Default for VoteAccountInner {
212 fn default() -> Self {
213 Self {
214 account: Account::default(),
215 vote_state: RwLock::new(INVALID_VOTE_STATE),
216 vote_state_once: Once::new(),
217 }
218 }
219}
220
221impl PartialEq<VoteAccountInner> for VoteAccountInner {
222 fn eq(&self, other: &Self) -> bool {
223 self.account == other.account
224 }
225}
226
227impl Default for VoteAccounts {
228 fn default() -> Self {
229 Self {
230 vote_accounts: Arc::default(),
231 staked_nodes: RwLock::default(),
232 staked_nodes_once: Once::new(),
233 }
234 }
235}
236
237impl Clone for VoteAccounts {
238 fn clone(&self) -> Self {
239 if self.staked_nodes_once.is_completed() {
240 let staked_nodes = self.staked_nodes.read().unwrap().clone();
241 let other = Self {
242 vote_accounts: self.vote_accounts.clone(),
243 staked_nodes: RwLock::new(staked_nodes),
244 staked_nodes_once: Once::new(),
245 };
246 other.staked_nodes_once.call_once(|| {});
247 other
248 } else {
249 Self {
250 vote_accounts: self.vote_accounts.clone(),
251 staked_nodes: RwLock::default(),
252 staked_nodes_once: Once::new(),
253 }
254 }
255 }
256}
257
258impl PartialEq<VoteAccounts> for VoteAccounts {
259 fn eq(&self, other: &Self) -> bool {
260 self.vote_accounts == other.vote_accounts
261 }
262}
263
264type VoteAccountsHashMap = HashMap<Pubkey, (u64, VoteAccount)>;
265
266impl From<Arc<VoteAccountsHashMap>> for VoteAccounts {
267 fn from(vote_accounts: Arc<VoteAccountsHashMap>) -> Self {
268 Self {
269 vote_accounts,
270 staked_nodes: RwLock::default(),
271 staked_nodes_once: Once::new(),
272 }
273 }
274}
275
276impl AsRef<VoteAccountsHashMap> for VoteAccounts {
277 fn as_ref(&self) -> &VoteAccountsHashMap {
278 &self.vote_accounts
279 }
280}
281
282impl From<&VoteAccounts> for Arc<VoteAccountsHashMap> {
283 fn from(vote_accounts: &VoteAccounts) -> Self {
284 Arc::clone(&vote_accounts.vote_accounts)
285 }
286}
287
288impl FromIterator<(Pubkey, (u64, VoteAccount))> for VoteAccounts {
289 fn from_iter<I>(iter: I) -> Self
290 where
291 I: IntoIterator<Item = (Pubkey, (u64, VoteAccount))>,
292 {
293 Self::from(Arc::new(HashMap::from_iter(iter)))
294 }
295}
296
297impl Serialize for VoteAccounts {
298 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
299 where
300 S: Serializer,
301 {
302 self.vote_accounts.serialize(serializer)
303 }
304}
305
306impl<'de> Deserialize<'de> for VoteAccounts {
307 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
308 where
309 D: Deserializer<'de>,
310 {
311 let vote_accounts = VoteAccountsHashMap::deserialize(deserializer)?;
312 Ok(Self::from(Arc::new(vote_accounts)))
313 }
314}
315
316#[cfg(test)]
317mod tests {
318 use super::*;
319 use bincode::Options;
320 use rand::Rng;
321 use gemachain_sdk::{pubkey::Pubkey, sysvar::clock::Clock};
322 use gemachain_vote_program::vote_state::{VoteInit, VoteStateVersions};
323 use std::iter::repeat_with;
324
325 fn new_rand_vote_account<R: Rng>(
326 rng: &mut R,
327 node_pubkey: Option<Pubkey>,
328 ) -> (Account, VoteState) {
329 let vote_init = VoteInit {
330 node_pubkey: node_pubkey.unwrap_or_else(Pubkey::new_unique),
331 authorized_voter: Pubkey::new_unique(),
332 authorized_withdrawer: Pubkey::new_unique(),
333 commission: rng.gen(),
334 };
335 let clock = Clock {
336 slot: rng.gen(),
337 epoch_start_timestamp: rng.gen(),
338 epoch: rng.gen(),
339 leader_schedule_epoch: rng.gen(),
340 unix_timestamp: rng.gen(),
341 };
342 let vote_state = VoteState::new(&vote_init, &clock);
343 let account = Account::new_data(
344 rng.gen(), &VoteStateVersions::new_current(vote_state.clone()),
346 &Pubkey::new_unique(), )
348 .unwrap();
349 (account, vote_state)
350 }
351
352 fn new_rand_vote_accounts<R: Rng>(
353 rng: &mut R,
354 num_nodes: usize,
355 ) -> impl Iterator<Item = (Pubkey, (u64, VoteAccount))> + '_ {
356 let nodes: Vec<_> = repeat_with(Pubkey::new_unique).take(num_nodes).collect();
357 repeat_with(move || {
358 let node = nodes[rng.gen_range(0, nodes.len())];
359 let (account, _) = new_rand_vote_account(rng, Some(node));
360 let stake = rng.gen_range(0, 997);
361 (Pubkey::new_unique(), (stake, VoteAccount::from(account)))
362 })
363 }
364
365 fn staked_nodes<'a, I>(vote_accounts: I) -> HashMap<Pubkey, u64>
366 where
367 I: IntoIterator<Item = &'a (Pubkey, (u64, VoteAccount))>,
368 {
369 let mut staked_nodes = HashMap::new();
370 for (_, (stake, vote_account)) in vote_accounts
371 .into_iter()
372 .filter(|(_, (stake, _))| *stake != 0)
373 {
374 if let Some(node_pubkey) = vote_account.node_pubkey() {
375 staked_nodes
376 .entry(node_pubkey)
377 .and_modify(|s| *s += *stake)
378 .or_insert(*stake);
379 }
380 }
381 staked_nodes
382 }
383
384 #[test]
385 fn test_vote_account() {
386 let mut rng = rand::thread_rng();
387 let (account, vote_state) = new_rand_vote_account(&mut rng, None);
388 let carats = account.carats;
389 let vote_account = VoteAccount::from(account);
390 assert_eq!(carats, vote_account.carats());
391 assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap());
392 assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap());
394 }
395
396 #[test]
397 fn test_vote_account_serialize() {
398 let mut rng = rand::thread_rng();
399 let (account, vote_state) = new_rand_vote_account(&mut rng, None);
400 let vote_account = VoteAccount::from(account.clone());
401 assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap());
402 assert_eq!(
404 bincode::serialize(&account).unwrap(),
405 bincode::serialize(&vote_account).unwrap()
406 );
407 }
408
409 #[test]
410 fn test_vote_account_deserialize() {
411 let mut rng = rand::thread_rng();
412 let (account, vote_state) = new_rand_vote_account(&mut rng, None);
413 let data = bincode::serialize(&account).unwrap();
414 let vote_account = VoteAccount::from(account);
415 assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap());
416 let other_vote_account: VoteAccount = bincode::deserialize(&data).unwrap();
417 assert_eq!(vote_account, other_vote_account);
418 assert_eq!(
419 vote_state,
420 *other_vote_account.vote_state().as_ref().unwrap()
421 );
422 }
423
424 #[test]
425 fn test_vote_account_round_trip() {
426 let mut rng = rand::thread_rng();
427 let (account, vote_state) = new_rand_vote_account(&mut rng, None);
428 let vote_account = VoteAccount::from(account);
429 assert_eq!(vote_state, *vote_account.vote_state().as_ref().unwrap());
430 let data = bincode::serialize(&vote_account).unwrap();
431 let other_vote_account: VoteAccount = bincode::deserialize(&data).unwrap();
432 assert_eq!(vote_account, other_vote_account);
434 assert_eq!(
435 vote_state,
436 *other_vote_account.vote_state().as_ref().unwrap()
437 );
438 }
439
440 #[test]
441 fn test_vote_accounts_serialize() {
442 let mut rng = rand::thread_rng();
443 let vote_accounts_hash_map: HashMap<Pubkey, (u64, VoteAccount)> =
444 new_rand_vote_accounts(&mut rng, 64).take(1024).collect();
445 let vote_accounts = VoteAccounts::from(Arc::new(vote_accounts_hash_map.clone()));
446 assert!(vote_accounts.staked_nodes().len() > 32);
447 assert_eq!(
448 bincode::serialize(&vote_accounts).unwrap(),
449 bincode::serialize(&vote_accounts_hash_map).unwrap(),
450 );
451 assert_eq!(
452 bincode::options().serialize(&vote_accounts).unwrap(),
453 bincode::options()
454 .serialize(&vote_accounts_hash_map)
455 .unwrap(),
456 )
457 }
458
459 #[test]
460 fn test_vote_accounts_deserialize() {
461 let mut rng = rand::thread_rng();
462 let vote_accounts_hash_map: HashMap<Pubkey, (u64, VoteAccount)> =
463 new_rand_vote_accounts(&mut rng, 64).take(1024).collect();
464 let data = bincode::serialize(&vote_accounts_hash_map).unwrap();
465 let vote_accounts: VoteAccounts = bincode::deserialize(&data).unwrap();
466 assert!(vote_accounts.staked_nodes().len() > 32);
467 assert_eq!(*vote_accounts.vote_accounts, vote_accounts_hash_map);
468 let data = bincode::options()
469 .serialize(&vote_accounts_hash_map)
470 .unwrap();
471 let vote_accounts: VoteAccounts = bincode::options().deserialize(&data).unwrap();
472 assert_eq!(*vote_accounts.vote_accounts, vote_accounts_hash_map);
473 }
474
475 #[test]
476 fn test_staked_nodes() {
477 let mut rng = rand::thread_rng();
478 let mut accounts: Vec<_> = new_rand_vote_accounts(&mut rng, 64).take(1024).collect();
479 let mut vote_accounts = VoteAccounts::default();
480 for (k, (pubkey, (stake, vote_account))) in accounts.iter().enumerate() {
482 vote_accounts.insert(*pubkey, (*stake, vote_account.clone()));
483 if (k + 1) % 128 == 0 {
484 assert_eq!(
485 staked_nodes(&accounts[..k + 1]),
486 *vote_accounts.staked_nodes()
487 );
488 }
489 }
490 for k in 0..256 {
492 let index = rng.gen_range(0, accounts.len());
493 let (pubkey, (_, _)) = accounts.swap_remove(index);
494 vote_accounts.remove(&pubkey);
495 if (k + 1) % 32 == 0 {
496 assert_eq!(staked_nodes(&accounts), *vote_accounts.staked_nodes());
497 }
498 }
499 for k in 0..2048 {
501 let index = rng.gen_range(0, accounts.len());
502 let (pubkey, (stake, _)) = &mut accounts[index];
503 let new_stake = rng.gen_range(0, 997);
504 if new_stake < *stake {
505 vote_accounts.sub_stake(pubkey, *stake - new_stake);
506 } else {
507 vote_accounts.add_stake(pubkey, new_stake - *stake);
508 }
509 *stake = new_stake;
510 if (k + 1) % 128 == 0 {
511 assert_eq!(staked_nodes(&accounts), *vote_accounts.staked_nodes());
512 }
513 }
514 while !accounts.is_empty() {
516 let index = rng.gen_range(0, accounts.len());
517 let (pubkey, (_, _)) = accounts.swap_remove(index);
518 vote_accounts.remove(&pubkey);
519 if accounts.len() % 32 == 0 {
520 assert_eq!(staked_nodes(&accounts), *vote_accounts.staked_nodes());
521 }
522 }
523 assert!(vote_accounts.staked_nodes.read().unwrap().is_empty());
524 }
525
526 #[test]
528 fn test_staked_nodes_cow() {
529 let mut rng = rand::thread_rng();
530 let mut accounts = new_rand_vote_accounts(&mut rng, 64);
531 let mut vote_accounts = VoteAccounts::default();
533 for (pubkey, (stake, vote_account)) in (&mut accounts).take(1024) {
534 vote_accounts.insert(pubkey, (stake, vote_account));
535 }
536 let staked_nodes = vote_accounts.staked_nodes();
537 let (pubkey, (more_stake, vote_account)) =
538 accounts.find(|(_, (stake, _))| *stake != 0).unwrap();
539 let node_pubkey = vote_account.node_pubkey().unwrap();
540 vote_accounts.insert(pubkey, (more_stake, vote_account));
541 assert_ne!(staked_nodes, vote_accounts.staked_nodes());
542 assert_eq!(
543 vote_accounts.staked_nodes()[&node_pubkey],
544 more_stake + staked_nodes.get(&node_pubkey).copied().unwrap_or_default()
545 );
546 for (pubkey, stake) in vote_accounts.staked_nodes().iter() {
547 if *pubkey != node_pubkey {
548 assert_eq!(*stake, staked_nodes[pubkey]);
549 } else {
550 assert_eq!(
551 *stake,
552 more_stake + staked_nodes.get(pubkey).copied().unwrap_or_default()
553 );
554 }
555 }
556 }
557
558 #[test]
560 fn test_vote_accounts_cow() {
561 let mut rng = rand::thread_rng();
562 let mut accounts = new_rand_vote_accounts(&mut rng, 64);
563 let mut vote_accounts = VoteAccounts::default();
565 for (pubkey, (stake, vote_account)) in (&mut accounts).take(1024) {
566 vote_accounts.insert(pubkey, (stake, vote_account));
567 }
568 let vote_accounts_hashmap = Arc::<VoteAccountsHashMap>::from(&vote_accounts);
569 assert_eq!(vote_accounts_hashmap, vote_accounts.vote_accounts);
570 assert!(Arc::ptr_eq(
571 &vote_accounts_hashmap,
572 &vote_accounts.vote_accounts
573 ));
574 let (pubkey, (more_stake, vote_account)) =
575 accounts.find(|(_, (stake, _))| *stake != 0).unwrap();
576 vote_accounts.insert(pubkey, (more_stake, vote_account.clone()));
577 assert!(!Arc::ptr_eq(
578 &vote_accounts_hashmap,
579 &vote_accounts.vote_accounts
580 ));
581 assert_ne!(vote_accounts_hashmap, vote_accounts.vote_accounts);
582 let other = (more_stake, vote_account);
583 for (pk, value) in vote_accounts.iter() {
584 if *pk != pubkey {
585 assert_eq!(value, &vote_accounts_hashmap[pk]);
586 } else {
587 assert_eq!(value, &other);
588 }
589 }
590 }
591}