difftreelog
refactor merge with new node template
in: master
6 files changed
node/src/chain_spec.rsdiffbeforeafterboth--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -3,19 +3,18 @@
// file 'LICENSE', which is part of this source code package.
//
-// use nft_runtime::{
-// AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,
-// SystemConfig, WASM_BINARY,
-// };
-// use nft_runtime::{ContractsConfig, ContractsSchedule, NftConfig, CollectionType};
use nft_runtime::*;
-use sc_service::ChainType;
+use sp_core::{Pair, Public, sr25519};
+use nft_runtime::{
+ AccountId, AuraConfig, BalancesConfig, EVMConfig, EthereumConfig, GenesisConfig, GrandpaConfig,
+ SudoConfig, SystemConfig, WASM_BINARY, Signature
+};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
-use sp_core::{sr25519, Pair, Public};
use sp_finality_grandpa::AuthorityId as GrandpaId;
-use sp_runtime::traits::{IdentifyAccount, Verify};
+use sp_runtime::traits::{Verify, IdentifyAccount};
+use sc_service::ChainType;
use serde_json::map::Map;
-// use crate::chain_spec::api::chain_extension::*;
+use std::collections::BTreeMap;
// Note this is the URL for the telemetry server
//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
@@ -25,9 +24,9 @@
/// Helper function to generate a crypto pair from seed
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")
- .public()
+ TPublic::Pair::from_string(&format!("//{}", seed), None)
+ .expect("static values are valid; qed")
+ .public()
}
type AccountPublic = <Signature as Verify>::Signer;
@@ -35,14 +34,14 @@
/// Helper function to generate an account ID from seed
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
- AccountPublic: From<<TPublic::Pair as Pair>::Public>,
+ AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
- AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
+ AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
/// Helper function to generate an authority key for Aura
pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {
- (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))
+ (get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))
}
pub fn development_config() -> Result<ChainSpec, String> {
@@ -138,88 +137,92 @@
}
fn testnet_genesis(
- wasm_binary: &[u8],
- initial_authorities: Vec<(AuraId, GrandpaId)>,
- root_key: AccountId,
- endowed_accounts: Vec<AccountId>,
- enable_println: bool,
+ wasm_binary: &[u8],
+ initial_authorities: Vec<(AuraId, GrandpaId)>,
+ root_key: AccountId,
+ endowed_accounts: Vec<AccountId>,
+ enable_println: bool,
) -> GenesisConfig {
let vested_accounts = vec![
get_account_id_from_seed::<sr25519::Public>("Bob"),
];
- GenesisConfig {
- system: Some(SystemConfig {
- code: wasm_binary.to_vec(),
- changes_trie_config: Default::default(),
- }),
- pallet_balances: Some(BalancesConfig {
- balances: endowed_accounts
- .iter()
- .cloned()
- .map(|k| (k, 1 << 100))
- .collect(),
- }),
- pallet_aura: Some(AuraConfig {
- authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),
- }),
- pallet_grandpa: Some(GrandpaConfig {
- authorities: initial_authorities
- .iter()
- .map(|x| (x.1.clone(), 1))
- .collect(),
- }),
- pallet_treasury: Some(Default::default()),
- pallet_sudo: Some(SudoConfig { key: root_key }),
- pallet_vesting: Some(VestingConfig {
- vesting: vested_accounts
- .iter()
- .cloned()
- .map(|k| (k, 1000, 100, 1 << 98))
- .collect(),
- }),
- pallet_nft: Some(NftConfig {
- collection_id: vec![(
- 1,
- Collection {
- owner: get_account_id_from_seed::<sr25519::Public>("Alice"),
- mode: CollectionMode::NFT,
- access: AccessMode::Normal,
- decimal_points: 0,
- name: vec![],
- description: vec![],
- token_prefix: vec![],
- mint_mode: false,
+ GenesisConfig {
+ system: SystemConfig {
+ code: wasm_binary.to_vec(),
+ changes_trie_config: Default::default(),
+ },
+ pallet_balances: BalancesConfig {
+ balances: endowed_accounts
+ .iter()
+ .cloned()
+ .map(|k| (k, 1 << 100))
+ .collect(),
+ },
+ pallet_aura: AuraConfig {
+ authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),
+ },
+ pallet_grandpa: GrandpaConfig {
+ authorities: initial_authorities
+ .iter()
+ .map(|x| (x.1.clone(), 1))
+ .collect(),
+ },
+ pallet_treasury: Default::default(),
+ pallet_sudo: SudoConfig { key: root_key },
+ pallet_vesting: VestingConfig {
+ vesting: vested_accounts
+ .iter()
+ .cloned()
+ .map(|k| (k, 1000, 100, 1 << 98))
+ .collect(),
+ },
+ pallet_nft: NftConfig {
+ collection_id: vec![(
+ 1,
+ Collection {
+ owner: get_account_id_from_seed::<sr25519::Public>("Alice"),
+ mode: CollectionMode::NFT,
+ access: AccessMode::Normal,
+ decimal_points: 0,
+ name: vec![],
+ description: vec![],
+ token_prefix: vec![],
+ mint_mode: false,
offchain_schema: vec![],
schema_version: SchemaVersion::default(),
- sponsorship: SponsorshipState::Confirmed(get_account_id_from_seed::<sr25519::Public>("Alice")),
- const_on_chain_schema: vec![],
+ sponsorship: SponsorshipState::Confirmed(get_account_id_from_seed::<sr25519::Public>("Alice")),
+ const_on_chain_schema: vec![],
variable_on_chain_schema: vec![],
limits: CollectionLimits::default()
- },
- )],
- nft_item_id: vec![],
- fungible_item_id: vec![],
- refungible_item_id: vec![],
- chain_limit: ChainLimits {
- collection_numbers_limit: 100000,
- account_token_ownership_limit: 1000000,
- collections_admins_limit: 5,
- custom_data_limit: 2048,
- nft_sponsor_transfer_timeout: 15,
- fungible_sponsor_transfer_timeout: 15,
+ },
+ )],
+ nft_item_id: vec![],
+ fungible_item_id: vec![],
+ refungible_item_id: vec![],
+ chain_limit: ChainLimits {
+ collection_numbers_limit: 100000,
+ account_token_ownership_limit: 1000000,
+ collections_admins_limit: 5,
+ custom_data_limit: 2048,
+ nft_sponsor_transfer_timeout: 15,
+ fungible_sponsor_transfer_timeout: 15,
refungible_sponsor_transfer_timeout: 15,
offchain_schema_limit: 1024,
variable_on_chain_schema_limit: 1024,
const_on_chain_schema_limit: 1024,
- },
- }),
- pallet_contracts: Some(ContractsConfig {
- current_schedule: ContractsSchedule {
- enable_println,
- ..Default::default()
- },
- }),
- }
+ },
+ },
+ pallet_contracts: ContractsConfig {
+ current_schedule: ContractsSchedule {
+ enable_println,
+ ..Default::default()
+ },
+ },
+ pallet_evm: EVMConfig {
+ accounts: BTreeMap::new(),
+ },
+ pallet_ethereum: EthereumConfig {},
+ }
}
node/src/command.rsdiffbeforeafterboth--- a/node/src/command.rs
+++ b/node/src/command.rs
@@ -75,7 +75,7 @@
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, ..}
- = service::new_partial(&config)?;
+ = service::new_partial(&config, &cli)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
@@ -83,7 +83,7 @@
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, ..}
- = service::new_partial(&config)?;
+ = service::new_partial(&config, &cli)?;
Ok((cmd.run(client, config.database), task_manager))
})
},
@@ -91,7 +91,7 @@
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, ..}
- = service::new_partial(&config)?;
+ = service::new_partial(&config, &cli)?;
Ok((cmd.run(client, config.chain_spec), task_manager))
})
},
@@ -99,7 +99,7 @@
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, ..}
- = service::new_partial(&config)?;
+ = service::new_partial(&config, &cli)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
@@ -111,7 +111,7 @@
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, backend, ..}
- = service::new_partial(&config)?;
+ = service::new_partial(&config, &cli)?;
Ok((cmd.run(client, backend), task_manager))
})
},
@@ -130,7 +130,7 @@
runner.run_node_until_exit(|config| async move {
match config.role {
Role::Light => service::new_light(config),
- _ => service::new_full(config),
+ _ => service::new_full(config, &cli),
}.map_err(sc_cli::Error::Service)
})
}
node/src/lib.rsdiffbeforeafterboth--- a/node/src/lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod chain_spec;
-pub mod service;
-pub mod rpc;
node/src/main.rsdiffbeforeafterboth--- a/node/src/main.rs
+++ b/node/src/main.rs
@@ -14,5 +14,5 @@
mod rpc;
fn main() -> sc_cli::Result<()> {
- command::run()
+ command::run()
}
node/src/rpc.rsdiffbeforeafterboth--- a/node/src/rpc.rs
+++ b/node/src/rpc.rs
@@ -3,17 +3,38 @@
//! used by Substrate nodes. This file extends those RPC definitions with
//! capabilities that are specific to this project's runtime configuration.
-#![warn(missing_docs)]
-
use std::sync::Arc;
-use nft_runtime::{opaque::Block, AccountId, Balance, Index, BlockNumber};
+use std::collections::BTreeMap;
+use fc_rpc_core::types::{PendingTransactions, FilterPool};
+use nft_runtime::{Hash, AccountId, Index, opaque::Block, Balance};
use sp_api::ProvideRuntimeApi;
use sp_blockchain::{Error as BlockChainError, HeaderMetadata, HeaderBackend};
+use sc_client_api::{
+ backend::{StorageProvider, Backend, StateBackend, AuxStore},
+ client::BlockchainEvents
+};
+use sc_rpc::SubscriptionTaskExecutor;
+use sp_runtime::traits::BlakeTwo256;
use sp_block_builder::BlockBuilder;
-pub use sc_rpc_api::DenyUnsafe;
+use sc_rpc_api::DenyUnsafe;
use sp_transaction_pool::TransactionPool;
-use pallet_contracts_rpc::{Contracts, ContractsApi};
+use sc_network::NetworkService;
+use jsonrpc_pubsub::manager::SubscriptionManager;
+use pallet_ethereum::EthereumStorageSchema;
+use fc_rpc::{StorageOverride, SchemaV1Override};
+
+/// Light client extra dependencies.
+pub struct LightDeps<C, F, P> {
+ /// The client instance to use.
+ pub client: Arc<C>,
+ /// Transaction pool instance.
+ pub pool: Arc<P>,
+ /// Remote access to the blockchain (async).
+ pub remote_blockchain: Arc<dyn sc_client_api::light::RemoteBlockchain<Block>>,
+ /// Fetcher instance.
+ pub fetcher: Arc<F>,
+}
/// Full client dependencies.
pub struct FullDeps<C, P> {
@@ -23,47 +44,155 @@
pub pool: Arc<P>,
/// Whether to deny unsafe calls
pub deny_unsafe: DenyUnsafe,
+ /// The Node authority flag
+ pub is_authority: bool,
+ /// Whether to enable dev signer
+ pub enable_dev_signer: bool,
+ /// Network service
+ pub network: Arc<NetworkService<Block, Hash>>,
+ /// Ethereum pending transactions.
+ pub pending_transactions: PendingTransactions,
+ /// EthFilterApi pool.
+ pub filter_pool: Option<FilterPool>,
+ /// Backend.
+ pub backend: Arc<fc_db::Backend<Block>>,
}
/// Instantiate all full RPC extensions.
-pub fn create_full<C, P>(
+pub fn create_full<C, P, BE>(
deps: FullDeps<C, P>,
+ subscription_task_executor: SubscriptionTaskExecutor
) -> jsonrpc_core::IoHandler<sc_rpc::Metadata> where
- C: ProvideRuntimeApi<Block>,
- C: HeaderBackend<Block> + HeaderMetadata<Block, Error=BlockChainError> + 'static,
+ BE: Backend<Block> + 'static,
+ BE::State: StateBackend<BlakeTwo256>,
+ C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,
+ C: BlockchainEvents<Block>,
+ C: HeaderBackend<Block> + HeaderMetadata<Block, Error=BlockChainError>,
C: Send + Sync + 'static,
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
- C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: BlockBuilder<Block>,
- C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber>,
- P: TransactionPool + 'static,
+ C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
+ C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
+ P: TransactionPool<Block=Block> + 'static,
{
use substrate_frame_rpc_system::{FullSystem, SystemApi};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
+ use fc_rpc::{
+ EthApi, EthApiServer, EthFilterApi, EthFilterApiServer, NetApi, NetApiServer,
+ EthPubSubApi, EthPubSubApiServer, Web3Api, Web3ApiServer, EthDevSigner, EthSigner,
+ HexEncodedIdProvider,
+ };
let mut io = jsonrpc_core::IoHandler::default();
let FullDeps {
client,
pool,
deny_unsafe,
+ is_authority,
+ network,
+ pending_transactions,
+ filter_pool,
+ backend,
+ enable_dev_signer,
} = deps;
io.extend_with(
- SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe))
+ SystemApi::to_delegate(FullSystem::new(client.clone(), pool.clone(), deny_unsafe))
);
io.extend_with(
TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))
);
- io.extend_with(
- ContractsApi::to_delegate(Contracts::new(client.clone()))
+ // io.extend_with(
+ // ContractsApi::to_delegate(Contracts::new(client.clone()))
+ // );
+
+ let mut signers = Vec::new();
+ if enable_dev_signer {
+ signers.push(Box::new(EthDevSigner::new()) as Box<dyn EthSigner>);
+ }
+ let mut overrides = BTreeMap::new();
+ overrides.insert(
+ EthereumStorageSchema::V1,
+ Box::new(SchemaV1Override::new(client.clone())) as Box<dyn StorageOverride<_> + Send + Sync>
+ );
+ io.extend_with(
+ EthApiServer::to_delegate(EthApi::new(
+ client.clone(),
+ pool.clone(),
+ nft_runtime::TransactionConverter,
+ network.clone(),
+ pending_transactions.clone(),
+ signers,
+ overrides,
+ backend,
+ is_authority,
+ ))
+ );
+
+ if let Some(filter_pool) = filter_pool {
+ io.extend_with(
+ EthFilterApiServer::to_delegate(EthFilterApi::new(
+ client.clone(),
+ filter_pool.clone(),
+ 500 as usize, // max stored filters
+ ))
+ );
+ }
+
+ io.extend_with(
+ NetApiServer::to_delegate(NetApi::new(
+ client.clone(),
+ network.clone(),
+ ))
);
-
- // Extend this RPC with a custom API by using the following syntax.
- // `YourRpcStruct` should have a reference to a client, which is needed
- // to call into the runtime.
- // `io.extend_with(YourRpcTrait::to_delegate(YourRpcStruct::new(ReferenceToClient, ...)));`
+ io.extend_with(
+ Web3ApiServer::to_delegate(Web3Api::new(
+ client.clone(),
+ ))
+ );
+
+ io.extend_with(
+ EthPubSubApiServer::to_delegate(EthPubSubApi::new(
+ pool.clone(),
+ client.clone(),
+ network.clone(),
+ SubscriptionManager::<HexEncodedIdProvider>::with_id_provider(
+ HexEncodedIdProvider::default(),
+ Arc::new(subscription_task_executor)
+ ),
+ ))
+ );
+
+ io
+}
+
+/// Instantiate all Light RPC extensions.
+pub fn create_light<C, P, M, F>(
+ deps: LightDeps<C, F, P>,
+) -> jsonrpc_core::IoHandler<M> where
+ C: sp_blockchain::HeaderBackend<Block>,
+ C: Send + Sync + 'static,
+ F: sc_client_api::light::Fetcher<Block> + 'static,
+ P: TransactionPool + 'static,
+ M: jsonrpc_core::Metadata + Default,
+{
+ use substrate_frame_rpc_system::{LightSystem, SystemApi};
+
+ let LightDeps {
+ client,
+ pool,
+ remote_blockchain,
+ fetcher
+ } = deps;
+ let mut io = jsonrpc_core::IoHandler::default();
+ io.extend_with(
+ SystemApi::<Hash, AccountId, Index>::to_delegate(
+ LightSystem::new(client, remote_blockchain, fetcher, pool)
+ )
+ );
+
io
}
node/src/service.rsdiffbeforeafterboth1//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.23//4// This file is subject to the terms and conditions defined in5// file 'LICENSE', which is part of this source code package.6//78use std::sync::Arc;9use std::time::Duration;10use sc_client_api::{ExecutorProvider, RemoteBackend};11use nft_runtime::{self, opaque::Block, RuntimeApi};12use sc_service::{error::Error as ServiceError, Configuration, TaskManager};13use sp_inherents::InherentDataProviders;14use sc_executor::native_executor_instance;15pub use sc_executor::NativeExecutor;16use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};17use sc_finality_grandpa::SharedVoterState;18use sc_keystore::LocalKeystore;1920// Our native executor instance.21native_executor_instance!(22 pub Executor,23 nft_runtime::api::dispatch,24 nft_runtime::native_version,25 frame_benchmarking::benchmarking::HostFunctions,26);2728type FullClient = sc_service::TFullClient<Block, RuntimeApi, Executor>;29type FullBackend = sc_service::TFullBackend<Block>;30type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;3132pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponents<33 FullClient, FullBackend, FullSelectChain,34 sp_consensus::DefaultImportQueue<Block, FullClient>,35 sc_transaction_pool::FullPool<Block, FullClient>,36 (37 sc_consensus_aura::AuraBlockImport<38 Block,39 FullClient,40 sc_finality_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>,41 AuraPair42 >,43 sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,44 )45>, ServiceError> {46 if config.keystore_remote.is_some() {47 return Err(ServiceError::Other(48 format!("Remote Keystores are not supported.")))49 }50 let inherent_data_providers = sp_inherents::InherentDataProviders::new();5152 let (client, backend, keystore_container, task_manager) =53 sc_service::new_full_parts::<Block, RuntimeApi, Executor>(&config)?;54 let client = Arc::new(client);5556 let select_chain = sc_consensus::LongestChain::new(backend.clone());5758 let transaction_pool = sc_transaction_pool::BasicPool::new_full(59 config.transaction_pool.clone(),60 config.role.is_authority().into(),61 config.prometheus_registry(),62 task_manager.spawn_handle(),63 client.clone(),64 );6566 let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import(67 client.clone(), &(client.clone() as Arc<_>), select_chain.clone(),68 )?;6970 let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(71 grandpa_block_import.clone(), client.clone(),72 );7374 let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(75 sc_consensus_aura::slot_duration(&*client)?,76 aura_block_import.clone(),77 Some(Box::new(grandpa_block_import.clone())),78 client.clone(),79 inherent_data_providers.clone(),80 &task_manager.spawn_handle(),81 config.prometheus_registry(),82 sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),83 )?;8485 Ok(sc_service::PartialComponents {86 client, backend, task_manager, import_queue, keystore_container, select_chain, transaction_pool,87 inherent_data_providers,88 other: (aura_block_import, grandpa_link),89 })90}9192fn remote_keystore(_url: &String) -> Result<Arc<LocalKeystore>, &'static str> {93 // FIXME: here would the concrete keystore be built,94 // must return a concrete type (NOT `LocalKeystore`) that95 // implements `CryptoStore` and `SyncCryptoStore`96 Err("Remote Keystore not supported.")97}9899/// Builds a new service for a full client.100pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError> {101 let sc_service::PartialComponents {102 client, backend, mut task_manager, import_queue, mut keystore_container, select_chain, transaction_pool,103 inherent_data_providers,104 other: (block_import, grandpa_link),105 } = new_partial(&config)?;106107 if let Some(url) = &config.keystore_remote {108 match remote_keystore(url) {109 Ok(k) => keystore_container.set_remote_keystore(k),110 Err(e) => {111 return Err(ServiceError::Other(112 format!("Error hooking up remote keystore for {}: {}", url, e)))113 }114 };115 }116117 config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());118119 let (network, network_status_sinks, system_rpc_tx, network_starter) =120 sc_service::build_network(sc_service::BuildNetworkParams {121 config: &config,122 client: client.clone(),123 transaction_pool: transaction_pool.clone(),124 spawn_handle: task_manager.spawn_handle(),125 import_queue,126 on_demand: None,127 block_announce_validator_builder: None,128 })?;129130 if config.offchain_worker.enabled {131 sc_service::build_offchain_workers(132 &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(),133 );134 }135136 let role = config.role.clone();137 let force_authoring = config.force_authoring;138 let backoff_authoring_blocks: Option<()> = None;139 let name = config.network.node_name.clone();140 let enable_grandpa = !config.disable_grandpa;141 let prometheus_registry = config.prometheus_registry().cloned();142143 let rpc_extensions_builder = {144 let client = client.clone();145 let pool = transaction_pool.clone();146147 Box::new(move |deny_unsafe, _| {148 let deps = crate::rpc::FullDeps {149 client: client.clone(),150 pool: pool.clone(),151 deny_unsafe,152 };153154 crate::rpc::create_full(deps)155 })156 };157158 let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(159 sc_service::SpawnTasksParams {160 network: network.clone(),161 client: client.clone(),162 keystore: keystore_container.sync_keystore(),163 task_manager: &mut task_manager,164 transaction_pool: transaction_pool.clone(),165 rpc_extensions_builder,166 on_demand: None,167 remote_blockchain: None,168 backend,169 network_status_sinks,170 system_rpc_tx,171 config,172 },173 )?;174175 if role.is_authority() {176 let proposer = sc_basic_authorship::ProposerFactory::new(177 task_manager.spawn_handle(),178 client.clone(),179 transaction_pool,180 prometheus_registry.as_ref(),181 );182183 let can_author_with =184 sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());185186 let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _, _>(187 sc_consensus_aura::slot_duration(&*client)?,188 client.clone(),189 select_chain,190 block_import,191 proposer,192 network.clone(),193 inherent_data_providers.clone(),194 force_authoring,195 backoff_authoring_blocks,196 keystore_container.sync_keystore(),197 can_author_with,198 )?;199200 // the AURA authoring task is considered essential, i.e. if it201 // fails we take down the service with it.202 task_manager.spawn_essential_handle().spawn_blocking("aura", aura);203 }204205 // if the node isn't actively participating in consensus then it doesn't206 // need a keystore, regardless of which protocol we use below.207 let keystore = if role.is_authority() {208 Some(keystore_container.sync_keystore())209 } else {210 None211 };212213 let grandpa_config = sc_finality_grandpa::Config {214 // FIXME #1578 make this available through chainspec215 gossip_duration: Duration::from_millis(333),216 justification_period: 512,217 name: Some(name),218 observer_enabled: false,219 keystore,220 is_authority: role.is_network_authority(),221 };222223 if enable_grandpa {224 // start the full GRANDPA voter225 // NOTE: non-authorities could run the GRANDPA observer protocol, but at226 // this point the full voter should provide better guarantees of block227 // and vote data availability than the observer. The observer has not228 // been tested extensively yet and having most nodes in a network run it229 // could lead to finality stalls.230 let grandpa_config = sc_finality_grandpa::GrandpaParams {231 config: grandpa_config,232 link: grandpa_link,233 network,234 telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()),235 voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(),236 prometheus_registry,237 shared_voter_state: SharedVoterState::empty(),238 };239240 // the GRANDPA voter task is considered infallible, i.e.241 // if it fails we take down the service with it.242 task_manager.spawn_essential_handle().spawn_blocking(243 "grandpa-voter",244 sc_finality_grandpa::run_grandpa_voter(grandpa_config)?245 );246 }247248 network_starter.start_network();249 Ok(task_manager)250}251/// Builds a new service for a light client.252pub fn new_light(mut config: Configuration) -> Result<TaskManager, ServiceError> {253 let (client, backend, keystore_container, mut task_manager, on_demand) =254 sc_service::new_light_parts::<Block, RuntimeApi, Executor>(&config)?;255256 config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());257258 let select_chain = sc_consensus::LongestChain::new(backend.clone());259260 let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light(261 config.transaction_pool.clone(),262 config.prometheus_registry(),263 task_manager.spawn_handle(),264 client.clone(),265 on_demand.clone(),266 ));267268 let (grandpa_block_import, _) = sc_finality_grandpa::block_import(269 client.clone(),270 &(client.clone() as Arc<_>),271 select_chain.clone(),272 )?;273274 let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(275 grandpa_block_import.clone(),276 client.clone(),277 );278279 let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(280 sc_consensus_aura::slot_duration(&*client)?,281 aura_block_import,282 Some(Box::new(grandpa_block_import)),283 client.clone(),284 InherentDataProviders::new(),285 &task_manager.spawn_handle(),286 config.prometheus_registry(),287 sp_consensus::NeverCanAuthor,288 )?;289290 let (network, network_status_sinks, system_rpc_tx, network_starter) =291 sc_service::build_network(sc_service::BuildNetworkParams {292 config: &config,293 client: client.clone(),294 transaction_pool: transaction_pool.clone(),295 spawn_handle: task_manager.spawn_handle(),296 import_queue,297 on_demand: Some(on_demand.clone()),298 block_announce_validator_builder: None,299 })?;300301 if config.offchain_worker.enabled {302 sc_service::build_offchain_workers(303 &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(),304 );305 }306307 sc_service::spawn_tasks(sc_service::SpawnTasksParams {308 remote_blockchain: Some(backend.remote_blockchain()),309 transaction_pool,310 task_manager: &mut task_manager,311 on_demand: Some(on_demand),312 rpc_extensions_builder: Box::new(|_, _| ()),313 config,314 client,315 keystore: keystore_container.sync_keystore(),316 backend,317 network,318 network_status_sinks,319 system_rpc_tx,320 })?;321322 network_starter.start_network();323324 Ok(task_manager)325}1//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.23//4// This file is subject to the terms and conditions defined in5// file 'LICENSE', which is part of this source code package.6//78use std::{sync::{Arc, Mutex}, cell::RefCell, time::Duration, collections::{HashMap, BTreeMap}};9use fc_rpc::EthTask;10use fc_rpc_core::types::{FilterPool, PendingTransactions};11use sc_client_api::{ExecutorProvider, RemoteBackend, BlockchainEvents};12use fc_consensus::FrontierBlockImport;13use fc_mapping_sync::MappingSyncWorker;14use nft_runtime::{self, opaque::Block, RuntimeApi, SLOT_DURATION};15use sc_service::{error::Error as ServiceError, Configuration, TaskManager, BasePath};16use sp_inherents::{InherentDataProviders, ProvideInherentData, InherentIdentifier, InherentData};17use sc_executor::native_executor_instance;18pub use sc_executor::NativeExecutor;19use sc_consensus_aura::{ImportQueueParams, StartAuraParams, SlotProportion};20use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};21use sc_finality_grandpa::SharedVoterState;22use sp_timestamp::InherentError;23use sc_telemetry::{Telemetry, TelemetryWorker};24use sc_cli::SubstrateCli;25use futures::StreamExt;2627use crate::cli::Cli;2829// Our native executor instance.30native_executor_instance!(31 pub Executor,32 nft_runtime::api::dispatch,33 nft_runtime::native_version,34 frame_benchmarking::benchmarking::HostFunctions,35);3637type FullClient = sc_service::TFullClient<Block, RuntimeApi, Executor>;38type FullBackend = sc_service::TFullBackend<Block>;39type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;4041pub type ConsensusResult = (42 sc_consensus_aura::AuraBlockImport<43 Block,44 FullClient,45 FrontierBlockImport<46 Block,47 sc_finality_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>,48 FullClient49 >,50 AuraPair51 >,52 sc_finality_grandpa::LinkHalf<Block, FullClient, FullSelectChain>53);5455/// Provide a mock duration starting at 0 in millisecond for timestamp inherent.56/// Each call will increment timestamp by slot_duration making Aura think time has passed.57pub struct MockTimestampInherentDataProvider;5859pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";6061thread_local!(static TIMESTAMP: RefCell<u64> = RefCell::new(0));6263impl ProvideInherentData for MockTimestampInherentDataProvider {64 fn inherent_identifier(&self) -> &'static InherentIdentifier {65 &INHERENT_IDENTIFIER66 }6768 fn provide_inherent_data(69 &self,70 inherent_data: &mut InherentData,71 ) -> Result<(), sp_inherents::Error> {72 TIMESTAMP.with(|x| {73 *x.borrow_mut() += SLOT_DURATION;74 inherent_data.put_data(INHERENT_IDENTIFIER, &*x.borrow())75 })76 }7778 fn error_to_string(&self, error: &[u8]) -> Option<String> {79 InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e))80 }81}8283pub fn open_frontier_backend(config: &Configuration) -> Result<Arc<fc_db::Backend<Block>>, String> {84 let config_dir = config.base_path.as_ref()85 .map(|base_path| base_path.config_dir(config.chain_spec.id()))86 .unwrap_or_else(|| {87 BasePath::from_project("", "", &crate::cli::Cli::executable_name())88 .config_dir(config.chain_spec.id())89 });90 let database_dir = config_dir.join("frontier").join("db");9192 Ok(Arc::new(fc_db::Backend::<Block>::new(&fc_db::DatabaseSettings {93 source: fc_db::DatabaseSettingsSrc::RocksDb {94 path: database_dir,95 cache_size: 0,96 }97 })?))98}99100pub fn new_partial(config: &Configuration, #[allow(unused_variables)] cli: &Cli) -> Result<101 sc_service::PartialComponents<102 FullClient, FullBackend, FullSelectChain,103 sp_consensus::import_queue::BasicQueue<Block, sp_api::TransactionFor<FullClient, Block>>,104 sc_transaction_pool::FullPool<Block, FullClient>,105 (ConsensusResult, PendingTransactions, Option<FilterPool>, Arc<fc_db::Backend<Block>>, Option<Telemetry>),106>, ServiceError> {107 let inherent_data_providers = sp_inherents::InherentDataProviders::new();108109 let telemetry = config.telemetry_endpoints.clone()110 .filter(|x| !x.is_empty())111 .map(|endpoints| -> Result<_, sc_telemetry::Error> {112 let worker = TelemetryWorker::new(16)?;113 let telemetry = worker.handle().new_telemetry(endpoints);114 Ok((worker, telemetry))115 })116 .transpose()?;117118 let (client, backend, keystore_container, task_manager) =119 sc_service::new_full_parts::<Block, RuntimeApi, Executor>(120 &config,121 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),122 )?;123 let client = Arc::new(client);124125 let telemetry = telemetry126 .map(|(worker, telemetry)| {127 task_manager.spawn_handle().spawn("telemetry", worker.run());128 telemetry129 });130131 let select_chain = sc_consensus::LongestChain::new(backend.clone());132133 let transaction_pool = sc_transaction_pool::BasicPool::new_full(134 config.transaction_pool.clone(),135 config.role.is_authority().into(),136 config.prometheus_registry(),137 task_manager.spawn_handle(),138 client.clone(),139 );140141 let pending_transactions: PendingTransactions142 = Some(Arc::new(Mutex::new(HashMap::new())));143144 let filter_pool: Option<FilterPool>145 = Some(Arc::new(Mutex::new(BTreeMap::new())));146147 let frontier_backend = open_frontier_backend(config)?;148149 let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import(150 client.clone(),151 &(client.clone() as Arc<_>),152 select_chain.clone(),153 telemetry.as_ref().map(|x| x.handle()),154 )?;155156 let frontier_block_import = FrontierBlockImport::new(157 grandpa_block_import.clone(),158 client.clone(),159 frontier_backend.clone(),160 );161162 let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(163 frontier_block_import, client.clone(),164 );165166 let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _>(167 ImportQueueParams {168 slot_duration: sc_consensus_aura::slot_duration(&*client)?,169 block_import: aura_block_import.clone(),170 justification_import: Some(Box::new(grandpa_block_import.clone())),171 client: client.clone(),172 inherent_data_providers: inherent_data_providers.clone(),173 spawner: &task_manager.spawn_essential_handle(),174 registry: config.prometheus_registry(),175 can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),176 check_for_equivocation: Default::default(),177 telemetry: telemetry.as_ref().map(|x| x.handle()),178 }179 )?;180181 Ok(sc_service::PartialComponents {182 client, backend, task_manager, import_queue, keystore_container,183 select_chain, transaction_pool, inherent_data_providers,184 other: (185 (aura_block_import, grandpa_link),186 pending_transactions,187 filter_pool,188 frontier_backend,189 telemetry,190 )191 })192}193194/// Builds a new service for a full client.195pub fn new_full(196 config: Configuration,197 cli: &Cli,198) -> Result<TaskManager, ServiceError> {199 let enable_dev_signer = cli.run.shared_params.dev;200201 let sc_service::PartialComponents {202 client, backend, mut task_manager, import_queue, keystore_container,203 select_chain, transaction_pool, inherent_data_providers,204 other: (consensus_result, pending_transactions, filter_pool, frontier_backend, mut telemetry),205 } = new_partial(&config, cli)?;206207 let (network, network_status_sinks, system_rpc_tx, network_starter) =208 sc_service::build_network(sc_service::BuildNetworkParams {209 config: &config,210 client: Arc::clone(&client),211 transaction_pool: Arc::clone(&transaction_pool),212 spawn_handle: task_manager.spawn_handle(),213 import_queue,214 on_demand: None,215 block_announce_validator_builder: None,216 })?;217218 if config.offchain_worker.enabled {219 sc_service::build_offchain_workers(220 &config, task_manager.spawn_handle(), Arc::clone(&client), network.clone(),221 );222 }223224 let role = config.role.clone();225 let force_authoring = config.force_authoring;226 let backoff_authoring_blocks: Option<()> = None;227 let name = config.network.node_name.clone();228 let enable_grandpa = !config.disable_grandpa;229 let prometheus_registry = config.prometheus_registry().cloned();230 let is_authority = role.is_authority();231 let subscription_task_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle());232233 let rpc_extensions_builder = {234 let client = Arc::clone(&client);235 let pool = Arc::clone(&transaction_pool);236 let network = network.clone();237 let pending = pending_transactions.clone();238 let filter_pool = filter_pool.clone();239 let frontier_backend = frontier_backend.clone();240241 Box::new(move |deny_unsafe, _| {242 let deps = crate::rpc::FullDeps {243 client: Arc::clone(&client),244 pool: Arc::clone(&pool),245 deny_unsafe,246 is_authority,247 enable_dev_signer,248 network: network.clone(),249 pending_transactions: pending.clone(),250 filter_pool: filter_pool.clone(),251 backend: frontier_backend.clone(),252 };253 crate::rpc::create_full(254 deps,255 subscription_task_executor.clone()256 )257 })258 };259260 task_manager.spawn_essential_handle().spawn(261 "frontier-mapping-sync-worker",262 MappingSyncWorker::new(263 client.import_notification_stream(),264 Duration::new(6, 0),265 Arc::clone(&client),266 Arc::clone(&backend),267 frontier_backend.clone(),268 ).for_each(|()| futures::future::ready(()))269 );270271 let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {272 network: network.clone(),273 client: Arc::clone(&client),274 keystore: keystore_container.sync_keystore(),275 task_manager: &mut task_manager,276 transaction_pool: Arc::clone(&transaction_pool),277 rpc_extensions_builder: rpc_extensions_builder,278 on_demand: None,279 remote_blockchain: None,280 backend, network_status_sinks, system_rpc_tx, config, telemetry: telemetry.as_mut(),281 })?;282283 // Spawn Frontier EthFilterApi maintenance task.284 if let Some(filter_pool) = filter_pool {285 // Each filter is allowed to stay in the pool for 100 blocks.286 const FILTER_RETAIN_THRESHOLD: u64 = 100;287 task_manager.spawn_essential_handle().spawn(288 "frontier-filter-pool",289 EthTask::filter_pool_task(290 Arc::clone(&client),291 filter_pool,292 FILTER_RETAIN_THRESHOLD,293 )294 );295 }296297 // Spawn Frontier pending transactions maintenance task (as essential, otherwise we leak).298 if let Some(pending_transactions) = pending_transactions {299 const TRANSACTION_RETAIN_THRESHOLD: u64 = 5;300 task_manager.spawn_essential_handle().spawn(301 "frontier-pending-transactions",302 EthTask::pending_transaction_task(303 Arc::clone(&client),304 pending_transactions,305 TRANSACTION_RETAIN_THRESHOLD,306 )307 );308 }309310 let (aura_block_import, grandpa_link) = consensus_result;311312 if role.is_authority() {313 let proposer = sc_basic_authorship::ProposerFactory::new(314 task_manager.spawn_handle(),315 Arc::clone(&client),316 Arc::clone(&transaction_pool),317 prometheus_registry.as_ref(),318 telemetry.as_ref().map(|x| x.handle()),319 );320321 let can_author_with =322 sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());323 let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _>(324 StartAuraParams {325 slot_duration: sc_consensus_aura::slot_duration(&*client)?,326 client: Arc::clone(&client),327 select_chain,328 block_import: aura_block_import,329 proposer_factory: proposer,330 sync_oracle: network.clone(),331 inherent_data_providers: inherent_data_providers.clone(),332 force_authoring,333 backoff_authoring_blocks,334 keystore: keystore_container.sync_keystore(),335 can_author_with,336 block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),337 telemetry: telemetry.as_ref().map(|x| x.handle()),338 }339 )?;340341 // the AURA authoring task is considered essential, i.e. if it342 // fails we take down the service with it.343 task_manager.spawn_essential_handle().spawn_blocking("aura", aura);344345 // if the node isn't actively participating in consensus then it doesn't346 // need a keystore, regardless of which protocol we use below.347 let keystore = if role.is_authority() {348 Some(keystore_container.sync_keystore())349 } else {350 None351 };352353 let grandpa_config = sc_finality_grandpa::Config {354 // FIXME #1578 make this available through chainspec355 gossip_duration: Duration::from_millis(333),356 justification_period: 512,357 name: Some(name),358 observer_enabled: false,359 keystore,360 is_authority: role.is_authority(),361 telemetry: telemetry.as_ref().map(|x| x.handle()),362 };363364 if enable_grandpa {365 // start the full GRANDPA voter366 // NOTE: non-authorities could run the GRANDPA observer protocol, but at367 // this point the full voter should provide better guarantees of block368 // and vote data availability than the observer. The observer has not369 // been tested extensively yet and having most nodes in a network run it370 // could lead to finality stalls.371 let grandpa_config = sc_finality_grandpa::GrandpaParams {372 config: grandpa_config,373 link: grandpa_link,374 network,375 telemetry: telemetry.as_ref().map(|x| x.handle()),376 voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(),377 prometheus_registry,378 shared_voter_state: SharedVoterState::empty(),379 };380381 // the GRANDPA voter task is considered infallible, i.e.382 // if it fails we take down the service with it.383 task_manager.spawn_essential_handle().spawn_blocking(384 "grandpa-voter",385 sc_finality_grandpa::run_grandpa_voter(grandpa_config)?386 );387 }388 }389390 network_starter.start_network();391 Ok(task_manager)392}393/// Builds a new service for a light client.394pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {395 let telemetry = config.telemetry_endpoints.clone()396 .filter(|x| !x.is_empty())397 .map(|endpoints| -> Result<_, sc_telemetry::Error> {398 let worker = TelemetryWorker::new(16)?;399 let telemetry = worker.handle().new_telemetry(endpoints);400 Ok((worker, telemetry))401 })402 .transpose()?;403404 let (client, backend, keystore_container, mut task_manager, on_demand) =405 sc_service::new_light_parts::<Block, RuntimeApi, Executor>(406 &config,407 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),408 )?;409410 let mut telemetry = telemetry411 .map(|(worker, telemetry)| {412 task_manager.spawn_handle().spawn("telemetry", worker.run());413 telemetry414 });415416 let select_chain = sc_consensus::LongestChain::new(backend.clone());417418 let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light(419 config.transaction_pool.clone(),420 config.prometheus_registry(),421 task_manager.spawn_handle(),422 client.clone(),423 on_demand.clone(),424 ));425426 let (grandpa_block_import, _) = sc_finality_grandpa::block_import(427 client.clone(),428 &(client.clone() as Arc<_>),429 select_chain.clone(),430 telemetry.as_ref().map(|x| x.handle()),431 )?;432433 let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _>(434 ImportQueueParams {435 slot_duration: sc_consensus_aura::slot_duration(&*client)?,436 block_import: grandpa_block_import.clone(),437 justification_import: Some(Box::new(grandpa_block_import)),438 client: client.clone(),439 inherent_data_providers: InherentDataProviders::new(),440 spawner: &task_manager.spawn_essential_handle(),441 registry: config.prometheus_registry(),442 can_author_with: sp_consensus::NeverCanAuthor,443 check_for_equivocation: Default::default(),444 telemetry: telemetry.as_ref().map(|x| x.handle()),445 }446 )?;447448 let light_deps = crate::rpc::LightDeps {449 remote_blockchain: backend.remote_blockchain(),450 fetcher: on_demand.clone(),451 client: client.clone(),452 pool: transaction_pool.clone(),453 };454455 let rpc_extensions = crate::rpc::create_light(light_deps);456457 let (network, network_status_sinks, system_rpc_tx, network_starter) =458 sc_service::build_network(sc_service::BuildNetworkParams {459 config: &config,460 client: client.clone(),461 transaction_pool: transaction_pool.clone(),462 spawn_handle: task_manager.spawn_handle(),463 import_queue,464 on_demand: Some(on_demand.clone()),465 block_announce_validator_builder: None,466 })?;467468 if config.offchain_worker.enabled {469 sc_service::build_offchain_workers(470 &config, task_manager.spawn_handle(), client.clone(), network.clone(),471 );472 }473474 sc_service::spawn_tasks(sc_service::SpawnTasksParams {475 remote_blockchain: Some(backend.remote_blockchain()),476 transaction_pool,477 task_manager: &mut task_manager,478 on_demand: Some(on_demand),479 rpc_extensions_builder: Box::new(sc_service::NoopRpcExtensionBuilder(rpc_extensions)),480 config,481 client,482 keystore: keystore_container.sync_keystore(),483 backend,484 network,485 network_status_sinks,486 system_rpc_tx,487 telemetry: telemetry.as_mut(),488 })?;489490 network_starter.start_network();491492 Ok(task_manager)493}