Skip to main content

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