1use 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
28pub trait ClientExt<Block: BlockT>: Sized {
30 fn finalize_block(
32 &self,
33 hash: Block::Hash,
34 justification: Option<Justification>,
35 ) -> sp_blockchain::Result<()>;
36
37 fn genesis_hash(&self) -> <Block as BlockT>::Hash;
39}
40
41#[async_trait::async_trait]
43pub trait ClientBlockImportExt<Block: BlockT>: Sized {
44 async fn import(&self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>;
46
47 async fn import_as_best(&self, origin: BlockOrigin, block: Block)
49 -> Result<(), ConsensusError>;
50
51 async fn import_as_final(
53 &self,
54 origin: BlockOrigin,
55 block: Block,
56 ) -> Result<(), ConsensusError>;
57
58 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#[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}