astar_collator/rpc/
tracing.rs

1// This file is part of Astar.
2
3// Copyright (C) Stake Technologies Pte.Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6// Astar is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// Astar is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with Astar. If not, see <http://www.gnu.org/licenses/>.
18
19///! EVM tracing RPC support.
20use crate::evm_tracing_types::{EthApi as EthApiCmd, FrontierConfig};
21
22use fc_storage::StorageOverride;
23use fp_rpc::EthereumRuntimeRPCApi;
24use moonbeam_rpc_debug::{DebugHandler, DebugRequester};
25use moonbeam_rpc_trace::{CacheRequester as TraceFilterCacheRequester, CacheTask};
26use sc_client_api::{
27    Backend, BlockOf, BlockchainEvents, HeaderBackend, StateBackend, StorageProvider,
28};
29use sc_service::TaskManager;
30use sp_api::ProvideRuntimeApi;
31use sp_block_builder::BlockBuilder;
32use sp_blockchain::{Error as BlockChainError, HeaderMetadata};
33use sp_core::H256;
34use sp_runtime::traits::{BlakeTwo256, Block as BlockT, Header as HeaderT};
35use std::sync::Arc;
36use substrate_prometheus_endpoint::Registry as PrometheusRegistry;
37use tokio::sync::Semaphore;
38
39#[derive(Clone)]
40pub struct RpcRequesters {
41    pub debug: Option<DebugRequester>,
42    pub trace: Option<TraceFilterCacheRequester>,
43}
44
45pub struct SpawnTasksParams<'a, B: BlockT, C, BE> {
46    pub task_manager: &'a TaskManager,
47    pub client: Arc<C>,
48    pub substrate_backend: Arc<BE>,
49    pub frontier_backend: Arc<fc_db::Backend<B, C>>,
50    pub storage_override: Arc<dyn StorageOverride<B>>,
51}
52
53/// Spawn the tasks that are required to run a EVM tracing.
54pub fn spawn_tracing_tasks<B, C, BE>(
55    rpc_config: &FrontierConfig,
56    prometheus: Option<PrometheusRegistry>,
57    params: SpawnTasksParams<B, C, BE>,
58) -> RpcRequesters
59where
60    C: ProvideRuntimeApi<B> + BlockOf,
61    C: StorageProvider<B, BE>,
62    C: HeaderBackend<B> + HeaderMetadata<B, Error = BlockChainError> + 'static,
63    C: BlockchainEvents<B>,
64    C: Send + Sync + 'static,
65    C::Api: EthereumRuntimeRPCApi<B> + moonbeam_rpc_primitives_debug::DebugRuntimeApi<B>,
66    C::Api: BlockBuilder<B>,
67    B: BlockT<Hash = H256> + Send + Sync + 'static,
68    B::Header: HeaderT<Number = u32>,
69    BE: Backend<B> + 'static,
70    BE::State: StateBackend<BlakeTwo256>,
71{
72    let permit_pool = Arc::new(Semaphore::new(rpc_config.ethapi_max_permits as usize));
73
74    let (trace_filter_task, trace_filter_requester) =
75        if rpc_config.ethapi.contains(&EthApiCmd::Trace) {
76            let (trace_filter_task, trace_filter_requester) = CacheTask::create(
77                Arc::clone(&params.client),
78                Arc::clone(&params.substrate_backend),
79                core::time::Duration::from_secs(rpc_config.ethapi_trace_cache_duration),
80                Arc::clone(&permit_pool),
81                Arc::clone(&params.storage_override),
82                prometheus,
83            );
84            (Some(trace_filter_task), Some(trace_filter_requester))
85        } else {
86            (None, None)
87        };
88
89    let (debug_task, debug_requester) = if rpc_config.ethapi.contains(&EthApiCmd::Debug) {
90        let (debug_task, debug_requester) = DebugHandler::task(
91            Arc::clone(&params.client),
92            Arc::clone(&params.substrate_backend),
93            match *params.frontier_backend {
94                fc_db::Backend::KeyValue(ref b) => b.clone(),
95                fc_db::Backend::Sql(ref b) => b.clone(),
96            },
97            Arc::clone(&permit_pool),
98            Arc::clone(&params.storage_override),
99            rpc_config.tracing_raw_max_memory_usage,
100        );
101        (Some(debug_task), Some(debug_requester))
102    } else {
103        (None, None)
104    };
105
106    // `trace_filter` cache task. Essential.
107    // Proxies rpc requests to it's handler.
108    if let Some(trace_filter_task) = trace_filter_task {
109        params.task_manager.spawn_essential_handle().spawn(
110            "trace-filter-cache",
111            Some("eth-tracing"),
112            trace_filter_task,
113        );
114    }
115
116    // `debug` task if enabled. Essential.
117    // Proxies rpc requests to it's handler.
118    if let Some(debug_task) = debug_task {
119        params.task_manager.spawn_essential_handle().spawn(
120            "ethapi-debug",
121            Some("eth-tracing"),
122            debug_task,
123        );
124    }
125
126    RpcRequesters {
127        debug: debug_requester,
128        trace: trace_filter_requester,
129    }
130}