1#![warn(unused_crate_dependencies)]
20
21use std::{marker::PhantomData, sync::Arc};
22
23use sc_consensus::{BlockCheckParams, BlockImport, BlockImportParams, ImportResult};
25use sp_api::ProvideRuntimeApi;
26use sp_block_builder::BlockBuilder as BlockBuilderApi;
27use sp_consensus::Error as ConsensusError;
28use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
29use fp_consensus::{ensure_log, FindLogError};
31use fp_rpc::EthereumRuntimeRPCApi;
32
33#[derive(Debug, thiserror::Error)]
34pub enum Error {
35 #[error("Multiple runtime Ethereum blocks, rejecting!")]
36 MultipleRuntimeLogs,
37 #[error("Runtime Ethereum block not found, rejecting!")]
38 NoRuntimeLog,
39 #[error("Cannot access the runtime at genesis, rejecting!")]
40 RuntimeApiCallFailed,
41}
42
43impl From<Error> for String {
44 fn from(error: Error) -> String {
45 error.to_string()
46 }
47}
48
49impl From<FindLogError> for Error {
50 fn from(error: FindLogError) -> Error {
51 match error {
52 FindLogError::NotFound => Error::NoRuntimeLog,
53 FindLogError::MultipleLogs => Error::MultipleRuntimeLogs,
54 }
55 }
56}
57
58impl From<Error> for ConsensusError {
59 fn from(error: Error) -> ConsensusError {
60 ConsensusError::ClientImport(error.to_string())
61 }
62}
63
64pub struct FrontierBlockImport<B: BlockT, I, C> {
65 inner: I,
66 client: Arc<C>,
67 _marker: PhantomData<B>,
68}
69
70impl<Block: BlockT, I: Clone + BlockImport<Block>, C> Clone for FrontierBlockImport<Block, I, C> {
71 fn clone(&self) -> Self {
72 FrontierBlockImport {
73 inner: self.inner.clone(),
74 client: self.client.clone(),
75 _marker: PhantomData,
76 }
77 }
78}
79
80impl<B, I, C> FrontierBlockImport<B, I, C>
81where
82 B: BlockT,
83 I: BlockImport<B>,
84 I::Error: Into<ConsensusError>,
85 C: ProvideRuntimeApi<B>,
86 C::Api: BlockBuilderApi<B> + EthereumRuntimeRPCApi<B>,
87{
88 pub fn new(inner: I, client: Arc<C>) -> Self {
89 Self {
90 inner,
91 client,
92 _marker: PhantomData,
93 }
94 }
95}
96
97#[async_trait::async_trait]
98impl<B, I, C> BlockImport<B> for FrontierBlockImport<B, I, C>
99where
100 B: BlockT,
101 I: BlockImport<B> + Send + Sync,
102 I::Error: Into<ConsensusError>,
103 C: ProvideRuntimeApi<B> + Send + Sync,
104 C::Api: BlockBuilderApi<B> + EthereumRuntimeRPCApi<B>,
105{
106 type Error = ConsensusError;
107
108 async fn check_block(&self, block: BlockCheckParams<B>) -> Result<ImportResult, Self::Error> {
109 self.inner.check_block(block).await.map_err(Into::into)
110 }
111
112 async fn import_block(&self, block: BlockImportParams<B>) -> Result<ImportResult, Self::Error> {
113 ensure_log(block.header.digest()).map_err(Error::from)?;
117
118 self.inner.import_block(block).await.map_err(Into::into)
119 }
120}