referrerpolicy=no-referrer-when-downgrade

substrate_test_runtime_client/
trait_tests.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! tests that should hold for all implementations of certain traits.
19//! to test implementations without duplication.
20
21#![allow(missing_docs)]
22
23use std::sync::Arc;
24
25use crate::{
26	BlockBuilderExt, ClientBlockImportExt, Sr25519Keyring, TestClientBuilder, TestClientBuilderExt,
27};
28use futures::executor::block_on;
29use sc_block_builder::BlockBuilderBuilder;
30use sc_client_api::{
31	backend,
32	blockchain::{Backend as BlockChainBackendT, HeaderBackend},
33};
34use sp_consensus::BlockOrigin;
35use sp_runtime::traits::Block as BlockT;
36use substrate_test_runtime::Transfer;
37
38/// helper to test the `leaves` implementation for various backends
39pub fn test_leaves_for_backend<B: 'static>(backend: Arc<B>)
40where
41	B: backend::Backend<substrate_test_runtime::Block>,
42{
43	// block tree:
44	// G -> A1 -> A2 -> A3 -> A4 -> A5
45	// 		A1 -> B2 -> B3 -> B4
46	// 			  B2 -> C3
47	// 		A1 -> D2
48
49	let client = TestClientBuilder::with_backend(backend.clone()).build();
50	let blockchain = backend.blockchain();
51
52	let genesis_hash = client.chain_info().genesis_hash;
53
54	assert_eq!(blockchain.leaves().unwrap(), vec![genesis_hash]);
55
56	// G -> A1
57	let a1 = BlockBuilderBuilder::new(&client)
58		.on_parent_block(genesis_hash)
59		.fetch_parent_block_number(&client)
60		.unwrap()
61		.build()
62		.unwrap()
63		.build()
64		.unwrap()
65		.block;
66	block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap();
67	assert_eq!(blockchain.leaves().unwrap(), vec![a1.hash()]);
68
69	// A1 -> A2
70	let a2 = BlockBuilderBuilder::new(&client)
71		.on_parent_block(a1.hash())
72		.fetch_parent_block_number(&client)
73		.unwrap()
74		.build()
75		.unwrap()
76		.build()
77		.unwrap()
78		.block;
79	block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap();
80
81	assert_eq!(blockchain.leaves().unwrap(), vec![a2.hash()]);
82
83	// A2 -> A3
84	let a3 = BlockBuilderBuilder::new(&client)
85		.on_parent_block(a2.hash())
86		.fetch_parent_block_number(&client)
87		.unwrap()
88		.build()
89		.unwrap()
90		.build()
91		.unwrap()
92		.block;
93	block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap();
94
95	assert_eq!(blockchain.leaves().unwrap(), vec![a3.hash()]);
96
97	// A3 -> A4
98	let a4 = BlockBuilderBuilder::new(&client)
99		.on_parent_block(a3.hash())
100		.fetch_parent_block_number(&client)
101		.unwrap()
102		.build()
103		.unwrap()
104		.build()
105		.unwrap()
106		.block;
107	block_on(client.import(BlockOrigin::Own, a4.clone())).unwrap();
108	assert_eq!(blockchain.leaves().unwrap(), vec![a4.hash()]);
109
110	// A4 -> A5
111	let a5 = BlockBuilderBuilder::new(&client)
112		.on_parent_block(a4.hash())
113		.fetch_parent_block_number(&client)
114		.unwrap()
115		.build()
116		.unwrap()
117		.build()
118		.unwrap()
119		.block;
120
121	block_on(client.import(BlockOrigin::Own, a5.clone())).unwrap();
122	assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash()]);
123
124	// A1 -> B2
125	let mut builder = BlockBuilderBuilder::new(&client)
126		.on_parent_block(a1.hash())
127		.fetch_parent_block_number(&client)
128		.unwrap()
129		.build()
130		.unwrap();
131
132	// this push is required as otherwise B2 has the same hash as A2 and won't get imported
133	builder
134		.push_transfer(Transfer {
135			from: Sr25519Keyring::Alice.into(),
136			to: Sr25519Keyring::Ferdie.into(),
137			amount: 41,
138			nonce: 0,
139		})
140		.unwrap();
141	let b2 = builder.build().unwrap().block;
142	block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap();
143	assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b2.hash()]);
144
145	// B2 -> B3
146	let b3 = BlockBuilderBuilder::new(&client)
147		.on_parent_block(b2.hash())
148		.fetch_parent_block_number(&client)
149		.unwrap()
150		.build()
151		.unwrap()
152		.build()
153		.unwrap()
154		.block;
155
156	block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap();
157	assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b3.hash()]);
158
159	// B3 -> B4
160	let b4 = BlockBuilderBuilder::new(&client)
161		.on_parent_block(b3.hash())
162		.fetch_parent_block_number(&client)
163		.unwrap()
164		.build()
165		.unwrap()
166		.build()
167		.unwrap()
168		.block;
169	block_on(client.import(BlockOrigin::Own, b4.clone())).unwrap();
170	assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash()]);
171
172	// // B2 -> C3
173	let mut builder = BlockBuilderBuilder::new(&client)
174		.on_parent_block(b2.hash())
175		.fetch_parent_block_number(&client)
176		.unwrap()
177		.build()
178		.unwrap();
179	// this push is required as otherwise C3 has the same hash as B3 and won't get imported
180	builder
181		.push_transfer(Transfer {
182			from: Sr25519Keyring::Alice.into(),
183			to: Sr25519Keyring::Ferdie.into(),
184			amount: 1,
185			nonce: 1,
186		})
187		.unwrap();
188	let c3 = builder.build().unwrap().block;
189	block_on(client.import(BlockOrigin::Own, c3.clone())).unwrap();
190	assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash(), c3.hash()]);
191
192	// A1 -> D2
193	let mut builder = BlockBuilderBuilder::new(&client)
194		.on_parent_block(a1.hash())
195		.fetch_parent_block_number(&client)
196		.unwrap()
197		.build()
198		.unwrap();
199	// this push is required as otherwise D2 has the same hash as B2 and won't get imported
200	builder
201		.push_transfer(Transfer {
202			from: Sr25519Keyring::Alice.into(),
203			to: Sr25519Keyring::Ferdie.into(),
204			amount: 1,
205			nonce: 0,
206		})
207		.unwrap();
208	let d2 = builder.build().unwrap().block;
209	block_on(client.import(BlockOrigin::Own, d2.clone())).unwrap();
210	assert_eq!(blockchain.leaves().unwrap(), vec![a5.hash(), b4.hash(), c3.hash(), d2.hash()]);
211}
212
213/// helper to test the `children` implementation for various backends
214pub fn test_children_for_backend<B: 'static>(backend: Arc<B>)
215where
216	B: backend::LocalBackend<substrate_test_runtime::Block>,
217{
218	// block tree:
219	// G -> A1 -> A2 -> A3 -> A4 -> A5
220	// 		A1 -> B2 -> B3 -> B4
221	// 			  B2 -> C3
222	// 		A1 -> D2
223
224	let client = TestClientBuilder::with_backend(backend.clone()).build();
225	let blockchain = backend.blockchain();
226	let genesis_hash = client.chain_info().genesis_hash;
227
228	// G -> A1
229	let a1 = BlockBuilderBuilder::new(&client)
230		.on_parent_block(genesis_hash)
231		.fetch_parent_block_number(&client)
232		.unwrap()
233		.build()
234		.unwrap()
235		.build()
236		.unwrap()
237		.block;
238	block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap();
239
240	// A1 -> A2
241	let a2 = BlockBuilderBuilder::new(&client)
242		.on_parent_block(a1.hash())
243		.fetch_parent_block_number(&client)
244		.unwrap()
245		.build()
246		.unwrap()
247		.build()
248		.unwrap()
249		.block;
250	block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap();
251
252	// A2 -> A3
253	let a3 = BlockBuilderBuilder::new(&client)
254		.on_parent_block(a2.hash())
255		.fetch_parent_block_number(&client)
256		.unwrap()
257		.build()
258		.unwrap()
259		.build()
260		.unwrap()
261		.block;
262	block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap();
263
264	// A3 -> A4
265	let a4 = BlockBuilderBuilder::new(&client)
266		.on_parent_block(a3.hash())
267		.fetch_parent_block_number(&client)
268		.unwrap()
269		.build()
270		.unwrap()
271		.build()
272		.unwrap()
273		.block;
274	block_on(client.import(BlockOrigin::Own, a4.clone())).unwrap();
275
276	// A4 -> A5
277	let a5 = BlockBuilderBuilder::new(&client)
278		.on_parent_block(a4.hash())
279		.fetch_parent_block_number(&client)
280		.unwrap()
281		.build()
282		.unwrap()
283		.build()
284		.unwrap()
285		.block;
286	block_on(client.import(BlockOrigin::Own, a5.clone())).unwrap();
287
288	// A1 -> B2
289	let mut builder = BlockBuilderBuilder::new(&client)
290		.on_parent_block(a1.hash())
291		.fetch_parent_block_number(&client)
292		.unwrap()
293		.build()
294		.unwrap();
295	// this push is required as otherwise B2 has the same hash as A2 and won't get imported
296	builder
297		.push_transfer(Transfer {
298			from: Sr25519Keyring::Alice.into(),
299			to: Sr25519Keyring::Ferdie.into(),
300			amount: 41,
301			nonce: 0,
302		})
303		.unwrap();
304	let b2 = builder.build().unwrap().block;
305	block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap();
306
307	// B2 -> B3
308	let b3 = BlockBuilderBuilder::new(&client)
309		.on_parent_block(b2.hash())
310		.fetch_parent_block_number(&client)
311		.unwrap()
312		.build()
313		.unwrap()
314		.build()
315		.unwrap()
316		.block;
317	block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap();
318
319	// B3 -> B4
320	let b4 = BlockBuilderBuilder::new(&client)
321		.on_parent_block(b3.hash())
322		.fetch_parent_block_number(&client)
323		.unwrap()
324		.build()
325		.unwrap()
326		.build()
327		.unwrap()
328		.block;
329	block_on(client.import(BlockOrigin::Own, b4)).unwrap();
330
331	// // B2 -> C3
332	let mut builder = BlockBuilderBuilder::new(&client)
333		.on_parent_block(b2.hash())
334		.fetch_parent_block_number(&client)
335		.unwrap()
336		.build()
337		.unwrap();
338	// this push is required as otherwise C3 has the same hash as B3 and won't get imported
339	builder
340		.push_transfer(Transfer {
341			from: Sr25519Keyring::Alice.into(),
342			to: Sr25519Keyring::Ferdie.into(),
343			amount: 1,
344			nonce: 1,
345		})
346		.unwrap();
347	let c3 = builder.build().unwrap().block;
348	block_on(client.import(BlockOrigin::Own, c3.clone())).unwrap();
349
350	// A1 -> D2
351	let mut builder = BlockBuilderBuilder::new(&client)
352		.on_parent_block(a1.hash())
353		.fetch_parent_block_number(&client)
354		.unwrap()
355		.build()
356		.unwrap();
357	// this push is required as otherwise D2 has the same hash as B2 and won't get imported
358	builder
359		.push_transfer(Transfer {
360			from: Sr25519Keyring::Alice.into(),
361			to: Sr25519Keyring::Ferdie.into(),
362			amount: 1,
363			nonce: 0,
364		})
365		.unwrap();
366	let d2 = builder.build().unwrap().block;
367	block_on(client.import(BlockOrigin::Own, d2.clone())).unwrap();
368
369	let genesis_hash = client.chain_info().genesis_hash;
370
371	let children1 = blockchain.children(a4.hash()).unwrap();
372	assert_eq!(vec![a5.hash()], children1);
373
374	let children2 = blockchain.children(a1.hash()).unwrap();
375	assert_eq!(vec![a2.hash(), b2.hash(), d2.hash()], children2);
376
377	let children3 = blockchain.children(genesis_hash).unwrap();
378	assert_eq!(vec![a1.hash()], children3);
379
380	let children4 = blockchain.children(b2.hash()).unwrap();
381	assert_eq!(vec![b3.hash(), c3.hash()], children4);
382}
383
384pub fn test_blockchain_query_by_number_gets_canonical<B: 'static>(backend: Arc<B>)
385where
386	B: backend::LocalBackend<substrate_test_runtime::Block>,
387{
388	// block tree:
389	// G -> A1 -> A2 -> A3 -> A4 -> A5
390	// 		A1 -> B2 -> B3 -> B4
391	// 			  B2 -> C3
392	// 		A1 -> D2
393	let client = TestClientBuilder::with_backend(backend.clone()).build();
394	let blockchain = backend.blockchain();
395	let genesis_hash = client.chain_info().genesis_hash;
396
397	// G -> A1
398	let a1 = BlockBuilderBuilder::new(&client)
399		.on_parent_block(genesis_hash)
400		.fetch_parent_block_number(&client)
401		.unwrap()
402		.build()
403		.unwrap()
404		.build()
405		.unwrap()
406		.block;
407	block_on(client.import(BlockOrigin::Own, a1.clone())).unwrap();
408
409	// A1 -> A2
410	let a2 = BlockBuilderBuilder::new(&client)
411		.on_parent_block(a1.hash())
412		.fetch_parent_block_number(&client)
413		.unwrap()
414		.build()
415		.unwrap()
416		.build()
417		.unwrap()
418		.block;
419	block_on(client.import(BlockOrigin::Own, a2.clone())).unwrap();
420
421	// A2 -> A3
422	let a3 = BlockBuilderBuilder::new(&client)
423		.on_parent_block(a2.hash())
424		.fetch_parent_block_number(&client)
425		.unwrap()
426		.build()
427		.unwrap()
428		.build()
429		.unwrap()
430		.block;
431	block_on(client.import(BlockOrigin::Own, a3.clone())).unwrap();
432
433	// A3 -> A4
434	let a4 = BlockBuilderBuilder::new(&client)
435		.on_parent_block(a3.hash())
436		.fetch_parent_block_number(&client)
437		.unwrap()
438		.build()
439		.unwrap()
440		.build()
441		.unwrap()
442		.block;
443	block_on(client.import(BlockOrigin::Own, a4.clone())).unwrap();
444
445	// A4 -> A5
446	let a5 = BlockBuilderBuilder::new(&client)
447		.on_parent_block(a4.hash())
448		.fetch_parent_block_number(&client)
449		.unwrap()
450		.build()
451		.unwrap()
452		.build()
453		.unwrap()
454		.block;
455	block_on(client.import(BlockOrigin::Own, a5.clone())).unwrap();
456
457	// A1 -> B2
458	let mut builder = BlockBuilderBuilder::new(&client)
459		.on_parent_block(a1.hash())
460		.fetch_parent_block_number(&client)
461		.unwrap()
462		.build()
463		.unwrap();
464	// this push is required as otherwise B2 has the same hash as A2 and won't get imported
465	builder
466		.push_transfer(Transfer {
467			from: Sr25519Keyring::Alice.into(),
468			to: Sr25519Keyring::Ferdie.into(),
469			amount: 41,
470			nonce: 0,
471		})
472		.unwrap();
473	let b2 = builder.build().unwrap().block;
474	block_on(client.import(BlockOrigin::Own, b2.clone())).unwrap();
475
476	// B2 -> B3
477	let b3 = BlockBuilderBuilder::new(&client)
478		.on_parent_block(b2.hash())
479		.fetch_parent_block_number(&client)
480		.unwrap()
481		.build()
482		.unwrap()
483		.build()
484		.unwrap()
485		.block;
486	block_on(client.import(BlockOrigin::Own, b3.clone())).unwrap();
487
488	// B3 -> B4
489	let b4 = BlockBuilderBuilder::new(&client)
490		.on_parent_block(b3.hash())
491		.fetch_parent_block_number(&client)
492		.unwrap()
493		.build()
494		.unwrap()
495		.build()
496		.unwrap()
497		.block;
498	block_on(client.import(BlockOrigin::Own, b4)).unwrap();
499
500	// // B2 -> C3
501	let mut builder = BlockBuilderBuilder::new(&client)
502		.on_parent_block(b2.hash())
503		.fetch_parent_block_number(&client)
504		.unwrap()
505		.build()
506		.unwrap();
507	// this push is required as otherwise C3 has the same hash as B3 and won't get imported
508	builder
509		.push_transfer(Transfer {
510			from: Sr25519Keyring::Alice.into(),
511			to: Sr25519Keyring::Ferdie.into(),
512			amount: 1,
513			nonce: 1,
514		})
515		.unwrap();
516	let c3 = builder.build().unwrap().block;
517	block_on(client.import(BlockOrigin::Own, c3)).unwrap();
518
519	// A1 -> D2
520	let mut builder = BlockBuilderBuilder::new(&client)
521		.on_parent_block(a1.hash())
522		.fetch_parent_block_number(&client)
523		.unwrap()
524		.build()
525		.unwrap();
526	// this push is required as otherwise D2 has the same hash as B2 and won't get imported
527	builder
528		.push_transfer(Transfer {
529			from: Sr25519Keyring::Alice.into(),
530			to: Sr25519Keyring::Ferdie.into(),
531			amount: 1,
532			nonce: 0,
533		})
534		.unwrap();
535	let d2 = builder.build().unwrap().block;
536	block_on(client.import(BlockOrigin::Own, d2)).unwrap();
537
538	let genesis_hash = client.chain_info().genesis_hash;
539
540	assert_eq!(blockchain.hash(0).unwrap().unwrap(), genesis_hash);
541	assert_eq!(blockchain.hash(1).unwrap().unwrap(), a1.hash());
542	assert_eq!(blockchain.hash(2).unwrap().unwrap(), a2.hash());
543	assert_eq!(blockchain.hash(3).unwrap().unwrap(), a3.hash());
544	assert_eq!(blockchain.hash(4).unwrap().unwrap(), a4.hash());
545	assert_eq!(blockchain.hash(5).unwrap().unwrap(), a5.hash());
546}