Skip to main content

commonware_p2p/authenticated/lookup/
config.rs

1use commonware_cryptography::Signer;
2use commonware_runtime::Quota;
3use commonware_utils::NZU32;
4use std::{net::SocketAddr, num::NonZeroU32, time::Duration};
5
6/// Configuration for the peer-to-peer instance.
7///
8/// # Warning
9/// It is recommended to synchronize this configuration across peers in the network (with the
10/// exception of `crypto`, `listen`, `allow_private_ips`, and `mailbox_size`).
11/// If this is not synchronized, connections could be unnecessarily dropped, messages could be parsed incorrectly,
12/// and/or peers will rate limit each other during normal operation.
13#[derive(Clone)]
14pub struct Config<C: Signer> {
15    /// Cryptographic primitives.
16    pub crypto: C,
17
18    /// Prefix for all signed messages to avoid replay attacks.
19    pub namespace: Vec<u8>,
20
21    /// Address to listen on.
22    pub listen: SocketAddr,
23
24    /// Whether or not to allow connections with private IP addresses.
25    pub allow_private_ips: bool,
26
27    /// Whether or not to allow DNS-based ingress addresses.
28    ///
29    /// When dialing a DNS-based address, the hostname is resolved and a random IP
30    /// is selected from the results (shuffled for each dial attempt).
31    pub allow_dns: bool,
32
33    /// Whether or not to skip IP verification for incoming connections
34    /// (allows known peers to connect from unknown IPs).
35    pub bypass_ip_check: bool,
36
37    /// Maximum size allowed for messages over any connection.
38    ///
39    /// The actual size of the network message will be higher due to overhead from the protocol;
40    /// this may include additional metadata, data from the codec, and/or cryptographic signatures.
41    pub max_message_size: u32,
42
43    /// Message backlog allowed for internal actors.
44    ///
45    /// When there are more messages in the mailbox than this value, any actor
46    /// sending a message will be blocked until the mailbox is processed.
47    pub mailbox_size: usize,
48
49    /// Time into the future that a timestamp can be and still be considered valid.
50    pub synchrony_bound: Duration,
51
52    /// Duration after which a handshake message is considered stale.
53    pub max_handshake_age: Duration,
54
55    /// Timeout for the handshake process.
56    ///
57    /// This is often set to some value less than the connection read timeout to prevent
58    /// unauthenticated peers from holding open connection.
59    pub handshake_timeout: Duration,
60
61    /// Quota for connection attempts per peer (incoming or outgoing).
62    pub allowed_connection_rate_per_peer: Quota,
63
64    /// Maximum number of concurrent handshake attempts allowed.
65    pub max_concurrent_handshakes: NonZeroU32,
66
67    /// Quota for handshake attempts originating from a single IP address.
68    ///
69    /// To cap the number of handshakes concurrently attempted for a single
70    /// IP, set this to [Config::handshake_timeout].
71    pub allowed_handshake_rate_per_ip: Quota,
72
73    /// Quota for handshake attempts originating from a single IP subnet.
74    pub allowed_handshake_rate_per_subnet: Quota,
75
76    /// Frequency at which we send ping messages to peers.
77    ///
78    /// This also determines the rate limit for incoming ping messages (one per half this
79    /// frequency to account for jitter).
80    pub ping_frequency: Duration,
81
82    /// Average frequency at which we make a single dial attempt across all peers.
83    pub dial_frequency: Duration,
84
85    /// Average frequency at which we will fetch a new list of dialable peers.
86    ///
87    /// This value also limits the rate at which we attempt to re-dial any single peer.
88    pub query_frequency: Duration,
89
90    /// Number of peer sets to track.
91    ///
92    /// We will attempt to maintain connections to peers stored
93    /// across all peer sets, not just the most recent. This allows
94    /// us to continue serving requests to peers that have recently
95    /// been evicted and/or to communicate with peers in a future
96    /// set (if we, for example, are trying to do a reshare of a threshold
97    /// key).
98    pub tracked_peer_sets: usize,
99
100    /// Duration after which a blocked peer is allowed to reconnect.
101    pub block_duration: Duration,
102}
103
104impl<C: Signer> Config<C> {
105    /// Generates a configuration with reasonable defaults for usage in production.
106    pub fn recommended(
107        crypto: C,
108        namespace: &[u8],
109        listen: SocketAddr,
110        max_message_size: u32,
111    ) -> Self {
112        Self {
113            crypto,
114            namespace: namespace.to_vec(),
115            listen,
116
117            allow_private_ips: false,
118            allow_dns: true,
119            bypass_ip_check: false,
120            max_message_size,
121            mailbox_size: 1_000,
122            synchrony_bound: Duration::from_secs(5),
123            max_handshake_age: Duration::from_secs(10),
124            handshake_timeout: Duration::from_secs(5),
125            allowed_connection_rate_per_peer: Quota::per_minute(NZU32!(1)),
126            max_concurrent_handshakes: NZU32!(512),
127            allowed_handshake_rate_per_ip: Quota::with_period(Duration::from_secs(5)).unwrap(), // 1 concurrent handshake per IP
128            allowed_handshake_rate_per_subnet: Quota::per_second(NZU32!(64)),
129            ping_frequency: Duration::from_secs(50),
130            dial_frequency: Duration::from_secs(1),
131            query_frequency: Duration::from_secs(60),
132            tracked_peer_sets: 4,
133            block_duration: Duration::from_hours(4),
134        }
135    }
136
137    /// Generates a configuration that minimizes peer discovery latency. This
138    /// can be useful when running local demos.
139    ///
140    /// # Warning
141    ///
142    /// It is not recommended to use this configuration in production.
143    pub fn local(crypto: C, namespace: &[u8], listen: SocketAddr, max_message_size: u32) -> Self {
144        Self {
145            crypto,
146            namespace: namespace.to_vec(),
147            listen,
148
149            allow_private_ips: true,
150            allow_dns: true,
151            bypass_ip_check: false,
152            max_message_size,
153            mailbox_size: 1_000,
154            synchrony_bound: Duration::from_secs(5),
155            max_handshake_age: Duration::from_secs(10),
156            handshake_timeout: Duration::from_secs(5),
157            allowed_connection_rate_per_peer: Quota::per_second(NZU32!(1)),
158            max_concurrent_handshakes: NZU32!(1_024),
159            allowed_handshake_rate_per_ip: Quota::per_second(NZU32!(16)), // 80 concurrent handshakes per IP
160            allowed_handshake_rate_per_subnet: Quota::per_second(NZU32!(128)),
161            ping_frequency: Duration::from_secs(5),
162            dial_frequency: Duration::from_millis(500),
163            query_frequency: Duration::from_secs(30),
164            tracked_peer_sets: 4,
165            block_duration: Duration::from_hours(1),
166        }
167    }
168
169    #[cfg(test)]
170    pub fn test(crypto: C, listen: SocketAddr, max_message_size: u32) -> Self {
171        Self {
172            crypto,
173            namespace: b"test_namespace".to_vec(),
174            listen,
175
176            allow_private_ips: true,
177            allow_dns: true,
178            bypass_ip_check: false,
179            max_message_size,
180            mailbox_size: 1_000,
181            synchrony_bound: Duration::from_secs(5),
182            max_handshake_age: Duration::from_secs(10),
183            handshake_timeout: Duration::from_secs(5),
184            allowed_connection_rate_per_peer: Quota::per_second(NZU32!(4)),
185            max_concurrent_handshakes: NZU32!(1_024),
186            allowed_handshake_rate_per_ip: Quota::per_second(NZU32!(128)), // 640 concurrent handshakes per IP
187            allowed_handshake_rate_per_subnet: Quota::per_second(NZU32!(256)),
188            ping_frequency: Duration::from_secs(1),
189            dial_frequency: Duration::from_millis(200),
190            query_frequency: Duration::from_secs(5),
191            tracked_peer_sets: 4,
192            block_duration: Duration::from_mins(1),
193        }
194    }
195}