hotshot_types/traits/
election.rs1use std::{collections::BTreeSet, fmt::Debug, sync::Arc};
9
10use alloy::primitives::U256;
11use async_lock::RwLock;
12use committable::{Commitment, Committable};
13use hotshot_utils::anytrace::Result;
14
15use super::node_implementation::NodeType;
16use crate::{
17 data::Leaf2, drb::DrbResult, stake_table::HSStakeTable,
18 traits::signature_key::StakeTableEntryType, PeerConfig,
19};
20
21pub struct NoStakeTableHash;
22
23impl Committable for NoStakeTableHash {
24 fn commit(&self) -> Commitment<Self> {
25 Commitment::from_raw([0u8; 32])
26 }
27}
28
29pub trait Membership<TYPES: NodeType>: Debug + Send + Sync {
31 type Error: std::fmt::Display;
33
34 type StakeTableHash: Committable;
35 fn new(
37 stake_committee_members: Vec<PeerConfig<TYPES>>,
40 da_committee_members: Vec<PeerConfig<TYPES>>,
41 ) -> Self;
42
43 fn total_stake(&self, epoch: Option<TYPES::Epoch>) -> U256 {
44 self.stake_table(epoch)
45 .iter()
46 .fold(U256::ZERO, |acc, entry| {
47 acc + entry.stake_table_entry.stake()
48 })
49 }
50
51 fn total_da_stake(&self, epoch: Option<TYPES::Epoch>) -> U256 {
52 self.da_stake_table(epoch)
53 .iter()
54 .fold(U256::ZERO, |acc, entry| {
55 acc + entry.stake_table_entry.stake()
56 })
57 }
58
59 fn stake_table(&self, epoch: Option<TYPES::Epoch>) -> HSStakeTable<TYPES>;
61
62 fn da_stake_table(&self, epoch: Option<TYPES::Epoch>) -> HSStakeTable<TYPES>;
64
65 fn committee_members(
67 &self,
68 view_number: TYPES::View,
69 epoch: Option<TYPES::Epoch>,
70 ) -> BTreeSet<TYPES::SignatureKey>;
71
72 fn da_committee_members(
74 &self,
75 view_number: TYPES::View,
76 epoch: Option<TYPES::Epoch>,
77 ) -> BTreeSet<TYPES::SignatureKey>;
78
79 fn stake(
82 &self,
83 pub_key: &TYPES::SignatureKey,
84 epoch: Option<TYPES::Epoch>,
85 ) -> Option<PeerConfig<TYPES>>;
86
87 fn da_stake(
90 &self,
91 pub_key: &TYPES::SignatureKey,
92 epoch: Option<TYPES::Epoch>,
93 ) -> Option<PeerConfig<TYPES>>;
94
95 fn has_stake(&self, pub_key: &TYPES::SignatureKey, epoch: Option<TYPES::Epoch>) -> bool;
97
98 fn has_da_stake(&self, pub_key: &TYPES::SignatureKey, epoch: Option<TYPES::Epoch>) -> bool;
100
101 fn leader(
109 &self,
110 view: TYPES::View,
111 epoch: Option<TYPES::Epoch>,
112 ) -> Result<TYPES::SignatureKey> {
113 use hotshot_utils::anytrace::*;
114
115 self.lookup_leader(view, epoch).wrap().context(info!(
116 "Failed to get leader for view {view} in epoch {epoch:?}"
117 ))
118 }
119
120 fn lookup_leader(
128 &self,
129 view: TYPES::View,
130 epoch: Option<TYPES::Epoch>,
131 ) -> std::result::Result<TYPES::SignatureKey, Self::Error>;
132
133 fn total_nodes(&self, epoch: Option<TYPES::Epoch>) -> usize;
135
136 fn da_total_nodes(&self, epoch: Option<TYPES::Epoch>) -> usize;
138
139 fn success_threshold(&self, epoch: Option<TYPES::Epoch>) -> U256;
141
142 fn da_success_threshold(&self, epoch: Option<TYPES::Epoch>) -> U256;
144
145 fn failure_threshold(&self, epoch: Option<TYPES::Epoch>) -> U256;
147
148 fn upgrade_threshold(&self, epoch: Option<TYPES::Epoch>) -> U256;
150
151 fn has_stake_table(&self, epoch: TYPES::Epoch) -> bool;
153
154 fn has_randomized_stake_table(&self, epoch: TYPES::Epoch) -> anyhow::Result<bool>;
156
157 fn get_epoch_root(
160 _membership: Arc<RwLock<Self>>,
161 _block_height: u64,
162 _epoch: TYPES::Epoch,
163 ) -> impl std::future::Future<Output = anyhow::Result<Leaf2<TYPES>>> + Send {
164 async move { anyhow::bail!("Not implemented") }
165 }
166
167 fn get_epoch_drb(
169 _membership: Arc<RwLock<Self>>,
170 _epoch: TYPES::Epoch,
171 ) -> impl std::future::Future<Output = anyhow::Result<DrbResult>> + Send;
172
173 fn add_epoch_root(
175 _membership: Arc<RwLock<Self>>,
176 _epoch: TYPES::Epoch,
177 _block_header: TYPES::BlockHeader,
178 ) -> impl std::future::Future<Output = anyhow::Result<()>> + Send {
179 async { Ok(()) }
180 }
181
182 fn add_drb_result(&mut self, _epoch: TYPES::Epoch, _drb_result: DrbResult);
185
186 fn set_first_epoch(&mut self, _epoch: TYPES::Epoch, _initial_drb_result: DrbResult);
191
192 fn first_epoch(&self) -> Option<TYPES::Epoch> {
194 None
195 }
196
197 fn stake_table_hash(&self, _epoch: TYPES::Epoch) -> Option<Commitment<Self::StakeTableHash>> {
200 None
201 }
202}
203
204pub fn membership_spawn_add_epoch_root<TYPES: NodeType>(
205 membership: Arc<RwLock<impl Membership<TYPES> + 'static>>,
206 epoch: TYPES::Epoch,
207 block_header: TYPES::BlockHeader,
208) {
209 tokio::spawn(async move {
210 if let Err(e) = Membership::<TYPES>::add_epoch_root(membership, epoch, block_header).await {
211 tracing::error!("Failed to add epoch root for epoch {epoch}: {e}");
212 }
213 });
214}