1extern crate alloc;
19
20use alloc::vec;
21
22use super::*;
23use crate::extension::{AsPerson, AsPersonInfo};
24
25use core::marker::{Send, Sync};
26use frame_benchmarking::{account, v2::*, BenchmarkError};
27use frame_support::{
28 assert_ok,
29 dispatch::RawOrigin,
30 pallet_prelude::{Get, Pays},
31 traits::{Len, OnIdle, OnPoll},
32};
33use frame_system::RawOrigin as SystemOrigin;
34use sp_runtime::{
35 generic::ExtensionVersion,
36 traits::{AppendZerosInput, AsTransactionAuthorizedOrigin, DispatchTransaction},
37 Weight,
38};
39
40const RI_ZERO: RingIndex = 0;
41const SEED: u32 = 0;
42
43type SecretOf<T> = <<T as Config>::Crypto as GenerateVerifiable>::Secret;
44
45fn new_member_from<T: Config + Send + Sync>(i: u32, seed: u32) -> (SecretOf<T>, MemberOf<T>) {
46 let mut entropy = &(i, seed).encode()[..];
47 let mut entropy = AppendZerosInput::new(&mut entropy);
48 let secret = T::Crypto::new_secret(Decode::decode(&mut entropy).unwrap());
49 let public = T::Crypto::member_from_secret(&secret);
50 (secret, public)
51}
52
53fn generate_members_for_ring<T: Config + Send + Sync>(
54 seed: u32,
55) -> Vec<(SecretOf<T>, MemberOf<T>)> {
56 (0..T::MaxRingSize::get())
57 .map(|i| new_member_from::<T>(i, seed))
58 .collect::<Vec<_>>()
59}
60
61fn generate_members<T: Config + Send + Sync>(
62 seed: u32,
63 start: u32,
64 end: u32,
65) -> Vec<(SecretOf<T>, MemberOf<T>)> {
66 (start..end).map(|i| new_member_from::<T>(i, seed)).collect::<Vec<_>>()
67}
68
69pub fn recognize_people<T: Config + Send + Sync>(
70 members: &[(SecretOf<T>, MemberOf<T>)],
71) -> Vec<(PersonalId, MemberOf<T>, SecretOf<T>)> {
72 let mut people = Vec::new();
73 for (secret, public) in members.iter() {
74 let person = pallet::Pallet::<T>::reserve_new_id();
75 pallet::Pallet::<T>::recognize_personhood(person, Some(public.clone())).unwrap();
76 people.push((person, public.clone(), secret.clone()));
77 }
78
79 people
80}
81
82pub trait BenchmarkHelper<Chunk> {
83 fn valid_account_context() -> Context;
84 fn initialize_chunks() -> Vec<Chunk>;
85}
86
87#[cfg(feature = "std")]
88impl BenchmarkHelper<()> for () {
89 fn valid_account_context() -> Context {
90 [0u8; 32]
91 }
92
93 fn initialize_chunks() -> Vec<()> {
94 vec![]
95 }
96}
97
98#[cfg(feature = "std")]
99impl BenchmarkHelper<verifiable::ring_vrf_impl::StaticChunk> for () {
100 fn valid_account_context() -> Context {
101 [0u8; 32]
102 }
103
104 fn initialize_chunks() -> Vec<verifiable::ring_vrf_impl::StaticChunk> {
105 vec![]
106 }
107}
108
109fn prepare_chunks<T: Config>() {
110 let chunks = T::BenchmarkHelper::initialize_chunks();
111
112 let page_size = <T as Config>::ChunkPageSize::get();
113
114 let mut page_idx = 0;
115 let mut chunk_idx = 0;
116 while chunk_idx < chunks.len() {
117 let chunk_idx_end = core::cmp::min(chunk_idx + page_size as usize, chunks.len());
118 let chunk_page: ChunksOf<T> = chunks[chunk_idx..chunk_idx_end]
119 .to_vec()
120 .try_into()
121 .expect("page size was checked against the array length; qed");
122 Chunks::<T>::insert(page_idx, chunk_page);
123 page_idx += 1;
124 chunk_idx = chunk_idx_end;
125 }
126}
127
128#[benchmarks(
129 where T: Send + Sync,
130 <T as frame_system::Config>::RuntimeCall:
131 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + From<Call<T>> + GetDispatchInfo,
132 <T as frame_system::Config>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
133)]
134mod benches {
135 use super::*;
136
137 #[benchmark]
138 fn under_alias() -> Result<(), BenchmarkError> {
139 prepare_chunks::<T>();
140
141 let members = generate_members_for_ring::<T>(SEED);
143 recognize_people::<T>(&members);
144 assert_ok!(pallet::Pallet::<T>::onboard_people());
145 let to_include =
146 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
147 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
148
149 let account: T::AccountId = whitelisted_caller();
151 let context = T::BenchmarkHelper::valid_account_context();
152 let alias_value: Alias = [0u8; 32];
153 let ra = RevisedContextualAlias {
154 revision: 0,
155 ring: RI_ZERO,
156 ca: ContextualAlias { context, alias: alias_value },
157 };
158
159 let block_number = frame_system::Pallet::<T>::block_number();
161 assert_ok!(pallet::Pallet::<T>::set_alias_account(
162 Origin::PersonalAlias(ra.clone()).into(),
163 account.clone(),
164 block_number
165 ));
166 assert!(AccountToAlias::<T>::contains_key(&account));
167 assert!(AliasToAccount::<T>::contains_key(&ra.ca));
168
169 let call = frame_system::Call::<T>::remark { remark: vec![] };
171 let boxed_call = Box::new(call.into());
172
173 #[extrinsic_call]
174 _(RawOrigin::Signed(account), boxed_call);
175
176 Ok(())
177 }
178
179 #[benchmark]
180 fn set_alias_account() -> Result<(), BenchmarkError> {
181 prepare_chunks::<T>();
182
183 let members = generate_members_for_ring::<T>(SEED);
185 recognize_people::<T>(&members);
186 assert_ok!(pallet::Pallet::<T>::onboard_people());
187 let to_include =
188 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
189 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
190
191 let block_number = frame_system::Pallet::<T>::block_number();
192
193 let alias_value: Alias = [0u8; 32];
194 let alias = RevisedContextualAlias {
195 ca: ContextualAlias {
196 context: T::BenchmarkHelper::valid_account_context(),
197 alias: alias_value,
198 },
199 revision: 0,
200 ring: 0,
201 };
202
203 let old_account: T::AccountId = account("test_old", 0, SEED);
205 assert_ok!(pallet::Pallet::<T>::set_alias_account(
206 Origin::PersonalAlias(alias.clone()).into(),
207 old_account.clone(),
208 block_number
209 ));
210 assert!(AccountToAlias::<T>::contains_key(&old_account));
211 assert!(AliasToAccount::<T>::contains_key(&alias.ca));
212
213 let account: T::AccountId = account("test", 0, SEED);
214
215 #[extrinsic_call]
216 _(Origin::PersonalAlias(alias.clone()), account.clone(), block_number);
217
218 assert!(!AccountToAlias::<T>::contains_key(&old_account));
219 assert!(AccountToAlias::<T>::contains_key(&account));
220 assert!(AliasToAccount::<T>::contains_key(&alias.ca));
221 assert_eq!(AliasToAccount::<T>::get(&alias.ca), Some(account));
222
223 Ok(())
224 }
225
226 #[benchmark]
227 fn unset_alias_account() -> Result<(), BenchmarkError> {
228 prepare_chunks::<T>();
229
230 let members = generate_members_for_ring::<T>(SEED);
232 recognize_people::<T>(&members);
233 assert_ok!(pallet::Pallet::<T>::onboard_people());
234 let to_include =
235 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
236 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
237
238 let account: T::AccountId = account("test", 0, SEED);
239 let block_number = frame_system::Pallet::<T>::block_number();
240
241 let alias_value: Alias = [0u8; 32];
242 let alias = RevisedContextualAlias {
243 ca: ContextualAlias {
244 context: T::BenchmarkHelper::valid_account_context(),
245 alias: alias_value,
246 },
247 revision: 0,
248 ring: 0,
249 };
250
251 assert_ok!(pallet::Pallet::<T>::set_alias_account(
252 Origin::PersonalAlias(alias.clone()).into(),
253 account.clone(),
254 block_number
255 ));
256 assert!(AccountToAlias::<T>::contains_key(&account));
257 assert!(AliasToAccount::<T>::contains_key(&alias.ca));
258
259 #[extrinsic_call]
260 _(Origin::PersonalAlias(alias.clone()));
261
262 assert!(!AccountToAlias::<T>::contains_key(&account));
263 assert!(!AliasToAccount::<T>::contains_key(&alias.ca));
264
265 Ok(())
266 }
267
268 #[benchmark]
269 fn force_recognize_personhood() -> Result<(), BenchmarkError> {
270 let members = generate_members_for_ring::<T>(SEED);
271
272 #[extrinsic_call]
273 _(SystemOrigin::Root, members.iter().map(|(_, m)| m.clone()).collect::<Vec<_>>());
274
275 for person in members {
276 assert!(pallet::Keys::<T>::get(person.1).is_some());
277 }
278
279 Ok(())
280 }
281
282 #[benchmark]
283 fn set_personal_id_account() -> Result<(), BenchmarkError> {
284 prepare_chunks::<T>();
285
286 let members = generate_members_for_ring::<T>(SEED);
288 let people = recognize_people::<T>(&members);
289 assert_ok!(pallet::Pallet::<T>::onboard_people());
290 let to_include =
291 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
292 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
293
294 let (personal_id, _, _): &(PersonalId, MemberOf<T>, SecretOf<T>) = &people[0];
296
297 let account: T::AccountId = account("test", 0, SEED);
298 let block_number = frame_system::Pallet::<T>::block_number();
299
300 let old_account: T::AccountId = frame_benchmarking::account("test_old", 0, SEED);
302 assert_ok!(pallet::Pallet::<T>::set_personal_id_account(
303 Origin::PersonalIdentity(*personal_id).into(),
304 old_account.clone(),
305 block_number
306 ));
307
308 #[extrinsic_call]
309 _(Origin::PersonalIdentity(*personal_id), account.clone(), block_number);
310
311 assert_eq!(AccountToPersonalId::<T>::get(&old_account), None);
312 assert_eq!(AccountToPersonalId::<T>::get(&account), Some(*personal_id));
313 assert!(People::<T>::get(personal_id).is_some());
314 assert_eq!(People::<T>::get(personal_id).unwrap().account, Some(account));
315
316 Ok(())
317 }
318
319 #[benchmark]
320 fn unset_personal_id_account() -> Result<(), BenchmarkError> {
321 prepare_chunks::<T>();
322
323 let members = generate_members_for_ring::<T>(SEED);
325 let people = recognize_people::<T>(&members);
326 assert_ok!(pallet::Pallet::<T>::onboard_people());
327 let to_include =
328 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
329 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
330
331 let (personal_id, _, _): &(PersonalId, MemberOf<T>, SecretOf<T>) = &people[0];
333
334 let account: T::AccountId = account("test", 0, SEED);
335 let block_number = frame_system::Pallet::<T>::block_number();
336
337 let old_account: T::AccountId = frame_benchmarking::account("test_old", 0, SEED);
339 assert_ok!(pallet::Pallet::<T>::set_personal_id_account(
340 Origin::PersonalIdentity(*personal_id).into(),
341 old_account.clone(),
342 block_number
343 ));
344
345 #[extrinsic_call]
346 _(Origin::PersonalIdentity(*personal_id));
347
348 assert_eq!(AccountToPersonalId::<T>::get(&old_account), None);
349 assert_eq!(AccountToPersonalId::<T>::get(&account), None);
350 assert!(People::<T>::get(personal_id).is_some());
351 assert_eq!(People::<T>::get(personal_id).unwrap().account, None);
352
353 Ok(())
354 }
355
356 #[benchmark]
357 fn set_onboarding_size() -> Result<(), BenchmarkError> {
358 #[extrinsic_call]
359 _(SystemOrigin::Root, 1);
360
361 assert_eq!(OnboardingSize::<T>::get(), 1);
362
363 Ok(())
364 }
365
366 #[benchmark]
367 fn merge_rings() -> Result<(), BenchmarkError> {
368 prepare_chunks::<T>();
369
370 let ring_size: u32 = <T as Config>::MaxRingSize::get();
372 let members = generate_members::<T>(SEED, 0, ring_size * 2);
373
374 recognize_people::<T>(&members);
375 assert_ok!(pallet::Pallet::<T>::onboard_people());
376 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO).total, ring_size);
377
378 assert_ok!(pallet::Pallet::<T>::onboard_people());
379 assert_eq!(RingKeysStatus::<T>::get(1).total, ring_size);
380
381 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, T::MaxRingSize::get()));
382 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO).included, ring_size);
383
384 assert_ok!(pallet::Pallet::<T>::build_ring(1, T::MaxRingSize::get()));
385 assert_eq!(RingKeysStatus::<T>::get(1).included, ring_size);
386
387 assert_ok!(pallet::Pallet::<T>::start_people_set_mutation_session());
389 let suspensions: Vec<PersonalId> = (1..ring_size / 2 + 3)
390 .chain(ring_size + 1..ring_size * 3 / 2 + 3)
391 .map(|i| i as PersonalId)
392 .collect();
393 assert_ok!(pallet::Pallet::<T>::suspend_personhood(&suspensions));
394 assert_ok!(pallet::Pallet::<T>::end_people_set_mutation_session());
395
396 assert!(PendingSuspensions::<T>::get(RI_ZERO).len() > (ring_size / 2) as usize);
397 assert!(PendingSuspensions::<T>::get(1).len() > (ring_size / 2) as usize);
398
399 let mut meter = WeightMeter::new();
400 pallet::Pallet::<T>::migrate_keys(&mut meter);
401
402 pallet::Pallet::<T>::remove_suspended_keys(RI_ZERO);
403 pallet::Pallet::<T>::remove_suspended_keys(1);
404
405 assert!(RingKeys::<T>::get(RI_ZERO).len() < (ring_size / 2) as usize);
406 assert!(RingKeys::<T>::get(1).len() < (ring_size / 2) as usize);
407
408 let keys_left_len = RingKeys::<T>::get(RI_ZERO).len() + RingKeys::<T>::get(1).len();
409
410 CurrentRingIndex::<T>::set(14);
412
413 let account: T::AccountId = account("caller", 0, SEED);
414
415 #[extrinsic_call]
416 _(SystemOrigin::Signed(account), RI_ZERO, 1);
417
418 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), keys_left_len);
419 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO).total, keys_left_len as u32);
420 assert!(Root::<T>::get(RI_ZERO).is_some());
421 assert!(Root::<T>::get(1).is_none());
422
423 Ok(())
424 }
425
426 #[benchmark]
427 fn migrate_included_key() -> Result<(), BenchmarkError> {
428 prepare_chunks::<T>();
429
430 let members = generate_members_for_ring::<T>(SEED);
432 recognize_people::<T>(&members);
433 assert_ok!(pallet::Pallet::<T>::onboard_people());
434 let to_include =
435 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
436 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
437
438 let temp_key = new_member_from::<T>(u32::MAX, SEED).1;
439 KeyMigrationQueue::<T>::insert(0, temp_key);
440
441 let new_key = new_member_from::<T>(u32::MAX - 1, SEED).1;
442
443 #[extrinsic_call]
444 _(Origin::PersonalIdentity(0u64), new_key.clone());
445
446 assert_eq!(KeyMigrationQueue::<T>::get(0), Some(new_key));
448
449 Ok(())
450 }
451
452 #[benchmark]
453 fn migrate_onboarding_key() -> Result<(), BenchmarkError> {
454 prepare_chunks::<T>();
455
456 let members = generate_members_for_ring::<T>(SEED);
458 recognize_people::<T>(&members);
459 assert_ok!(pallet::Pallet::<T>::onboard_people());
460 let to_include =
461 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
462 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
463
464 let temp_key = new_member_from::<T>(u32::MAX, SEED).1;
465
466 let new_person = pallet::Pallet::<T>::reserve_new_id();
467 pallet::Pallet::<T>::recognize_personhood(new_person, Some(temp_key.clone())).unwrap();
468
469 let new_key = new_member_from::<T>(u32::MAX - 1, SEED).1;
470
471 #[extrinsic_call]
472 _(Origin::PersonalIdentity(new_person), new_key.clone());
473
474 assert!(KeyMigrationQueue::<T>::iter().next().is_none());
476 assert_eq!(OnboardingQueue::<T>::get(0)[0], new_key);
477
478 Ok(())
479 }
480
481 #[benchmark]
482 fn should_build_ring(n: Linear<1, { T::MaxRingSize::get() }>) -> Result<(), BenchmarkError> {
483 prepare_chunks::<T>();
484
485 let queue_page_size: u32 = <T as Config>::OnboardingQueuePageSize::get();
487 let ring_size: u32 = <T as Config>::MaxRingSize::get();
488 let members = generate_members::<T>(SEED, 0, queue_page_size);
489 recognize_people::<T>(&members);
490 assert_ok!(pallet::Pallet::<T>::onboard_people());
491
492 assert!(Root::<T>::get(RI_ZERO).is_none());
494 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), ring_size as usize);
495 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO), RingStatus { total: ring_size, included: 0 });
496
497 #[block]
498 {
499 let _ = Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get());
500 }
501
502 Ok(())
503 }
504
505 #[benchmark]
506 fn build_ring(n: Linear<1, { T::MaxRingSize::get() }>) -> Result<(), BenchmarkError> {
507 prepare_chunks::<T>();
508
509 let queue_page_size: u32 = <T as Config>::OnboardingQueuePageSize::get();
511 let ring_size: u32 = <T as Config>::MaxRingSize::get();
512 let members = generate_members::<T>(SEED, 0, queue_page_size);
513 recognize_people::<T>(&members);
514 assert_ok!(pallet::Pallet::<T>::onboard_people());
515
516 assert!(Root::<T>::get(RI_ZERO).is_none());
518 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), ring_size as usize);
519 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO), RingStatus { total: ring_size, included: 0 });
520
521 #[block]
522 {
523 assert_ok!(Pallet::<T>::build_ring(RI_ZERO, n));
524 }
525
526 assert!(Root::<T>::get(RI_ZERO).is_some());
528 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), ring_size as usize);
529 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO), RingStatus { total: ring_size, included: n });
530
531 Ok(())
532 }
533
534 #[benchmark]
535 fn onboard_people() -> Result<(), BenchmarkError> {
536 prepare_chunks::<T>();
537
538 let ring_size: u32 = <T as Config>::MaxRingSize::get();
540 let members = generate_members::<T>(SEED, 0, ring_size);
541 recognize_people::<T>(&members);
542 assert_ok!(pallet::Pallet::<T>::onboard_people());
543 let to_include =
544 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
545 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
546 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), ring_size as usize);
547 assert_eq!(
548 RingKeysStatus::<T>::get(RI_ZERO),
549 RingStatus { total: ring_size, included: ring_size }
550 );
551
552 assert_eq!(QueuePageIndices::<T>::get(), (0, 0));
553 assert!(OnboardingQueue::<T>::get(0).is_empty());
554
555 let keys_len: u32 = Keys::<T>::iter().collect::<Vec<_>>().len().try_into().unwrap();
557 let members = generate_members::<T>(SEED, keys_len, keys_len + ring_size / 2);
558 recognize_people::<T>(&members);
559 assert_eq!(OnboardingQueue::<T>::get(0).len(), (ring_size as u8 / 2) as usize);
560
561 QueuePageIndices::<T>::put((0, 1));
563 assert!(OnboardingQueue::<T>::get(1).is_empty());
564
565 let keys_len: u32 = Keys::<T>::iter().collect::<Vec<_>>().len().try_into().unwrap();
567 assert_eq!(keys_len, (ring_size + ring_size / 2));
568 let queue_page_size: u32 = <T as Config>::OnboardingQueuePageSize::get();
569 let members = generate_members::<T>(SEED, keys_len, keys_len + queue_page_size);
570 recognize_people::<T>(&members);
571
572 assert_eq!(QueuePageIndices::<T>::get(), (0, 1));
573 assert_eq!(OnboardingQueue::<T>::get(0).len(), (ring_size / 2) as usize);
574 assert!(OnboardingQueue::<T>::get(1).is_full());
575
576 assert_eq!(RingKeys::<T>::get(1).len(), 0);
577
578 #[block]
579 {
580 assert_ok!(Pallet::<T>::onboard_people());
581 }
582
583 assert_eq!(RingKeys::<T>::get(1).len(), ring_size as usize);
584 assert_eq!(RingKeysStatus::<T>::get(1), RingStatus { total: ring_size, included: 0 });
585
586 Ok(())
587 }
588
589 #[benchmark]
590 fn pending_suspensions_iteration() -> Result<(), BenchmarkError> {
591 prepare_chunks::<T>();
592
593 let members = generate_members_for_ring::<T>(SEED);
595 let max_ring_size = T::MaxRingSize::get();
596 recognize_people::<T>(&members);
597 assert_ok!(pallet::Pallet::<T>::onboard_people());
598 let to_include = pallet::Pallet::<T>::should_build_ring(RI_ZERO, max_ring_size).unwrap();
599 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
600
601 assert_ok!(pallet::Pallet::<T>::start_people_set_mutation_session());
603 let suspensions: Vec<PersonalId> = (0..max_ring_size as PersonalId).collect();
604 assert_ok!(pallet::Pallet::<T>::suspend_personhood(&suspensions));
605 assert_ok!(pallet::Pallet::<T>::end_people_set_mutation_session());
606 let mut meter = WeightMeter::new();
607 pallet::Pallet::<T>::migrate_keys(&mut meter);
608
609 assert_eq!(PendingSuspensions::<T>::get(RI_ZERO).len(), max_ring_size as usize);
611
612 #[block]
613 {
614 assert!(PendingSuspensions::<T>::iter_keys().next().is_some());
615 }
616
617 Ok(())
618 }
619
620 #[benchmark]
621 fn remove_suspended_keys(
622 n: Linear<1, { T::MaxRingSize::get() }>,
623 ) -> Result<(), BenchmarkError> {
624 prepare_chunks::<T>();
625
626 let members = generate_members_for_ring::<T>(SEED);
628 recognize_people::<T>(&members);
629 assert_ok!(pallet::Pallet::<T>::onboard_people());
630 let to_include =
631 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
632 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
633
634 let initial_root = Root::<T>::get(RI_ZERO).unwrap();
636
637 assert_ok!(pallet::Pallet::<T>::start_people_set_mutation_session());
639 let suspensions: Vec<PersonalId> = (0..n as PersonalId).collect();
640 assert_ok!(pallet::Pallet::<T>::suspend_personhood(&suspensions));
641 assert_ok!(pallet::Pallet::<T>::end_people_set_mutation_session());
642 let mut meter = WeightMeter::new();
643 pallet::Pallet::<T>::migrate_keys(&mut meter);
644
645 assert_eq!(PendingSuspensions::<T>::get(RI_ZERO).len(), n as usize);
647
648 #[block]
649 {
650 pallet::Pallet::<T>::remove_suspended_keys(RI_ZERO);
651 }
652
653 assert!(PendingSuspensions::<T>::get(RI_ZERO).is_empty());
655
656 let ring_size: u32 = <T as Config>::MaxRingSize::get();
658 assert_eq!(
659 RingKeysStatus::<T>::get(RI_ZERO),
660 RingStatus { included: 0, total: ring_size - n as u32 }
661 );
662 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), (ring_size - n as u32) as usize);
663 assert_ne!(Root::<T>::get(RI_ZERO).unwrap().intermediate, initial_root.intermediate);
664
665 Ok(())
666 }
667
668 #[benchmark]
669 fn migrate_keys_single_included_key() -> Result<(), BenchmarkError> {
670 prepare_chunks::<T>();
671
672 let max_members = T::MaxRingSize::get();
673 let members = generate_members_for_ring::<T>(SEED);
675 recognize_people::<T>(&members);
676 assert_ok!(pallet::Pallet::<T>::onboard_people());
677 let to_include =
678 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
679 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
680
681 for (personal_id, key) in (0..max_members as PersonalId)
683 .map(|i| new_member_from::<T>(u32::MAX - i as u32, SEED).1)
684 .enumerate()
685 {
686 assert_ok!(pallet::Pallet::<T>::migrate_included_key(
687 Origin::PersonalIdentity(personal_id as PersonalId).into(),
688 key
689 ));
690 }
691 assert_ok!(pallet::Pallet::<T>::start_people_set_mutation_session());
692 assert_ok!(pallet::Pallet::<T>::end_people_set_mutation_session());
693 assert!(PendingSuspensions::<T>::get(RI_ZERO).is_empty());
694 assert_eq!(KeyMigrationQueue::<T>::iter().count(), T::MaxRingSize::get() as usize);
697 let (first_id, first_key) = KeyMigrationQueue::<T>::iter().next().unwrap();
698
699 #[block]
700 {
701 assert_ok!(pallet::Pallet::<T>::migrate_keys_single_included_key(first_id, first_key));
702 }
703
704 assert_eq!(PendingSuspensions::<T>::get(RI_ZERO).len(), 1);
706
707 Ok(())
708 }
709
710 #[benchmark]
711 fn merge_queue_pages() -> Result<(), BenchmarkError> {
712 prepare_chunks::<T>();
713
714 let queue_page_size: u32 = <T as Config>::OnboardingQueuePageSize::get();
716 let members = generate_members::<T>(SEED, 0, queue_page_size + 1);
717 recognize_people::<T>(&members);
718
719 assert_eq!(QueuePageIndices::<T>::get(), (0, 1));
720 assert!(OnboardingQueue::<T>::get(0).is_full());
721 assert_eq!(OnboardingQueue::<T>::get(1).len(), 1);
722
723 OnboardingQueue::<T>::mutate(0, |keys| {
725 keys.pop();
726 });
727 assert_eq!(OnboardingQueue::<T>::get(0).len(), queue_page_size as usize - 1);
728
729 let QueueMergeAction::Merge { initial_head, new_head, first_key_page, second_key_page } =
731 pallet::Pallet::<T>::should_merge_queue_pages()
732 else {
733 panic!("should be mergeable")
734 };
735
736 #[block]
737 {
738 pallet::Pallet::<T>::merge_queue_pages(
739 initial_head,
740 new_head,
741 first_key_page,
742 second_key_page,
743 );
744 }
745
746 assert_eq!(QueuePageIndices::<T>::get(), (1, 1));
748 assert!(OnboardingQueue::<T>::get(0).is_empty());
749 assert!(OnboardingQueue::<T>::get(1).is_full());
750
751 Ok(())
752 }
753
754 #[benchmark]
755 fn on_poll_base() -> Result<(), BenchmarkError> {
756 let queue_page_size: u32 = <T as Config>::OnboardingQueuePageSize::get();
758 let members = generate_members::<T>(SEED, 0, queue_page_size + 1);
759 recognize_people::<T>(&members);
760
761 assert_eq!(QueuePageIndices::<T>::get(), (0, 1));
762 assert!(OnboardingQueue::<T>::get(0).is_full());
763 assert_eq!(OnboardingQueue::<T>::get(1).len(), 1);
764 assert!(RingsState::<T>::get().append_only());
765
766 let mut meter = WeightMeter::new();
767
768 #[block]
769 {
770 pallet::Pallet::<T>::on_poll(0u32.into(), &mut meter);
771 }
772
773 assert_eq!(meter.consumed(), T::WeightInfo::on_poll_base());
774 Ok(())
775 }
776
777 #[benchmark]
778 fn on_idle_base() -> Result<(), BenchmarkError> {
779 prepare_chunks::<T>();
780
781 let queue_page_size: u32 = <T as Config>::OnboardingQueuePageSize::get();
783 let ring_size = T::MaxRingSize::get();
784 let members = generate_members::<T>(SEED, 0, queue_page_size + 1);
785 recognize_people::<T>(&members);
786 assert_ok!(pallet::Pallet::<T>::onboard_people());
787
788 assert!(Root::<T>::get(RI_ZERO).is_none());
790 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), ring_size as usize);
791 assert_eq!(RingKeysStatus::<T>::get(RI_ZERO), RingStatus { total: ring_size, included: 0 });
792 let to_include = Pallet::<T>::should_build_ring(RI_ZERO, ring_size).unwrap();
793 assert_ok!(Pallet::<T>::build_ring(RI_ZERO, to_include));
794 assert!(Root::<T>::get(RI_ZERO).is_some());
796 assert_eq!(RingKeys::<T>::get(RI_ZERO).len(), ring_size as usize);
797 assert_eq!(
798 RingKeysStatus::<T>::get(RI_ZERO),
799 RingStatus { total: ring_size, included: ring_size }
800 );
801
802 #[block]
803 {
804 pallet::Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
805 }
806
807 Ok(())
808 }
809
810 #[benchmark]
811 fn as_person_alias_with_account() -> Result<(), BenchmarkError> {
812 prepare_chunks::<T>();
813
814 let members = generate_members_for_ring::<T>(SEED);
816 recognize_people::<T>(&members);
817 assert_ok!(pallet::Pallet::<T>::onboard_people());
818 let to_include =
819 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
820 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
821
822 let account: T::AccountId = account("caller", 0, SEED);
824 let context = T::BenchmarkHelper::valid_account_context();
825 let alias_value: Alias = [0u8; 32];
826 let ra = RevisedContextualAlias {
827 revision: 0,
828 ring: RI_ZERO,
829 ca: ContextualAlias { context, alias: alias_value },
830 };
831
832 let block_number = frame_system::Pallet::<T>::block_number();
834 assert_ok!(pallet::Pallet::<T>::set_alias_account(
835 Origin::PersonalAlias(ra.clone()).into(),
836 account.clone(),
837 block_number
838 ));
839 assert!(AccountToAlias::<T>::contains_key(&account));
840 assert!(AliasToAccount::<T>::contains_key(&ra.ca));
841
842 let inner = frame_system::Call::<T>::remark { remark: vec![] };
844 let call: <T as frame_system::Config>::RuntimeCall = inner.into();
845
846 let ext =
847 AsPerson::new(Some(AsPersonInfo::<T>::AsPersonalAliasWithAccount(T::Nonce::default())));
848 let info = call.get_dispatch_info();
849 let post_info = PostDispatchInfo {
850 actual_weight: Some(Weight::from_parts(10, 0)),
851 pays_fee: Pays::Yes,
852 };
853 let len = call.encoded_size();
854
855 #[block]
856 {
857 ext.test_run(RawOrigin::Signed(account).into(), &call, &info, len, 0, |_| {
858 Ok(post_info)
859 })
860 .unwrap()
861 .unwrap();
862 }
863
864 Ok(())
865 }
866
867 #[benchmark]
868 fn as_person_identity_with_account() -> Result<(), BenchmarkError> {
869 prepare_chunks::<T>();
870
871 let members = generate_members_for_ring::<T>(SEED);
873 let recognized_people = recognize_people::<T>(&members);
874 assert_ok!(pallet::Pallet::<T>::onboard_people());
875 let to_include =
876 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
877 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
878
879 let (personal_id, _, _): &(PersonalId, MemberOf<T>, SecretOf<T>) = &recognized_people[0];
881
882 let account: T::AccountId = account("caller", 0, SEED);
884 let block_number = frame_system::Pallet::<T>::block_number();
885 assert_ok!(pallet::Pallet::<T>::set_personal_id_account(
886 Origin::PersonalIdentity(*personal_id).into(),
887 account.clone(),
888 block_number
889 ));
890 assert!(AccountToPersonalId::<T>::contains_key(&account));
891
892 let inner = frame_system::Call::<T>::remark { remark: vec![] };
894 let call: <T as frame_system::Config>::RuntimeCall = inner.into();
895
896 let ext = AsPerson::new(Some(AsPersonInfo::<T>::AsPersonalIdentityWithAccount(
897 T::Nonce::default(),
898 )));
899 let info = call.get_dispatch_info();
900 let post_info = PostDispatchInfo {
901 actual_weight: Some(Weight::from_parts(10, 0)),
902 pays_fee: Pays::Yes,
903 };
904 let len = call.encoded_size();
905
906 #[block]
907 {
908 ext.test_run(RawOrigin::Signed(account).into(), &call, &info, len, 0, |_| {
909 Ok(post_info)
910 })
911 .unwrap()
912 .unwrap();
913 }
914
915 Ok(())
916 }
917
918 #[benchmark]
919 fn as_person_alias_with_proof() -> Result<(), BenchmarkError> {
920 prepare_chunks::<T>();
921
922 let account: T::AccountId = account("caller", 0, SEED);
924 let members = generate_members_for_ring::<T>(SEED);
925 recognize_people::<T>(&members);
926 assert_ok!(pallet::Pallet::<T>::onboard_people());
927 let to_include =
928 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
929 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
930
931 let block_number = frame_system::Pallet::<T>::block_number();
933 let inner = Call::<T>::set_alias_account { account, call_valid_at: block_number };
934 let call: <T as frame_system::Config>::RuntimeCall = inner.into();
935
936 let context = T::BenchmarkHelper::valid_account_context();
937 let ext_version: ExtensionVersion = 0;
938
939 let proof = (ext_version, &call).using_encoded(|msg| {
941 let (secret, member) = &members[0];
942 T::Crypto::create(
943 T::Crypto::open(member, members.iter().map(|(_, m)| m.clone())).unwrap(),
944 secret,
945 &context[..],
946 &sp_io::hashing::blake2_256(msg),
947 )
948 .map(|(p, _)| p)
949 .expect("should create proof")
950 });
951
952 let ext = AsPerson::new(Some(AsPersonInfo::<T>::AsPersonalAliasWithProof(
953 proof, RI_ZERO, context,
954 )));
955 let info = call.get_dispatch_info();
956 let post_info = PostDispatchInfo {
957 actual_weight: Some(Weight::from_parts(10, 0)),
958 pays_fee: Pays::Yes,
959 };
960 let len = call.encoded_size();
961
962 #[block]
963 {
964 ext.test_run(RawOrigin::None.into(), &call, &info, len, 0, |_| Ok(post_info))
965 .unwrap()
966 .unwrap();
967 }
968
969 Ok(())
970 }
971
972 #[benchmark]
973 fn as_person_identity_with_proof() -> Result<(), BenchmarkError> {
974 prepare_chunks::<T>();
975
976 let account: T::AccountId = account("caller", 0, SEED);
978 let members = generate_members_for_ring::<T>(SEED);
979 let recognized_people = recognize_people::<T>(&members);
980 assert_ok!(pallet::Pallet::<T>::onboard_people());
981 let to_include =
982 pallet::Pallet::<T>::should_build_ring(RI_ZERO, T::MaxRingSize::get()).unwrap();
983 assert_ok!(pallet::Pallet::<T>::build_ring(RI_ZERO, to_include));
984
985 let (personal_id, _, secret): &(PersonalId, MemberOf<T>, SecretOf<T>) =
987 &recognized_people[0];
988
989 let block_number = frame_system::Pallet::<T>::block_number();
991 let inner = Call::<T>::set_personal_id_account { account, call_valid_at: block_number };
992 let call: <T as frame_system::Config>::RuntimeCall = inner.into();
993 let ext_version: ExtensionVersion = 0;
994 let signature = (ext_version, &call).using_encoded(|msg| {
995 <T::Crypto as GenerateVerifiable>::sign(secret, &sp_io::hashing::blake2_256(msg))
996 .expect("failed to create signature")
997 });
998
999 let ext = AsPerson::new(Some(AsPersonInfo::<T>::AsPersonalIdentityWithProof(
1000 signature,
1001 *personal_id,
1002 )));
1003 let info = call.get_dispatch_info();
1004 let post_info = PostDispatchInfo {
1005 actual_weight: Some(Weight::from_parts(10, 0)),
1006 pays_fee: Pays::Yes,
1007 };
1008 let len = call.encoded_size();
1009
1010 #[block]
1011 {
1012 ext.test_run(RawOrigin::None.into(), &call, &info, len, 0, |_| Ok(post_info))
1013 .unwrap()
1014 .unwrap();
1015 }
1016
1017 Ok(())
1018 }
1019
1020 impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
1023}