diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index a74b25c4af..a580a8450e 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1594,9 +1594,19 @@ name = "node-cli" version = "0.1.0" dependencies = [ "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "node-service 0.1.0", + "node-executor 0.1.0", + "node-network 0.1.0", + "node-primitives 0.1.0", + "node-runtime 0.1.0", + "sr-primitives 0.1.0", "substrate-cli 0.3.0", + "substrate-network 0.1.0", + "substrate-primitives 0.1.0", + "substrate-service 0.3.0", + "substrate-service-test 0.3.0", + "substrate-transaction-pool 0.1.0", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1713,37 +1723,6 @@ dependencies = [ "substrate-primitives 0.1.0", ] -[[package]] -name = "node-service" -version = "0.1.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "node-consensus 0.1.0", - "node-executor 0.1.0", - "node-network 0.1.0", - "node-primitives 0.1.0", - "node-runtime 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "substrate-client 0.1.0", - "substrate-keyring 0.1.0", - "substrate-network 0.1.0", - "substrate-primitives 0.1.0", - "substrate-service 0.3.0", - "substrate-service-test 0.3.0", - "substrate-telemetry 0.3.0", - "substrate-test-client 0.1.0", - "substrate-transaction-pool 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nodrop" version = "0.1.12" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index bc0fc5feef..869309d6aa 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -68,7 +68,6 @@ members = [ "node/network", "node/primitives", "node/runtime", - "node/service", "subkey", ] exclude = [ diff --git a/substrate/core/service/src/components.rs b/substrate/core/service/src/components.rs index 50d27845e2..a30fb9940e 100644 --- a/substrate/core/service/src/components.rs +++ b/substrate/core/service/src/components.rs @@ -16,7 +16,6 @@ //! Substrate service components. -use std::fmt; use std::sync::Arc; use std::marker::PhantomData; use std::ops::Deref; @@ -39,7 +38,7 @@ use primitives::{Blake2Hasher}; pub type NetworkService = network::Service< ::Block, ::NetworkProtocol, - ::ExtrinsicHash, + <::Block as BlockT>::Hash, >; /// Code executor type for a factory. @@ -121,16 +120,14 @@ impl RuntimeGenesis for T {} pub trait ServiceFactory: 'static + Sized { /// Block type. type Block: BlockT; - /// Extrinsic hash type. - type ExtrinsicHash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Serialize + DeserializeOwned + ::std::str::FromStr + Send + Sync + Default + 'static; /// Network protocol extensions. type NetworkProtocol: network::specialization::Specialization; /// Chain runtime. type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static; /// Extrinsic pool backend type for the full client. - type FullTransactionPoolApi: txpool::ChainApi + Send + 'static; + type FullTransactionPoolApi: txpool::ChainApi::Hash, Block = Self::Block> + Send + 'static; /// Extrinsic pool backend type for the light client. - type LightTransactionPoolApi: txpool::ChainApi + 'static; + type LightTransactionPoolApi: txpool::ChainApi::Hash, Block = Self::Block> + 'static; /// Genesis configuration for the runtime. type Genesis: RuntimeGenesis; /// Other configuration for service members. @@ -202,7 +199,7 @@ pub trait Components: 'static { type Executor: 'static + client::CallExecutor, Blake2Hasher> + Send + Sync; /// Extrinsic pool type. type TransactionPoolApi: 'static + txpool::ChainApi< - Hash = ::ExtrinsicHash, + Hash = <::Block as BlockT>::Hash, Block = FactoryBlock >; diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index 7232517a9b..47472feea3 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -59,8 +59,9 @@ pub mod chain_ops; use std::io; use std::net::SocketAddr; -use std::sync::Arc; use std::collections::HashMap; +#[doc(hidden)] +pub use std::{ops::Deref, result::Result, sync::Arc}; use futures::prelude::*; use parking_lot::Mutex; use keystore::Store as Keystore; @@ -68,7 +69,8 @@ use client::BlockchainEvents; use runtime_primitives::traits::{Header, As}; use runtime_primitives::generic::BlockId; use exit_future::Signal; -use tokio::runtime::TaskExecutor; +#[doc(hidden)] +pub use tokio::runtime::TaskExecutor; use substrate_executor::NativeExecutor; use codec::{Encode, Decode}; @@ -438,3 +440,163 @@ impl network::TransactionPool, ComponentBlock< self.pool.on_broadcasted(propagations) } } + +/// Creates a simple `Service` implementation. +/// This `Service` just holds an instance to a `service::Service` and implements `Deref`. +/// It also provides a `new` function that takes a `config` and a `TaskExecutor`. +#[macro_export] +macro_rules! construct_simple_service { + ( + $name: ident + ) => { + pub struct $name { + inner: $crate::Service, + } + + impl $name { + fn new( + config: FactoryFullConfiguration, + executor: $crate::TaskExecutor + ) -> $crate::Result { + Ok( + Self { + inner: $crate::Service::new(config, executor)? + } + ) + } + } + + impl $crate::Deref for $name { + type Target = $crate::Service; + + fn deref(&self) -> &Self::Target { + &self.inner + } + } + } +} + +/// Constructs a service factory with the given name that implements the `ServiceFactory` trait. +/// The required parameters are required to be given in the exact order. Some parameters are followed +/// by `{}` blocks. These blocks are required and used to initialize the given parameter. +/// In these block it is required to write a closure that takes the same number of arguments, +/// the corresponding function in the `ServiceFactory` trait provides. +/// +/// # Example +/// +/// ```nocompile +/// construct_service_factory! { +/// struct Factory { +/// // Declare the block type +/// Block = Block, +/// // Declare the network protocol and give an initializer. +/// NetworkProtocol = DemoProtocol { |config| Ok(DemoProtocol::new()) }, +/// RuntimeDispatch = node_executor::Executor, +/// FullTransactionPoolApi = transaction_pool::ChainApi, FullExecutor, Block> +/// { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, +/// LightTransactionPoolApi = transaction_pool::ChainApi, LightExecutor, Block> +/// { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, +/// Genesis = GenesisConfig, +/// Configuration = (), +/// FullService = Service> +/// { |config, executor| Service::>::new(config, executor) }, +/// LightService = Service> +/// { |config, executor| Service::>::new(config, executor) }, +/// // Declare the import queue. The import queue is special as it takes two initializers. +/// // The first one is for the initializing the full import queue and the second for the +/// // light import queue. +/// ImportQueue = BasicQueue +/// { |_, _| Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) } +/// { |_, _| Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) }, +/// } +/// } +/// ``` +#[macro_export] +macro_rules! construct_service_factory { + ( + $(#[$attr:meta])* + struct $name:ident { + Block = $block:ty, + NetworkProtocol = $protocol:ty { $( $protocol_init:tt )* }, + RuntimeDispatch = $dispatch:ty, + FullTransactionPoolApi = $full_transaction:ty { $( $full_transaction_init:tt )* }, + LightTransactionPoolApi = $light_transaction:ty { $( $light_transaction_init:tt )* }, + Genesis = $genesis:ty, + Configuration = $config:ty, + FullService = $full_service:ty { $( $full_service_init:tt )* }, + LightService = $light_service:ty { $( $light_service_init:tt )* }, + ImportQueue = $import_queue:ty + { $( $full_import_queue_init:tt )* } + { $( $light_import_queue_init:tt )* }, + } + ) => { + $( #[$attr] )* + pub struct $name {} + + #[allow(unused_variables)] + impl $crate::ServiceFactory for $name { + type Block = $block; + type NetworkProtocol = $protocol; + type RuntimeDispatch = $dispatch; + type FullTransactionPoolApi = $full_transaction; + type LightTransactionPoolApi = $light_transaction; + type Genesis = $genesis; + type Configuration = $config; + type FullService = $full_service; + type LightService = $light_service; + type ImportQueue = $import_queue; + + fn build_full_transaction_pool( + config: $crate::TransactionPoolOptions, + client: $crate::Arc<$crate::FullClient> + ) -> $crate::Result<$crate::TransactionPool, $crate::Error> + { + ( $( $full_transaction_init )* ) (config, client) + } + + fn build_light_transaction_pool( + config: $crate::TransactionPoolOptions, + client: $crate::Arc<$crate::LightClient> + ) -> $crate::Result<$crate::TransactionPool, $crate::Error> + { + ( $( $light_transaction_init )* ) (config, client) + } + + fn build_network_protocol(config: &$crate::FactoryFullConfiguration) + -> $crate::Result + { + ( $( $protocol_init )* ) (config) + } + + fn build_full_import_queue( + config: &$crate::FactoryFullConfiguration, + client: $crate::Arc<$crate::FullClient>, + ) -> $crate::Result { + ( $( $full_import_queue_init )* ) (config, client) + } + + fn build_light_import_queue( + config: &FactoryFullConfiguration, + client: Arc<$crate::LightClient>, + ) -> Result { + ( $( $light_import_queue_init )* ) (config, client) + } + + fn new_light( + config: $crate::FactoryFullConfiguration, + executor: $crate::TaskExecutor + ) -> $crate::Result + { + ( $( $light_service_init )* ) (config, executor) + } + + fn new_full( + config: $crate::FactoryFullConfiguration, + executor: $crate::TaskExecutor + ) -> Result + { + ( $( $full_service_init )* ) (config, executor) + } + } + } +} diff --git a/substrate/node/cli/Cargo.toml b/substrate/node/cli/Cargo.toml index 0b939bf01e..61b31a5f67 100644 --- a/substrate/node/cli/Cargo.toml +++ b/substrate/node/cli/Cargo.toml @@ -9,4 +9,16 @@ log = "0.4" tokio = "0.1.7" exit-future = "0.1" substrate-cli = { path = "../../core/cli" } -node-service = { path = "../service" } +substrate-primitives = { path = "../../core/primitives" } +node-runtime = { path = "../runtime" } +node-primitives = { path = "../primitives" } +node-network = { path = "../network" } +hex-literal = "0.1" +substrate-service = { path = "../../core/service" } +substrate-transaction-pool = { path = "../../core/transaction-pool" } +substrate-network = { path = "../../core/network" } +sr-primitives = { path = "../../core/sr-primitives" } +node-executor = { path = "../executor" } + +[dev-dependencies] +substrate-service-test = { path = "../../core/service/test" } diff --git a/substrate/node/service/res/bbq-birch.json b/substrate/node/cli/res/bbq-birch.json similarity index 100% rename from substrate/node/service/res/bbq-birch.json rename to substrate/node/cli/res/bbq-birch.json diff --git a/substrate/node/service/src/chain_spec.rs b/substrate/node/cli/src/chain_spec.rs similarity index 90% rename from substrate/node/service/src/chain_spec.rs rename to substrate/node/cli/src/chain_spec.rs index 7d11daa366..cc4612f27b 100644 --- a/substrate/node/service/src/chain_spec.rs +++ b/substrate/node/cli/src/chain_spec.rs @@ -20,11 +20,14 @@ use primitives::{AuthorityId, ed25519}; use node_runtime::{GenesisConfig, ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, DemocracyConfig, SessionConfig, StakingConfig, TimestampConfig, BalancesConfig, TreasuryConfig, ContractConfig, Permill, Perbill}; -use service::ChainSpec; +use substrate_service; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; -pub fn bbq_birch_config() -> Result, String> { +/// Specialised `ChainSpec`. +pub type ChainSpec = substrate_service::ChainSpec; + +pub fn bbq_birch_config() -> Result { ChainSpec::from_embedded(include_bytes!("../res/bbq-birch.json")) } @@ -122,7 +125,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { } /// Staging testnet config. -pub fn staging_testnet_config() -> ChainSpec { +pub fn staging_testnet_config() -> ChainSpec { let boot_nodes = vec![ ]; ChainSpec::from_genesis( @@ -227,7 +230,7 @@ fn development_config_genesis() -> GenesisConfig { } /// Development config (single validator Alice) -pub fn development_config() -> ChainSpec { +pub fn development_config() -> ChainSpec { ChainSpec::from_genesis("Development", "development", development_config_genesis, vec![], None, None, None) } @@ -238,18 +241,30 @@ fn local_testnet_genesis() -> GenesisConfig { ]) } -fn local_testnet_genesis_instant() -> GenesisConfig { - let mut genesis = local_testnet_genesis(); - genesis.timestamp = Some(TimestampConfig { period: 0 }); - genesis -} - /// Local testnet config (multivalidator Alice + Bob) -pub fn local_testnet_config() -> ChainSpec { +pub fn local_testnet_config() -> ChainSpec { ChainSpec::from_genesis("Local Testnet", "local_testnet", local_testnet_genesis, vec![], None, None, None) } -/// Local testnet config (multivalidator Alice + Bob) -pub fn integration_test_config() -> ChainSpec { - ChainSpec::from_genesis("Integration Test", "test", local_testnet_genesis_instant, vec![], None, None, None) +#[cfg(test)] +mod tests { + use super::*; + use service_test; + use service::Factory; + + fn local_testnet_genesis_instant() -> GenesisConfig { + let mut genesis = local_testnet_genesis(); + genesis.timestamp = Some(TimestampConfig { period: 0 }); + genesis + } + + /// Local testnet config (multivalidator Alice + Bob) + pub fn integration_test_config() -> ChainSpec { + ChainSpec::from_genesis("Integration Test", "test", local_testnet_genesis_instant, vec![], None, None, None) + } + + #[test] + fn test_connectivity() { + service_test::connectivity::(integration_test_config()); + } } diff --git a/substrate/node/cli/src/lib.rs b/substrate/node/cli/src/lib.rs index c83f8bb8fa..0d8c9c4d71 100644 --- a/substrate/node/cli/src/lib.rs +++ b/substrate/node/cli/src/lib.rs @@ -22,17 +22,32 @@ extern crate tokio; extern crate substrate_cli as cli; -extern crate node_service as service; +extern crate substrate_primitives as primitives; +extern crate node_runtime; extern crate exit_future; +#[macro_use] +extern crate hex_literal; +#[cfg(test)] +extern crate substrate_service_test as service_test; +extern crate substrate_transaction_pool as transaction_pool; +extern crate substrate_network as network; +extern crate node_network; +extern crate sr_primitives as runtime_primitives; +extern crate node_primitives; +#[macro_use] +extern crate substrate_service; +extern crate node_executor; #[macro_use] extern crate log; pub use cli::error; +mod chain_spec; +mod service; use tokio::runtime::Runtime; -pub use service::{Components as ServiceComponents, Service, CustomConfiguration, ServiceFactory}; pub use cli::{VersionInfo, IntoExit}; +use substrate_service::{ServiceFactory, Roles as ServiceRoles}; /// The chain specification option. #[derive(Clone, Debug)] @@ -49,12 +64,12 @@ pub enum ChainSpec { /// Get a chain config from a spec setting. impl ChainSpec { - pub(crate) fn load(self) -> Result { + pub(crate) fn load(self) -> Result { Ok(match self { - ChainSpec::BbqBirch => service::chain_spec::bbq_birch_config()?, - ChainSpec::Development => service::chain_spec::development_config(), - ChainSpec::LocalTestnet => service::chain_spec::local_testnet_config(), - ChainSpec::StagingTestnet => service::chain_spec::staging_testnet_config(), + ChainSpec::BbqBirch => chain_spec::bbq_birch_config()?, + ChainSpec::Development => chain_spec::development_config(), + ChainSpec::LocalTestnet => chain_spec::local_testnet_config(), + ChainSpec::StagingTestnet => chain_spec::staging_testnet_config(), }) } @@ -69,7 +84,7 @@ impl ChainSpec { } } -fn load_spec(id: &str) -> Result, String> { +fn load_spec(id: &str) -> Result, String> { Ok(match ChainSpec::from(id) { Some(spec) => Some(spec.load()?), None => None, @@ -93,7 +108,7 @@ pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Resul info!("Roles: {:?}", config.roles); let mut runtime = Runtime::new()?; let executor = runtime.executor(); - match config.roles == service::Roles::LIGHT { + match config.roles == ServiceRoles::LIGHT { true => run_until_exit(&mut runtime, service::Factory::new_light(config, executor)?, exit)?, false => run_until_exit(&mut runtime, service::Factory::new_full(config, executor)?, exit)?, } @@ -108,7 +123,7 @@ fn run_until_exit( e: E, ) -> error::Result<()> where - C: service::Components, + C: substrate_service::Components, E: IntoExit, { let (exit_send, exit) = exit_future::signal(); diff --git a/substrate/node/cli/src/service.rs b/substrate/node/cli/src/service.rs new file mode 100644 index 0000000000..470ac3db78 --- /dev/null +++ b/substrate/node/cli/src/service.rs @@ -0,0 +1,133 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![warn(unused_extern_crates)] + +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +use std::sync::Arc; +use transaction_pool::{self, txpool::{Pool as TransactionPool}}; +use node_primitives::Block; +use node_runtime::GenesisConfig; +use node_network::Protocol as DemoProtocol; +use substrate_service::{ + FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, + LightBackend, FullExecutor, LightExecutor +}; +use network::import_queue::{BasicQueue, BlockOrigin, ImportBlock, Verifier}; +use runtime_primitives::{traits::Block as BlockT}; +use primitives::AuthorityId; +use node_executor; + +// TODO: Remove me, when we have a functional consensus. +/// A verifier that doesn't actually do any checks +pub struct NoneVerifier; +/// This Verifiyer accepts all data as valid +impl Verifier for NoneVerifier { + fn verify( + &self, + origin: BlockOrigin, + header: B::Header, + justification: Vec, + body: Option> + ) -> Result<(ImportBlock, Option>), String> { + Ok((ImportBlock { + origin, + header, + body, + finalized: true, + external_justification: justification, + internal_justification: vec![], + auxiliary: Vec::new(), + }, None)) + } +} + +construct_simple_service!(Service); + +construct_service_factory! { + struct Factory { + Block = Block, + NetworkProtocol = DemoProtocol { |config| Ok(DemoProtocol::new()) }, + RuntimeDispatch = node_executor::Executor, + FullTransactionPoolApi = transaction_pool::ChainApi, FullExecutor, Block> + { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, + LightTransactionPoolApi = transaction_pool::ChainApi, LightExecutor, Block> + { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, + Genesis = GenesisConfig, + Configuration = (), + FullService = Service> + { |config, executor| Service::>::new(config, executor) }, + LightService = Service> + { |config, executor| Service::>::new(config, executor) }, + ImportQueue = BasicQueue + { |_, _| Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) } + { |_, _| Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) }, + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "rhd")] + fn test_sync() { + use {service_test, Factory}; + use client::{ImportBlock, BlockOrigin}; + + let alice: Arc = Arc::new(Keyring::Alice.into()); + let bob: Arc = Arc::new(Keyring::Bob.into()); + let validators = vec![alice.public().0.into(), bob.public().0.into()]; + let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob]; + let offline = Arc::new(RwLock::new(OfflineTracker::new())); + let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap(); + let block_factory = |service: &::FullService| { + let block_id = BlockId::number(service.client().info().unwrap().chain.best_number); + let parent_header = service.client().header(&block_id).unwrap().unwrap(); + let consensus_net = ConsensusNetwork::new(service.network(), service.client().clone()); + let proposer_factory = consensus::ProposerFactory { + client: service.client().clone(), + transaction_pool: service.transaction_pool().clone(), + network: consensus_net, + offline: offline.clone(), + force_delay: 0, + handle: dummy_runtime.executor(), + }; + let (proposer, _, _) = proposer_factory.init(&parent_header, &validators, alice.clone()).unwrap(); + let block = proposer.propose().expect("Error making test block"); + ImportBlock { + origin: BlockOrigin::File, + external_justification: Vec::new(), + internal_justification: Vec::new(), + finalized: true, + body: Some(block.extrinsics), + header: block.header, + auxiliary: Vec::new(), + } + }; + let extrinsic_factory = |service: &::FullService| { + let payload = (0, Call::Balances(BalancesCall::transfer(RawAddress::Id(bob.public().0.into()), 69.into())), Era::immortal(), service.client().genesis_hash()); + let signature = alice.sign(&payload.encode()).into(); + let id = alice.public().0.into(); + let xt = UncheckedExtrinsic { + signature: Some((RawAddress::Id(id), signature, payload.0, Era::immortal())), + function: payload.1, + }.encode(); + let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); + OpaqueExtrinsic(v) + }; + service_test::sync::(chain_spec::integration_test_config(), block_factory, extrinsic_factory); + } + +} diff --git a/substrate/node/service/Cargo.toml b/substrate/node/service/Cargo.toml deleted file mode 100644 index 2ef8ae5a12..0000000000 --- a/substrate/node/service/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "node-service" -version = "0.1.0" -authors = ["Parity Technologies "] - -[dependencies] -error-chain = "0.12" -hex-literal = "0.1" -lazy_static = "1.0" -log = "0.4" -node-consensus = { path = "../consensus" } -node-executor = { path = "../executor" } -node-network = { path = "../network" } -node-primitives = { path = "../primitives" } -node-runtime = { path = "../runtime" } -parity-codec = { version = "2.1" } -parking_lot = "0.4" -slog = "^2" -sr-io = { path = "../../core/sr-io" } -sr-primitives = { path = "../../core/sr-primitives" } -substrate-client = { path = "../../core/client" } -substrate-network = { path = "../../core/network" } -substrate-primitives = { path = "../../core/primitives" } -substrate-service = { path = "../../core/service" } -substrate-telemetry = { path = "../../core/telemetry" } -substrate-transaction-pool = { path = "../../core/transaction-pool" } -tokio = "0.1.7" - -[dev-dependencies] -substrate-service-test = { path = "../../core/service/test" } -substrate-test-client = { path = "../../core/test-client" } -substrate-keyring = { path = "../../core/keyring" } -rhododendron = "0.3" diff --git a/substrate/node/service/src/lib.rs b/substrate/node/service/src/lib.rs deleted file mode 100644 index dc799ba4dd..0000000000 --- a/substrate/node/service/src/lib.rs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![warn(unused_extern_crates)] - -//! Substrate service. Specialized wrapper over substrate service. - -extern crate node_primitives; -extern crate node_runtime; -extern crate node_executor; -extern crate node_network; -extern crate substrate_client as client; -extern crate substrate_network as network; -extern crate substrate_primitives as primitives; -extern crate substrate_service as service; -extern crate substrate_transaction_pool as transaction_pool; -extern crate tokio; -#[cfg(test)] -extern crate substrate_service_test as service_test; - -#[macro_use] -extern crate hex_literal; -#[cfg(all(test, feature="rhd"))] -extern crate rhododendron as rhd; -extern crate sr_primitives as runtime_primitives; -pub mod chain_spec; - -use std::sync::Arc; -use transaction_pool::txpool::{Pool as TransactionPool}; -use node_primitives::{Block, Hash}; -use node_runtime::GenesisConfig; -use client::Client; -use node_network::Protocol as DemoProtocol; -use tokio::runtime::TaskExecutor; -use service::FactoryFullConfiguration; -use network::import_queue::{BasicQueue, BlockOrigin, ImportBlock, Verifier}; -use runtime_primitives::{traits::Block as BlockT}; -use primitives::{Blake2Hasher, AuthorityId}; - -pub use service::{Roles, PruningMode, TransactionPoolOptions, ServiceFactory, - ErrorKind, Error, ComponentBlock, LightComponents, FullComponents}; -pub use client::ExecutionStrategy; - -/// Specialised `ChainSpec`. -pub type ChainSpec = service::ChainSpec; -/// Client type for specialised `Components`. -pub type ComponentClient = Client<::Backend, ::Executor, Block>; -pub type NetworkService = network::Service::NetworkProtocol, Hash>; - -/// A verifier that doesn't actually do any checks -pub struct NoneVerifier; -/// This Verifiyer accepts all data as valid -impl Verifier for NoneVerifier { - fn verify( - &self, - origin: BlockOrigin, - header: B::Header, - justification: Vec, - body: Option> - ) -> Result<(ImportBlock, Option>), String> { - Ok((ImportBlock { - origin, - header, - body, - finalized: true, - external_justification: justification, - internal_justification: vec![], - auxiliary: Vec::new(), - }, None)) - } -} - -/// A collection of type to generalise specific components over full / light client. -pub trait Components: service::Components { - /// Demo API. - type Api: 'static + Send + Sync; - /// Client backend. - type Backend: 'static + client::backend::Backend; - /// Client executor. - type Executor: 'static + client::CallExecutor + Send + Sync; -} - -impl Components for service::LightComponents { - type Api = service::LightClient; - type Executor = service::LightExecutor; - type Backend = service::LightBackend; -} - -impl Components for service::FullComponents { - type Api = service::FullClient; - type Executor = service::FullExecutor; - type Backend = service::FullBackend; -} - -/// All configuration for the node. -pub type Configuration = FactoryFullConfiguration; - -/// Demo-specific configuration. -#[derive(Default)] -pub struct CustomConfiguration; - -/// Config for the substrate service. -pub struct Factory; - -impl service::ServiceFactory for Factory { - type Block = Block; - type ExtrinsicHash = Hash; - type NetworkProtocol = DemoProtocol; - type RuntimeDispatch = node_executor::Executor; - type FullTransactionPoolApi = transaction_pool::ChainApi, service::FullExecutor, Block>; - type LightTransactionPoolApi = transaction_pool::ChainApi, service::LightExecutor, Block>; - type Genesis = GenesisConfig; - type Configuration = CustomConfiguration; - type FullService = Service>; - type LightService = Service>; - /// instance of import queue for clients - type ImportQueue = BasicQueue; - - fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc>) - -> Result, Error> - { - Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) - } - - fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc>) - -> Result, Error> - { - Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) - } - - fn build_network_protocol(_config: &Configuration) - -> Result - { - Ok(DemoProtocol::new()) - } - - fn build_full_import_queue( - _config: &FactoryFullConfiguration, - _client: Arc>, - ) -> Result, service::Error> { - Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) - } - - fn build_light_import_queue( - _config: &FactoryFullConfiguration, - _client: Arc>, - ) -> Result, service::Error> { - Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) - } - - fn new_light(config: Configuration, executor: TaskExecutor) - -> Result>, Error> - { - let service = service::Service::>::new(config, executor.clone())?; - Ok(Service { - inner: service, - _consensus: None, - }) - } - - fn new_full(config: Configuration, executor: TaskExecutor) - -> Result>, Error> - { - let service = service::Service::>::new(config, executor.clone())?; - // FIXME: Spin consensus service if configured - let consensus = None; - Ok(Service { - inner: service, - _consensus: consensus, - }) - } -} -/// Demo service. -pub struct Service { - inner: service::Service, - _consensus: Option, // FIXME: add actual consensus engine -} - -impl ::std::ops::Deref for Service { - type Target = service::Service; - fn deref(&self) -> &Self::Target { - &self.inner - } -} - - -/// Creates bare client without any networking. -pub fn new_client(config: Configuration) - -> Result>>, Error> -{ - service::new_client::(&config) -} - -#[cfg(test)] -mod tests { - use {service_test, Factory, chain_spec}; - - #[test] - fn test_connectivity() { - service_test::connectivity::(chain_spec::integration_test_config()); - } - - #[test] - #[cfg(feature = "rhd")] - fn test_sync() { - use client::{ImportBlock, BlockOrigin}; - - let alice: Arc = Arc::new(Keyring::Alice.into()); - let bob: Arc = Arc::new(Keyring::Bob.into()); - let validators = vec![alice.public().0.into(), bob.public().0.into()]; - let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob]; - let offline = Arc::new(RwLock::new(OfflineTracker::new())); - let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap(); - let block_factory = |service: &::FullService| { - let block_id = BlockId::number(service.client().info().unwrap().chain.best_number); - let parent_header = service.client().header(&block_id).unwrap().unwrap(); - let consensus_net = ConsensusNetwork::new(service.network(), service.client().clone()); - let proposer_factory = consensus::ProposerFactory { - client: service.client().clone(), - transaction_pool: service.transaction_pool().clone(), - network: consensus_net, - offline: offline.clone(), - force_delay: 0, - handle: dummy_runtime.executor(), - }; - let (proposer, _, _) = proposer_factory.init(&parent_header, &validators, alice.clone()).unwrap(); - let block = proposer.propose().expect("Error making test block"); - ImportBlock { - origin: BlockOrigin::File, - external_justification: Vec::new(), - internal_justification: Vec::new(), - finalized: true, - body: Some(block.extrinsics), - header: block.header, - auxiliary: Vec::new(), - } - }; - let extrinsic_factory = |service: &::FullService| { - let payload = (0, Call::Balances(BalancesCall::transfer(RawAddress::Id(bob.public().0.into()), 69.into())), Era::immortal(), service.client().genesis_hash()); - let signature = alice.sign(&payload.encode()).into(); - let id = alice.public().0.into(); - let xt = UncheckedExtrinsic { - signature: Some((RawAddress::Id(id), signature, payload.0, Era::immortal())), - function: payload.1, - }.encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); - OpaqueExtrinsic(v) - }; - service_test::sync::(chain_spec::integration_test_config(), block_factory, extrinsic_factory); - } - -}