1#[cfg(test)]
19pub mod ah;
20#[cfg(test)]
21pub mod rc;
22
23#[cfg(test)]
24pub mod shared;
25
26#[cfg(test)]
28mod tests {
29 use super::*;
30 use crate::{
31 ah::{rc_client_events_since_last_call, staking_events_since_last_call},
32 rc::RootOffences,
33 };
34 use ah_client::OperatingMode;
35 use frame::testing_prelude::*;
36 use frame_support::traits::Get;
37 use pallet_election_provider_multi_block as multi_block;
38 use pallet_staking as staking_classic;
39 use pallet_staking_async::{ActiveEra, ActiveEraInfo, Forcing};
40 use pallet_staking_async_ah_client::{self as ah_client, OffenceSendQueue};
41 use pallet_staking_async_rc_client as rc_client;
42
43 #[test]
44 fn rc_session_change_reported_to_ah() {
45 shared::put_ah_state(ah::ExtBuilder::default().build());
47 shared::put_rc_state(rc::ExtBuilder::default().build());
48 shared::in_ah(|| {
52 assert_eq!(frame_system::Pallet::<ah::Runtime>::block_number(), 1);
53 assert_eq!(pallet_staking_async::CurrentEra::<ah::Runtime>::get(), Some(0));
54 assert_eq!(
55 ActiveEra::<ah::Runtime>::get(),
56 Some(ActiveEraInfo { index: 0, start: Some(0) })
57 );
58 });
59
60 shared::in_rc(|| {
61 assert_eq!(ah_client::Mode::<rc::Runtime>::get(), OperatingMode::Active);
63 assert!(frame_system::Pallet::<rc::Runtime>::block_number() == 1);
66
67 rc::roll_until_matches(
69 || pallet_session::CurrentIndex::<rc::Runtime>::get() == 1,
70 true,
71 );
72
73 assert_eq!(frame_system::Pallet::<rc::Runtime>::block_number(), rc::Period::get());
75 });
76
77 shared::in_rc(|| {
78 rc::roll_until_matches(
80 || pallet_session::CurrentIndex::<rc::Runtime>::get() == 4,
81 true,
82 );
83 });
84
85 shared::in_ah(|| {
86 assert_eq!(frame_system::Pallet::<ah::Runtime>::block_number(), 120);
88 assert!(matches!(
90 multi_block::CurrentPhase::<ah::Runtime>::get(),
91 multi_block::Phase::Snapshot(_)
92 ));
93 });
94
95 shared::in_rc(|| {
97 rc::roll_until_matches(
98 || pallet_session::CurrentIndex::<rc::Runtime>::get() == 5,
99 true,
100 );
101 });
102
103 shared::in_ah(|| {
105 assert_eq!(pallet_staking_async::CurrentEra::<ah::Runtime>::get(), Some(1));
106 assert_eq!(
107 ActiveEra::<ah::Runtime>::get(),
108 Some(ActiveEraInfo { index: 0, start: Some(0) })
109 );
110 });
111
112 shared::in_rc(|| {
114 rc::roll_until_matches(
115 || pallet_session::CurrentIndex::<rc::Runtime>::get() == 6,
116 true,
117 );
118 });
119 }
120
121 #[test]
122 fn ah_takes_over_staking_post_migration() {
123 shared::put_rc_state(
125 rc::ExtBuilder::default()
126 .pre_migration()
127 .session_keys(vec![1, 2, 3, 4, 5, 6, 7, 8])
129 .max_offence_batch_size(2)
131 .build(),
132 );
133 shared::put_ah_state(ah::ExtBuilder::default().build());
134
135 shared::in_rc(|| {
136 assert!(staking_classic::ActiveEra::<rc::Runtime>::get().is_none());
137
138 rc::roll_until_matches(
140 || {
141 staking_classic::ActiveEra::<rc::Runtime>::get().map(|a| a.index).unwrap_or(0) ==
142 1
143 },
144 true,
145 );
146
147 assert!(staking_classic::UnappliedSlashes::<rc::Runtime>::get(4).is_empty());
149
150 assert_ok!(RootOffences::create_offence(
151 rc::RuntimeOrigin::root(),
152 vec![(2, Perbill::from_percent(100))],
153 None,
154 None
155 ));
156
157 assert_eq!(staking_classic::UnappliedSlashes::<rc::Runtime>::get(4).len(), 1);
159 });
160
161 shared::in_ah(|| {
163 assert_eq!(shared::CounterRCAHNewOffence::get(), 0);
167 assert_eq!(shared::CounterRCAHSessionReport::get(), 0);
168
169 assert_eq!(ah::mock::staking_events_since_last_call(), vec![]);
170 });
171
172 let mut pre_migration_block_number = 0;
174 shared::in_rc(|| {
175 rc::roll_next();
176
177 let pre_migration_era_points =
178 staking_classic::ErasRewardPoints::<rc::Runtime>::get(1).total;
179
180 ah_client::Pallet::<rc::Runtime>::on_migration_start();
181 assert_eq!(ah_client::Mode::<rc::Runtime>::get(), OperatingMode::Buffered);
182
183 let current_session = pallet_session::CurrentIndex::<rc::Runtime>::get();
185 pre_migration_block_number = frame_system::Pallet::<rc::Runtime>::block_number();
186
187 rc::roll_until_matches(
191 || {
192 pallet_session::CurrentIndex::<rc::Runtime>::get() ==
193 current_session + ah::SessionsPerEra::get() + 1
194 },
195 true,
196 );
197 let migration_start_block_number = frame_system::Pallet::<rc::Runtime>::block_number();
198
199 assert_eq!(staking_classic::ActiveEra::<rc::Runtime>::get().unwrap().index, 1);
203 assert_eq!(staking_classic::CurrentEra::<rc::Runtime>::get().unwrap(), 1);
205
206 assert_eq!(
208 staking_classic::ErasRewardPoints::<rc::Runtime>::get(1).total,
209 pre_migration_era_points
210 );
211
212 assert_eq!(
214 ah_client::ValidatorPoints::<rc::Runtime>::iter().count(),
215 1,
216 "only 11 has authored blocks in rc"
217 );
218 assert_eq!(
219 ah_client::ValidatorPoints::<rc::Runtime>::get(&11),
220 (migration_start_block_number - pre_migration_block_number) as u32 *
221 <<rc::Runtime as ah_client::Config>::PointsPerBlock as Get<u32>>::get()
222 );
223
224 let offence_counter_before = shared::CounterRCAHNewOffence::get();
226
227 assert_eq!(pallet_session::CurrentIndex::<rc::Runtime>::get(), 12);
229
230 assert_ok!(RootOffences::create_offence(
232 rc::RuntimeOrigin::root(),
233 vec![(2, Perbill::from_percent(50))],
234 None,
235 None,
236 ));
237 assert_ok!(RootOffences::create_offence(
238 rc::RuntimeOrigin::root(),
239 vec![(2, Perbill::from_percent(100))],
240 None,
241 None,
242 ));
243 assert_ok!(RootOffences::create_offence(
244 rc::RuntimeOrigin::root(),
245 vec![(2, Perbill::from_percent(25))],
246 None,
247 None,
248 ));
249
250 assert_ok!(RootOffences::create_offence(
252 rc::RuntimeOrigin::root(),
253 vec![(1, Perbill::from_percent(75))],
254 None,
255 None,
256 ));
257 assert_ok!(RootOffences::create_offence(
258 rc::RuntimeOrigin::root(),
259 vec![(1, Perbill::from_percent(60))],
260 None,
261 None,
262 ));
263
264 assert_ok!(RootOffences::create_offence(
266 rc::RuntimeOrigin::root(),
267 vec![(5, Perbill::from_percent(55))],
268 None,
269 None,
270 ));
271
272 rc::roll_to_next_session(false);
274
275 assert_eq!(pallet_session::CurrentIndex::<rc::Runtime>::get(), 13);
277
278 assert_ok!(RootOffences::create_offence(
280 rc::RuntimeOrigin::root(),
281 vec![(2, Perbill::from_percent(90))],
282 None,
283 None,
284 ));
285 assert_ok!(RootOffences::create_offence(
286 rc::RuntimeOrigin::root(),
287 vec![(2, Perbill::from_percent(80))],
288 None,
289 None,
290 ));
291 assert_ok!(RootOffences::create_offence(
293 rc::RuntimeOrigin::root(),
294 vec![(1, Perbill::from_percent(85))],
295 None,
296 None,
297 ));
298 assert_ok!(RootOffences::create_offence(
300 rc::RuntimeOrigin::root(),
301 vec![(5, Perbill::from_percent(45))],
302 None,
303 None,
304 ));
305
306 rc::roll_to_next_session(false);
308
309 assert_eq!(pallet_session::CurrentIndex::<rc::Runtime>::get(), 14);
311
312 assert_ok!(RootOffences::create_offence(
314 rc::RuntimeOrigin::root(),
315 vec![(2, Perbill::from_percent(70))],
316 None,
317 None,
318 ));
319 assert_ok!(RootOffences::create_offence(
321 rc::RuntimeOrigin::root(),
322 vec![(1, Perbill::from_percent(65))],
323 None,
324 None,
325 ));
326 assert_ok!(RootOffences::create_offence(
328 rc::RuntimeOrigin::root(),
329 vec![(5, Perbill::from_percent(40))],
330 None,
331 None,
332 ));
333
334 assert_eq!(
338 shared::CounterRCAHNewOffence::get(),
339 offence_counter_before,
340 "No offences should be sent to AH in buffered mode"
341 );
342
343 assert_eq!(staking_classic::UnappliedSlashes::<rc::Runtime>::get(4).len(), 1);
346
347 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 13);
349 assert_eq!(OffenceSendQueue::<rc::Runtime>::pages(), 7);
350 });
351
352 shared::in_ah(|| {
354 assert_eq!(shared::CounterRCAHNewOffence::get(), 0);
355 assert_eq!(shared::CounterRCAHSessionReport::get(), 0);
356
357 assert_eq!(ah::mock::staking_events_since_last_call(), vec![]);
358 });
359
360 shared::migrate_state();
362
363 shared::in_rc(|| {
365 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 13);
367
368 ah_client::Pallet::<rc::Runtime>::on_migration_end();
369 assert_eq!(ah_client::Mode::<rc::Runtime>::get(), OperatingMode::Active);
370
371 assert_eq!(crate::rc::MaxOffenceBatchSize::get(), 2);
374
375 rc::roll_next();
377 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 12);
378 assert_eq!(shared::CounterRCAHNewOffence::get(), 1);
379
380 rc::roll_next();
382 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 10);
383 assert_eq!(shared::CounterRCAHNewOffence::get(), 3);
384 rc::roll_next();
385 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 8);
386 assert_eq!(shared::CounterRCAHNewOffence::get(), 5);
387 rc::roll_next();
388 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 6);
389 assert_eq!(shared::CounterRCAHNewOffence::get(), 7);
390 rc::roll_next();
391 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 4);
392 assert_eq!(shared::CounterRCAHNewOffence::get(), 9);
393 rc::roll_next();
394 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 2);
395 assert_eq!(shared::CounterRCAHNewOffence::get(), 11);
396 rc::roll_next();
397 assert_eq!(OffenceSendQueue::<rc::Runtime>::count(), 0);
398 assert_eq!(shared::CounterRCAHNewOffence::get(), 13);
399 });
400
401 let mut post_migration_era_reward_points = 0;
402 shared::in_ah(|| {
403 assert_eq!(
407 rc_client_events_since_last_call(),
408 vec![
409 rc_client::Event::OffenceReceived { slash_session: 14, offences_count: 1 },
410 rc_client::Event::OffenceReceived { slash_session: 14, offences_count: 2 },
411 rc_client::Event::OffenceReceived { slash_session: 13, offences_count: 2 },
412 rc_client::Event::OffenceReceived { slash_session: 13, offences_count: 2 },
413 rc_client::Event::OffenceReceived { slash_session: 12, offences_count: 2 },
414 rc_client::Event::OffenceReceived { slash_session: 12, offences_count: 2 },
415 rc_client::Event::OffenceReceived { slash_session: 12, offences_count: 2 }
416 ]
417 );
418
419 post_migration_era_reward_points =
420 pallet_staking_async::ErasRewardPoints::<ah::Runtime>::get(1).total;
421 assert_eq!(pallet_staking_async::ForceEra::<ah::Runtime>::get(), Forcing::NotForcing);
424
425 assert!(pallet_staking_async::OffenceQueue::<ah::Runtime>::get(1, 1).is_some());
429 assert!(pallet_staking_async::OffenceQueue::<ah::Runtime>::get(1, 2).is_some());
430 assert!(pallet_staking_async::OffenceQueue::<ah::Runtime>::get(1, 5).is_some());
431
432 let offence_record_v1 =
434 pallet_staking_async::OffenceQueue::<ah::Runtime>::get(1, 1).unwrap();
435 assert_eq!(
436 offence_record_v1,
437 pallet_staking_async::slashing::OffenceRecord {
438 reporter: None,
439 reported_era: 1,
440 exposure_page: 0,
441 slash_fraction: Perbill::from_percent(85), prior_slash_fraction: Perbill::from_percent(0),
444 }
445 );
446
447 let offence_record_v2 =
448 pallet_staking_async::OffenceQueue::<ah::Runtime>::get(1, 2).unwrap();
449 assert_eq!(
450 offence_record_v2,
451 pallet_staking_async::slashing::OffenceRecord {
452 reporter: None,
453 reported_era: 1,
454 exposure_page: 0,
455 slash_fraction: Perbill::from_percent(100), prior_slash_fraction: Perbill::from_percent(0),
458 }
459 );
460
461 let offence_record_v5 =
462 pallet_staking_async::OffenceQueue::<ah::Runtime>::get(1, 5).unwrap();
463 assert_eq!(
464 offence_record_v5,
465 pallet_staking_async::slashing::OffenceRecord {
466 reporter: None,
467 reported_era: 1,
468 exposure_page: 0,
469 slash_fraction: Perbill::from_percent(55), prior_slash_fraction: Perbill::from_percent(0),
472 }
473 );
474
475 for _ in 0..3 {
486 ah::roll_next();
487 }
488
489 let staking_events = ah::mock::staking_events_since_last_call();
491
492 let offence_reported_events: Vec<_> = staking_events
494 .iter()
495 .filter_map(|event| {
496 if let pallet_staking_async::Event::OffenceReported {
497 offence_era,
498 validator,
499 fraction,
500 } = event
501 {
502 Some((offence_era, validator, fraction))
503 } else {
504 None
505 }
506 })
507 .collect();
508
509 assert_eq!(
511 offence_reported_events,
512 vec![
513 (&1, &5, &Perbill::from_percent(40)),
515 (&1, &2, &Perbill::from_percent(70)),
516 (&1, &1, &Perbill::from_percent(65)),
517 (&1, &1, &Perbill::from_percent(85)),
518 (&1, &5, &Perbill::from_percent(45)),
519 (&1, &2, &Perbill::from_percent(90)),
520 (&1, &2, &Perbill::from_percent(80)),
521 (&1, &1, &Perbill::from_percent(60)),
522 (&1, &5, &Perbill::from_percent(55)),
523 (&1, &2, &Perbill::from_percent(25)),
524 (&1, &1, &Perbill::from_percent(75)),
525 (&1, &2, &Perbill::from_percent(50)),
526 (&1, &2, &Perbill::from_percent(100))
527 ]
528 );
529
530 let slash_computed_events: Vec<_> = staking_events
532 .iter()
533 .filter_map(|event| {
534 if let pallet_staking_async::Event::SlashComputed {
535 offence_era,
536 slash_era,
537 offender,
538 page,
539 } = event
540 {
541 Some((offence_era, slash_era, offender, page))
542 } else {
543 None
544 }
545 })
546 .collect();
547
548 assert_eq!(
552 slash_computed_events,
553 vec![
554 (&1, &3, &5, &0), (&1, &3, &1, &0), (&1, &3, &2, &0), ]
561 );
562
563 assert!(
565 !pallet_staking_async::OffenceQueue::<ah::Runtime>::contains_key(1, 1),
566 "Expected no remaining offences for validator 1"
567 );
568 assert!(
569 !pallet_staking_async::OffenceQueue::<ah::Runtime>::contains_key(1, 2),
570 "Expected no remaining offences for validator 2"
571 );
572 assert!(
573 !pallet_staking_async::OffenceQueue::<ah::Runtime>::contains_key(1, 5),
574 "Expected no remaining offences for validator 5"
575 );
576 let slash_v2_100_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
584 3,
585 (2, Perbill::from_percent(100), 0),
586 )
587 .is_some();
588 let slash_v2_90_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
589 3,
590 (2, Perbill::from_percent(90), 0),
591 )
592 .is_some();
593 let slash_v2_70_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
594 3,
595 (2, Perbill::from_percent(70), 0),
596 )
597 .is_some();
598
599 let total_slashes_v2 =
600 slash_v2_100_present as u8 + slash_v2_90_present as u8 + slash_v2_70_present as u8;
601 assert_eq!(
602 total_slashes_v2, 1,
603 "Expected exactly 1 unapplied slash for validator 2, got {} (100%:{}, 90%:{}, 70%:{})",
604 total_slashes_v2, slash_v2_100_present, slash_v2_90_present, slash_v2_70_present
605 );
606
607 let slash_v1_75_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
609 3,
610 (1, Perbill::from_percent(75), 0),
611 )
612 .is_some();
613 let slash_v1_85_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
614 3,
615 (1, Perbill::from_percent(85), 0),
616 )
617 .is_some();
618 let slash_v1_65_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
619 3,
620 (1, Perbill::from_percent(65), 0),
621 )
622 .is_some();
623
624 let total_slashes_v1 =
625 slash_v1_75_present as u8 + slash_v1_85_present as u8 + slash_v1_65_present as u8;
626 assert_eq!(
627 total_slashes_v1, 1,
628 "Expected exactly 1 unapplied slash for validator 1, got {} (75%:{}, 85%:{}, 65%:{})",
629 total_slashes_v1, slash_v1_75_present, slash_v1_85_present, slash_v1_65_present
630 );
631
632 let slash_v5_55_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
634 3,
635 (5, Perbill::from_percent(55), 0),
636 )
637 .is_some();
638 let slash_v5_45_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
639 3,
640 (5, Perbill::from_percent(45), 0),
641 )
642 .is_some();
643 let slash_v5_40_present = pallet_staking_async::UnappliedSlashes::<ah::Runtime>::get(
644 3,
645 (5, Perbill::from_percent(40), 0),
646 )
647 .is_some();
648
649 let total_slashes_v5 =
650 slash_v5_55_present as u8 + slash_v5_45_present as u8 + slash_v5_40_present as u8;
651 assert_eq!(
652 total_slashes_v5, 1,
653 "Expected exactly 1 unapplied slash for validator 5, got {} (55%:{}, 45%:{}, 40%:{})",
654 total_slashes_v5, slash_v5_55_present, slash_v5_45_present, slash_v5_40_present
655 );
656 });
657
658 shared::in_ah(|| {
660 ah::roll_next();
663
664 assert_eq!(pallet_staking_async::CurrentEra::<ah::Runtime>::get(), Some(1));
667 assert_eq!(pallet_staking_async::ActiveEra::<ah::Runtime>::get().unwrap().index, 1);
668 assert_eq!(shared::CounterRCAHSessionReport::get(), 0);
670 });
671
672 let mut post_migration_session_block_number = 0;
676 shared::in_rc(|| {
677 rc::roll_to_next_session(true);
678 post_migration_session_block_number =
679 frame_system::Pallet::<rc::Runtime>::block_number();
680
681 assert_eq!(ah_client::ValidatorPoints::<rc::Runtime>::iter().count(), 0,);
683 });
684
685 assert_eq!(shared::CounterRCAHSessionReport::get(), 1);
687 shared::in_ah(|| {
688 assert_eq!(pallet_staking_async::ActiveEra::<ah::Runtime>::get().unwrap().index, 1);
689 assert_eq!(pallet_staking_async::CurrentEra::<ah::Runtime>::get(), Some(1 + 1));
690
691 assert_eq!(
693 ah::rc_client_events_since_last_call(),
694 vec![rc_client::Event::SessionReportReceived {
695 end_index: 14,
696 activation_timestamp: None,
697 validator_points_counts: 1,
698 leftover: false
699 }]
700 );
701
702 assert_eq!(
703 staking_events_since_last_call(),
704 vec![pallet_staking_async::Event::SessionRotated {
705 starting_session: 15,
706 active_era: 1,
707 planned_era: 2
708 }]
709 );
710
711 assert_eq!(
713 pallet_staking_async::ErasRewardPoints::<ah::Runtime>::get(1).total,
714 ((post_migration_session_block_number - pre_migration_block_number) * 20) as u32 +
715 post_migration_era_reward_points );
718
719 ah::roll_until_matches(|| shared::CounterAHRCValidatorSet::get() == 1, true);
721
722 assert_eq!(
723 ah::staking_events_since_last_call(),
724 vec![
725 pallet_staking_async::Event::PagedElectionProceeded { page: 2, result: Ok(4) },
726 pallet_staking_async::Event::PagedElectionProceeded { page: 1, result: Ok(0) },
727 pallet_staking_async::Event::PagedElectionProceeded { page: 0, result: Ok(0) }
728 ]
729 );
730 });
731
732 shared::in_rc(|| {
733 assert_eq!(
734 rc::ah_client_events_since_last_call(),
735 vec![ah_client::Event::ValidatorSetReceived {
736 id: 2,
737 new_validator_set_count: 4,
738 prune_up_to: None,
739 leftover: false
740 }]
741 );
742
743 let (planned_era, next_validator_set) =
744 ah_client::ValidatorSet::<rc::Runtime>::get().unwrap();
745
746 assert_eq!(planned_era, 2);
747 assert!(next_validator_set.len() >= rc::MinimumValidatorSetSize::get() as usize);
748 });
749
750 shared::in_ah(|| {
751 assert_eq!(pallet_staking_async::ActiveEra::<ah::Runtime>::get().unwrap().index, 1);
752 ah::roll_until_matches(|| shared::CounterRCAHSessionReport::get() == 2, true);
754 assert_eq!(pallet_staking_async::ActiveEra::<ah::Runtime>::get().unwrap().index, 1);
756 ah::roll_until_matches(|| shared::CounterRCAHSessionReport::get() == 3, true);
758 assert_eq!(pallet_staking_async::ActiveEra::<ah::Runtime>::get().unwrap().index, 2);
759 });
760 }
761
762 #[test]
763 fn election_result_on_ah_reported_to_rc() {
764 }
769
770 #[test]
771 fn rc_continues_with_same_validators_if_ah_is_late() {
772 }
774
775 #[test]
776 fn authoring_points_reported_to_ah_per_session() {}
777
778 #[test]
779 fn rc_is_late_to_report_session_change() {}
780
781 #[test]
782 fn pruning_is_at_least_bonding_duration() {}
783
784 #[test]
785 fn ah_eras_are_delayed() {
786 }
790
791 #[test]
792 fn ah_knows_good_era_duration() {
793 }
795
796 #[test]
797 fn election_provider_fails_to_start() {
798 }
800
801 #[test]
802 fn overlapping_election_wont_happen() {
803 }
806
807 #[test]
808 fn session_report_burst() {
809 }
812
813 mod message_queue_sizes {
814 use super::*;
815 use sp_core::crypto::AccountId32;
816
817 #[test]
818 fn normal_session_report() {
819 assert_eq!(
820 rc_client::SessionReport::<AccountId32> {
821 end_index: 0,
822 activation_timestamp: Some((0, 0)),
823 leftover: false,
824 validator_points: (0..1000)
825 .map(|i| (AccountId32::from([i as u8; 32]), 1000))
826 .collect(),
827 }
828 .encoded_size(),
829 36_020
830 );
831 }
832
833 #[test]
834 fn normal_validator_set() {
835 assert_eq!(
836 rc_client::ValidatorSetReport::<AccountId32> {
837 id: 42,
838 leftover: false,
839 new_validator_set: (0..1000)
840 .map(|i| AccountId32::from([i as u8; 32]))
841 .collect(),
842 prune_up_to: Some(69),
843 }
844 .encoded_size(),
845 32_012
846 );
847 }
848
849 #[test]
850 fn offence() {
851 let offences = (0..1)
853 .map(|i| rc_client::Offence::<AccountId32> {
854 offender: AccountId32::from([i as u8; 32]),
855 reporters: vec![AccountId32::from([42; 32])],
856 slash_fraction: Perbill::from_percent(50),
857 })
858 .collect::<Vec<_>>();
859
860 let encoded_size = offences.encoded_size() + 42u32.encoded_size();
862 assert_eq!(encoded_size, 74);
863 }
864
865 const POLKADOT_MAX_DOWNWARD_MESSAGE_SIZE: u32 = 51200; const POLKADOT_MAX_UPWARD_MESSAGE_SIZE: u32 = 65531; #[test]
870 fn maximum_session_report() {
871 let mut num_validator_points = 1;
872 loop {
873 let session_report = rc_client::SessionReport::<AccountId32> {
874 end_index: 0,
875 activation_timestamp: Some((0, 0)),
876 leftover: false,
877 validator_points: (0..num_validator_points)
878 .map(|i| (AccountId32::from([i as u8; 32]), 1000))
879 .collect(),
880 };
881
882 let encoded_size = session_report.encoded_size() as u32;
885
886 if encoded_size > POLKADOT_MAX_DOWNWARD_MESSAGE_SIZE {
887 println!(
888 "SessionReport: num_validator_points: {}, encoded len: {}, max: {:?}, largest session report: {}",
889 num_validator_points, encoded_size, POLKADOT_MAX_DOWNWARD_MESSAGE_SIZE, num_validator_points - 1
890 );
891 break;
892 }
893 num_validator_points += 1;
894 }
895
896 assert_eq!(num_validator_points, 1422);
899 }
900
901 #[test]
902 fn maximum_validator_set() {
903 let mut num_validators = 1;
904 loop {
905 let validator_set_report = rc_client::ValidatorSetReport::<AccountId32> {
906 id: 42,
907 leftover: false,
908 new_validator_set: (0..num_validators)
909 .map(|i| AccountId32::from([i as u8; 32]))
910 .collect(),
911 prune_up_to: Some(69),
912 };
913
914 let encoded_size = validator_set_report.encoded_size() as u32;
917 if encoded_size > POLKADOT_MAX_DOWNWARD_MESSAGE_SIZE {
918 println!(
919 "ValidatorSetReport: num_validators: {}, encoded len: {}, max: {:?}, largest validator set: {}",
920 num_validators, encoded_size, POLKADOT_MAX_DOWNWARD_MESSAGE_SIZE, num_validators - 1
921 );
922 break;
923 }
924 num_validators += 1;
925 }
926
927 assert_eq!(num_validators, 1600);
930 }
931
932 #[test]
933 fn maximum_offence_batched() {
934 let mut num_offences = 1;
935 let session_index: u32 = 42;
936 loop {
937 let offences = (0..num_offences)
938 .map(|i| {
939 (
940 session_index,
941 rc_client::Offence::<AccountId32> {
942 offender: AccountId32::from([i as u8; 32]),
943 reporters: vec![AccountId32::from([42; 32])],
944 slash_fraction: Perbill::from_percent(50),
945 },
946 )
947 })
948 .collect::<Vec<_>>();
949 let encoded_size = offences.encoded_size();
950
951 if encoded_size as u32 > POLKADOT_MAX_UPWARD_MESSAGE_SIZE {
952 println!(
953 "Offence (batched): num_offences: {}, encoded len: {}, max: {:?}, largest offence batch: {}",
954 num_offences, encoded_size, POLKADOT_MAX_UPWARD_MESSAGE_SIZE, num_offences - 1
955 );
956 break;
957 }
958
959 num_offences += 1;
960 }
961
962 assert_eq!(num_offences, 898);
965 }
966 }
967}