referrerpolicy=no-referrer-when-downgrade

substrate_test_client/
client_ext.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//! Client extension for tests.
19
20use sc_client_api::{backend::Finalizer, client::BlockBackend};
21use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy};
22use sc_service::client::Client;
23use sp_consensus::Error as ConsensusError;
24use sp_runtime::{traits::Block as BlockT, Justification, Justifications};
25
26pub use sp_consensus::BlockOrigin;
27
28/// Extension trait for a test client.
29pub trait ClientExt<Block: BlockT>: Sized {
30	/// Finalize a block.
31	fn finalize_block(
32		&self,
33		hash: Block::Hash,
34		justification: Option<Justification>,
35	) -> sp_blockchain::Result<()>;
36
37	/// Returns hash of the genesis block.
38	fn genesis_hash(&self) -> <Block as BlockT>::Hash;
39}
40
41/// Extension trait for a test client around block importing.
42#[async_trait::async_trait]
43pub trait ClientBlockImportExt<Block: BlockT>: Sized {
44	/// Import block to the chain. No finality.
45	async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>;
46
47	/// Import a block and make it our best block if possible.
48	async fn import_as_best(&self, origin: BlockOrigin, block: Block)
49		-> Result<(), ConsensusError>;
50
51	/// Import a block and finalize it.
52	async fn import_as_final(
53		&self,
54		origin: BlockOrigin,
55		block: Block,
56	) -> Result<(), ConsensusError>;
57
58	/// Import block with justification(s), finalizes block.
59	async fn import_justified(
60		&self,
61		origin: BlockOrigin,
62		block: Block,
63		justifications: Justifications,
64	) -> Result<(), ConsensusError>;
65}
66
67impl<B, E, RA, Block> ClientExt<Block> for Client<B, E, Block, RA>
68where
69	B: sc_client_api::backend::Backend<Block>,
70	E: sc_client_api::CallExecutor<Block> + sc_executor::RuntimeVersionOf + 'static,
71	Self: BlockImport<Block, Error = ConsensusError>,
72	Block: BlockT,
73{
74	fn finalize_block(
75		&self,
76		hash: Block::Hash,
77		justification: Option<Justification>,
78	) -> sp_blockchain::Result<()> {
79		Finalizer::finalize_block(self, hash, justification, true)
80	}
81
82	fn genesis_hash(&self) -> <Block as BlockT>::Hash {
83		self.block_hash(0u32.into()).unwrap().unwrap()
84	}
85}
86
87/// This implementation is required, because of the weird api requirements around `BlockImport`.
88#[async_trait::async_trait]
89impl<Block: BlockT, T> ClientBlockImportExt<Block> for std::sync::Arc<T>
90where
91	for<'r> &'r T: BlockImport<Block, Error = ConsensusError>,
92	T: Send + Sync,
93{
94	async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> {
95		let (header, extrinsics) = block.deconstruct();
96		let mut import = BlockImportParams::new(origin, header);
97		import.body = Some(extrinsics);
98		import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
99
100		BlockImport::import_block(self, import).await.map(|_| ())
101	}
102
103	async fn import_as_best(
104		&self,
105		origin: BlockOrigin,
106		block: Block,
107	) -> Result<(), ConsensusError> {
108		let (header, extrinsics) = block.deconstruct();
109		let mut import = BlockImportParams::new(origin, header);
110		import.body = Some(extrinsics);
111		import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
112
113		BlockImport::import_block(self, import).await.map(|_| ())
114	}
115
116	async fn import_as_final(
117		&self,
118		origin: BlockOrigin,
119		block: Block,
120	) -> Result<(), ConsensusError> {
121		let (header, extrinsics) = block.deconstruct();
122		let mut import = BlockImportParams::new(origin, header);
123		import.body = Some(extrinsics);
124		import.finalized = true;
125		import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
126
127		BlockImport::import_block(self, import).await.map(|_| ())
128	}
129
130	async fn import_justified(
131		&self,
132		origin: BlockOrigin,
133		block: Block,
134		justifications: Justifications,
135	) -> Result<(), ConsensusError> {
136		let (header, extrinsics) = block.deconstruct();
137		let mut import = BlockImportParams::new(origin, header);
138		import.justifications = Some(justifications);
139		import.body = Some(extrinsics);
140		import.finalized = true;
141		import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
142
143		BlockImport::import_block(self, import).await.map(|_| ())
144	}
145}
146
147#[async_trait::async_trait]
148impl<B, E, RA, Block: BlockT> ClientBlockImportExt<Block> for Client<B, E, Block, RA>
149where
150	Self: BlockImport<Block, Error = ConsensusError>,
151	RA: Send + Sync,
152	B: Send + Sync,
153	E: Send + Sync,
154{
155	async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> {
156		let (header, extrinsics) = block.deconstruct();
157		let mut import = BlockImportParams::new(origin, header);
158		import.body = Some(extrinsics);
159		import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
160
161		BlockImport::import_block(self, import).await.map(|_| ())
162	}
163
164	async fn import_as_best(
165		&self,
166		origin: BlockOrigin,
167		block: Block,
168	) -> Result<(), ConsensusError> {
169		let (header, extrinsics) = block.deconstruct();
170		let mut import = BlockImportParams::new(origin, header);
171		import.body = Some(extrinsics);
172		import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
173
174		BlockImport::import_block(self, import).await.map(|_| ())
175	}
176
177	async fn import_as_final(
178		&self,
179		origin: BlockOrigin,
180		block: Block,
181	) -> Result<(), ConsensusError> {
182		let (header, extrinsics) = block.deconstruct();
183		let mut import = BlockImportParams::new(origin, header);
184		import.body = Some(extrinsics);
185		import.finalized = true;
186		import.fork_choice = Some(ForkChoiceStrategy::Custom(true));
187
188		BlockImport::import_block(self, import).await.map(|_| ())
189	}
190
191	async fn import_justified(
192		&self,
193		origin: BlockOrigin,
194		block: Block,
195		justifications: Justifications,
196	) -> Result<(), ConsensusError> {
197		let (header, extrinsics) = block.deconstruct();
198		let mut import = BlockImportParams::new(origin, header);
199		import.justifications = Some(justifications);
200		import.body = Some(extrinsics);
201		import.finalized = true;
202		import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
203
204		BlockImport::import_block(self, import).await.map(|_| ())
205	}
206}