1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use log::*;
use serde_derive::{Deserialize, Serialize};
use solana_sdk::{clock::Epoch, pubkey::Pubkey};
use std::collections::BTreeMap;
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone, AbiExample)]
pub struct AuthorizedVoters {
authorized_voters: BTreeMap<Epoch, Pubkey>,
}
impl AuthorizedVoters {
pub fn new(epoch: Epoch, pubkey: Pubkey) -> Self {
let mut authorized_voters = BTreeMap::new();
authorized_voters.insert(epoch, pubkey);
Self { authorized_voters }
}
pub fn get_authorized_voter(&self, epoch: Epoch) -> Option<Pubkey> {
self.get_or_calculate_authorized_voter_for_epoch(epoch)
.map(|(pubkey, _)| pubkey)
}
pub fn get_and_cache_authorized_voter_for_epoch(&mut self, epoch: Epoch) -> Option<Pubkey> {
let res = self.get_or_calculate_authorized_voter_for_epoch(epoch);
res.map(|(pubkey, existed)| {
if !existed {
self.authorized_voters.insert(epoch, pubkey);
}
pubkey
})
}
pub fn insert(&mut self, epoch: Epoch, authorized_voter: Pubkey) {
self.authorized_voters.insert(epoch, authorized_voter);
}
pub fn purge_authorized_voters(&mut self, current_epoch: Epoch) -> bool {
let expired_keys: Vec<_> = self
.authorized_voters
.range(0..current_epoch)
.map(|(authorized_epoch, _)| *authorized_epoch)
.collect();
for key in expired_keys {
self.authorized_voters.remove(&key);
}
assert!(!self.authorized_voters.is_empty());
true
}
pub fn is_empty(&self) -> bool {
self.authorized_voters.is_empty()
}
pub fn first(&self) -> Option<(&u64, &Pubkey)> {
self.authorized_voters.iter().next()
}
pub fn last(&self) -> Option<(&u64, &Pubkey)> {
self.authorized_voters.iter().next_back()
}
pub fn len(&self) -> usize {
self.authorized_voters.len()
}
pub fn contains(&self, epoch: Epoch) -> bool {
self.authorized_voters.get(&epoch).is_some()
}
pub fn iter(&self) -> std::collections::btree_map::Iter<Epoch, Pubkey> {
self.authorized_voters.iter()
}
fn get_or_calculate_authorized_voter_for_epoch(&self, epoch: Epoch) -> Option<(Pubkey, bool)> {
let res = self.authorized_voters.get(&epoch);
if res.is_none() {
let res = self.authorized_voters.range(0..epoch).next_back();
if res.is_none() {
warn!(
"Tried to query for the authorized voter of an epoch earlier
than the current epoch. Earlier epochs have been purged"
);
}
res.map(|(_, pubkey)| (*pubkey, false))
} else {
res.map(|pubkey| (*pubkey, true))
}
}
}