fedimint_hbbft/
network_info.rs

1use std::borrow::Borrow;
2use std::collections::{BTreeMap, BTreeSet};
3use std::sync::Arc;
4
5use crate::crypto::{self, PublicKeySet, PublicKeyShare, SecretKeyShare};
6
7use crate::{util, NodeIdT};
8
9/// The set of all node IDs of the network's validators.
10#[derive(Debug, Clone)]
11pub struct ValidatorSet<N> {
12    num_faulty: usize,
13    indices: BTreeMap<N, usize>,
14}
15
16impl<I, N> From<I> for ValidatorSet<N>
17where
18    I: IntoIterator,
19    I::Item: Borrow<N>,
20    N: NodeIdT,
21{
22    fn from(i: I) -> Self {
23        let mut ids: Vec<N> = i.into_iter().map(|id| id.borrow().clone()).collect();
24        ids.sort();
25        let indices: BTreeMap<N, usize> = ids
26            .into_iter()
27            .enumerate()
28            .map(|(n, id)| (id.borrow().clone(), n))
29            .collect();
30        let num_faulty = util::max_faulty(indices.len());
31        assert!(3 * num_faulty < indices.len(), "3 f >= N. This is a bug!");
32        ValidatorSet {
33            num_faulty,
34            indices,
35        }
36    }
37}
38
39impl<N: NodeIdT> ValidatorSet<N> {
40    /// Returns `true` if the given ID belongs to a known validator.
41    #[inline]
42    pub fn contains(&self, id: &N) -> bool {
43        self.indices.contains_key(id)
44    }
45
46    /// Returns the validators index in the ordered list of all IDs.
47    #[inline]
48    pub fn index(&self, id: &N) -> Option<usize> {
49        self.indices.get(id).cloned()
50    }
51
52    /// The total number _N_ of validators.
53    #[inline]
54    pub fn num(&self) -> usize {
55        self.indices.len()
56    }
57
58    /// The maximum number _f_ of faulty, Byzantine validators up to which Honey Badger is
59    /// guaranteed to be correct.
60    #[inline]
61    pub fn num_faulty(&self) -> usize {
62        self.num_faulty
63    }
64
65    /// The minimum number _N - f_ of correct validators with which Honey Badger is guaranteed to
66    /// be correct.
67    #[inline]
68    pub fn num_correct(&self) -> usize {
69        // As asserted in `new`, `num_faulty` is never greater than `num`.
70        self.num() - self.num_faulty
71    }
72
73    /// IDs of all validators in the network.
74    #[inline]
75    pub fn all_ids(&self) -> impl Iterator<Item = &N> + Clone {
76        self.indices.keys()
77    }
78
79    /// IDs and indices of all validators in the network.
80    #[inline]
81    pub fn all_indices(&self) -> impl Iterator<Item = (&N, &usize)> + Clone {
82        self.indices.iter()
83    }
84}
85
86/// Common data shared between algorithms: the nodes' IDs and key shares.
87#[derive(Debug, Clone)]
88pub struct NetworkInfo<N> {
89    /// This node's ID.
90    our_id: N,
91    /// Whether this node is a validator. This is true if `public_keys` contains our own ID.
92    is_validator: bool,
93    /// This node's secret key share. Only validators have one.
94    secret_key_share: Option<SecretKeyShare>,
95    /// The public key set for threshold cryptography. Each validator has a secret key share.
96    public_key_set: PublicKeySet,
97    /// The validators' public key shares, computed from `public_key_set`.
98    public_key_shares: BTreeMap<N, PublicKeyShare>,
99    /// The indices in the list of sorted validator IDs.
100    val_set: Arc<ValidatorSet<N>>,
101}
102
103impl<N: NodeIdT> NetworkInfo<N> {
104    /// Creates a new `NetworkInfo` with the given ID and keys.
105    ///
106    /// All nodes in the network must share the same public information. Validators' IDs must be
107    /// keys in the `public_keys` map, and their secret key share must match their share in the
108    /// `public_key_set`.
109    ///
110    /// # Panics
111    ///
112    /// Panics if `public_keys` is empty or the requirement above is not satisfied, i.e. if the
113    /// secret key doesn't match the public key or is missing.
114    pub fn new<SKS: Into<Option<SecretKeyShare>>, V: Into<ValidatorSet<N>>>(
115        our_id: N,
116        secret_key_share: SKS,
117        public_key_set: PublicKeySet,
118        val_set: V,
119    ) -> Self {
120        let val_set = Arc::new(val_set.into());
121        let is_validator = val_set.contains(&our_id);
122        let secret_key_share = secret_key_share.into();
123        assert_eq!(is_validator, secret_key_share.is_some());
124        let public_key_shares: BTreeMap<N, PublicKeyShare> = val_set
125            .all_indices()
126            .map(|(id, idx)| (id.clone(), public_key_set.public_key_share(idx)))
127            .collect();
128        if let Some(sks) = &secret_key_share {
129            assert_eq!(
130                Some(&sks.public_key_share()),
131                public_key_shares.get(&our_id)
132            );
133        }
134        NetworkInfo {
135            our_id,
136            is_validator,
137            secret_key_share,
138            public_key_set,
139            public_key_shares,
140            val_set,
141        }
142    }
143
144    /// The ID of the node the algorithm runs on.
145    #[inline]
146    pub fn our_id(&self) -> &N {
147        &self.our_id
148    }
149
150    /// ID of all nodes in the network.
151    #[inline]
152    pub fn all_ids(&self) -> impl Iterator<Item = &N> + Clone {
153        self.val_set.all_ids()
154    }
155
156    /// ID of all nodes in the network except this one.
157    #[inline]
158    pub fn other_ids(&self) -> impl Iterator<Item = &N> + Clone {
159        let our_id = self.our_id.clone();
160        self.all_ids().filter(move |id| **id != our_id)
161    }
162
163    /// The total number _N_ of nodes.
164    #[inline]
165    pub fn num_nodes(&self) -> usize {
166        self.val_set.num()
167    }
168
169    /// The maximum number _f_ of faulty, Byzantine nodes up to which Honey Badger is guaranteed to
170    /// be correct.
171    #[inline]
172    pub fn num_faulty(&self) -> usize {
173        self.val_set.num_faulty()
174    }
175
176    /// The minimum number _N - f_ of correct nodes with which Honey Badger is guaranteed to be
177    /// correct.
178    #[inline]
179    pub fn num_correct(&self) -> usize {
180        self.val_set.num_correct()
181    }
182
183    /// Returns our secret key share for threshold cryptography, or `None` if not a validator.
184    #[inline]
185    pub fn secret_key_share(&self) -> Option<&SecretKeyShare> {
186        self.secret_key_share.as_ref()
187    }
188
189    /// Returns the public key set for threshold cryptography.
190    #[inline]
191    pub fn public_key_set(&self) -> &PublicKeySet {
192        &self.public_key_set
193    }
194
195    /// Returns the public key share if a node with that ID exists, otherwise `None`.
196    #[inline]
197    pub fn public_key_share(&self, id: &N) -> Option<&PublicKeyShare> {
198        self.public_key_shares.get(id)
199    }
200
201    /// Returns a map of all node IDs to their public key shares.
202    #[inline]
203    pub fn public_key_share_map(&self) -> &BTreeMap<N, PublicKeyShare> {
204        &self.public_key_shares
205    }
206
207    /// The index of a node in a canonical numbering of all nodes. This is the index where the
208    /// node appears in `all_ids`.
209    #[inline]
210    pub fn node_index(&self, id: &N) -> Option<usize> {
211        self.val_set.index(id)
212    }
213
214    /// Returns `true` if this node takes part in the consensus itself. If not, it is only an
215    /// observer.
216    #[inline]
217    pub fn is_validator(&self) -> bool {
218        self.is_validator
219    }
220
221    /// Returns `true` if the given node takes part in the consensus itself. If not, it is only an
222    /// observer.
223    #[inline]
224    pub fn is_node_validator(&self, id: &N) -> bool {
225        self.val_set.contains(id)
226    }
227
228    /// Returns the set of validator IDs.
229    pub fn validator_set(&self) -> &Arc<ValidatorSet<N>> {
230        &self.val_set
231    }
232
233    /// Generates a map of matching `NetworkInfo`s for testing.
234    pub fn generate_map<I, R>(
235        ids: I,
236        rng: &mut R,
237    ) -> Result<BTreeMap<N, NetworkInfo<N>>, crypto::error::Error>
238    where
239        I: IntoIterator<Item = N>,
240        R: rand::Rng,
241    {
242        use crate::crypto::SecretKeySet;
243
244        let all_ids: BTreeSet<N> = ids.into_iter().collect();
245        let num_faulty = util::max_faulty(all_ids.len());
246
247        // Generate the keys for threshold cryptography.
248        let sk_set = SecretKeySet::random(num_faulty, rng);
249        let pk_set = sk_set.public_keys();
250
251        // Create the corresponding `NetworkInfo` for each node.
252        let create_netinfo = |(index, id): (usize, &N)| {
253            let sks = sk_set.secret_key_share(index);
254            let netinfo = NetworkInfo::new(id.clone(), sks, pk_set.clone(), &all_ids);
255            Ok((id.clone(), netinfo))
256        };
257        all_ids.iter().enumerate().map(create_netinfo).collect()
258    }
259}