1use fc_rpc::{
22 Eth, EthApiServer, EthBlockDataCacheTask, EthFilter, EthFilterApiServer, EthPubSub,
23 EthPubSubApiServer, LogsJournal, Net, NetApiServer, TxPool, TxPoolApiServer, Web3,
24 Web3ApiServer,
25};
26use fc_rpc_core::types::{FeeHistoryCache, FilterPool};
27use fc_storage::{StorageOverride, StorageOverrideHandler};
28use jsonrpsee::RpcModule;
29use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
30use std::path::Path;
31
32use cumulus_primitives_core::{ParaId, RelayParentOffsetApi};
33use sc_client_api::{
34 AuxStore, Backend, BlockchainEvents, StateBackend, StorageProvider, UsageProvider,
35};
36use sc_consensus_manual_seal::rpc::ManualSealApiServer;
37use sc_network::service::traits::NetworkService;
38use sc_network_sync::SyncingService;
39use sc_rpc::dev::DevApiServer;
40pub use sc_rpc::SubscriptionTaskExecutor;
41use sc_transaction_pool_api::TransactionPool;
42use sp_api::{CallApiAt, ProvideRuntimeApi};
43use sp_block_builder::BlockBuilder;
44use sp_blockchain::{
45 Backend as BlockchainBackend, Error as BlockChainError, HeaderBackend, HeaderMetadata,
46};
47use sp_consensus_aura::{sr25519::AuthorityId as AuraId, AuraApi};
48use sp_inherents::CreateInherentDataProviders;
49use sp_runtime::traits::{BlakeTwo256, Block as BlockT};
50use std::sync::Arc;
51use substrate_frame_rpc_system::{System, SystemApiServer};
52
53use moonbeam_rpc_debug::{Debug, DebugServer};
54use moonbeam_rpc_trace::{Trace, TraceServer};
55
56use crate::evm_tracing_types::{FrontierBackendConfig, FrontierConfig};
57use astar_primitives::*;
58
59pub mod tracing;
60
61type HashFor<Block> = <Block as BlockT>::Hash;
62
63#[derive(Clone)]
64pub struct EvmTracingConfig {
65 pub tracing_requesters: tracing::RpcRequesters,
66 pub trace_filter_max_count: u32,
67 pub trace_filter_max_block_range: u32,
68 pub enable_txpool: bool,
69}
70
71#[derive(Debug, Copy, Clone, Default, clap::ValueEnum)]
73pub enum FrontierBackendType {
74 #[default]
76 KeyValue,
77 Sql,
79}
80
81pub fn open_frontier_backend<C, BE>(
84 client: Arc<C>,
85 config: &sc_service::Configuration,
86 rpc_config: &FrontierConfig,
87) -> Result<fc_db::Backend<Block, C>, String>
88where
89 C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,
90 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,
91 C: Send + Sync + 'static,
92 C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
93 BE: Backend<Block> + 'static,
94 BE::State: StateBackend<BlakeTwo256>,
95{
96 let config_dir = config.base_path.config_dir(config.chain_spec.id());
97 let path = config_dir.join("frontier").join("db");
98
99 let frontier_backend = match rpc_config.frontier_backend_config {
100 FrontierBackendConfig::KeyValue => {
101 fc_db::Backend::KeyValue(Arc::new(fc_db::kv::Backend::<Block, C>::new(
102 client,
103 &fc_db::kv::DatabaseSettings {
104 source: fc_db::DatabaseSource::RocksDb {
105 path,
106 cache_size: 0,
107 },
108 },
109 )?))
110 }
111 FrontierBackendConfig::Sql {
112 pool_size,
113 num_ops_timeout,
114 thread_count,
115 cache_size,
116 } => {
117 let overrides = Arc::new(StorageOverrideHandler::new(client.clone()));
118 std::fs::create_dir_all(&path).expect("failed creating sql db directory");
119 let backend = futures::executor::block_on(fc_db::sql::Backend::new(
120 fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig {
121 path: Path::new("sqlite:///")
122 .join(path)
123 .join("frontier.db3")
124 .to_str()
125 .expect("frontier sql path error"),
126 create_if_missing: true,
127 thread_count: thread_count,
128 cache_size: cache_size,
129 }),
130 pool_size,
131 std::num::NonZeroU32::new(num_ops_timeout),
132 overrides.clone(),
133 ))
134 .unwrap_or_else(|err| panic!("failed creating sql backend: {:?}", err));
135 fc_db::Backend::Sql(Arc::new(backend))
136 }
137 };
138
139 Ok(frontier_backend)
140}
141
142pub struct AstarEthConfig<C, BE>(std::marker::PhantomData<(C, BE)>);
143
144impl<C, BE> fc_rpc::EthConfig<Block, C> for AstarEthConfig<C, BE>
145where
146 C: sc_client_api::StorageProvider<Block, BE> + Sync + Send + 'static,
147 BE: Backend<Block> + 'static,
148{
149 type EstimateGasAdapter = ();
152 type RuntimeStorageOverride =
154 fc_rpc::frontier_backend_client::SystemAccountId32StorageOverride<Block, C, BE>;
155}
156
157pub struct FullDeps<C, P> {
159 pub client: Arc<C>,
161 pub pool: Arc<P>,
163 pub graph: Arc<P>,
165 pub network: Arc<dyn NetworkService>,
167 pub sync: Arc<SyncingService<Block>>,
169 pub is_authority: bool,
171 pub frontier_backend: Arc<dyn fc_api::Backend<Block>>,
173 pub filter_pool: FilterPool,
175 pub fee_history_limit: u64,
177 pub fee_history_cache: FeeHistoryCache,
179 pub storage_override: Arc<dyn StorageOverride<Block>>,
181 pub block_data_cache: Arc<EthBlockDataCacheTask<Block>>,
183 pub enable_evm_rpc: bool,
185 pub command_sink:
187 Option<futures::channel::mpsc::Sender<sc_consensus_manual_seal::EngineCommand<Hash>>>,
188}
189
190pub fn create_full<C, P, BE>(
192 deps: FullDeps<C, P>,
193 subscription_task_executor: SubscriptionTaskExecutor,
194 pubsub_notification_sinks: Arc<
195 fc_mapping_sync::EthereumBlockNotificationSinks<
196 fc_mapping_sync::EthereumBlockNotification<Block>,
197 >,
198 >,
199 tracing_config: EvmTracingConfig,
200) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
201where
202 C: ProvideRuntimeApi<Block>
203 + HeaderBackend<Block>
204 + UsageProvider<Block>
205 + CallApiAt<Block>
206 + AuxStore
207 + StorageProvider<Block, BE>
208 + HeaderMetadata<Block, Error = BlockChainError>
209 + BlockchainEvents<Block>
210 + Send
211 + Sync
212 + 'static,
213 C: sc_client_api::BlockBackend<Block>,
214 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
215 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
216 + fp_rpc::ConvertTransactionRuntimeApi<Block>
217 + fp_rpc::EthereumRuntimeRPCApi<Block>
218 + BlockBuilder<Block>
219 + AuraApi<Block, AuraId>
220 + moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block>
221 + moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block>
222 + RelayParentOffsetApi<Block>,
223 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
224 BE: Backend<Block> + 'static,
225 BE::State: StateBackend<BlakeTwo256>,
226 BE::Blockchain: BlockchainBackend<Block>,
227{
228 let client = Arc::clone(&deps.client);
229 let graph = Arc::clone(&deps.graph);
230
231 let mut io = create_full_rpc(deps, subscription_task_executor, pubsub_notification_sinks)?;
232
233 if tracing_config.enable_txpool {
234 io.merge(TxPool::new(Arc::clone(&client), graph).into_rpc())?;
235 }
236
237 if let Some(trace_filter_requester) = tracing_config.tracing_requesters.trace {
238 io.merge(
239 Trace::new(
240 client,
241 trace_filter_requester,
242 tracing_config.trace_filter_max_count,
243 tracing_config.trace_filter_max_block_range,
244 )
245 .into_rpc(),
246 )?;
247 }
248
249 if let Some(debug_requester) = tracing_config.tracing_requesters.debug {
250 io.merge(Debug::new(debug_requester).into_rpc())?;
251 }
252
253 Ok(io)
254}
255
256pub fn create_full_local_dev<C, P, BE>(
261 deps: FullDeps<C, P>,
262 subscription_task_executor: SubscriptionTaskExecutor,
263 pubsub_notification_sinks: Arc<
264 fc_mapping_sync::EthereumBlockNotificationSinks<
265 fc_mapping_sync::EthereumBlockNotification<Block>,
266 >,
267 >,
268 local_para_id: ParaId,
269 tracing_config: EvmTracingConfig,
270) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
271where
272 C: ProvideRuntimeApi<Block>
273 + HeaderBackend<Block>
274 + UsageProvider<Block>
275 + CallApiAt<Block>
276 + AuxStore
277 + StorageProvider<Block, BE>
278 + HeaderMetadata<Block, Error = BlockChainError>
279 + BlockchainEvents<Block>
280 + Send
281 + Sync
282 + 'static,
283 C: sc_client_api::BlockBackend<Block>,
284 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
285 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
286 + fp_rpc::ConvertTransactionRuntimeApi<Block>
287 + fp_rpc::EthereumRuntimeRPCApi<Block>
288 + BlockBuilder<Block>
289 + AuraApi<Block, AuraId>
290 + moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block>
291 + moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block>
292 + RelayParentOffsetApi<Block>,
293 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
294 BE: Backend<Block> + 'static,
295 BE::State: StateBackend<BlakeTwo256>,
296 BE::Blockchain: BlockchainBackend<Block>,
297{
298 let client = Arc::clone(&deps.client);
299 let graph = Arc::clone(&deps.graph);
300
301 let mut io = create_full_rpc_local_dev(
302 deps,
303 subscription_task_executor,
304 pubsub_notification_sinks,
305 local_para_id,
306 )?;
307
308 if tracing_config.enable_txpool {
309 io.merge(TxPool::new(Arc::clone(&client), graph).into_rpc())?;
310 }
311
312 if let Some(trace_filter_requester) = tracing_config.tracing_requesters.trace {
313 io.merge(
314 Trace::new(
315 client,
316 trace_filter_requester,
317 tracing_config.trace_filter_max_count,
318 tracing_config.trace_filter_max_block_range,
319 )
320 .into_rpc(),
321 )?;
322 }
323
324 if let Some(debug_requester) = tracing_config.tracing_requesters.debug {
325 io.merge(Debug::new(debug_requester).into_rpc())?;
326 }
327
328 Ok(io)
329}
330
331fn create_full_rpc_local_dev<C, P, BE>(
332 deps: FullDeps<C, P>,
333 subscription_task_executor: SubscriptionTaskExecutor,
334 pubsub_notification_sinks: Arc<
335 fc_mapping_sync::EthereumBlockNotificationSinks<
336 fc_mapping_sync::EthereumBlockNotification<Block>,
337 >,
338 >,
339 local_para_id: ParaId,
340) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
341where
342 C: ProvideRuntimeApi<Block>
343 + UsageProvider<Block>
344 + HeaderBackend<Block>
345 + CallApiAt<Block>
346 + AuxStore
347 + StorageProvider<Block, BE>
348 + HeaderMetadata<Block, Error = BlockChainError>
349 + BlockchainEvents<Block>
350 + Send
351 + Sync
352 + 'static,
353 C: sc_client_api::BlockBackend<Block>,
354 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
355 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
356 + fp_rpc::ConvertTransactionRuntimeApi<Block>
357 + fp_rpc::EthereumRuntimeRPCApi<Block>
358 + BlockBuilder<Block>
359 + AuraApi<Block, AuraId>
360 + RelayParentOffsetApi<Block>,
361 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
362 BE: Backend<Block> + 'static,
363 BE::State: StateBackend<BlakeTwo256>,
364 BE::Blockchain: BlockchainBackend<Block>,
365{
366 create_full_rpc_with_pending_provider(
367 deps,
368 subscription_task_executor,
369 pubsub_notification_sinks,
370 |client| crate::local::LocalPendingInherentDataProvider::new(client, local_para_id),
371 )
372}
373
374fn create_full_rpc<C, P, BE>(
375 deps: FullDeps<C, P>,
376 subscription_task_executor: SubscriptionTaskExecutor,
377 pubsub_notification_sinks: Arc<
378 fc_mapping_sync::EthereumBlockNotificationSinks<
379 fc_mapping_sync::EthereumBlockNotification<Block>,
380 >,
381 >,
382) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
383where
384 C: ProvideRuntimeApi<Block>
385 + UsageProvider<Block>
386 + HeaderBackend<Block>
387 + CallApiAt<Block>
388 + AuxStore
389 + StorageProvider<Block, BE>
390 + HeaderMetadata<Block, Error = BlockChainError>
391 + BlockchainEvents<Block>
392 + Send
393 + Sync
394 + 'static,
395 C: sc_client_api::BlockBackend<Block>,
396 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
397 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
398 + fp_rpc::ConvertTransactionRuntimeApi<Block>
399 + fp_rpc::EthereumRuntimeRPCApi<Block>
400 + BlockBuilder<Block>
401 + AuraApi<Block, AuraId>
402 + RelayParentOffsetApi<Block>,
403 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
404 BE: Backend<Block> + 'static,
405 BE::State: StateBackend<BlakeTwo256>,
406 BE::Blockchain: BlockchainBackend<Block>,
407{
408 create_full_rpc_with_pending_provider(
409 deps,
410 subscription_task_executor,
411 pubsub_notification_sinks,
412 crate::parachain::PendingCrateInherentDataProvider::new,
413 )
414}
415
416fn create_full_rpc_with_pending_provider<C, P, BE, CIDP, F>(
417 deps: FullDeps<C, P>,
418 subscription_task_executor: SubscriptionTaskExecutor,
419 pubsub_notification_sinks: Arc<
420 fc_mapping_sync::EthereumBlockNotificationSinks<
421 fc_mapping_sync::EthereumBlockNotification<Block>,
422 >,
423 >,
424 make_pending_inherent_data_provider: F,
425) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
426where
427 C: ProvideRuntimeApi<Block>
428 + UsageProvider<Block>
429 + HeaderBackend<Block>
430 + CallApiAt<Block>
431 + AuxStore
432 + StorageProvider<Block, BE>
433 + HeaderMetadata<Block, Error = BlockChainError>
434 + BlockchainEvents<Block>
435 + Send
436 + Sync
437 + 'static,
438 C: sc_client_api::BlockBackend<Block>,
439 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
440 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
441 + fp_rpc::ConvertTransactionRuntimeApi<Block>
442 + fp_rpc::EthereumRuntimeRPCApi<Block>
443 + BlockBuilder<Block>
444 + AuraApi<Block, AuraId>
445 + RelayParentOffsetApi<Block>,
446 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
447 BE: Backend<Block> + 'static,
448 BE::State: StateBackend<BlakeTwo256>,
449 BE::Blockchain: BlockchainBackend<Block>,
450 CIDP: CreateInherentDataProviders<Block, ()> + Send + Sync + 'static,
451 F: FnOnce(Arc<C>) -> CIDP,
452{
453 let mut io = RpcModule::new(());
454 let FullDeps {
455 client,
456 pool,
457 graph,
458 network,
459 sync,
460 is_authority,
461 frontier_backend,
462 filter_pool,
463 fee_history_limit,
464 fee_history_cache,
465 storage_override,
466 block_data_cache,
467 enable_evm_rpc,
468 command_sink,
469 } = deps;
470
471 io.merge(System::new(client.clone(), pool.clone()).into_rpc())?;
472 io.merge(TransactionPayment::new(client.clone()).into_rpc())?;
473 io.merge(sc_rpc::dev::Dev::new(client.clone()).into_rpc())?;
474
475 if let Some(command_sink) = command_sink {
476 io.merge(sc_consensus_manual_seal::rpc::ManualSeal::new(command_sink).into_rpc())?;
477 }
478
479 if !enable_evm_rpc {
480 return Ok(io);
481 }
482
483 let no_tx_converter: Option<fp_rpc::NoTransactionConverter> = None;
484
485 io.merge(
486 Eth::<_, _, _, _, _, _, ()>::new(
487 client.clone(),
488 pool.clone(),
489 no_tx_converter,
490 sync.clone(),
491 Default::default(),
492 storage_override.clone(),
493 frontier_backend.clone(),
494 is_authority,
495 block_data_cache.clone(),
496 fee_history_cache,
497 fee_history_limit,
498 10,
500 false, None,
502 make_pending_inherent_data_provider(client.clone()),
503 Some(Box::new(
504 crate::parachain::AuraConsensusDataProviderFallback::new(client.clone()),
505 )),
506 )
507 .replace_config::<AstarEthConfig<C, BE>>()
508 .into_rpc(),
509 )?;
510
511 let max_past_logs: u32 = 10_000;
512 let max_block_range: u32 = 1024;
513 let max_stored_filters: usize = 500;
514
515 let logs_journal = Arc::new(LogsJournal::new::<Block>(
516 subscription_task_executor.clone(),
517 storage_override.clone(),
518 pubsub_notification_sinks.clone(),
519 ));
520
521 io.merge(
522 EthFilter::new(
523 client.clone(),
524 frontier_backend,
525 graph.clone(),
526 filter_pool,
527 max_stored_filters,
528 max_past_logs,
529 max_block_range,
530 block_data_cache,
531 logs_journal.clone(),
532 )
533 .into_rpc(),
534 )?;
535
536 io.merge(Net::new(client.clone(), network.clone(), true).into_rpc())?;
537
538 io.merge(Web3::new(client.clone()).into_rpc())?;
539
540 io.merge(
541 EthPubSub::new(
542 pool,
543 client.clone(),
544 sync,
545 subscription_task_executor,
546 storage_override,
547 pubsub_notification_sinks,
548 logs_journal,
549 )
550 .into_rpc(),
551 )?;
552
553 Ok(io)
554}