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