hotshot/traits/election/
static_committee_leader_two_views.rs1use std::collections::{BTreeMap, BTreeSet};
8
9use alloy::primitives::U256;
10use hotshot_types::{
11 drb::DrbResult,
12 stake_table::HSStakeTable,
13 traits::{
14 election::Membership,
15 node_implementation::NodeType,
16 signature_key::{SignatureKey, StakeTableEntryType},
17 },
18 PeerConfig,
19};
20use hotshot_utils::anytrace::Result;
21
22#[derive(Clone, Debug, Eq, PartialEq, Hash)]
23
24pub struct StaticCommitteeLeaderForTwoViews<T: NodeType> {
26 eligible_leaders: Vec<PeerConfig<T>>,
30
31 stake_table: HSStakeTable<T>,
33
34 da_stake_table: HSStakeTable<T>,
36
37 indexed_stake_table: BTreeMap<T::SignatureKey, PeerConfig<T>>,
39
40 indexed_da_stake_table: BTreeMap<T::SignatureKey, PeerConfig<T>>,
42}
43
44impl<TYPES: NodeType> Membership<TYPES> for StaticCommitteeLeaderForTwoViews<TYPES> {
45 type Error = hotshot_utils::anytrace::Error;
46 fn new(committee_members: Vec<PeerConfig<TYPES>>, da_members: Vec<PeerConfig<TYPES>>) -> Self {
48 let eligible_leaders: Vec<PeerConfig<TYPES>> = committee_members
50 .iter()
51 .filter(|&member| member.stake_table_entry.stake() > U256::ZERO)
52 .cloned()
53 .collect();
54
55 let members: Vec<PeerConfig<TYPES>> = committee_members
57 .iter()
58 .filter(|&member| member.stake_table_entry.stake() > U256::ZERO)
59 .cloned()
60 .collect();
61
62 let da_members: Vec<PeerConfig<TYPES>> = da_members
64 .iter()
65 .filter(|&member| member.stake_table_entry.stake() > U256::ZERO)
66 .cloned()
67 .collect();
68
69 let indexed_stake_table: BTreeMap<TYPES::SignatureKey, PeerConfig<TYPES>> = members
71 .iter()
72 .map(|member| {
73 (
74 TYPES::SignatureKey::public_key(&member.stake_table_entry),
75 member.clone(),
76 )
77 })
78 .collect();
79
80 let indexed_da_stake_table: BTreeMap<TYPES::SignatureKey, PeerConfig<TYPES>> = da_members
82 .iter()
83 .map(|member| {
84 (
85 TYPES::SignatureKey::public_key(&member.stake_table_entry),
86 member.clone(),
87 )
88 })
89 .collect();
90
91 Self {
92 eligible_leaders,
93 stake_table: members.into(),
94 da_stake_table: da_members.into(),
95 indexed_stake_table,
96 indexed_da_stake_table,
97 }
98 }
99
100 fn stake_table(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> HSStakeTable<TYPES> {
102 self.stake_table.clone()
103 }
104
105 fn da_stake_table(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> HSStakeTable<TYPES> {
107 self.da_stake_table.clone()
108 }
109
110 fn committee_members(
112 &self,
113 _view_number: <TYPES as NodeType>::View,
114 _epoch: Option<<TYPES as NodeType>::Epoch>,
115 ) -> BTreeSet<<TYPES as NodeType>::SignatureKey> {
116 self.stake_table
117 .iter()
118 .map(|sc| TYPES::SignatureKey::public_key(&sc.stake_table_entry))
119 .collect()
120 }
121
122 fn da_committee_members(
124 &self,
125 _view_number: <TYPES as NodeType>::View,
126 _epoch: Option<<TYPES as NodeType>::Epoch>,
127 ) -> BTreeSet<<TYPES as NodeType>::SignatureKey> {
128 self.da_stake_table
129 .iter()
130 .map(|da| TYPES::SignatureKey::public_key(&da.stake_table_entry))
131 .collect()
132 }
133
134 fn stake(
136 &self,
137 pub_key: &<TYPES as NodeType>::SignatureKey,
138 _epoch: Option<<TYPES as NodeType>::Epoch>,
139 ) -> Option<PeerConfig<TYPES>> {
140 self.indexed_stake_table.get(pub_key).cloned()
142 }
143
144 fn da_stake(
146 &self,
147 pub_key: &<TYPES as NodeType>::SignatureKey,
148 _epoch: Option<<TYPES as NodeType>::Epoch>,
149 ) -> Option<PeerConfig<TYPES>> {
150 self.indexed_da_stake_table.get(pub_key).cloned()
152 }
153
154 fn has_stake(
156 &self,
157 pub_key: &<TYPES as NodeType>::SignatureKey,
158 _epoch: Option<<TYPES as NodeType>::Epoch>,
159 ) -> bool {
160 self.indexed_stake_table
161 .get(pub_key)
162 .is_some_and(|x| x.stake_table_entry.stake() > U256::ZERO)
163 }
164
165 fn has_da_stake(
167 &self,
168 pub_key: &<TYPES as NodeType>::SignatureKey,
169 _epoch: Option<<TYPES as NodeType>::Epoch>,
170 ) -> bool {
171 self.indexed_da_stake_table
172 .get(pub_key)
173 .is_some_and(|x| x.stake_table_entry.stake() > U256::ZERO)
174 }
175
176 fn lookup_leader(
178 &self,
179 view_number: <TYPES as NodeType>::View,
180 _epoch: Option<<TYPES as NodeType>::Epoch>,
181 ) -> Result<TYPES::SignatureKey> {
182 let index =
183 usize::try_from((*view_number / 2) % self.eligible_leaders.len() as u64).unwrap();
184 let res = self.eligible_leaders[index].clone();
185
186 Ok(TYPES::SignatureKey::public_key(&res.stake_table_entry))
187 }
188
189 fn total_nodes(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> usize {
191 self.stake_table.len()
192 }
193
194 fn da_total_nodes(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> usize {
196 self.da_stake_table.len()
197 }
198
199 fn success_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
201 U256::from(((self.stake_table.len() as u64 * 2) / 3) + 1)
202 }
203
204 fn da_success_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
206 U256::from(((self.da_stake_table.len() as u64 * 2) / 3) + 1)
207 }
208
209 fn failure_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
211 U256::from(((self.stake_table.len() as u64) / 3) + 1)
212 }
213
214 fn upgrade_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
216 U256::from(((self.stake_table.len() as u64 * 9) / 10) + 1)
217 }
218 fn has_stake_table(&self, _epoch: TYPES::Epoch) -> bool {
219 true
220 }
221 fn has_randomized_stake_table(&self, _epoch: TYPES::Epoch) -> anyhow::Result<bool> {
222 Ok(true)
223 }
224
225 fn add_drb_result(&mut self, _epoch: <TYPES as NodeType>::Epoch, _drb_result: DrbResult) {}
226}