use crate::{
configuration, inclusion, initializer, paras,
paras::ParaKind,
paras_inherent,
scheduler::{
self,
common::{Assignment, AssignmentProvider},
},
session_info, shared,
};
use alloc::{
collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque},
vec,
vec::Vec,
};
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use polkadot_primitives::{
node_features::FeatureIndex,
vstaging::{
BackedCandidate, CandidateDescriptorV2, ClaimQueueOffset,
CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreSelector,
InherentData as ParachainsInherentData, UMPSignal, UMP_SEPARATOR,
},
AvailabilityBitfield, CandidateCommitments, CandidateDescriptor, CandidateHash, CollatorId,
CollatorSignature, CompactStatement, CoreIndex, DisputeStatement, DisputeStatementSet,
GroupIndex, HeadData, Id as ParaId, IndexedVec, InvalidDisputeStatementKind,
PersistedValidationData, SessionIndex, SigningContext, UncheckedSigned,
ValidDisputeStatementKind, ValidationCode, ValidatorId, ValidatorIndex, ValidityAttestation,
};
use sp_core::{ByteArray, H256};
use sp_runtime::{
generic::Digest,
traits::{Header as HeaderT, One, TrailingZeroInput, Zero},
RuntimeAppPublic,
};
fn mock_validation_code() -> ValidationCode {
ValidationCode(vec![1, 2, 3])
}
pub fn junk_collator() -> CollatorId {
CollatorId::from_slice(&mut (0..32).into_iter().collect::<Vec<_>>().as_slice())
.expect("32 bytes; qed")
}
pub fn junk_collator_signature() -> CollatorSignature {
CollatorSignature::from_slice(&mut (0..64).into_iter().collect::<Vec<_>>().as_slice())
.expect("64 bytes; qed")
}
fn account<AccountId: Decode>(name: &'static str, index: u32, seed: u32) -> AccountId {
let entropy = (name, index, seed).using_encoded(sp_io::hashing::blake2_256);
AccountId::decode(&mut TrailingZeroInput::new(&entropy[..]))
.expect("infinite input; no invalid input; qed")
}
pub fn generate_validator_pairs<T: frame_system::Config>(
validator_count: u32,
) -> Vec<(T::AccountId, ValidatorId)> {
(0..validator_count)
.map(|i| {
let public = ValidatorId::generate_pair(None);
let account: T::AccountId = account("validator", i, i);
(account, public)
})
.collect()
}
fn byte32_slice_from(n: u32) -> [u8; 32] {
let mut slice = [0u8; 32];
slice[31] = (n % (1 << 8)) as u8;
slice[30] = ((n >> 8) % (1 << 8)) as u8;
slice[29] = ((n >> 16) % (1 << 8)) as u8;
slice[28] = ((n >> 24) % (1 << 8)) as u8;
slice
}
pub(crate) struct BenchBuilder<T: paras_inherent::Config> {
validators: Option<IndexedVec<ValidatorIndex, ValidatorId>>,
block_number: BlockNumberFor<T>,
session: SessionIndex,
target_session: u32,
max_validators_per_core: Option<u32>,
max_validators: Option<u32>,
dispute_statements: BTreeMap<u32, u32>,
dispute_sessions: Vec<u32>,
backed_and_concluding_paras: BTreeMap<u32, u32>,
backed_in_inherent_paras: BTreeMap<u32, u32>,
elastic_paras: BTreeMap<u32, u8>,
code_upgrade: Option<u32>,
unavailable_cores: Vec<u32>,
candidate_descriptor_v2: bool,
candidate_modifier: Option<CandidateModifier<T::Hash>>,
_phantom: core::marker::PhantomData<T>,
}
pub type CandidateModifier<Hash> =
fn(CommittedCandidateReceipt<Hash>) -> CommittedCandidateReceipt<Hash>;
#[cfg(any(feature = "runtime-benchmarks", test))]
pub(crate) struct Bench<T: paras_inherent::Config> {
pub(crate) data: ParachainsInherentData<HeaderFor<T>>,
pub(crate) _session: u32,
pub(crate) _block_number: BlockNumberFor<T>,
}
#[allow(dead_code)]
impl<T: paras_inherent::Config> BenchBuilder<T> {
pub(crate) fn new() -> Self {
BenchBuilder {
validators: None,
block_number: Zero::zero(),
session: SessionIndex::from(0u32),
target_session: 2u32,
max_validators_per_core: None,
max_validators: None,
dispute_statements: BTreeMap::new(),
dispute_sessions: Default::default(),
backed_and_concluding_paras: Default::default(),
backed_in_inherent_paras: Default::default(),
elastic_paras: Default::default(),
code_upgrade: None,
unavailable_cores: vec![],
candidate_descriptor_v2: false,
candidate_modifier: None,
_phantom: core::marker::PhantomData::<T>,
}
}
pub(crate) fn set_dispute_sessions(mut self, dispute_sessions: impl AsRef<[u32]>) -> Self {
self.dispute_sessions = dispute_sessions.as_ref().to_vec();
self
}
pub(crate) fn set_unavailable_cores(mut self, unavailable_cores: Vec<u32>) -> Self {
self.unavailable_cores = unavailable_cores;
self
}
pub(crate) fn set_backed_and_concluding_paras(
mut self,
backed_and_concluding_paras: BTreeMap<u32, u32>,
) -> Self {
self.backed_and_concluding_paras = backed_and_concluding_paras;
self
}
pub(crate) fn set_backed_in_inherent_paras(mut self, backed: BTreeMap<u32, u32>) -> Self {
self.backed_in_inherent_paras = backed;
self
}
pub(crate) fn set_elastic_paras(mut self, elastic_paras: BTreeMap<u32, u8>) -> Self {
self.elastic_paras = elastic_paras;
self
}
pub(crate) fn set_code_upgrade(mut self, code_upgrade: impl Into<Option<u32>>) -> Self {
self.code_upgrade = code_upgrade.into();
self
}
pub(crate) fn header(block_number: BlockNumberFor<T>) -> HeaderFor<T> {
HeaderFor::<T>::new(
block_number, Default::default(), Default::default(), Default::default(), Default::default(), )
}
fn relay_parent_number(&self) -> u32 {
(self.block_number - One::one())
.try_into()
.map_err(|_| ())
.expect("self.block_number is u32")
}
pub(crate) fn fallback_max_validators() -> u32 {
configuration::ActiveConfig::<T>::get().max_validators.unwrap_or(1024)
}
fn max_validators(&self) -> u32 {
self.max_validators.unwrap_or(Self::fallback_max_validators())
}
#[cfg(not(feature = "runtime-benchmarks"))]
pub(crate) fn set_max_validators(mut self, n: u32) -> Self {
self.max_validators = Some(n);
self
}
pub(crate) fn fallback_max_validators_per_core() -> u32 {
configuration::ActiveConfig::<T>::get()
.scheduler_params
.max_validators_per_core
.unwrap_or(5)
}
#[cfg(not(feature = "runtime-benchmarks"))]
pub(crate) fn set_dispute_statements(mut self, m: BTreeMap<u32, u32>) -> Self {
self.dispute_statements = m;
self
}
pub(crate) fn set_candidate_descriptor_v2(mut self, enable: bool) -> Self {
self.candidate_descriptor_v2 = enable;
self
}
pub(crate) fn set_candidate_modifier(
mut self,
modifier: Option<CandidateModifier<T::Hash>>,
) -> Self {
self.candidate_modifier = modifier;
self
}
fn max_validators_per_core(&self) -> u32 {
self.max_validators_per_core.unwrap_or(Self::fallback_max_validators_per_core())
}
#[cfg(not(feature = "runtime-benchmarks"))]
pub(crate) fn set_max_validators_per_core(mut self, n: u32) -> Self {
self.max_validators_per_core = Some(n);
self
}
pub(crate) fn max_cores(&self) -> u32 {
self.max_validators() / self.max_validators_per_core()
}
#[cfg(feature = "runtime-benchmarks")]
pub(crate) fn fallback_min_backing_votes() -> u32 {
2
}
fn mock_head_data() -> HeadData {
let max_head_size = configuration::ActiveConfig::<T>::get().max_head_data_size;
HeadData(vec![0xFF; max_head_size as usize])
}
fn candidate_descriptor_mock(
para_id: ParaId,
candidate_descriptor_v2: bool,
) -> CandidateDescriptorV2<T::Hash> {
if candidate_descriptor_v2 {
CandidateDescriptorV2::new(
para_id,
Default::default(),
CoreIndex(200),
2,
Default::default(),
Default::default(),
Default::default(),
Default::default(),
mock_validation_code().hash(),
)
} else {
CandidateDescriptor::<T::Hash> {
para_id,
relay_parent: Default::default(),
collator: junk_collator(),
persisted_validation_data_hash: Default::default(),
pov_hash: Default::default(),
erasure_root: Default::default(),
signature: junk_collator_signature(),
para_head: Default::default(),
validation_code_hash: mock_validation_code().hash(),
}
.into()
}
.into()
}
fn candidate_availability_mock(
para_id: ParaId,
group_idx: GroupIndex,
core_idx: CoreIndex,
candidate_hash: CandidateHash,
availability_votes: BitVec<u8, BitOrderLsb0>,
commitments: CandidateCommitments,
candidate_descriptor_v2: bool,
) -> inclusion::CandidatePendingAvailability<T::Hash, BlockNumberFor<T>> {
inclusion::CandidatePendingAvailability::<T::Hash, BlockNumberFor<T>>::new(
core_idx, candidate_hash, Self::candidate_descriptor_mock(para_id, candidate_descriptor_v2), commitments, availability_votes, Default::default(), Zero::zero(), One::one(), group_idx, )
}
fn add_availability(
para_id: ParaId,
core_idx: CoreIndex,
group_idx: GroupIndex,
availability_votes: BitVec<u8, BitOrderLsb0>,
candidate_hash: CandidateHash,
candidate_descriptor_v2: bool,
) {
let commitments = CandidateCommitments::<u32> {
upward_messages: Default::default(),
horizontal_messages: Default::default(),
new_validation_code: None,
head_data: Self::mock_head_data(),
processed_downward_messages: 0,
hrmp_watermark: 0u32.into(),
};
let candidate_availability = Self::candidate_availability_mock(
para_id,
group_idx,
core_idx,
candidate_hash,
availability_votes,
commitments,
candidate_descriptor_v2,
);
inclusion::PendingAvailability::<T>::mutate(para_id, |maybe_candidates| {
if let Some(candidates) = maybe_candidates {
candidates.push_back(candidate_availability);
} else {
*maybe_candidates =
Some([candidate_availability].into_iter().collect::<VecDeque<_>>());
}
});
}
fn availability_bitvec(concluding_cores: &BTreeSet<u32>, cores: usize) -> AvailabilityBitfield {
let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0];
for i in 0..cores {
if concluding_cores.contains(&(i as u32)) {
bitfields.push(true);
} else {
bitfields.push(false)
}
}
bitfields.into()
}
fn run_to_block(to: u32) {
let to = to.into();
while frame_system::Pallet::<T>::block_number() < to {
let b = frame_system::Pallet::<T>::block_number();
initializer::Pallet::<T>::on_finalize(b);
let b = b + One::one();
frame_system::Pallet::<T>::set_block_number(b);
initializer::Pallet::<T>::on_initialize(b);
}
}
fn setup_para_ids(n_paras: usize) {
for i in 0..n_paras {
let para_id = ParaId::from(i as u32);
let validation_code = mock_validation_code();
paras::Pallet::<T>::schedule_para_initialize(
para_id,
paras::ParaGenesisArgs {
genesis_head: Self::mock_head_data(),
validation_code: validation_code.clone(),
para_kind: ParaKind::Parachain,
},
)
.unwrap();
paras::Pallet::<T>::add_trusted_validation_code(
frame_system::Origin::<T>::Root.into(),
validation_code,
)
.unwrap();
}
}
fn signing_context(&self) -> SigningContext<T::Hash> {
SigningContext {
parent_hash: Self::header(self.block_number).hash(),
session_index: self.session,
}
}
fn validator_availability_votes_yes(validators: usize) -> BitVec<u8, bitvec::order::Lsb0> {
bitvec::bitvec![u8, bitvec::order::Lsb0; 1; validators as usize]
}
fn setup_session(
mut self,
target_session: SessionIndex,
validators: Vec<(T::AccountId, ValidatorId)>,
total_cores: usize,
extra_cores: usize,
) -> Self {
let mut block = 1;
for session in 0..=target_session {
initializer::Pallet::<T>::test_trigger_on_new_session(
false,
session,
validators.iter().map(|(a, v)| (a, v.clone())),
None,
);
block += 1;
Self::run_to_block(block);
}
let block_number = BlockNumberFor::<T>::from(block);
let header = Self::header(block_number);
frame_system::Pallet::<T>::reset_events();
frame_system::Pallet::<T>::initialize(
&header.number(),
&header.hash(),
&Digest { logs: Vec::new() },
);
assert_eq!(shared::CurrentSessionIndex::<T>::get(), target_session);
let validators_shuffled =
session_info::Sessions::<T>::get(target_session).unwrap().validators.clone();
self.validators = Some(validators_shuffled);
self.block_number = block_number;
self.session = target_session;
assert_eq!(paras::Parachains::<T>::get().len(), total_cores - extra_cores);
self
}
fn create_availability_bitfields(
&self,
concluding_paras: &BTreeMap<u32, u32>,
elastic_paras: &BTreeMap<u32, u8>,
total_cores: usize,
) -> Vec<UncheckedSigned<AvailabilityBitfield>> {
let validators =
self.validators.as_ref().expect("must have some validators prior to calling");
let mut current_core_idx = 0u32;
let mut concluding_cores = BTreeSet::new();
for (seed, _) in concluding_paras.iter() {
let para_id = ParaId::from(*seed);
for _chain_idx in 0..elastic_paras.get(&seed).cloned().unwrap_or(1) {
let core_idx = CoreIndex::from(current_core_idx);
let group_idx =
scheduler::Pallet::<T>::group_assigned_to_core(core_idx, self.block_number)
.unwrap();
Self::add_availability(
para_id,
core_idx,
group_idx,
bitvec::bitvec![u8, bitvec::order::Lsb0; 0; validators.len()],
CandidateHash(H256::from(byte32_slice_from(current_core_idx))),
self.candidate_descriptor_v2,
);
if !self.unavailable_cores.contains(¤t_core_idx) {
concluding_cores.insert(current_core_idx);
}
current_core_idx += 1;
}
}
let availability_bitvec = Self::availability_bitvec(&concluding_cores, total_cores);
let bitfields: Vec<UncheckedSigned<AvailabilityBitfield>> = validators
.iter()
.enumerate()
.map(|(i, public)| {
let unchecked_signed = UncheckedSigned::<AvailabilityBitfield>::benchmark_sign(
public,
availability_bitvec.clone(),
&self.signing_context(),
ValidatorIndex(i as u32),
);
unchecked_signed
})
.collect();
bitfields
}
fn create_backed_candidates(
&self,
paras_with_backed_candidates: &BTreeMap<u32, u32>,
elastic_paras: &BTreeMap<u32, u8>,
includes_code_upgrade: Option<u32>,
) -> Vec<BackedCandidate<T::Hash>> {
let validators =
self.validators.as_ref().expect("must have some validators prior to calling");
let config = configuration::ActiveConfig::<T>::get();
let mut current_core_idx = 0u32;
paras_with_backed_candidates
.iter()
.flat_map(|(seed, num_votes)| {
assert!(*num_votes <= validators.len() as u32);
let para_id = ParaId::from(*seed);
let mut prev_head = None;
(0..elastic_paras.get(&seed).cloned().unwrap_or(1))
.map(|chain_idx| {
let core_idx = CoreIndex::from(current_core_idx);
current_core_idx += 1;
let group_idx = scheduler::Pallet::<T>::group_assigned_to_core(
core_idx,
self.block_number,
)
.unwrap();
let header = Self::header(self.block_number);
let relay_parent = header.hash();
let mut head_data = Self::mock_head_data();
if chain_idx == 0 {
paras::Pallet::<T>::heads_insert(¶_id, head_data.clone());
} else {
head_data.0[0] = chain_idx;
}
let persisted_validation_data_hash = PersistedValidationData::<H256> {
parent_head: prev_head.take().unwrap_or(head_data.clone()),
relay_parent_number: self.relay_parent_number(),
relay_parent_storage_root: Default::default(),
max_pov_size: config.max_pov_size,
}
.hash();
prev_head = Some(head_data.clone());
let pov_hash = Default::default();
let validation_code_hash = mock_validation_code().hash();
let mut past_code_meta =
paras::ParaPastCodeMeta::<BlockNumberFor<T>>::default();
past_code_meta.note_replacement(0u32.into(), 0u32.into());
let group_validators =
scheduler::Pallet::<T>::group_validators(group_idx).unwrap();
let descriptor = if self.candidate_descriptor_v2 {
CandidateDescriptorV2::new(
para_id,
relay_parent,
core_idx,
self.target_session,
persisted_validation_data_hash,
pov_hash,
Default::default(),
head_data.hash(),
validation_code_hash,
)
} else {
CandidateDescriptor::<T::Hash> {
para_id,
relay_parent,
collator: junk_collator(),
persisted_validation_data_hash,
pov_hash,
erasure_root: Default::default(),
signature: junk_collator_signature(),
para_head: head_data.hash(),
validation_code_hash,
}
.into()
};
let mut candidate = CommittedCandidateReceipt::<T::Hash> {
descriptor,
commitments: CandidateCommitments::<u32> {
upward_messages: Default::default(),
horizontal_messages: Default::default(),
new_validation_code: includes_code_upgrade
.map(|v| ValidationCode(vec![42u8; v as usize])),
head_data,
processed_downward_messages: 0,
hrmp_watermark: self.relay_parent_number(),
},
};
if self.candidate_descriptor_v2 {
candidate.commitments.upward_messages.force_push(UMP_SEPARATOR);
candidate.commitments.upward_messages.force_push(
UMPSignal::SelectCore(
CoreSelector(chain_idx as u8),
ClaimQueueOffset(0),
)
.encode(),
);
}
if let Some(modifier) = self.candidate_modifier {
candidate = modifier(candidate);
}
let candidate_hash = candidate.hash();
let validity_votes: Vec<_> = group_validators
.iter()
.take(*num_votes as usize)
.map(|val_idx| {
let public = validators.get(*val_idx).unwrap();
let sig = UncheckedSigned::<CompactStatement>::benchmark_sign(
public,
CompactStatement::Valid(candidate_hash),
&self.signing_context(),
*val_idx,
)
.benchmark_signature();
ValidityAttestation::Explicit(sig.clone())
})
.collect();
let core_idx = if candidate.descriptor.core_index().is_some() {
None
} else {
configuration::ActiveConfig::<T>::get()
.node_features
.get(FeatureIndex::ElasticScalingMVP as usize)
.and_then(|the_bit| if *the_bit { Some(core_idx) } else { None })
};
BackedCandidate::<T::Hash>::new(
candidate,
validity_votes,
bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()],
core_idx,
)
})
.collect::<Vec<_>>()
})
.collect()
}
fn create_disputes(
&self,
start: u32,
last: u32,
dispute_sessions: impl AsRef<[u32]>,
) -> Vec<DisputeStatementSet> {
let validators =
self.validators.as_ref().expect("must have some validators prior to calling");
let dispute_sessions = dispute_sessions.as_ref();
let mut current_core_idx = start;
(start..last)
.map(|seed| {
let dispute_session_idx = (seed - start) as usize;
let session = dispute_sessions
.get(dispute_session_idx)
.cloned()
.unwrap_or(self.target_session);
let para_id = ParaId::from(seed);
let core_idx = CoreIndex::from(current_core_idx);
current_core_idx +=1;
let group_idx =
scheduler::Pallet::<T>::group_assigned_to_core(core_idx, self.block_number)
.unwrap();
let candidate_hash = CandidateHash(H256::from(byte32_slice_from(seed)));
let relay_parent = H256::from(byte32_slice_from(seed));
Self::add_availability(
para_id,
core_idx,
group_idx,
Self::validator_availability_votes_yes(validators.len()),
candidate_hash,
self.candidate_descriptor_v2,
);
let statements_len =
self.dispute_statements.get(&seed).cloned().unwrap_or(validators.len() as u32);
let statements = (0..statements_len)
.map(|validator_index| {
let validator_public = &validators.get(ValidatorIndex::from(validator_index)).expect("Test case is not borked. `ValidatorIndex` out of bounds of `ValidatorId`s.");
let dispute_statement = if validator_index % 4 == 0 {
DisputeStatement::Invalid(InvalidDisputeStatementKind::Explicit)
} else if validator_index < 3 {
DisputeStatement::Valid(
ValidDisputeStatementKind::BackingValid(relay_parent)
)
} else {
DisputeStatement::Valid(ValidDisputeStatementKind::Explicit)
};
let data = dispute_statement.payload_data(candidate_hash, session).unwrap();
let statement_sig = validator_public.sign(&data).unwrap();
(dispute_statement, ValidatorIndex(validator_index), statement_sig)
})
.collect();
DisputeStatementSet { candidate_hash, session, statements }
})
.collect()
}
pub(crate) fn build(self) -> Bench<T> {
#[allow(deprecated)]
inclusion::PendingAvailability::<T>::remove_all(None);
let max_cores = self.max_cores() as usize;
let extra_cores = self
.elastic_paras
.values()
.map(|count| *count as usize)
.sum::<usize>()
.saturating_sub(self.elastic_paras.len() as usize);
let used_cores = self.dispute_sessions.len() +
self.backed_and_concluding_paras.len() +
self.backed_in_inherent_paras.len() +
extra_cores;
assert!(used_cores <= max_cores);
Self::setup_para_ids(used_cores - extra_cores);
configuration::Pallet::<T>::set_coretime_cores_unchecked(used_cores as u32).unwrap();
let validator_ids = generate_validator_pairs::<T>(self.max_validators());
let target_session = SessionIndex::from(self.target_session);
let builder = self.setup_session(target_session, validator_ids, used_cores, extra_cores);
let bitfields = builder.create_availability_bitfields(
&builder.backed_and_concluding_paras,
&builder.elastic_paras,
scheduler::Pallet::<T>::num_availability_cores(),
);
let mut backed_in_inherent = BTreeMap::new();
backed_in_inherent.append(&mut builder.backed_and_concluding_paras.clone());
backed_in_inherent.append(&mut builder.backed_in_inherent_paras.clone());
let backed_candidates = builder.create_backed_candidates(
&backed_in_inherent,
&builder.elastic_paras,
builder.code_upgrade,
);
let disputes = builder.create_disputes(
builder.backed_and_concluding_paras.len() as u32,
(used_cores - extra_cores) as u32,
builder.dispute_sessions.as_slice(),
);
let mut disputed_cores = (builder.backed_and_concluding_paras.len() as u32..
((used_cores - extra_cores) as u32))
.into_iter()
.map(|idx| (idx, 0))
.collect::<BTreeMap<_, _>>();
let mut all_cores = builder.backed_and_concluding_paras.clone();
all_cores.append(&mut disputed_cores);
assert_eq!(inclusion::PendingAvailability::<T>::iter().count(), used_cores - extra_cores);
let mut core_idx = 0u32;
let elastic_paras = &builder.elastic_paras;
let mut occupied_cores = inclusion::Pallet::<T>::get_occupied_cores()
.map(|(core, candidate)| (core, candidate.candidate_descriptor().para_id()))
.collect::<Vec<_>>();
occupied_cores.sort_by(|(core_a, _), (core_b, _)| core_a.0.cmp(&core_b.0));
let mut expected_cores = all_cores
.iter()
.flat_map(|(para_id, _)| {
(0..elastic_paras.get(¶_id).cloned().unwrap_or(1))
.map(|_para_local_core_idx| {
let old_core_idx = core_idx;
core_idx += 1;
(CoreIndex(old_core_idx), ParaId::from(*para_id))
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
expected_cores.sort_by(|(core_a, _), (core_b, _)| core_a.0.cmp(&core_b.0));
assert_eq!(expected_cores, occupied_cores);
all_cores.append(&mut builder.backed_in_inherent_paras.clone());
let mut core_idx = 0u32;
let cores = all_cores
.keys()
.flat_map(|para_id| {
(0..elastic_paras.get(¶_id).cloned().unwrap_or(1))
.map(|_para_local_core_idx| {
let assignment =
<T as scheduler::Config>::AssignmentProvider::get_mock_assignment(
CoreIndex(core_idx),
ParaId::from(*para_id),
);
core_idx += 1;
(CoreIndex(core_idx - 1), [assignment].into())
})
.collect::<Vec<(CoreIndex, VecDeque<Assignment>)>>()
})
.collect::<BTreeMap<CoreIndex, VecDeque<Assignment>>>();
scheduler::ClaimQueue::<T>::set(cores);
Bench::<T> {
data: ParachainsInherentData {
bitfields,
backed_candidates,
disputes,
parent_header: Self::header(builder.block_number),
},
_session: target_session,
_block_number: builder.block_number,
}
}
}