use crate::{configuration, paras::*, shared::Pallet as ParasShared};
use alloc::{vec, vec::Vec};
use frame_support::assert_ok;
use frame_system::RawOrigin;
use polkadot_primitives::{HeadData, Id as ParaId, ValidationCode, ValidatorId, ValidatorIndex};
use sp_application_crypto::RuntimeAppPublic;
const SESSION_INDEX: SessionIndex = 1;
const VALIDATOR_NUM: usize = 800;
const CAUSES_NUM: usize = 100;
fn validation_code() -> ValidationCode {
ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9])
}
fn old_validation_code() -> ValidationCode {
ValidationCode(vec![9, 8, 7, 6, 5, 4, 3, 2, 1])
}
pub fn prepare_inclusion_bench<T>() -> (PvfCheckStatement, ValidatorSignature)
where
T: Config + shared::Config,
{
initialize::<T>();
initialize_pvf_active_vote::<T>(VoteCause::Onboarding, CAUSES_NUM);
let stmt_n_sig = generate_statements::<T>(VoteOutcome::Accept).next().unwrap();
stmt_n_sig
}
pub fn prepare_finalization_bench<T>(
cause: VoteCause,
outcome: VoteOutcome,
) -> (PvfCheckStatement, ValidatorSignature)
where
T: Config + shared::Config,
{
initialize::<T>();
initialize_pvf_active_vote::<T>(cause, CAUSES_NUM);
let mut stmts = generate_statements::<T>(outcome).collect::<Vec<_>>();
assert!(stmts.len() > 2);
let stmt_n_sig = stmts.pop().unwrap();
for (stmt, sig) in stmts {
let r = Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, sig);
assert!(r.is_ok());
}
stmt_n_sig
}
pub fn prepare_bypassing_bench<T>(validation_code: ValidationCode)
where
T: Config + shared::Config,
{
const PARAS_NUM: usize = 10;
initialize::<T>();
for i in 0..PARAS_NUM {
let id = ParaId::from(i as u32);
assert_ok!(Pallet::<T>::schedule_para_initialize(
id,
ParaGenesisArgs {
para_kind: ParaKind::Parachain,
genesis_head: HeadData(vec![1, 2, 3, 4]),
validation_code: validation_code.clone(),
},
));
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum VoteCause {
Onboarding,
Upgrade,
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum VoteOutcome {
Accept,
Reject,
}
fn initialize<T>()
where
T: Config + shared::Config,
{
let validators = (0..VALIDATOR_NUM)
.map(|_| <ValidatorId as RuntimeAppPublic>::generate_pair(None))
.collect::<Vec<_>>();
let config = configuration::ActiveConfig::<T>::get();
configuration::Pallet::<T>::force_set_active_config(config.clone());
ParasShared::<T>::set_active_validators_ascending(validators.clone());
ParasShared::<T>::set_session_index(SESSION_INDEX);
}
fn initialize_pvf_active_vote<T>(vote_cause: VoteCause, causes_num: usize)
where
T: Config + shared::Config,
{
for i in 0..causes_num {
let id = ParaId::from(i as u32);
if vote_cause == VoteCause::Upgrade {
let old_validation_code = old_validation_code();
let validation_code = validation_code();
let mut parachains = ParachainsCache::new();
Pallet::<T>::initialize_para_now(
&mut parachains,
id,
&ParaGenesisArgs {
para_kind: ParaKind::Parachain,
genesis_head: HeadData(vec![1, 2, 3, 4]),
validation_code: old_validation_code,
},
);
drop(parachains);
Pallet::<T>::schedule_code_upgrade(
id,
validation_code,
1u32.into(),
&configuration::ActiveConfig::<T>::get(),
UpgradeStrategy::SetGoAheadSignal,
);
} else {
let r = Pallet::<T>::schedule_para_initialize(
id,
ParaGenesisArgs {
para_kind: ParaKind::Parachain,
genesis_head: HeadData(vec![1, 2, 3, 4]),
validation_code: validation_code(),
},
);
assert!(r.is_ok());
}
}
}
fn generate_statements<T>(
vote_outcome: VoteOutcome,
) -> impl Iterator<Item = (PvfCheckStatement, ValidatorSignature)>
where
T: Config + shared::Config,
{
let validators = shared::ActiveValidatorKeys::<T>::get();
let accept_threshold = polkadot_primitives::supermajority_threshold(validators.len());
let required_votes = match vote_outcome {
VoteOutcome::Accept => accept_threshold,
VoteOutcome::Reject => validators.len() - accept_threshold,
};
(0..required_votes).map(move |validator_index| {
let stmt = PvfCheckStatement {
accept: vote_outcome == VoteOutcome::Accept,
subject: validation_code().hash(),
session_index: SESSION_INDEX,
validator_index: ValidatorIndex(validator_index as u32),
};
let signature = validators[validator_index].sign(&stmt.signing_payload()).unwrap();
(stmt, signature)
})
}