commonware_p2p/authenticated/discovery/config.rs
1use commonware_cryptography::Signer;
2use commonware_utils::NZU32;
3use governor::Quota;
4use std::{net::SocketAddr, time::Duration};
5
6/// Known peer and its accompanying address that will be dialed on startup.
7pub type Bootstrapper<P> = (P, SocketAddr);
8
9/// Configuration for the peer-to-peer instance.
10///
11/// # Warning
12/// It is recommended to synchronize this configuration across peers in the network (with the
13/// exception of `crypto`, `listen`, `bootstrappers`, `allow_private_ips`, and `mailbox_size`).
14/// If this is not synchronized, connections could be unnecessarily dropped, messages could be parsed incorrectly,
15/// and/or peers will rate limit each other during normal operation.
16#[derive(Clone)]
17pub struct Config<C: Signer> {
18 /// Cryptographic primitives.
19 pub crypto: C,
20
21 /// Prefix for all signed messages to avoid replay attacks.
22 pub namespace: Vec<u8>,
23
24 /// Address to listen on.
25 pub listen: SocketAddr,
26
27 /// Dialable address of the peer.
28 pub dialable: SocketAddr,
29
30 /// Peers dialed on startup.
31 pub bootstrappers: Vec<Bootstrapper<C::PublicKey>>,
32
33 /// Whether or not to allow connections with private IP addresses.
34 pub allow_private_ips: bool,
35
36 /// Maximum size allowed for messages over any connection.
37 ///
38 /// The actual size of the network message will be higher due to overhead from the protocol;
39 /// this may include additional metadata, data from the codec, and/or cryptographic signatures.
40 pub max_message_size: usize,
41
42 /// Message backlog allowed for internal actors.
43 ///
44 /// When there are more messages in the mailbox than this value, any actor
45 /// sending a message will be blocked until the mailbox is processed.
46 pub mailbox_size: usize,
47
48 /// Time into the future that a timestamp can be and still be considered valid.
49 pub synchrony_bound: Duration,
50
51 /// Duration after which a handshake message is considered stale.
52 pub max_handshake_age: Duration,
53
54 /// Timeout for the handshake process.
55 ///
56 /// This is often set to some value less than the connection read timeout to prevent
57 /// unauthenticated peers from holding open connection.
58 pub handshake_timeout: Duration,
59
60 /// Quota for connection attempts per peer (incoming or outgoing).
61 pub allowed_connection_rate_per_peer: Quota,
62
63 /// Quota for incoming connections across all peers.
64 pub allowed_incoming_connection_rate: Quota,
65
66 /// Average frequency at which we make a single dial attempt across all peers.
67 pub dial_frequency: Duration,
68
69 /// Average frequency at which we will fetch a new list of dialable peers.
70 ///
71 /// This value also limits the rate at which we attempt to re-dial any single peer.
72 pub query_frequency: Duration,
73
74 /// Times that dialing a given peer should fail before asking for updated peer information for
75 /// that peer.
76 pub dial_fail_limit: usize,
77
78 /// Number of peer sets to track.
79 ///
80 /// We will attempt to maintain connections to peers stored
81 /// across all peer sets, not just the most recent. This allows
82 /// us to continue serving requests to peers that have recently
83 /// been evicted and/or to communicate with peers in a future
84 /// set (if we, for example, are trying to do a reshare of a threshold
85 /// key).
86 pub tracked_peer_sets: usize,
87
88 /// Maximum number of peers to track in a single peer set.
89 ///
90 /// This is used to limit the size of the bit vec messages, which will take one bit per peer in
91 /// the set. This number can be set to a reasonably high value that we never expect to reach.
92 pub max_peer_set_size: usize,
93
94 /// Frequency we gossip about known peers.
95 ///
96 /// If there is no other network activity, this message is used as a ping
97 /// and should be sent more often than the read_timeout.
98 pub gossip_bit_vec_frequency: Duration,
99
100 /// Quota for bit vector messages a peer can send us.
101 pub allowed_bit_vec_rate: Quota,
102
103 /// Maximum number of peers we will send or consider valid when receiving in a single message.
104 ///
105 /// This is used to prevent malicious peers from sending us a large number of peers at one time (each
106 /// of which requires a signature verification).
107 pub peer_gossip_max_count: usize,
108
109 /// Quota for peers messages a peer can send us.
110 pub allowed_peers_rate: Quota,
111}
112
113impl<C: Signer> Config<C> {
114 /// Generates a configuration with reasonable defaults for usage in production.
115 pub fn recommended(
116 crypto: C,
117 namespace: &[u8],
118 listen: SocketAddr,
119 dialable: SocketAddr,
120 bootstrappers: Vec<Bootstrapper<C::PublicKey>>,
121 max_message_size: usize,
122 ) -> Self {
123 Self {
124 crypto,
125 namespace: namespace.to_vec(),
126 listen,
127 dialable,
128 bootstrappers,
129
130 allow_private_ips: false,
131 max_message_size,
132 mailbox_size: 1_000,
133 synchrony_bound: Duration::from_secs(5),
134 max_handshake_age: Duration::from_secs(10),
135 handshake_timeout: Duration::from_secs(5),
136 allowed_connection_rate_per_peer: Quota::per_minute(NZU32!(1)),
137 allowed_incoming_connection_rate: Quota::per_second(NZU32!(256)),
138 dial_frequency: Duration::from_millis(1_000),
139 query_frequency: Duration::from_secs(60),
140 dial_fail_limit: 2,
141 tracked_peer_sets: 4,
142 max_peer_set_size: 1 << 16, // 2^16
143 gossip_bit_vec_frequency: Duration::from_secs(50),
144 allowed_bit_vec_rate: Quota::per_second(NZU32!(2)),
145 peer_gossip_max_count: 32,
146 allowed_peers_rate: Quota::per_second(NZU32!(2)),
147 }
148 }
149
150 /// Generates a configuration that minimizes peer discovery latency. This
151 /// can be useful when running local demos.
152 ///
153 /// # Warning
154 /// It is not recommended to use this configuration in production.
155 pub fn aggressive(
156 crypto: C,
157 namespace: &[u8],
158 listen: SocketAddr,
159 dialable: SocketAddr,
160 bootstrappers: Vec<Bootstrapper<C::PublicKey>>,
161 max_message_size: usize,
162 ) -> Self {
163 Self {
164 crypto,
165 namespace: namespace.to_vec(),
166 listen,
167 dialable,
168 bootstrappers,
169
170 allow_private_ips: true,
171 max_message_size,
172 mailbox_size: 1_000,
173 synchrony_bound: Duration::from_secs(5),
174 max_handshake_age: Duration::from_secs(10),
175 handshake_timeout: Duration::from_secs(5),
176 allowed_connection_rate_per_peer: Quota::per_second(NZU32!(1)),
177 allowed_incoming_connection_rate: Quota::per_second(NZU32!(256)),
178 dial_frequency: Duration::from_millis(500),
179 query_frequency: Duration::from_secs(30),
180 dial_fail_limit: 1,
181 tracked_peer_sets: 4,
182 max_peer_set_size: 1 << 16, // 2^16
183 gossip_bit_vec_frequency: Duration::from_secs(5),
184 allowed_bit_vec_rate: Quota::per_second(NZU32!(2)),
185 peer_gossip_max_count: 32,
186 allowed_peers_rate: Quota::per_second(NZU32!(5)),
187 }
188 }
189
190 #[cfg(test)]
191 pub fn test(
192 crypto: C,
193 listen: SocketAddr,
194 bootstrappers: Vec<Bootstrapper<C::PublicKey>>,
195 max_message_size: usize,
196 ) -> Self {
197 Self {
198 crypto,
199 namespace: b"test_namespace".to_vec(),
200 listen,
201 dialable: listen,
202 bootstrappers,
203
204 allow_private_ips: true,
205 max_message_size,
206 mailbox_size: 1_000,
207 synchrony_bound: Duration::from_secs(5),
208 max_handshake_age: Duration::from_secs(10),
209 handshake_timeout: Duration::from_secs(5),
210 allowed_connection_rate_per_peer: Quota::per_second(NZU32!(4)),
211 allowed_incoming_connection_rate: Quota::per_second(NZU32!(1_024)),
212 dial_frequency: Duration::from_millis(200),
213 query_frequency: Duration::from_millis(5_000),
214 dial_fail_limit: 1,
215 tracked_peer_sets: 4,
216 max_peer_set_size: 1 << 8, // 2^8
217 gossip_bit_vec_frequency: Duration::from_secs(1),
218 allowed_bit_vec_rate: Quota::per_second(NZU32!(5)),
219 peer_gossip_max_count: 32,
220 allowed_peers_rate: Quota::per_second(NZU32!(5)),
221 }
222 }
223}