v3 into main (#390)

This commit is contained in:
Amar Singh
2024-12-25 00:20:08 -05:00
committed by GitHub
parent 8cb7cda000
commit 9158633607
36 changed files with 3296 additions and 1222 deletions
+79 -4
View File
@@ -1,16 +1,19 @@
use std::collections::BTreeMap;
use cumulus_primitives_core::ParaId;
use evm_runtime_template::{
AccountId, AuraId, OpenZeppelinPrecompiles as Precompiles, Runtime, Signature,
};
use evm_runtime_template::{AccountId, OpenZeppelinPrecompiles as Precompiles, Runtime};
#[cfg(not(feature = "tanssi"))]
use evm_runtime_template::{AuraId, Signature};
use fp_evm::GenesisAccount;
use hex_literal::hex;
use log::error;
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
use sc_service::ChainType;
use serde::{Deserialize, Serialize};
use sp_core::{ecdsa, Pair, Public, H160};
use sp_core::H160;
#[cfg(not(feature = "tanssi"))]
use sp_core::{ecdsa, Pair, Public};
#[cfg(not(feature = "tanssi"))]
use sp_runtime::traits::{IdentifyAccount, Verify};
use crate::contracts::{parse_contracts, ContractsPath};
@@ -22,6 +25,7 @@ pub type ChainSpec = sc_service::GenericChainSpec<Extensions>;
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
/// Helper function to generate a crypto pair from seed
#[cfg(not(feature = "tanssi"))]
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
@@ -45,17 +49,20 @@ impl Extensions {
}
}
#[cfg(not(feature = "tanssi"))]
type AccountPublic = <Signature as Verify>::Signer;
/// Generate collator keys from seed.
///
/// This function's return type must always match the session keys of the chain
/// in tuple format.
#[cfg(not(feature = "tanssi"))]
pub fn get_collator_keys_from_seed(seed: &str) -> AuraId {
get_from_seed::<AuraId>(seed)
}
/// Helper function to generate an account ID from seed
#[cfg(not(feature = "tanssi"))]
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
@@ -67,6 +74,7 @@ where
///
/// The input must be a tuple of individual keys (a single arg for now since we
/// have just one key).
#[cfg(not(feature = "tanssi"))]
pub fn template_session_keys(keys: AuraId) -> evm_runtime_template::SessionKeys {
evm_runtime_template::SessionKeys { aura: keys }
}
@@ -94,6 +102,7 @@ pub fn development_config(contracts_path: ContractsPath) -> ChainSpec {
.with_chain_type(ChainType::Development)
.with_genesis_config_patch(testnet_genesis(
// initial collators.
#[cfg(not(feature = "tanssi"))]
vec![
(
get_account_id_from_seed::<ecdsa::Public>("Alice"),
@@ -140,6 +149,7 @@ pub fn local_testnet_config(contracts_path: ContractsPath) -> ChainSpec {
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(testnet_genesis(
// initial collators.
#[cfg(not(feature = "tanssi"))]
vec![
(
get_account_id_from_seed::<ecdsa::Public>("Alice"),
@@ -165,6 +175,7 @@ pub fn local_testnet_config(contracts_path: ContractsPath) -> ChainSpec {
.build()
}
#[cfg(not(feature = "tanssi"))]
fn testnet_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
#[cfg(not(feature = "runtime-benchmarks"))] endowed_accounts: Vec<AccountId>,
@@ -245,3 +256,67 @@ fn testnet_genesis(
"sudo": { "key": Some(root) }
})
}
#[cfg(feature = "tanssi")]
fn testnet_genesis(
#[cfg(not(feature = "runtime-benchmarks"))] endowed_accounts: Vec<AccountId>,
#[cfg(feature = "runtime-benchmarks")] mut endowed_accounts: Vec<AccountId>,
root: AccountId,
id: ParaId,
contracts_path: ContractsPath,
) -> serde_json::Value {
let contracts = parse_contracts(contracts_path)
.map_err(|e| error!("Error while parsing contracts: {e:?}"))
.unwrap_or_default();
let precompiles = Precompiles::<Runtime>::used_addresses()
.map(|addr| {
(
addr,
GenesisAccount {
nonce: Default::default(),
balance: Default::default(),
storage: Default::default(),
// bytecode to revert without returning data
// (PUSH1 0x00 PUSH1 0x00 REVERT)
code: vec![0x60, 0x00, 0x60, 0x00, 0xFD],
},
)
})
.into_iter();
let accounts: BTreeMap<H160, GenesisAccount> = contracts
.into_iter()
.map(|(address, contract)| {
(
address,
GenesisAccount {
code: contract.bytecode(),
nonce: Default::default(),
balance: Default::default(),
storage: Default::default(),
},
)
})
.chain(precompiles)
.collect();
#[cfg(feature = "runtime-benchmarks")]
endowed_accounts.push(AccountId::from(hex!("1000000000000000000000000000000000000001")));
serde_json::json!({
"balances": {
"balances": endowed_accounts.iter().cloned().map(|k| (k, 1u64 << 60)).collect::<Vec<_>>(),
},
"parachainInfo": {
"parachainId": id,
},
"treasury": {},
"evmChainId": {
"chainId": 9999
},
"evm": {
"accounts": accounts
},
"polkadotXcm": {
"safeXcmVersion": Some(SAFE_XCM_VERSION),
},
"sudo": { "key": Some(root) }
})
}
+2
View File
@@ -9,6 +9,8 @@ mod cli;
mod command;
mod contracts;
mod eth;
#[cfg_attr(feature = "tanssi", path = "tanssi_rpc/mod.rs")]
mod rpc;
fn main() -> sc_cli::Result<()> {
+70 -11
View File
@@ -6,23 +6,27 @@ use std::{path::Path, sync::Arc, time::Duration};
use cumulus_client_cli::CollatorOptions;
// Cumulus Imports
#[cfg(not(feature = "tanssi"))]
use cumulus_client_collator::service::CollatorService;
use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport;
#[cfg(not(feature = "tanssi"))]
use cumulus_client_consensus_proposer::Proposer;
use cumulus_client_service::{
build_network, build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks,
BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams,
};
#[cfg(not(feature = "tanssi"))]
use cumulus_primitives_core::relay_chain::CollatorPair;
#[cfg(feature = "async-backing")]
use cumulus_primitives_core::relay_chain::ValidationCode;
use cumulus_primitives_core::{relay_chain::CollatorPair, ParaId};
use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};
use cumulus_primitives_core::ParaId;
#[cfg(not(feature = "tanssi"))]
use cumulus_relay_chain_interface::OverseerHandle;
use cumulus_relay_chain_interface::RelayChainInterface;
#[cfg(not(feature = "tanssi"))]
use evm_runtime_template::opaque::Hash;
// Local Runtime Types
use evm_runtime_template::{
configs::TransactionConverter,
opaque::{Block, Hash},
RuntimeApi,
};
use evm_runtime_template::{configs::TransactionConverter, opaque::Block, RuntimeApi};
// Substrate Imports
use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE;
use sc_client_api::Backend;
@@ -30,10 +34,16 @@ use sc_consensus::ImportQueue;
use sc_executor::WasmExecutor;
use sc_network::{config::FullNetworkConfiguration, NetworkBlock};
use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager};
use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
#[cfg(not(feature = "tanssi"))]
use sc_telemetry::TelemetryHandle;
use sc_telemetry::{Telemetry, TelemetryWorker, TelemetryWorkerHandle};
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sp_core::{H256, U256};
use sp_core::H256;
#[cfg(not(feature = "tanssi"))]
use sp_core::U256;
#[cfg(not(feature = "tanssi"))]
use sp_keystore::KeystorePtr;
#[cfg(not(feature = "tanssi"))]
use substrate_prometheus_endpoint::Registry;
use crate::eth::{
@@ -121,8 +131,13 @@ pub fn new_partial(
client.clone(),
);
let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
#[cfg(feature = "tanssi")]
let (block_import, import_queue) =
import_queue(config, client.clone(), backend.clone(), &task_manager);
#[cfg(not(feature = "tanssi"))]
let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
#[cfg(not(feature = "tanssi"))]
let import_queue = build_import_queue(
client.clone(),
block_import.clone(),
@@ -180,6 +195,35 @@ pub fn new_partial(
})
}
#[cfg(feature = "tanssi")]
pub fn import_queue(
parachain_config: &Configuration,
client: Arc<ParachainClient>,
backend: Arc<ParachainBackend>,
task_manager: &TaskManager,
) -> (ParachainBlockImport, sc_consensus::BasicQueue<Block>) {
// The nimbus import queue ONLY checks the signature correctness
// Any other checks corresponding to the author-correctness should be done
// in the runtime
let block_import = ParachainBlockImport::new(client.clone(), backend);
let import_queue = nimbus_consensus::import_queue(
client,
block_import.clone(),
move |_, _| async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
Ok((time,))
},
&task_manager.spawn_essential_handle(),
parachain_config.prometheus_registry(),
false,
)
.expect("function never fails");
(block_import, import_queue)
}
/// Start a node with the given parachain `Configuration` and relay chain
/// `Configuration`.
///
@@ -201,8 +245,11 @@ async fn start_node_impl(
let FrontierPartialComponents { filter_pool, fee_history_cache, fee_history_cache_limit } =
new_frontier_partial(eth_config)?;
#[cfg(not(feature = "tanssi"))]
let (block_import, mut telemetry, telemetry_worker_handle, frontier_backend, overrides) =
params.other;
#[cfg(feature = "tanssi")]
let (_, mut telemetry, telemetry_worker_handle, frontier_backend, overrides) = params.other;
let frontier_backend = Arc::new(frontier_backend);
let net_config: FullNetworkConfiguration<Block, H256, sc_network::NetworkWorker<_, _>> =
@@ -212,7 +259,7 @@ async fn start_node_impl(
let backend = params.backend.clone();
let mut task_manager = params.task_manager;
let (relay_chain_interface, collator_key) = build_relay_chain_interface(
let relay_chain_interface = build_relay_chain_interface(
polkadot_config,
&parachain_config,
telemetry_worker_handle,
@@ -223,10 +270,16 @@ async fn start_node_impl(
.await
.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
#[cfg(not(feature = "tanssi"))]
let (relay_chain_interface, collator_key) = relay_chain_interface;
#[cfg(feature = "tanssi")]
let (relay_chain_interface, _) = relay_chain_interface;
let validator = parachain_config.role.is_authority();
let prometheus_registry = parachain_config.prometheus_registry().cloned();
let transaction_pool = params.transaction_pool.clone();
let import_queue_service = params.import_queue.service();
#[cfg(not(feature = "tanssi"))]
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) =
@@ -274,8 +327,10 @@ async fn start_node_impl(
let rpc_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
#[cfg(not(feature = "tanssi"))]
let target_gas_price = eth_config.target_gas_price;
let enable_dev_signer = eth_config.enable_dev_signer;
#[cfg(not(feature = "tanssi"))]
let pending_create_inherent_data_providers = move |_, ()| async move {
let current = sp_timestamp::InherentDataProvider::from_system_time();
let next_slot = current.timestamp().as_millis() + slot_duration.as_millis();
@@ -326,6 +381,7 @@ async fn start_node_impl(
fee_history_cache_limit,
execute_gas_limit_multiplier,
forced_parent_hashes: None,
#[cfg(not(feature = "tanssi"))]
pending_create_inherent_data_providers,
};
let deps = crate::rpc::FullDeps {
@@ -428,6 +484,7 @@ async fn start_node_impl(
)
.await;
#[cfg(not(feature = "tanssi"))]
if validator {
start_consensus(
client.clone(),
@@ -453,6 +510,7 @@ async fn start_node_impl(
Ok((task_manager, client))
}
#[cfg(not(feature = "tanssi"))]
/// Build the import queue for the parachain runtime.
fn build_import_queue(
client: Arc<ParachainClient>,
@@ -480,6 +538,7 @@ fn build_import_queue(
))
}
#[cfg(not(feature = "tanssi"))]
fn start_consensus(
client: Arc<ParachainClient>,
#[cfg(feature = "async-backing")] backend: Arc<ParachainBackend>,
+240
View File
@@ -0,0 +1,240 @@
use std::{collections::BTreeMap, sync::Arc};
use cumulus_client_parachain_inherent::ParachainInherentData;
use cumulus_primitives_core::PersistedValidationData;
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
// Frontier
pub use fc_rpc::{EthBlockDataCacheTask, EthConfig};
pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool};
pub use fc_storage::StorageOverride;
use fp_rpc::{ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi};
use jsonrpsee::RpcModule;
// Substrate
use sc_client_api::{
backend::{Backend, StorageProvider},
client::BlockchainEvents,
AuxStore, UsageProvider,
};
use sc_network::service::traits::NetworkService;
use sc_network_sync::SyncingService;
use sc_rpc::SubscriptionTaskExecutor;
use sc_transaction_pool::{ChainApi, Pool};
use sc_transaction_pool_api::TransactionPool;
use sp_api::{CallApiAt, ProvideRuntimeApi};
use sp_block_builder::BlockBuilder as BlockBuilderApi;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use sp_core::H256;
use sp_runtime::traits::Block as BlockT;
/// Extra dependencies for Ethereum compatibility.
pub struct EthDeps<B: BlockT, C, P, A: ChainApi, CT> {
/// The client instance to use.
pub client: Arc<C>,
/// Transaction pool instance.
pub pool: Arc<P>,
/// Graph pool instance.
pub graph: Arc<Pool<A>>,
/// Ethereum transaction converter.
pub converter: Option<CT>,
/// The Node authority flag
pub is_authority: bool,
/// Whether to enable dev signer
pub enable_dev_signer: bool,
/// Network service
pub network: Arc<dyn NetworkService>,
/// Chain syncing service
pub sync: Arc<SyncingService<B>>,
/// Frontier Backend.
pub frontier_backend: Arc<dyn fc_api::Backend<B>>,
/// Ethereum data access overrides.
pub overrides: Arc<dyn StorageOverride<B>>,
/// Cache for Ethereum block data.
pub block_data_cache: Arc<EthBlockDataCacheTask<B>>,
/// EthFilterApi pool.
pub filter_pool: Option<FilterPool>,
/// Maximum number of logs in a query.
pub max_past_logs: u32,
/// Fee history cache.
pub fee_history_cache: FeeHistoryCache,
/// Maximum fee history cache size.
pub fee_history_cache_limit: FeeHistoryCacheLimit,
/// Maximum allowed gas limit will be ` block.gas_limit * execute_gas_limit_multiplier` when
/// using eth_call/eth_estimateGas.
pub execute_gas_limit_multiplier: u64,
/// Mandated parent hashes for a given block hash.
pub forced_parent_hashes: Option<BTreeMap<H256, H256>>,
}
#[cfg(feature = "tanssi")]
/// Instantiate Ethereum-compatible RPC extensions.
pub fn create_eth<B, C, BE, P, A, CT, EC>(
mut io: RpcModule<()>,
deps: EthDeps<B, C, P, A, CT>,
subscription_task_executor: SubscriptionTaskExecutor,
pubsub_notification_sinks: Arc<
fc_mapping_sync::EthereumBlockNotificationSinks<
fc_mapping_sync::EthereumBlockNotification<B>,
>,
>,
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
where
B: BlockT<Hash = H256>,
C: CallApiAt<B> + ProvideRuntimeApi<B>,
C::Api: BlockBuilderApi<B> + ConvertTransactionRuntimeApi<B> + EthereumRuntimeRPCApi<B>,
C: HeaderBackend<B> + HeaderMetadata<B, Error = BlockChainError>,
C: BlockchainEvents<B> + AuxStore + UsageProvider<B> + StorageProvider<B, BE> + 'static,
BE: Backend<B> + 'static,
P: TransactionPool<Block = B> + 'static,
A: ChainApi<Block = B> + 'static,
CT: ConvertTransaction<<B as BlockT>::Extrinsic> + Send + Sync + 'static,
EC: EthConfig<B, C>,
{
use fc_rpc::{
Debug, DebugApiServer, Eth, EthApiServer, EthDevSigner, EthFilter, EthFilterApiServer,
EthPubSub, EthPubSubApiServer, EthSigner, Net, NetApiServer, Web3, Web3ApiServer,
};
#[cfg(feature = "txpool")]
use fc_rpc::{TxPool, TxPoolApiServer};
let EthDeps {
client,
pool,
graph,
converter,
is_authority,
enable_dev_signer,
network,
sync,
frontier_backend,
overrides,
block_data_cache,
filter_pool,
max_past_logs,
fee_history_cache,
fee_history_cache_limit,
execute_gas_limit_multiplier,
forced_parent_hashes,
} = deps;
let authorities = vec![tc_consensus::get_aura_id_from_seed("alice")];
let authorities_for_cdp = authorities.clone();
let pending_create_inherent_data_providers = move |_, _| {
let authorities_for_cidp = authorities.clone();
async move {
let mocked_authorities_noting =
ccp_authorities_noting_inherent::MockAuthoritiesNotingInherentDataProvider {
current_para_block: 1000,
relay_offset: 1000,
relay_blocks_per_para_block: 2,
orchestrator_para_id: 1000u32.into(),
container_para_id: 2000u32.into(),
authorities: authorities_for_cidp,
};
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
// Create a dummy parachain inherent data provider which is required to pass
// the checks by the para chain system. We use dummy values because in the 'pending context'
// neither do we have access to the real values nor do we need them.
let (relay_parent_storage_root, relay_chain_state) = RelayStateSproofBuilder {
additional_key_values: mocked_authorities_noting.get_key_values(),
..Default::default()
}
.into_state_root_and_proof();
let vfp = PersistedValidationData {
// This is a hack to make `cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases`
// happy. Relay parent number can't be bigger than u32::MAX.
relay_parent_number: u32::MAX,
relay_parent_storage_root,
..Default::default()
};
let parachain_inherent_data = ParachainInherentData {
validation_data: vfp,
relay_chain_state,
downward_messages: Default::default(),
horizontal_messages: Default::default(),
};
Ok((timestamp, parachain_inherent_data, mocked_authorities_noting))
}
};
let mut signers = Vec::new();
if enable_dev_signer {
signers.push(Box::new(EthDevSigner::new()) as Box<dyn EthSigner>);
}
io.merge(
Eth::<B, C, P, CT, BE, A, _, EC>::new(
client.clone(),
pool.clone(),
graph.clone(),
converter,
sync.clone(),
signers,
overrides.clone(),
frontier_backend.clone(),
is_authority,
block_data_cache.clone(),
fee_history_cache,
fee_history_cache_limit,
execute_gas_limit_multiplier,
forced_parent_hashes,
pending_create_inherent_data_providers,
Some(Box::new(tc_consensus::ContainerManualSealAuraConsensusDataProvider::new(
sp_consensus_aura::SlotDuration::from_millis(
evm_runtime_template::constants::SLOT_DURATION,
),
authorities_for_cdp.clone(),
))),
)
.replace_config::<EC>()
.into_rpc(),
)?;
if let Some(filter_pool) = filter_pool {
io.merge(
EthFilter::new(
client.clone(),
frontier_backend.clone(),
graph.clone(),
filter_pool,
500_usize, // max stored filters
max_past_logs,
block_data_cache.clone(),
)
.into_rpc(),
)?;
}
io.merge(
EthPubSub::new(
pool,
client.clone(),
sync,
subscription_task_executor,
overrides.clone(),
pubsub_notification_sinks,
)
.into_rpc(),
)?;
io.merge(
Net::new(
client.clone(),
network,
// Whether to format the `peer_count` response as Hex (default) or not.
true,
)
.into_rpc(),
)?;
io.merge(Web3::new(client.clone()).into_rpc())?;
io.merge(Debug::new(client.clone(), frontier_backend, overrides, block_data_cache).into_rpc())?;
#[cfg(feature = "txpool")]
io.merge(TxPool::new(client, graph).into_rpc())?;
Ok(io)
}
+98
View File
@@ -0,0 +1,98 @@
//! A collection of node-specific RPC methods.
//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer
//! used by Substrate nodes. This file extends those RPC definitions with
//! capabilities that are specific to this project's runtime configuration.
#![warn(missing_docs)]
mod eth;
use std::sync::Arc;
use evm_runtime_template::{opaque::Block, AccountId, Balance, Nonce};
use sc_client_api::{backend::Backend, AuxStore, BlockchainEvents, StorageProvider, UsageProvider};
pub use sc_rpc::DenyUnsafe;
use sc_rpc::SubscriptionTaskExecutor;
use sc_transaction_pool::ChainApi;
use sc_transaction_pool_api::TransactionPool;
use sp_api::{CallApiAt, ProvideRuntimeApi};
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use sp_runtime::traits::Block as BlockT;
pub use self::eth::EthDeps;
use crate::rpc::eth::create_eth;
/// A type representing all RPC extensions.
pub type RpcExtension = jsonrpsee::RpcModule<()>;
/// Full client dependencies
pub struct FullDeps<C, P, A: ChainApi, CT> {
/// The client instance to use.
pub client: Arc<C>,
/// Transaction pool instance.
pub pool: Arc<P>,
/// Whether to deny unsafe calls
pub deny_unsafe: DenyUnsafe,
/// Ethereum-compatibility specific dependencies.
pub eth: EthDeps<Block, C, P, A, CT>,
}
pub struct DefaultEthConfig<C, BE>(std::marker::PhantomData<(C, BE)>);
impl<C, BE> fc_rpc::EthConfig<Block, C> for DefaultEthConfig<C, BE>
where
C: StorageProvider<Block, BE> + Sync + Send + 'static,
BE: Backend<Block> + 'static,
{
type EstimateGasAdapter = ();
type RuntimeStorageOverride =
fc_rpc::frontier_backend_client::SystemAccountId20StorageOverride<Block, C, BE>;
}
/// Instantiate all RPC extensions.
pub fn create_full<C, P, A, CT, BE>(
deps: FullDeps<C, P, A, CT>,
subscription_task_executor: SubscriptionTaskExecutor,
pubsub_notification_sinks: Arc<
fc_mapping_sync::EthereumBlockNotificationSinks<
fc_mapping_sync::EthereumBlockNotification<Block>,
>,
>,
) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>>
where
C: ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ AuxStore
+ HeaderMetadata<Block, Error = BlockChainError>
+ Send
+ Sync
+ CallApiAt<Block>
+ UsageProvider<Block>
+ StorageProvider<Block, BE>
+ BlockchainEvents<Block>
+ 'static,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
C::Api: BlockBuilder<Block>,
C::Api: fp_rpc::ConvertTransactionRuntimeApi<Block>,
C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
P: TransactionPool<Block = Block> + Sync + Send + 'static,
A: ChainApi<Block = Block> + 'static,
CT: fp_rpc::ConvertTransaction<<Block as BlockT>::Extrinsic> + Send + Sync + 'static,
BE: Backend<Block> + 'static,
{
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
use substrate_frame_rpc_system::{System, SystemApiServer};
let mut module = RpcExtension::new(());
let FullDeps { client, pool, deny_unsafe, eth } = deps;
module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?;
module.merge(TransactionPayment::new(client).into_rpc())?;
let module = create_eth::<_, _, _, _, _, _, DefaultEthConfig<C, BE>>(
module,
eth,
subscription_task_executor,
pubsub_notification_sinks,
)?;
Ok(module)
}