polkadot_runtime_parachains/paras/benchmarking/
pvf_check.rs1use crate::{configuration, paras::*, shared::Pallet as ParasShared};
20use alloc::{vec, vec::Vec};
21use frame_support::assert_ok;
22use frame_system::RawOrigin;
23use polkadot_primitives::{HeadData, Id as ParaId, ValidationCode, ValidatorId, ValidatorIndex};
24use sp_application_crypto::RuntimeAppPublic;
25
26const SESSION_INDEX: SessionIndex = 1;
28const VALIDATOR_NUM: usize = 800;
29const CAUSES_NUM: usize = 100;
30fn validation_code() -> ValidationCode {
31 ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9])
32}
33fn old_validation_code() -> ValidationCode {
34 ValidationCode(vec![9, 8, 7, 6, 5, 4, 3, 2, 1])
35}
36
37pub fn prepare_inclusion_bench<T>() -> (PvfCheckStatement, ValidatorSignature)
43where
44 T: Config + shared::Config,
45{
46 initialize::<T>();
47 initialize_pvf_active_vote::<T>(VoteCause::Onboarding, CAUSES_NUM);
49
50 let stmt_n_sig = generate_statements::<T>(VoteOutcome::Accept).next().unwrap();
55
56 stmt_n_sig
57}
58
59pub fn prepare_finalization_bench<T>(
66 cause: VoteCause,
67 outcome: VoteOutcome,
68) -> (PvfCheckStatement, ValidatorSignature)
69where
70 T: Config + shared::Config,
71{
72 initialize::<T>();
73 initialize_pvf_active_vote::<T>(cause, CAUSES_NUM);
74
75 let mut stmts = generate_statements::<T>(outcome).collect::<Vec<_>>();
76 assert!(stmts.len() > 2);
78
79 let stmt_n_sig = stmts.pop().unwrap();
81
82 for (stmt, sig) in stmts {
83 let r = Pallet::<T>::include_pvf_check_statement(RawOrigin::None.into(), stmt, sig);
84 assert!(r.is_ok());
85 }
86
87 stmt_n_sig
88}
89
90pub fn prepare_bypassing_bench<T>(validation_code: ValidationCode)
93where
94 T: Config + shared::Config,
95{
96 const PARAS_NUM: usize = 10;
98
99 initialize::<T>();
100 for i in 0..PARAS_NUM {
101 let id = ParaId::from(i as u32);
102 assert_ok!(Pallet::<T>::schedule_para_initialize(
103 id,
104 ParaGenesisArgs {
105 para_kind: ParaKind::Parachain,
106 genesis_head: HeadData(vec![1, 2, 3, 4]),
107 validation_code: validation_code.clone(),
108 },
109 ));
110 }
111}
112
113#[derive(PartialEq, Eq, Copy, Clone, Debug)]
115pub enum VoteCause {
116 Onboarding,
117 Upgrade,
118}
119
120#[derive(PartialEq, Eq, Copy, Clone, Debug)]
122pub enum VoteOutcome {
123 Accept,
124 Reject,
125}
126
127fn initialize<T>()
128where
129 T: Config + shared::Config,
130{
131 let validators = (0..VALIDATOR_NUM)
133 .map(|_| <ValidatorId as RuntimeAppPublic>::generate_pair(None))
134 .collect::<Vec<_>>();
135
136 let config = configuration::ActiveConfig::<T>::get();
138 configuration::Pallet::<T>::force_set_active_config(config.clone());
139
140 ParasShared::<T>::set_active_validators_ascending(validators.clone());
142 ParasShared::<T>::set_session_index(SESSION_INDEX);
143}
144
145fn initialize_pvf_active_vote<T>(vote_cause: VoteCause, causes_num: usize)
150where
151 T: Config + shared::Config,
152{
153 for i in 0..causes_num {
154 let id = ParaId::from(i as u32);
155
156 if vote_cause == VoteCause::Upgrade {
157 let old_validation_code = old_validation_code();
160 let validation_code = validation_code();
161
162 let mut parachains = ParachainsCache::new();
163 Pallet::<T>::initialize_para_now(
164 &mut parachains,
165 id,
166 &ParaGenesisArgs {
167 para_kind: ParaKind::Parachain,
168 genesis_head: HeadData(vec![1, 2, 3, 4]),
169 validation_code: old_validation_code,
170 },
171 );
172 drop(parachains);
175
176 Pallet::<T>::schedule_code_upgrade(
177 id,
178 validation_code,
179 1u32.into(),
180 &configuration::ActiveConfig::<T>::get(),
181 UpgradeStrategy::SetGoAheadSignal,
182 );
183 } else {
184 let r = Pallet::<T>::schedule_para_initialize(
185 id,
186 ParaGenesisArgs {
187 para_kind: ParaKind::Parachain,
188 genesis_head: HeadData(vec![1, 2, 3, 4]),
189 validation_code: validation_code(),
190 },
191 );
192 assert!(r.is_ok());
193 }
194 }
195}
196
197fn generate_statements<T>(
201 vote_outcome: VoteOutcome,
202) -> impl Iterator<Item = (PvfCheckStatement, ValidatorSignature)>
203where
204 T: Config + shared::Config,
205{
206 let validators = shared::ActiveValidatorKeys::<T>::get();
207
208 let accept_threshold = polkadot_primitives::supermajority_threshold(validators.len());
209 let required_votes = match vote_outcome {
210 VoteOutcome::Accept => accept_threshold,
211 VoteOutcome::Reject => validators.len() - accept_threshold,
212 };
213 (0..required_votes).map(move |validator_index| {
214 let stmt = PvfCheckStatement {
215 accept: vote_outcome == VoteOutcome::Accept,
216 subject: validation_code().hash(),
217 session_index: SESSION_INDEX,
218
219 validator_index: ValidatorIndex(validator_index as u32),
220 };
221 let signature = validators[validator_index].sign(&stmt.signing_payload()).unwrap();
222
223 (stmt, signature)
224 })
225}