fedimint_core/
peer_id.rs

1use std::collections::{BTreeMap, BTreeSet};
2use std::fmt::Debug;
3use std::str::FromStr;
4
5use fedimint_core::config::PeerUrl;
6use serde::{Deserialize, Serialize};
7
8use crate::encoding::{Decodable, Encodable};
9
10#[derive(
11    Debug,
12    Clone,
13    Copy,
14    PartialEq,
15    Eq,
16    Hash,
17    PartialOrd,
18    Ord,
19    Serialize,
20    Deserialize,
21    Encodable,
22    Decodable,
23)]
24pub struct PeerId(u16);
25
26impl PeerId {
27    pub fn new(id: u16) -> Self {
28        Self(id)
29    }
30
31    pub fn to_usize(self) -> usize {
32        self.0 as usize
33    }
34}
35
36impl std::fmt::Display for PeerId {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{}", self.0)
39    }
40}
41
42impl FromStr for PeerId {
43    type Err = <u16 as FromStr>::Err;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        s.parse().map(PeerId)
47    }
48}
49
50impl From<u16> for PeerId {
51    fn from(id: u16) -> Self {
52        Self(id)
53    }
54}
55
56impl From<PeerId> for u16 {
57    fn from(peer: PeerId) -> Self {
58        peer.0
59    }
60}
61
62/// The number of guardians in a federation.
63#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
64pub struct NumPeers(usize);
65
66impl NumPeers {
67    /// Returns an iterator over all peer IDs in the federation.
68    pub fn peer_ids(self) -> impl Iterator<Item = PeerId> {
69        (0u16..(self.0 as u16)).map(PeerId)
70    }
71
72    /// Returns the total number of guardians in the federation.
73    pub fn total(self) -> usize {
74        self.0
75    }
76
77    /// Returns the number of guardians that can be evil without disrupting the
78    /// federation.
79    pub fn max_evil(self) -> usize {
80        (self.total() - 1) / 3
81    }
82
83    /// Returns the number of guardians to select such that at least one is
84    /// honest (assuming the federation is not compromised).
85    pub fn one_honest(self) -> usize {
86        self.max_evil() + 1
87    }
88
89    /// Returns the degree of an underlying polynomial to require threshold
90    /// signatures.
91    pub fn degree(self) -> usize {
92        self.threshold() - 1
93    }
94
95    /// Returns the number of guardians required to achieve consensus and
96    /// produce valid signatures.
97    pub fn threshold(self) -> usize {
98        self.total() - self.max_evil()
99    }
100}
101
102impl From<usize> for NumPeers {
103    fn from(value: usize) -> Self {
104        Self(value)
105    }
106}
107
108/// Types that can be easily converted to [`NumPeers`]
109pub trait NumPeersExt {
110    fn to_num_peers(&self) -> NumPeers;
111}
112
113impl<T> From<T> for NumPeers
114where
115    T: NumPeersExt,
116{
117    fn from(value: T) -> Self {
118        value.to_num_peers()
119    }
120}
121
122impl<T> NumPeersExt for BTreeMap<PeerId, T> {
123    fn to_num_peers(&self) -> NumPeers {
124        NumPeers(self.len())
125    }
126}
127
128impl NumPeersExt for &[PeerId] {
129    fn to_num_peers(&self) -> NumPeers {
130        NumPeers(self.len())
131    }
132}
133
134impl NumPeersExt for Vec<PeerId> {
135    fn to_num_peers(&self) -> NumPeers {
136        NumPeers(self.len())
137    }
138}
139
140impl NumPeersExt for Vec<PeerUrl> {
141    fn to_num_peers(&self) -> NumPeers {
142        NumPeers(self.len())
143    }
144}
145
146impl NumPeersExt for BTreeSet<PeerId> {
147    fn to_num_peers(&self) -> NumPeers {
148        NumPeers(self.len())
149    }
150}