polkadot_subsystem_bench/
configuration.rs1use crate::keyring::Keyring;
20use itertools::Itertools;
21use polkadot_node_network_protocol::authority_discovery::AuthorityDiscovery;
22use polkadot_primitives::{AssignmentId, AuthorityDiscoveryId, ValidatorId, ValidatorPair};
23use rand::thread_rng;
24use rand_distr::{Distribution, Normal, Uniform};
25use sc_network::Multiaddr;
26use sc_network_types::PeerId;
27use serde::{Deserialize, Serialize};
28use sp_consensus_babe::AuthorityId;
29use sp_core::Pair;
30use std::collections::{HashMap, HashSet};
31
32#[derive(Clone, Debug, Default, Serialize, Deserialize)]
34pub struct PeerLatency {
35 pub mean_latency_ms: usize,
37 pub std_dev: f64,
39}
40
41fn default_n_validators() -> usize {
43 300
44}
45
46fn default_n_cores() -> usize {
48 60
49}
50
51fn default_pov_size() -> usize {
53 5 * 1024
54}
55
56fn default_bandwidth() -> usize {
58 42 * 1024 * 1024
59}
60
61fn default_peer_latency() -> Option<PeerLatency> {
63 Some(PeerLatency { mean_latency_ms: 30, std_dev: 2.0 })
64}
65
66fn default_connectivity() -> usize {
68 90
69}
70
71fn default_backing_group_size() -> usize {
73 5
74}
75
76fn default_needed_approvals() -> usize {
78 30
79}
80
81fn default_zeroth_delay_tranche_width() -> usize {
82 0
83}
84
85fn default_relay_vrf_modulo_samples() -> usize {
86 6
87}
88
89fn default_n_delay_tranches() -> usize {
90 89
91}
92fn default_no_show_slots() -> usize {
93 3
94}
95fn default_minimum_backing_votes() -> u32 {
96 2
97}
98fn default_max_candidate_depth() -> u32 {
99 3
100}
101fn default_allowed_ancestry_len() -> u32 {
102 2
103}
104
105#[derive(Clone, Debug, Serialize, Deserialize)]
107pub struct TestConfiguration {
108 #[serde(default = "default_n_validators")]
110 pub n_validators: usize,
111 #[serde(default = "default_n_cores")]
113 pub n_cores: usize,
114 #[serde(default = "default_needed_approvals")]
116 pub needed_approvals: usize,
117 #[serde(default = "default_zeroth_delay_tranche_width")]
118 pub zeroth_delay_tranche_width: usize,
119 #[serde(default = "default_relay_vrf_modulo_samples")]
120 pub relay_vrf_modulo_samples: usize,
121 #[serde(default = "default_n_delay_tranches")]
122 pub n_delay_tranches: usize,
123 #[serde(default = "default_no_show_slots")]
124 pub no_show_slots: usize,
125 #[serde(default = "default_backing_group_size")]
127 pub max_validators_per_core: usize,
128 #[serde(default = "default_pov_size")]
130 pub min_pov_size: usize,
131 #[serde(default = "default_pov_size")]
133 pub max_pov_size: usize,
134 #[serde(skip)]
136 pub pov_sizes: Vec<usize>,
137 #[serde(default = "default_bandwidth")]
139 pub peer_bandwidth: usize,
140 #[serde(default = "default_bandwidth")]
142 pub bandwidth: usize,
143 #[serde(default = "default_peer_latency")]
145 pub latency: Option<PeerLatency>,
146 #[serde(default = "default_connectivity")]
149 pub connectivity: usize,
150 pub num_blocks: usize,
152 #[serde(default = "default_minimum_backing_votes")]
154 pub minimum_backing_votes: u32,
155 #[serde(default = "default_max_candidate_depth")]
157 pub max_candidate_depth: u32,
158 #[serde(default = "default_allowed_ancestry_len")]
160 pub allowed_ancestry_len: u32,
161}
162
163impl Default for TestConfiguration {
164 fn default() -> Self {
165 Self {
166 n_validators: default_n_validators(),
167 n_cores: default_n_cores(),
168 needed_approvals: default_needed_approvals(),
169 zeroth_delay_tranche_width: default_zeroth_delay_tranche_width(),
170 relay_vrf_modulo_samples: default_relay_vrf_modulo_samples(),
171 n_delay_tranches: default_n_delay_tranches(),
172 no_show_slots: default_no_show_slots(),
173 max_validators_per_core: default_backing_group_size(),
174 min_pov_size: default_pov_size(),
175 max_pov_size: default_pov_size(),
176 pov_sizes: Default::default(),
177 peer_bandwidth: default_bandwidth(),
178 bandwidth: default_bandwidth(),
179 latency: default_peer_latency(),
180 connectivity: default_connectivity(),
181 num_blocks: Default::default(),
182 minimum_backing_votes: default_minimum_backing_votes(),
183 max_candidate_depth: default_max_candidate_depth(),
184 allowed_ancestry_len: default_allowed_ancestry_len(),
185 }
186 }
187}
188
189impl TestConfiguration {
190 pub fn generate_pov_sizes(&mut self) {
191 self.pov_sizes = generate_pov_sizes(self.n_cores, self.min_pov_size, self.max_pov_size);
192 }
193
194 pub fn pov_sizes(&self) -> &[usize] {
195 &self.pov_sizes
196 }
197 pub fn connected_count(&self) -> usize {
199 ((self.n_validators - 1) as f64 / (100.0 / self.connectivity as f64)) as usize
200 }
201
202 pub fn generate_authorities(&self) -> TestAuthorities {
204 let keyring = Keyring::default();
205
206 let key_seeds = (0..self.n_validators)
207 .map(|peer_index| format!("//Node{peer_index}"))
208 .collect_vec();
209
210 let keys = key_seeds
211 .iter()
212 .map(|seed| keyring.sr25519_new(seed.as_str()))
213 .collect::<Vec<_>>();
214
215 let validator_public: Vec<ValidatorId> =
217 keys.iter().map(|key| (*key).into()).collect::<Vec<_>>();
218
219 let validator_authority_id: Vec<AuthorityDiscoveryId> =
220 keys.iter().map(|key| (*key).into()).collect::<Vec<_>>();
221
222 let validator_babe_id: Vec<AuthorityId> =
223 keys.iter().map(|key| (*key).into()).collect::<Vec<_>>();
224
225 let validator_assignment_id: Vec<AssignmentId> =
226 keys.iter().map(|key| (*key).into()).collect::<Vec<_>>();
227 let peer_ids: Vec<PeerId> = keys.iter().map(|_| PeerId::random()).collect::<Vec<_>>();
228
229 let peer_id_to_authority = peer_ids
230 .iter()
231 .zip(validator_authority_id.iter())
232 .map(|(peer_id, authority_id)| (*peer_id, authority_id.clone()))
233 .collect();
234
235 let validator_pairs = key_seeds
236 .iter()
237 .map(|seed| ValidatorPair::from_string_with_seed(seed, None).unwrap().0)
238 .collect();
239
240 TestAuthorities {
241 keyring,
242 validator_public,
243 validator_authority_id,
244 peer_ids,
245 validator_babe_id,
246 validator_assignment_id,
247 key_seeds,
248 peer_id_to_authority,
249 validator_pairs,
250 }
251 }
252}
253
254fn random_uniform_sample<T: Into<usize> + From<usize>>(min_value: T, max_value: T) -> T {
255 Uniform::from(min_value.into()..=max_value.into())
256 .sample(&mut thread_rng())
257 .into()
258}
259
260fn random_pov_size(min_pov_size: usize, max_pov_size: usize) -> usize {
261 random_uniform_sample(min_pov_size, max_pov_size)
262}
263
264fn generate_pov_sizes(count: usize, min_kib: usize, max_kib: usize) -> Vec<usize> {
265 (0..count).map(|_| random_pov_size(min_kib * 1024, max_kib * 1024)).collect()
266}
267
268#[derive(Clone)]
270pub struct TestAuthorities {
271 pub keyring: Keyring,
272 pub validator_public: Vec<ValidatorId>,
273 pub validator_authority_id: Vec<AuthorityDiscoveryId>,
274 pub validator_babe_id: Vec<AuthorityId>,
275 pub validator_assignment_id: Vec<AssignmentId>,
276 pub key_seeds: Vec<String>,
277 pub peer_ids: Vec<PeerId>,
278 pub peer_id_to_authority: HashMap<PeerId, AuthorityDiscoveryId>,
279 pub validator_pairs: Vec<ValidatorPair>,
280}
281
282impl std::fmt::Debug for TestAuthorities {
283 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
284 write!(f, "TestAuthorities")
285 }
286}
287
288pub fn random_latency(maybe_peer_latency: Option<&PeerLatency>) -> usize {
291 maybe_peer_latency
292 .map(|latency_config| {
293 Normal::new(latency_config.mean_latency_ms as f64, latency_config.std_dev)
294 .expect("normal distribution parameters are good")
295 .sample(&mut thread_rng())
296 })
297 .unwrap_or(0.0) as usize
298}
299
300#[async_trait::async_trait]
301impl AuthorityDiscovery for TestAuthorities {
302 async fn get_addresses_by_authority_id(
304 &mut self,
305 _authority: AuthorityDiscoveryId,
306 ) -> Option<HashSet<Multiaddr>> {
307 None
308 }
309
310 async fn get_authority_ids_by_peer_id(
312 &mut self,
313 peer_id: PeerId,
314 ) -> Option<HashSet<AuthorityDiscoveryId>> {
315 self.peer_id_to_authority.get(&peer_id).cloned().map(|id| HashSet::from([id]))
316 }
317}