hotshot/traits/election/
static_committee_leader_two_views.rs1use std::collections::{BTreeMap, BTreeSet};
8
9use alloy::primitives::U256;
10use anyhow::Context;
11use hotshot_types::{
12 drb::DrbResult,
13 stake_table::HSStakeTable,
14 traits::{
15 election::{Membership, NoStakeTableHash},
16 node_implementation::NodeType,
17 signature_key::{SignatureKey, StakeTableEntryType},
18 },
19 PeerConfig,
20};
21use hotshot_utils::anytrace::Result;
22
23use crate::{Arc, RwLock};
24
25#[derive(Clone, Debug, Eq, PartialEq, Hash)]
26
27pub struct StaticCommitteeLeaderForTwoViews<T: NodeType> {
29 eligible_leaders: Vec<PeerConfig<T>>,
33
34 stake_table: HSStakeTable<T>,
36
37 da_stake_table: HSStakeTable<T>,
39
40 indexed_stake_table: BTreeMap<T::SignatureKey, PeerConfig<T>>,
42
43 indexed_da_stake_table: BTreeMap<T::SignatureKey, PeerConfig<T>>,
45
46 drb_results: BTreeMap<T::Epoch, DrbResult>,
48}
49
50impl<TYPES: NodeType> Membership<TYPES> for StaticCommitteeLeaderForTwoViews<TYPES> {
51 type Error = hotshot_utils::anytrace::Error;
52 type StakeTableHash = NoStakeTableHash;
53 fn new(committee_members: Vec<PeerConfig<TYPES>>, da_members: Vec<PeerConfig<TYPES>>) -> Self {
55 let eligible_leaders: Vec<PeerConfig<TYPES>> = committee_members
57 .iter()
58 .filter(|&member| member.stake_table_entry.stake() > U256::ZERO)
59 .cloned()
60 .collect();
61
62 let members: Vec<PeerConfig<TYPES>> = committee_members
64 .iter()
65 .filter(|&member| member.stake_table_entry.stake() > U256::ZERO)
66 .cloned()
67 .collect();
68
69 let da_members: Vec<PeerConfig<TYPES>> = da_members
71 .iter()
72 .filter(|&member| member.stake_table_entry.stake() > U256::ZERO)
73 .cloned()
74 .collect();
75
76 let indexed_stake_table: BTreeMap<TYPES::SignatureKey, PeerConfig<TYPES>> = members
78 .iter()
79 .map(|member| {
80 (
81 TYPES::SignatureKey::public_key(&member.stake_table_entry),
82 member.clone(),
83 )
84 })
85 .collect();
86
87 let indexed_da_stake_table: BTreeMap<TYPES::SignatureKey, PeerConfig<TYPES>> = da_members
89 .iter()
90 .map(|member| {
91 (
92 TYPES::SignatureKey::public_key(&member.stake_table_entry),
93 member.clone(),
94 )
95 })
96 .collect();
97
98 Self {
99 eligible_leaders,
100 stake_table: members.into(),
101 da_stake_table: da_members.into(),
102 indexed_stake_table,
103 indexed_da_stake_table,
104 drb_results: BTreeMap::new(),
105 }
106 }
107
108 fn stake_table(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> HSStakeTable<TYPES> {
110 self.stake_table.clone()
111 }
112
113 fn da_stake_table(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> HSStakeTable<TYPES> {
115 self.da_stake_table.clone()
116 }
117
118 fn committee_members(
120 &self,
121 _view_number: <TYPES as NodeType>::View,
122 _epoch: Option<<TYPES as NodeType>::Epoch>,
123 ) -> BTreeSet<<TYPES as NodeType>::SignatureKey> {
124 self.stake_table
125 .iter()
126 .map(|sc| TYPES::SignatureKey::public_key(&sc.stake_table_entry))
127 .collect()
128 }
129
130 fn da_committee_members(
132 &self,
133 _view_number: <TYPES as NodeType>::View,
134 _epoch: Option<<TYPES as NodeType>::Epoch>,
135 ) -> BTreeSet<<TYPES as NodeType>::SignatureKey> {
136 self.da_stake_table
137 .iter()
138 .map(|da| TYPES::SignatureKey::public_key(&da.stake_table_entry))
139 .collect()
140 }
141
142 fn stake(
144 &self,
145 pub_key: &<TYPES as NodeType>::SignatureKey,
146 _epoch: Option<<TYPES as NodeType>::Epoch>,
147 ) -> Option<PeerConfig<TYPES>> {
148 self.indexed_stake_table.get(pub_key).cloned()
150 }
151
152 fn da_stake(
154 &self,
155 pub_key: &<TYPES as NodeType>::SignatureKey,
156 _epoch: Option<<TYPES as NodeType>::Epoch>,
157 ) -> Option<PeerConfig<TYPES>> {
158 self.indexed_da_stake_table.get(pub_key).cloned()
160 }
161
162 fn has_stake(
164 &self,
165 pub_key: &<TYPES as NodeType>::SignatureKey,
166 _epoch: Option<<TYPES as NodeType>::Epoch>,
167 ) -> bool {
168 self.indexed_stake_table
169 .get(pub_key)
170 .is_some_and(|x| x.stake_table_entry.stake() > U256::ZERO)
171 }
172
173 fn has_da_stake(
175 &self,
176 pub_key: &<TYPES as NodeType>::SignatureKey,
177 _epoch: Option<<TYPES as NodeType>::Epoch>,
178 ) -> bool {
179 self.indexed_da_stake_table
180 .get(pub_key)
181 .is_some_and(|x| x.stake_table_entry.stake() > U256::ZERO)
182 }
183
184 fn lookup_leader(
186 &self,
187 view_number: <TYPES as NodeType>::View,
188 _epoch: Option<<TYPES as NodeType>::Epoch>,
189 ) -> Result<TYPES::SignatureKey> {
190 let index =
191 usize::try_from((*view_number / 2) % self.eligible_leaders.len() as u64).unwrap();
192 let res = self.eligible_leaders[index].clone();
193
194 Ok(TYPES::SignatureKey::public_key(&res.stake_table_entry))
195 }
196
197 fn total_nodes(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> usize {
199 self.stake_table.len()
200 }
201
202 fn da_total_nodes(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> usize {
204 self.da_stake_table.len()
205 }
206
207 fn success_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
209 U256::from(((self.stake_table.len() as u64 * 2) / 3) + 1)
210 }
211
212 fn da_success_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
214 U256::from(((self.da_stake_table.len() as u64 * 2) / 3) + 1)
215 }
216
217 fn failure_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
219 U256::from(((self.stake_table.len() as u64) / 3) + 1)
220 }
221
222 fn upgrade_threshold(&self, _epoch: Option<<TYPES as NodeType>::Epoch>) -> U256 {
224 U256::from(((self.stake_table.len() as u64 * 9) / 10) + 1)
225 }
226 fn has_stake_table(&self, _epoch: TYPES::Epoch) -> bool {
227 true
228 }
229 fn has_randomized_stake_table(&self, _epoch: TYPES::Epoch) -> anyhow::Result<bool> {
230 Ok(true)
231 }
232
233 fn add_drb_result(&mut self, epoch: <TYPES as NodeType>::Epoch, drb_result: DrbResult) {
234 self.drb_results.insert(epoch, drb_result);
235 }
236
237 async fn get_epoch_drb(
238 membership: Arc<RwLock<Self>>,
239 epoch: TYPES::Epoch,
240 ) -> anyhow::Result<DrbResult> {
241 let membership_reader = membership.read().await;
242
243 membership_reader
244 .drb_results
245 .get(&epoch)
246 .context("DRB result missing")
247 .copied()
248 }
249
250 fn set_first_epoch(&mut self, epoch: TYPES::Epoch, initial_drb_result: DrbResult) {
251 self.add_drb_result(epoch, initial_drb_result);
252 self.add_drb_result(epoch + 1, initial_drb_result);
253 }
254}