1#![warn(missing_docs)]
20#![cfg_attr(not(feature = "std"), no_std)]
21
22use pezbp_header_pez_chain::justification::{required_justification_precommits, GrandpaJustification};
23use pezbp_pezkuwi_core::teyrchains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
24use pezbp_teyrchains::teyrchain_head_storage_key_at_source;
25use codec::Encode;
26use pezbp_runtime::record_all_trie_keys;
27use pezsp_consensus_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId};
28use pezsp_runtime::traits::{Header as HeaderT, One, Zero};
29use pezsp_std::prelude::*;
30use pezsp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut};
31
32pub use keyring::*;
34
35mod keyring;
36
37pub const TEST_GRANDPA_ROUND: u64 = 1;
39pub const TEST_GRANDPA_SET_ID: SetId = 1;
41pub const PARAS_PALLET_NAME: &str = "Paras";
43
44#[derive(Clone)]
46pub struct JustificationGeneratorParams<H> {
47 pub header: H,
49 pub round: u64,
51 pub set_id: SetId,
53 pub authorities: Vec<(Account, AuthorityWeight)>,
57 pub ancestors: u32,
61 pub forks: u32,
65}
66
67impl<H: HeaderT> Default for JustificationGeneratorParams<H> {
68 fn default() -> Self {
69 let required_signatures = required_justification_precommits(test_keyring().len() as _);
70 Self {
71 header: test_header(One::one()),
72 round: TEST_GRANDPA_ROUND,
73 set_id: TEST_GRANDPA_SET_ID,
74 authorities: test_keyring().into_iter().take(required_signatures as _).collect(),
75 ancestors: 2,
76 forks: 1,
77 }
78 }
79}
80
81pub fn make_default_justification<H: HeaderT>(header: &H) -> GrandpaJustification<H> {
83 let params = JustificationGeneratorParams::<H> { header: header.clone(), ..Default::default() };
84
85 make_justification_for_header(params)
86}
87
88pub fn make_justification_for_header<H: HeaderT>(
98 params: JustificationGeneratorParams<H>,
99) -> GrandpaJustification<H> {
100 let JustificationGeneratorParams { header, round, set_id, authorities, mut ancestors, forks } =
101 params;
102 let (target_hash, target_number) = (header.hash(), *header.number());
103 let mut votes_ancestries = vec![];
104 let mut precommits = vec![];
105
106 assert!(forks != 0, "Need at least one fork to have a chain..");
107 assert!(
108 forks as usize <= authorities.len(),
109 "If we have more forks than authorities we can't create valid pre-commits for all the forks."
110 );
111
112 let target_depth = ancestors.div_ceil(forks);
114
115 let mut unsigned_precommits = vec![];
116 for i in 0..forks {
117 let depth = if ancestors >= target_depth {
118 ancestors -= target_depth;
119 target_depth
120 } else {
121 ancestors
122 };
123
124 let chain = generate_chain(i, depth + 1, &header);
126
127 for child in &chain[1..] {
129 votes_ancestries.push(child.clone());
130 }
131
132 let precommit_candidate = chain.last().map(|h| (h.hash(), *h.number())).unwrap();
135 unsigned_precommits.push(precommit_candidate);
136 }
137
138 for (i, (id, _weight)) in authorities.iter().enumerate() {
139 let target = unsigned_precommits[i % forks as usize];
141 let precommit = signed_precommit::<H>(id, target, round, set_id);
142
143 precommits.push(precommit);
144 }
145
146 GrandpaJustification {
147 round,
148 commit: finality_grandpa::Commit { target_hash, target_number, precommits },
149 votes_ancestries,
150 }
151}
152
153fn generate_chain<H: HeaderT>(fork_id: u32, depth: u32, ancestor: &H) -> Vec<H> {
154 let mut headers = vec![ancestor.clone()];
155
156 for i in 1..depth {
157 let parent = &headers[(i - 1) as usize];
158 let (hash, num) = (parent.hash(), *parent.number());
159
160 let mut header = test_header::<H>(num + One::one());
161 header.set_parent_hash(hash);
162
163 header
166 .digest_mut()
167 .logs
168 .push(pezsp_runtime::DigestItem::Other(fork_id.encode()));
169
170 headers.push(header);
171 }
172
173 headers
174}
175
176pub fn prepare_teyrchain_heads_proof<H: HeaderT>(
178 heads: Vec<(u32, ParaHead)>,
179) -> (H::Hash, ParaHeadsProof, Vec<(ParaId, ParaHash)>) {
180 let mut teyrchains = Vec::with_capacity(heads.len());
181 let mut root = Default::default();
182 let mut mdb = MemoryDB::default();
183 let mut storage_keys = vec![];
184 {
185 let mut trie = TrieDBMutBuilderV1::<H::Hashing>::new(&mut mdb, &mut root).build();
186 for (teyrchain, head) in heads {
187 let storage_key =
188 teyrchain_head_storage_key_at_source(PARAS_PALLET_NAME, ParaId(teyrchain));
189 trie.insert(&storage_key.0, &head.encode())
190 .map_err(|_| "TrieMut::insert has failed")
191 .expect("TrieMut::insert should not fail in tests");
192 storage_keys.push(storage_key.0);
193 teyrchains.push((ParaId(teyrchain), head.hash()));
194 }
195 }
196
197 let storage_proof = record_all_trie_keys::<LayoutV1<H::Hashing>, _>(&mdb, &root)
199 .map_err(|_| "record_all_trie_keys has failed")
200 .expect("record_all_trie_keys should not fail in benchmarks");
201
202 (root, ParaHeadsProof { storage_proof }, teyrchains)
203}
204
205pub fn signed_precommit<H: HeaderT>(
207 signer: &Account,
208 target: (H::Hash, H::Number),
209 round: u64,
210 set_id: SetId,
211) -> finality_grandpa::SignedPrecommit<H::Hash, H::Number, AuthoritySignature, AuthorityId> {
212 let precommit = finality_grandpa::Precommit { target_hash: target.0, target_number: target.1 };
213
214 let encoded = pezsp_consensus_grandpa::localized_payload(
215 round,
216 set_id,
217 &finality_grandpa::Message::Precommit(precommit.clone()),
218 );
219
220 let signature = signer.sign(&encoded);
221 let raw_signature: Vec<u8> = signature.to_bytes().into();
222
223 let signature = AuthoritySignature::try_from(raw_signature).expect(
226 "We know our Keypair is good,
227 so our signature must also be good.",
228 );
229 let id = (*signer).into();
230
231 finality_grandpa::SignedPrecommit { precommit, signature, id }
232}
233
234pub fn test_header<H: HeaderT>(number: H::Number) -> H {
238 let default = |num| {
239 H::new(num, Default::default(), Default::default(), Default::default(), Default::default())
240 };
241
242 let mut header = default(number);
243 if number != Zero::zero() {
244 let parent_hash = default(number - One::one()).hash();
245 header.set_parent_hash(parent_hash);
246 }
247
248 header
249}
250
251pub fn test_header_with_root<H: HeaderT>(number: H::Number, state_root: H::Hash) -> H {
255 let mut header: H = test_header(number);
256 header.set_state_root(state_root);
257 header
258}
259
260pub fn header_id<H: HeaderT>(index: u8) -> (H::Hash, H::Number) {
262 (test_header::<H>(index.into()).hash(), index.into())
263}
264
265#[macro_export]
266macro_rules! generate_owned_bridge_module_tests {
275 ($normal_operating_mode: expr, $halted_operating_mode: expr) => {
276 #[test]
277 fn test_set_owner() {
278 run_test(|| {
279 PalletOwner::<TestRuntime>::put(1);
280
281 assert_ok!(Pezpallet::<TestRuntime>::set_owner(RuntimeOrigin::root(), Some(2)));
283 assert_eq!(PalletOwner::<TestRuntime>::get(), Some(2));
284
285 assert_ok!(Pezpallet::<TestRuntime>::set_owner(RuntimeOrigin::signed(2), Some(3)));
287 assert_eq!(PalletOwner::<TestRuntime>::get(), Some(3));
288
289 assert_noop!(
291 Pezpallet::<TestRuntime>::set_owner(RuntimeOrigin::signed(1), Some(4)),
292 DispatchError::BadOrigin
293 );
294 assert_eq!(PalletOwner::<TestRuntime>::get(), Some(3));
295 });
296 }
297
298 #[test]
299 fn test_set_operating_mode() {
300 run_test(|| {
301 PalletOwner::<TestRuntime>::put(1);
302 PalletOperatingMode::<TestRuntime>::put($normal_operating_mode);
303
304 assert_ok!(Pezpallet::<TestRuntime>::set_operating_mode(
306 RuntimeOrigin::root(),
307 $halted_operating_mode
308 ));
309 assert_eq!(PalletOperatingMode::<TestRuntime>::get(), $halted_operating_mode);
310 assert_ok!(Pezpallet::<TestRuntime>::set_operating_mode(
312 RuntimeOrigin::root(),
313 $normal_operating_mode
314 ));
315 assert_eq!(PalletOperatingMode::<TestRuntime>::get(), $normal_operating_mode);
316
317 assert_ok!(Pezpallet::<TestRuntime>::set_operating_mode(
319 RuntimeOrigin::signed(1),
320 $halted_operating_mode
321 ));
322 assert_eq!(PalletOperatingMode::<TestRuntime>::get(), $halted_operating_mode);
323 assert_ok!(Pezpallet::<TestRuntime>::set_operating_mode(
325 RuntimeOrigin::signed(1),
326 $normal_operating_mode
327 ));
328 assert_eq!(PalletOperatingMode::<TestRuntime>::get(), $normal_operating_mode);
329
330 assert_noop!(
332 Pezpallet::<TestRuntime>::set_operating_mode(
333 RuntimeOrigin::signed(2),
334 $halted_operating_mode
335 ),
336 DispatchError::BadOrigin
337 );
338 assert_eq!(PalletOperatingMode::<TestRuntime>::get(), $normal_operating_mode);
339 PalletOperatingMode::<TestRuntime>::put($halted_operating_mode);
341 assert_noop!(
342 Pezpallet::<TestRuntime>::set_operating_mode(
343 RuntimeOrigin::signed(2),
344 $normal_operating_mode
345 ),
346 DispatchError::BadOrigin
347 );
348 assert_eq!(PalletOperatingMode::<TestRuntime>::get(), $halted_operating_mode);
349 });
350 }
351 };
352}