consensus_config/
committee.rs1use std::{
6 fmt::{Display, Formatter},
7 ops::{Index, IndexMut},
8};
9
10use iota_network_stack::Multiaddr;
11use serde::{Deserialize, Serialize};
12
13use crate::{AuthorityPublicKey, NetworkPublicKey, ProtocolPublicKey};
14
15pub type Epoch = u64;
17
18pub type Stake = u64;
22
23#[derive(Clone, Debug, Serialize, Deserialize)]
26pub struct Committee {
27 epoch: Epoch,
29 total_stake: Stake,
31 quorum_threshold: Stake,
33 validity_threshold: Stake,
35 authorities: Vec<Authority>,
37}
38
39impl Committee {
40 pub fn new(epoch: Epoch, authorities: Vec<Authority>) -> Self {
41 assert!(!authorities.is_empty(), "Committee cannot be empty!");
42 assert!(
43 authorities.len() < u32::MAX as usize,
44 "Too many authorities ({})!",
45 authorities.len()
46 );
47
48 let total_stake = authorities.iter().map(|a| a.stake).sum::<u64>();
49 assert_ne!(total_stake, 0, "Total stake cannot be zero!");
50 let quorum_threshold = 2 * total_stake / 3 + 1;
51 let validity_threshold = total_stake.div_ceil(3);
52 Self {
53 epoch,
54 total_stake,
55 quorum_threshold,
56 validity_threshold,
57 authorities,
58 }
59 }
60
61 pub fn epoch(&self) -> Epoch {
65 self.epoch
66 }
67
68 pub fn total_stake(&self) -> Stake {
69 self.total_stake
70 }
71
72 pub fn quorum_threshold(&self) -> Stake {
73 self.quorum_threshold
74 }
75
76 pub fn validity_threshold(&self) -> Stake {
77 self.validity_threshold
78 }
79
80 pub fn stake(&self, authority_index: AuthorityIndex) -> Stake {
81 self.authorities[authority_index].stake
82 }
83
84 pub fn authority(&self, authority_index: AuthorityIndex) -> &Authority {
85 &self.authorities[authority_index]
86 }
87
88 pub fn authorities(&self) -> impl Iterator<Item = (AuthorityIndex, &Authority)> {
89 self.authorities
90 .iter()
91 .enumerate()
92 .map(|(i, a)| (AuthorityIndex(i as u32), a))
93 }
94
95 pub fn reached_quorum(&self, stake: Stake) -> bool {
100 stake >= self.quorum_threshold()
101 }
102
103 pub fn reached_validity(&self, stake: Stake) -> bool {
105 stake >= self.validity_threshold()
106 }
107
108 pub fn to_authority_index(&self, index: usize) -> Option<AuthorityIndex> {
111 if index < self.authorities.len() {
112 Some(AuthorityIndex(index as u32))
113 } else {
114 None
115 }
116 }
117
118 pub fn is_valid_index(&self, index: AuthorityIndex) -> bool {
120 index.value() < self.size()
121 }
122
123 pub fn size(&self) -> usize {
125 self.authorities.len()
126 }
127}
128
129#[derive(Clone, Debug, Serialize, Deserialize)]
134pub struct Authority {
135 pub stake: Stake,
137 pub address: Multiaddr,
139 pub hostname: String,
141 pub authority_key: AuthorityPublicKey,
144 pub protocol_key: ProtocolPublicKey,
147 pub network_key: NetworkPublicKey,
150}
151
152#[derive(
160 Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Default, Hash, Serialize, Deserialize,
161)]
162pub struct AuthorityIndex(u32);
163
164impl AuthorityIndex {
165 pub const ZERO: Self = Self(0);
167
168 pub const MIN: Self = Self::ZERO;
170 pub const MAX: Self = Self(u32::MAX);
171
172 pub fn value(&self) -> usize {
173 self.0 as usize
174 }
175}
176
177impl AuthorityIndex {
178 pub fn new_for_test(index: u32) -> Self {
179 Self(index)
180 }
181}
182
183impl Display for AuthorityIndex {
184 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
185 write!(f, "[{}]", self.value())
186 }
187}
188
189impl<T, const N: usize> Index<AuthorityIndex> for [T; N] {
190 type Output = T;
191
192 fn index(&self, index: AuthorityIndex) -> &Self::Output {
193 self.get(index.value()).unwrap()
194 }
195}
196
197impl<T> Index<AuthorityIndex> for Vec<T> {
198 type Output = T;
199
200 fn index(&self, index: AuthorityIndex) -> &Self::Output {
201 self.get(index.value()).unwrap()
202 }
203}
204
205impl<T, const N: usize> IndexMut<AuthorityIndex> for [T; N] {
206 fn index_mut(&mut self, index: AuthorityIndex) -> &mut Self::Output {
207 self.get_mut(index.value()).unwrap()
208 }
209}
210
211impl<T> IndexMut<AuthorityIndex> for Vec<T> {
212 fn index_mut(&mut self, index: AuthorityIndex) -> &mut Self::Output {
213 self.get_mut(index.value()).unwrap()
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 use crate::local_committee_and_keys;
221
222 #[test]
223 fn committee_basic() {
224 let epoch = 100;
226 let num_of_authorities = 9;
227 let authority_stakes = (1..=9).map(|s| s as Stake).collect();
228 let (committee, _) = local_committee_and_keys(epoch, authority_stakes);
229
230 assert_eq!(committee.size(), num_of_authorities);
232 for (i, authority) in committee.authorities() {
233 assert_eq!((i.value() + 1) as Stake, authority.stake);
234 }
235
236 assert_eq!(committee.total_stake(), 45);
238 assert_eq!(committee.quorum_threshold(), 31);
239 assert_eq!(committee.validity_threshold(), 15);
240 }
241}