1use crate::{
18 configuration, inclusion, initializer, paras,
19 paras::ParaKind,
20 paras_inherent,
21 scheduler::{
22 self,
23 common::{Assignment, AssignmentProvider},
24 },
25 session_info, shared,
26};
27use alloc::{
28 collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque},
29 vec,
30 vec::Vec,
31};
32use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
33use frame_support::pallet_prelude::*;
34use frame_system::pallet_prelude::*;
35use polkadot_primitives::{
36 ApprovedPeerId, AvailabilityBitfield, BackedCandidate, CandidateCommitments,
37 CandidateDescriptorV2, CandidateHash, ClaimQueueOffset,
38 CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CompactStatement, CoreIndex,
39 CoreSelector, DisputeStatement, DisputeStatementSet, GroupIndex, HeadData, Id as ParaId,
40 IndexedVec, InherentData as ParachainsInherentData, InvalidDisputeStatementKind,
41 PersistedValidationData, SessionIndex, SigningContext, UMPSignal, UncheckedSigned,
42 ValidDisputeStatementKind, ValidationCode, ValidatorId, ValidatorIndex, ValidityAttestation,
43 UMP_SEPARATOR,
44};
45use sp_core::H256;
46use sp_runtime::{
47 generic::Digest,
48 traits::{Header as HeaderT, One, TrailingZeroInput, Zero},
49 RuntimeAppPublic,
50};
51fn mock_validation_code() -> ValidationCode {
52 ValidationCode(vec![1, 2, 3])
53}
54
55fn account<AccountId: Decode>(name: &'static str, index: u32, seed: u32) -> AccountId {
60 let entropy = (name, index, seed).using_encoded(sp_io::hashing::blake2_256);
61 AccountId::decode(&mut TrailingZeroInput::new(&entropy[..]))
62 .expect("infinite input; no invalid input; qed")
63}
64
65pub fn generate_validator_pairs<T: frame_system::Config>(
66 validator_count: u32,
67) -> Vec<(T::AccountId, ValidatorId)> {
68 (0..validator_count)
69 .map(|i| {
70 let public = ValidatorId::generate_pair(None);
71
72 let account: T::AccountId = account("validator", i, i);
75 (account, public)
76 })
77 .collect()
78}
79
80fn byte32_slice_from(n: u32) -> [u8; 32] {
82 let mut slice = [0u8; 32];
83 slice[31] = (n % (1 << 8)) as u8;
84 slice[30] = ((n >> 8) % (1 << 8)) as u8;
85 slice[29] = ((n >> 16) % (1 << 8)) as u8;
86 slice[28] = ((n >> 24) % (1 << 8)) as u8;
87
88 slice
89}
90
91pub(crate) struct BenchBuilder<T: paras_inherent::Config> {
93 validators: Option<IndexedVec<ValidatorIndex, ValidatorId>>,
95 block_number: BlockNumberFor<T>,
97 session: SessionIndex,
99 target_session: u32,
101 max_validators_per_core: Option<u32>,
103 max_validators: Option<u32>,
105 dispute_statements: BTreeMap<u32, u32>,
107 dispute_sessions: Vec<u32>,
113 backed_and_concluding_paras: BTreeMap<u32, u32>,
121
122 backed_in_inherent_paras: BTreeMap<u32, u32>,
124 elastic_paras: BTreeMap<u32, u8>,
126 code_upgrade: Option<u32>,
129 unavailable_cores: Vec<u32>,
131 candidate_descriptor_v2: bool,
133 approved_peer_signal: Option<ApprovedPeerId>,
135 candidate_modifier: Option<CandidateModifier<T::Hash>>,
137 _phantom: core::marker::PhantomData<T>,
138}
139
140pub type CandidateModifier<Hash> =
141 fn(CommittedCandidateReceipt<Hash>) -> CommittedCandidateReceipt<Hash>;
142
143#[cfg(any(feature = "runtime-benchmarks", test))]
145pub(crate) struct Bench<T: paras_inherent::Config> {
146 pub(crate) data: ParachainsInherentData<HeaderFor<T>>,
147 pub(crate) _session: u32,
148 pub(crate) _block_number: BlockNumberFor<T>,
149}
150
151#[allow(dead_code)]
152impl<T: paras_inherent::Config> BenchBuilder<T> {
153 pub(crate) fn new() -> Self {
156 BenchBuilder {
157 validators: None,
158 block_number: Zero::zero(),
159 session: SessionIndex::from(0u32),
160 target_session: 2u32,
161 max_validators_per_core: None,
162 max_validators: None,
163 dispute_statements: BTreeMap::new(),
164 dispute_sessions: Default::default(),
165 backed_and_concluding_paras: Default::default(),
166 backed_in_inherent_paras: Default::default(),
167 elastic_paras: Default::default(),
168 code_upgrade: None,
169 unavailable_cores: vec![],
170 candidate_descriptor_v2: false,
171 approved_peer_signal: None,
172 candidate_modifier: None,
173 _phantom: core::marker::PhantomData::<T>,
174 }
175 }
176
177 pub(crate) fn set_dispute_sessions(mut self, dispute_sessions: impl AsRef<[u32]>) -> Self {
185 self.dispute_sessions = dispute_sessions.as_ref().to_vec();
186 self
187 }
188
189 pub(crate) fn set_unavailable_cores(mut self, unavailable_cores: Vec<u32>) -> Self {
191 self.unavailable_cores = unavailable_cores;
192 self
193 }
194
195 pub(crate) fn set_backed_and_concluding_paras(
197 mut self,
198 backed_and_concluding_paras: BTreeMap<u32, u32>,
199 ) -> Self {
200 self.backed_and_concluding_paras = backed_and_concluding_paras;
201 self
202 }
203
204 pub(crate) fn set_backed_in_inherent_paras(mut self, backed: BTreeMap<u32, u32>) -> Self {
206 self.backed_in_inherent_paras = backed;
207 self
208 }
209
210 pub(crate) fn set_elastic_paras(mut self, elastic_paras: BTreeMap<u32, u8>) -> Self {
212 self.elastic_paras = elastic_paras;
213 self
214 }
215
216 pub(crate) fn set_code_upgrade(mut self, code_upgrade: impl Into<Option<u32>>) -> Self {
219 self.code_upgrade = code_upgrade.into();
220 self
221 }
222
223 pub(crate) fn header(block_number: BlockNumberFor<T>) -> HeaderFor<T> {
225 HeaderFor::<T>::new(
226 block_number, Default::default(), Default::default(), Default::default(), Default::default(), )
232 }
233
234 fn relay_parent_number(&self) -> u32 {
236 (self.block_number - One::one())
237 .try_into()
238 .map_err(|_| ())
239 .expect("self.block_number is u32")
240 }
241
242 pub(crate) fn fallback_max_validators() -> u32 {
245 configuration::ActiveConfig::<T>::get().max_validators.unwrap_or(1024)
246 }
247
248 fn max_validators(&self) -> u32 {
251 self.max_validators.unwrap_or(Self::fallback_max_validators())
252 }
253
254 #[cfg(not(feature = "runtime-benchmarks"))]
256 pub(crate) fn set_max_validators(mut self, n: u32) -> Self {
257 self.max_validators = Some(n);
258 self
259 }
260
261 pub(crate) fn fallback_max_validators_per_core() -> u32 {
264 configuration::ActiveConfig::<T>::get()
265 .scheduler_params
266 .max_validators_per_core
267 .unwrap_or(5)
268 }
269
270 #[cfg(not(feature = "runtime-benchmarks"))]
276 pub(crate) fn set_dispute_statements(mut self, m: BTreeMap<u32, u32>) -> Self {
277 self.dispute_statements = m;
278 self
279 }
280
281 pub(crate) fn set_candidate_descriptor_v2(mut self, enable: bool) -> Self {
283 self.candidate_descriptor_v2 = enable;
284 self
285 }
286
287 pub(crate) fn set_approved_peer_signal(mut self, peer_id: ApprovedPeerId) -> Self {
289 self.approved_peer_signal = Some(peer_id);
290 self
291 }
292
293 pub(crate) fn set_candidate_modifier(
295 mut self,
296 modifier: Option<CandidateModifier<T::Hash>>,
297 ) -> Self {
298 self.candidate_modifier = modifier;
299 self
300 }
301
302 fn max_validators_per_core(&self) -> u32 {
304 self.max_validators_per_core.unwrap_or(Self::fallback_max_validators_per_core())
305 }
306
307 #[cfg(not(feature = "runtime-benchmarks"))]
309 pub(crate) fn set_max_validators_per_core(mut self, n: u32) -> Self {
310 self.max_validators_per_core = Some(n);
311 self
312 }
313
314 pub(crate) fn max_cores(&self) -> u32 {
316 self.max_validators() / self.max_validators_per_core()
317 }
318
319 #[cfg(feature = "runtime-benchmarks")]
321 pub(crate) fn fallback_min_backing_votes() -> u32 {
322 2
323 }
324
325 fn mock_head_data() -> HeadData {
326 let max_head_size = configuration::ActiveConfig::<T>::get().max_head_data_size;
327 HeadData(vec![0xFF; max_head_size as usize])
328 }
329
330 fn candidate_descriptor_mock(para_id: ParaId) -> CandidateDescriptorV2<T::Hash> {
331 CandidateDescriptorV2::new(
332 para_id,
333 Default::default(),
334 CoreIndex(200),
335 2,
336 Default::default(),
337 Default::default(),
338 Default::default(),
339 Default::default(),
340 mock_validation_code().hash(),
341 )
342 }
343
344 fn candidate_availability_mock(
346 para_id: ParaId,
347 group_idx: GroupIndex,
348 core_idx: CoreIndex,
349 candidate_hash: CandidateHash,
350 availability_votes: BitVec<u8, BitOrderLsb0>,
351 commitments: CandidateCommitments,
352 ) -> inclusion::CandidatePendingAvailability<T::Hash, BlockNumberFor<T>> {
353 inclusion::CandidatePendingAvailability::<T::Hash, BlockNumberFor<T>>::new(
354 core_idx, candidate_hash, Self::candidate_descriptor_mock(para_id), commitments, availability_votes, Default::default(), Zero::zero(), One::one(), group_idx, )
366 }
367
368 fn add_availability(
374 para_id: ParaId,
375 core_idx: CoreIndex,
376 group_idx: GroupIndex,
377 availability_votes: BitVec<u8, BitOrderLsb0>,
378 candidate_hash: CandidateHash,
379 ) {
380 let commitments = CandidateCommitments::<u32> {
381 upward_messages: Default::default(),
382 horizontal_messages: Default::default(),
383 new_validation_code: None,
384 head_data: Self::mock_head_data(),
385 processed_downward_messages: 0,
386 hrmp_watermark: 0u32.into(),
387 };
388 let candidate_availability = Self::candidate_availability_mock(
389 para_id,
390 group_idx,
391 core_idx,
392 candidate_hash,
393 availability_votes,
394 commitments,
395 );
396 inclusion::PendingAvailability::<T>::mutate(para_id, |maybe_candidates| {
397 if let Some(candidates) = maybe_candidates {
398 candidates.push_back(candidate_availability);
399 } else {
400 *maybe_candidates =
401 Some([candidate_availability].into_iter().collect::<VecDeque<_>>());
402 }
403 });
404 }
405
406 fn availability_bitvec(concluding_cores: &BTreeSet<u32>, cores: usize) -> AvailabilityBitfield {
409 let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0];
410 for i in 0..cores {
411 if concluding_cores.contains(&(i as u32)) {
412 bitfields.push(true);
413 } else {
414 bitfields.push(false)
415 }
416 }
417
418 bitfields.into()
419 }
420
421 fn run_to_block(to: u32) {
424 let to = to.into();
425 while frame_system::Pallet::<T>::block_number() < to {
426 let b = frame_system::Pallet::<T>::block_number();
427 initializer::Pallet::<T>::on_finalize(b);
428
429 let b = b + One::one();
430 frame_system::Pallet::<T>::set_block_number(b);
431 initializer::Pallet::<T>::on_initialize(b);
432 }
433 }
434
435 fn setup_para_ids(n_paras: usize) {
440 for i in 0..n_paras {
442 let para_id = ParaId::from(i as u32);
443 let validation_code = mock_validation_code();
444
445 paras::Pallet::<T>::schedule_para_initialize(
446 para_id,
447 paras::ParaGenesisArgs {
448 genesis_head: Self::mock_head_data(),
449 validation_code: validation_code.clone(),
450 para_kind: ParaKind::Parachain,
451 },
452 )
453 .unwrap();
454 paras::Pallet::<T>::add_trusted_validation_code(
455 frame_system::Origin::<T>::Root.into(),
456 validation_code,
457 )
458 .unwrap();
459 }
460 }
461
462 fn signing_context(&self) -> SigningContext<T::Hash> {
463 SigningContext {
464 parent_hash: Self::header(self.block_number).hash(),
465 session_index: self.session,
466 }
467 }
468
469 fn validator_availability_votes_yes(validators: usize) -> BitVec<u8, bitvec::order::Lsb0> {
471 bitvec::bitvec![u8, bitvec::order::Lsb0; 1; validators as usize]
473 }
474
475 fn setup_session(
477 mut self,
478 target_session: SessionIndex,
479 validators: Vec<(T::AccountId, ValidatorId)>,
480 total_cores: usize,
482 extra_cores: usize,
484 ) -> Self {
485 let mut block = 1;
486 for session in 0..=target_session {
487 initializer::Pallet::<T>::test_trigger_on_new_session(
488 false,
489 session,
490 validators.iter().map(|(a, v)| (a, v.clone())),
491 None,
492 );
493 block += 1;
494 Self::run_to_block(block);
495 }
496
497 let block_number = BlockNumberFor::<T>::from(block);
498 let header = Self::header(block_number);
499
500 frame_system::Pallet::<T>::reset_events();
501 frame_system::Pallet::<T>::initialize(
502 &header.number(),
503 &header.hash(),
504 &Digest { logs: Vec::new() },
505 );
506
507 assert_eq!(shared::CurrentSessionIndex::<T>::get(), target_session);
508
509 let validators_shuffled =
511 session_info::Sessions::<T>::get(target_session).unwrap().validators.clone();
512
513 self.validators = Some(validators_shuffled);
514 self.block_number = block_number;
515 self.session = target_session;
516 assert_eq!(paras::Parachains::<T>::get().len(), total_cores - extra_cores);
517
518 self
519 }
520
521 fn create_availability_bitfields(
526 &self,
527 concluding_paras: &BTreeMap<u32, u32>,
528 elastic_paras: &BTreeMap<u32, u8>,
529 total_cores: usize,
530 ) -> Vec<UncheckedSigned<AvailabilityBitfield>> {
531 let validators =
532 self.validators.as_ref().expect("must have some validators prior to calling");
533
534 let mut current_core_idx = 0u32;
535 let mut concluding_cores = BTreeSet::new();
536
537 for (seed, _) in concluding_paras.iter() {
538 let para_id = ParaId::from(*seed);
540
541 for _chain_idx in 0..elastic_paras.get(&seed).cloned().unwrap_or(1) {
542 let core_idx = CoreIndex::from(current_core_idx);
543 let group_idx =
544 scheduler::Pallet::<T>::group_assigned_to_core(core_idx, self.block_number)
545 .unwrap();
546
547 Self::add_availability(
548 para_id,
549 core_idx,
550 group_idx,
551 bitvec::bitvec![u8, bitvec::order::Lsb0; 0; validators.len()],
553 CandidateHash(H256::from(byte32_slice_from(current_core_idx))),
554 );
555 if !self.unavailable_cores.contains(¤t_core_idx) {
556 concluding_cores.insert(current_core_idx);
557 }
558 current_core_idx += 1;
559 }
560 }
561
562 let availability_bitvec = Self::availability_bitvec(&concluding_cores, total_cores);
563
564 let bitfields: Vec<UncheckedSigned<AvailabilityBitfield>> = validators
565 .iter()
566 .enumerate()
567 .map(|(i, public)| {
568 let unchecked_signed = UncheckedSigned::<AvailabilityBitfield>::benchmark_sign(
569 public,
570 availability_bitvec.clone(),
571 &self.signing_context(),
572 ValidatorIndex(i as u32),
573 );
574
575 unchecked_signed
576 })
577 .collect();
578
579 bitfields
580 }
581
582 fn create_backed_candidates(
588 &self,
589 paras_with_backed_candidates: &BTreeMap<u32, u32>,
590 elastic_paras: &BTreeMap<u32, u8>,
591 includes_code_upgrade: Option<u32>,
592 ) -> Vec<BackedCandidate<T::Hash>> {
593 let validators =
594 self.validators.as_ref().expect("must have some validators prior to calling");
595 let config = configuration::ActiveConfig::<T>::get();
596
597 let mut current_core_idx = 0u32;
598 paras_with_backed_candidates
599 .iter()
600 .flat_map(|(seed, num_votes)| {
601 assert!(*num_votes <= validators.len() as u32);
602
603 let para_id = ParaId::from(*seed);
604 let mut prev_head = None;
605 (0..elastic_paras.get(&seed).cloned().unwrap_or(1))
607 .map(|chain_idx| {
608 let core_idx = CoreIndex::from(current_core_idx);
609 current_core_idx += 1;
611 let group_idx = scheduler::Pallet::<T>::group_assigned_to_core(
612 core_idx,
613 self.block_number,
614 )
615 .unwrap();
616
617 let header = Self::header(self.block_number);
620 let relay_parent = header.hash();
621
622 let mut head_data = Self::mock_head_data();
625
626 if chain_idx == 0 {
627 paras::Pallet::<T>::heads_insert(¶_id, head_data.clone());
629 } else {
630 head_data.0[0] = chain_idx;
632 }
633
634 let persisted_validation_data_hash = PersistedValidationData::<H256> {
635 parent_head: prev_head.take().unwrap_or(head_data.clone()),
638 relay_parent_number: self.relay_parent_number(),
639 relay_parent_storage_root: Default::default(),
640 max_pov_size: config.max_pov_size,
641 }
642 .hash();
643
644 prev_head = Some(head_data.clone());
645
646 let pov_hash = Default::default();
647 let validation_code_hash = mock_validation_code().hash();
648
649 let mut past_code_meta =
650 paras::ParaPastCodeMeta::<BlockNumberFor<T>>::default();
651 past_code_meta.note_replacement(0u32.into(), 0u32.into());
652
653 let group_validators =
654 scheduler::Pallet::<T>::group_validators(group_idx).unwrap();
655
656 let descriptor = CandidateDescriptorV2::new(
657 para_id,
658 relay_parent,
659 core_idx,
660 self.target_session,
661 persisted_validation_data_hash,
662 pov_hash,
663 Default::default(),
664 head_data.hash(),
665 validation_code_hash,
666 );
667
668 let mut candidate = CommittedCandidateReceipt::<T::Hash> {
669 descriptor,
670 commitments: CandidateCommitments::<u32> {
671 upward_messages: Default::default(),
672 horizontal_messages: Default::default(),
673 new_validation_code: includes_code_upgrade
674 .map(|v| ValidationCode(vec![42u8; v as usize])),
675 head_data,
676 processed_downward_messages: 0,
677 hrmp_watermark: self.relay_parent_number(),
678 },
679 };
680
681 if self.candidate_descriptor_v2 {
682 candidate.commitments.upward_messages.force_push(UMP_SEPARATOR);
684
685 candidate.commitments.upward_messages.force_push(
689 UMPSignal::SelectCore(
690 CoreSelector(chain_idx as u8),
691 ClaimQueueOffset(0),
692 )
693 .encode(),
694 );
695
696 if let Some(approved_peer_signal) = &self.approved_peer_signal {
697 candidate.commitments.upward_messages.force_push(
698 UMPSignal::ApprovedPeer(approved_peer_signal.clone()).encode(),
699 );
700 }
701 }
702
703 if let Some(modifier) = self.candidate_modifier {
705 candidate = modifier(candidate);
706 }
707
708 let candidate_hash = candidate.hash();
709
710 let validity_votes: Vec<_> = group_validators
711 .iter()
712 .take(*num_votes as usize)
713 .map(|val_idx| {
714 let public = validators.get(*val_idx).unwrap();
715 let sig = UncheckedSigned::<CompactStatement>::benchmark_sign(
716 public,
717 CompactStatement::Valid(candidate_hash),
718 &self.signing_context(),
719 *val_idx,
720 )
721 .benchmark_signature();
722
723 ValidityAttestation::Explicit(sig.clone())
724 })
725 .collect();
726
727 BackedCandidate::<T::Hash>::new(
728 candidate,
729 validity_votes,
730 bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()],
731 core_idx,
732 )
733 })
734 .collect::<Vec<_>>()
735 })
736 .collect()
737 }
738
739 fn create_disputes(
742 &self,
743 start: u32,
744 last: u32,
745 dispute_sessions: impl AsRef<[u32]>,
746 ) -> Vec<DisputeStatementSet> {
747 let validators =
748 self.validators.as_ref().expect("must have some validators prior to calling");
749
750 let dispute_sessions = dispute_sessions.as_ref();
751 let mut current_core_idx = start;
752
753 (start..last)
754 .map(|seed| {
755 let dispute_session_idx = (seed - start) as usize;
756 let session = dispute_sessions
757 .get(dispute_session_idx)
758 .cloned()
759 .unwrap_or(self.target_session);
760
761 let para_id = ParaId::from(seed);
762 let core_idx = CoreIndex::from(current_core_idx);
763 current_core_idx +=1;
764
765 let group_idx =
766 scheduler::Pallet::<T>::group_assigned_to_core(core_idx, self.block_number)
767 .unwrap();
768
769 let candidate_hash = CandidateHash(H256::from(byte32_slice_from(seed)));
770 let relay_parent = H256::from(byte32_slice_from(seed));
771
772 Self::add_availability(
773 para_id,
774 core_idx,
775 group_idx,
776 Self::validator_availability_votes_yes(validators.len()),
777 candidate_hash,
778 );
779
780 let statements_len =
781 self.dispute_statements.get(&seed).cloned().unwrap_or(validators.len() as u32);
782 let statements = (0..statements_len)
783 .map(|validator_index| {
784 let validator_public = &validators.get(ValidatorIndex::from(validator_index)).expect("Test case is not borked. `ValidatorIndex` out of bounds of `ValidatorId`s.");
785
786 let dispute_statement = if validator_index % 4 == 0 {
789 DisputeStatement::Invalid(InvalidDisputeStatementKind::Explicit)
790 } else if validator_index < 3 {
791 DisputeStatement::Valid(
793 ValidDisputeStatementKind::BackingValid(relay_parent)
794 )
795 } else {
796 DisputeStatement::Valid(ValidDisputeStatementKind::Explicit)
797 };
798 let data = dispute_statement.payload_data(candidate_hash, session).unwrap();
799 let statement_sig = validator_public.sign(&data).unwrap();
800
801 (dispute_statement, ValidatorIndex(validator_index), statement_sig)
802 })
803 .collect();
804
805 DisputeStatementSet { candidate_hash, session, statements }
806 })
807 .collect()
808 }
809
810 pub(crate) fn build(self) -> Bench<T> {
817 #[allow(deprecated)]
820 inclusion::PendingAvailability::<T>::remove_all(None);
821
822 let max_cores = self.max_cores() as usize;
824
825 let extra_cores = self
826 .elastic_paras
827 .values()
828 .map(|count| *count as usize)
829 .sum::<usize>()
830 .saturating_sub(self.elastic_paras.len() as usize);
831
832 let used_cores = self.dispute_sessions.len() +
833 self.backed_and_concluding_paras.len() +
834 self.backed_in_inherent_paras.len() +
835 extra_cores;
836
837 assert!(used_cores <= max_cores);
838
839 Self::setup_para_ids(used_cores - extra_cores);
842 configuration::Pallet::<T>::set_coretime_cores_unchecked(used_cores as u32).unwrap();
843
844 let validator_ids = generate_validator_pairs::<T>(self.max_validators());
845 let target_session = SessionIndex::from(self.target_session);
846 let builder = self.setup_session(target_session, validator_ids, used_cores, extra_cores);
847
848 let bitfields = builder.create_availability_bitfields(
849 &builder.backed_and_concluding_paras,
850 &builder.elastic_paras,
851 scheduler::Pallet::<T>::num_availability_cores(),
852 );
853
854 let mut backed_in_inherent = BTreeMap::new();
855 backed_in_inherent.append(&mut builder.backed_and_concluding_paras.clone());
856 backed_in_inherent.append(&mut builder.backed_in_inherent_paras.clone());
857 let backed_candidates = builder.create_backed_candidates(
858 &backed_in_inherent,
859 &builder.elastic_paras,
860 builder.code_upgrade,
861 );
862
863 let disputes = builder.create_disputes(
864 builder.backed_and_concluding_paras.len() as u32,
865 (used_cores - extra_cores) as u32,
866 builder.dispute_sessions.as_slice(),
867 );
868 let mut disputed_cores = (builder.backed_and_concluding_paras.len() as u32..
869 ((used_cores - extra_cores) as u32))
870 .into_iter()
871 .map(|idx| (idx, 0))
872 .collect::<BTreeMap<_, _>>();
873
874 let mut all_cores = builder.backed_and_concluding_paras.clone();
875 all_cores.append(&mut disputed_cores);
876
877 assert_eq!(inclusion::PendingAvailability::<T>::iter().count(), used_cores - extra_cores);
878
879 let mut core_idx = 0u32;
882 let elastic_paras = &builder.elastic_paras;
883
884 let mut occupied_cores = inclusion::Pallet::<T>::get_occupied_cores()
885 .map(|(core, candidate)| (core, candidate.candidate_descriptor().para_id()))
886 .collect::<Vec<_>>();
887 occupied_cores.sort_by(|(core_a, _), (core_b, _)| core_a.0.cmp(&core_b.0));
888
889 let mut expected_cores = all_cores
890 .iter()
891 .flat_map(|(para_id, _)| {
892 (0..elastic_paras.get(¶_id).cloned().unwrap_or(1))
893 .map(|_para_local_core_idx| {
894 let old_core_idx = core_idx;
895 core_idx += 1;
896 (CoreIndex(old_core_idx), ParaId::from(*para_id))
897 })
898 .collect::<Vec<_>>()
899 })
900 .collect::<Vec<_>>();
901
902 expected_cores.sort_by(|(core_a, _), (core_b, _)| core_a.0.cmp(&core_b.0));
903
904 assert_eq!(expected_cores, occupied_cores);
905
906 all_cores.append(&mut builder.backed_in_inherent_paras.clone());
908
909 let mut core_idx = 0u32;
910 let cores = all_cores
911 .keys()
912 .flat_map(|para_id| {
913 (0..elastic_paras.get(¶_id).cloned().unwrap_or(1))
914 .map(|_para_local_core_idx| {
915 let assignment =
917 <T as scheduler::Config>::AssignmentProvider::get_mock_assignment(
918 CoreIndex(core_idx),
919 ParaId::from(*para_id),
920 );
921
922 core_idx += 1;
923 (CoreIndex(core_idx - 1), [assignment].into())
924 })
925 .collect::<Vec<(CoreIndex, VecDeque<Assignment>)>>()
926 })
927 .collect::<BTreeMap<CoreIndex, VecDeque<Assignment>>>();
928
929 scheduler::ClaimQueue::<T>::set(cores);
930
931 Bench::<T> {
932 data: ParachainsInherentData {
933 bitfields,
934 backed_candidates,
935 disputes,
936 parent_header: Self::header(builder.block_number),
937 },
938 _session: target_session,
939 _block_number: builder.block_number,
940 }
941 }
942}