domain_eth_service/
rpc.rs

1use domain_service::rpc::FullDeps;
2use fc_mapping_sync::{EthereumBlockNotification, EthereumBlockNotificationSinks};
3use fc_rpc::{
4    Eth, EthApiServer, EthDevSigner, EthFilter, EthFilterApiServer, EthPubSub, EthPubSubApiServer,
5    EthSigner, Net, NetApiServer, Web3, Web3ApiServer,
6};
7pub use fc_rpc::{EthBlockDataCacheTask, EthConfig};
8pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool};
9use fc_storage::StorageOverride;
10use fp_rpc::{ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi};
11use jsonrpsee::RpcModule;
12use sc_client_api::backend::{Backend, StorageProvider};
13use sc_client_api::client::BlockchainEvents;
14use sc_network_sync::SyncingService;
15use sc_rpc::SubscriptionTaskExecutor;
16use sc_transaction_pool::ChainApi;
17use sc_transaction_pool_api::TransactionPool;
18use sp_api::{CallApiAt, ProvideRuntimeApi};
19use sp_block_builder::BlockBuilder as BlockBuilderApi;
20use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
21use sp_core::H256;
22use sp_inherents::CreateInherentDataProviders;
23use sp_runtime::traits::Block as BlockT;
24use std::collections::BTreeMap;
25use std::sync::Arc;
26
27pub struct DefaultEthConfig<Client, Backend>(std::marker::PhantomData<(Client, Backend)>);
28
29impl<Block, Client, BE> EthConfig<Block, Client> for DefaultEthConfig<Client, BE>
30where
31    Block: BlockT,
32    Client: StorageProvider<Block, BE> + Sync + Send + 'static,
33    BE: Backend<Block> + 'static,
34{
35    type EstimateGasAdapter = ();
36    type RuntimeStorageOverride =
37        fc_rpc::frontier_backend_client::SystemAccountId20StorageOverride<Block, Client, BE>;
38}
39
40/// Extra dependencies for Ethereum compatibility.
41pub struct EthDeps<Client, TxPool, CA: ChainApi, CT, Block: BlockT, BE, CIDP> {
42    /// Full Rpc deps
43    pub full_deps: FullDeps<Block, Client, TxPool, CA, BE, CIDP>,
44    /// Ethereum transaction converter.
45    pub converter: Option<CT>,
46    /// Whether to enable dev signer
47    pub enable_dev_signer: bool,
48    /// Chain syncing service
49    pub sync: Arc<SyncingService<Block>>,
50    /// Frontier Backend.
51    pub frontier_backend: Arc<fc_db::kv::Backend<Block, Client>>,
52    /// Ethereum data access overrides.
53    pub storage_override: Arc<dyn StorageOverride<Block>>,
54    /// Cache for Ethereum block data.
55    pub block_data_cache: Arc<EthBlockDataCacheTask<Block>>,
56    /// EthFilterApi pool.
57    pub filter_pool: Option<FilterPool>,
58    /// Maximum number of logs in a query.
59    pub max_past_logs: u32,
60    /// Fee history cache.
61    pub fee_history_cache: FeeHistoryCache,
62    /// Maximum fee history cache size.
63    pub fee_history_cache_limit: FeeHistoryCacheLimit,
64    /// Maximum allowed gas limit will be ` block.gas_limit * execute_gas_limit_multiplier` when
65    /// using eth_call/eth_estimateGas.
66    pub execute_gas_limit_multiplier: u64,
67    /// Mandated parent hashes for a given block hash.
68    pub forced_parent_hashes: Option<BTreeMap<H256, H256>>,
69    /// Pending inherent data provider
70    pub pending_inherent_data_provider: CIDP,
71}
72
73impl<Client, TxPool, CA: ChainApi, CT: Clone, Block: BlockT, BE, CIDP: Clone> Clone
74    for EthDeps<Client, TxPool, CA, CT, Block, BE, CIDP>
75{
76    fn clone(&self) -> Self {
77        Self {
78            full_deps: self.full_deps.clone(),
79            converter: self.converter.clone(),
80            enable_dev_signer: self.enable_dev_signer,
81            sync: self.sync.clone(),
82            frontier_backend: self.frontier_backend.clone(),
83            storage_override: self.storage_override.clone(),
84            block_data_cache: self.block_data_cache.clone(),
85            filter_pool: self.filter_pool.clone(),
86            max_past_logs: self.max_past_logs,
87            fee_history_cache: self.fee_history_cache.clone(),
88            fee_history_cache_limit: self.fee_history_cache_limit,
89            execute_gas_limit_multiplier: self.execute_gas_limit_multiplier,
90            forced_parent_hashes: self.forced_parent_hashes.clone(),
91            pending_inherent_data_provider: self.pending_inherent_data_provider.clone(),
92        }
93    }
94}
95
96/// Instantiate Ethereum-compatible RPC extensions.
97pub(crate) fn create_eth_rpc<Client, BE, TxPool, CA, CT, Block, EC, CIDP>(
98    mut io: RpcModule<()>,
99    deps: EthDeps<Client, TxPool, CA, CT, Block, BE, CIDP>,
100    subscription_task_executor: SubscriptionTaskExecutor,
101    pubsub_notification_sinks: Arc<
102        EthereumBlockNotificationSinks<EthereumBlockNotification<Block>>,
103    >,
104) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
105where
106    Block: BlockT<Hash = H256>,
107    Client: CallApiAt<Block> + ProvideRuntimeApi<Block>,
108    Client::Api:
109        BlockBuilderApi<Block> + EthereumRuntimeRPCApi<Block> + ConvertTransactionRuntimeApi<Block>,
110    Client: BlockchainEvents<Block> + 'static,
111    Client: HeaderBackend<Block>
112        + HeaderMetadata<Block, Error = BlockChainError>
113        + StorageProvider<Block, BE>,
114    BE: Backend<Block> + 'static,
115    TxPool: TransactionPool<Block = Block> + 'static,
116    CA: ChainApi<Block = Block> + 'static,
117    CT: ConvertTransaction<Block::Extrinsic> + Send + Sync + 'static,
118    EC: EthConfig<Block, Client>,
119    CIDP: CreateInherentDataProviders<Block, ()> + Send + 'static,
120{
121    let EthDeps {
122        full_deps,
123        converter,
124        enable_dev_signer,
125        sync: _,
126        frontier_backend,
127        storage_override,
128        block_data_cache,
129        filter_pool,
130        max_past_logs,
131        fee_history_cache,
132        fee_history_cache_limit,
133        execute_gas_limit_multiplier,
134        forced_parent_hashes,
135        pending_inherent_data_provider,
136    } = deps;
137
138    let FullDeps {
139        client,
140        pool,
141        graph,
142        network,
143        sync,
144        is_authority,
145        ..
146    } = full_deps;
147
148    let mut signers = Vec::<Box<dyn EthSigner>>::new();
149    if enable_dev_signer {
150        signers.push(Box::new(EthDevSigner::new()));
151    }
152
153    io.merge(
154        Eth::<Block, Client, TxPool, CT, BE, CA, CIDP, EC>::new(
155            client.clone(),
156            pool.clone(),
157            graph.clone(),
158            converter,
159            sync.clone(),
160            signers,
161            storage_override.clone(),
162            frontier_backend.clone(),
163            is_authority,
164            block_data_cache.clone(),
165            fee_history_cache,
166            fee_history_cache_limit,
167            execute_gas_limit_multiplier,
168            forced_parent_hashes,
169            pending_inherent_data_provider,
170            None,
171        )
172        .replace_config::<EC>()
173        .into_rpc(),
174    )?;
175
176    if let Some(filter_pool) = filter_pool {
177        io.merge(
178            EthFilter::new(
179                client.clone(),
180                frontier_backend,
181                graph.clone(),
182                filter_pool,
183                500_usize, // max stored filters
184                max_past_logs,
185                block_data_cache,
186            )
187            .into_rpc(),
188        )?;
189    }
190
191    io.merge(
192        EthPubSub::new(
193            pool,
194            client.clone(),
195            sync,
196            subscription_task_executor,
197            storage_override,
198            pubsub_notification_sinks,
199        )
200        .into_rpc(),
201    )?;
202
203    io.merge(
204        Net::new(
205            client.clone(),
206            network,
207            // Whether to format the `peer_count` response as Hex (default) or not.
208            true,
209        )
210        .into_rpc(),
211    )?;
212
213    io.merge(Web3::new(client).into_rpc())?;
214
215    Ok(io)
216}