diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index f9e4f913c6..9395f4a6df 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -594,6 +594,7 @@ dependencies = [ "ansi_term 0.12.1", "node-cli", "rand 0.7.3", + "sc-chain-spec", "sc-keystore", "sp-core", "structopt", @@ -5841,6 +5842,7 @@ dependencies = [ "sc-telemetry", "serde", "serde_json", + "sp-chain-spec", "sp-core", "sp-runtime", ] @@ -6539,6 +6541,7 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", + "sp-chain-spec", "sp-core", "sp-io", "sp-offchain", @@ -6568,6 +6571,7 @@ dependencies = [ "parking_lot 0.10.0", "serde", "serde_json", + "sp-chain-spec", "sp-core", "sp-rpc", "sp-runtime", @@ -7267,6 +7271,14 @@ dependencies = [ "sp-state-machine", ] +[[package]] +name = "sp-chain-spec" +version = "2.0.0-alpha.5" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "sp-consensus" version = "0.8.0-alpha.5" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 035ae7bc37..ab19142da6 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -122,6 +122,7 @@ members = [ "primitives/consensus/pow", "primitives/consensus/vrf", "primitives/core", + "primitives/chain-spec", "primitives/debug-derive", "primitives/storage", "primitives/externalities", diff --git a/substrate/bin/node-template/node/src/chain_spec.rs b/substrate/bin/node-template/node/src/chain_spec.rs index 8ed91698eb..fb53edd9a1 100644 --- a/substrate/bin/node-template/node/src/chain_spec.rs +++ b/substrate/bin/node-template/node/src/chain_spec.rs @@ -3,10 +3,10 @@ use node_template_runtime::{ AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, SudoConfig, SystemConfig, WASM_BINARY, Signature }; -use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; -use sp_finality_grandpa::{AuthorityId as GrandpaId}; -use sc_service; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{Verify, IdentifyAccount}; +use sc_service::ChainType; // Note this is the URL for the telemetry server //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -42,6 +42,7 @@ pub fn development_config() -> ChainSpec { ChainSpec::from_genesis( "Development", "dev", + ChainType::Development, || testnet_genesis( vec![ authority_keys_from_seed("Alice"), @@ -67,6 +68,7 @@ pub fn local_testnet_config() -> ChainSpec { ChainSpec::from_genesis( "Local Testnet", "local_testnet", + ChainType::Local, || testnet_genesis( vec![ authority_keys_from_seed("Alice"), diff --git a/substrate/bin/node/cli/src/chain_spec.rs b/substrate/bin/node/cli/src/chain_spec.rs index 087977daaf..6d67c61381 100644 --- a/substrate/bin/node/cli/src/chain_spec.rs +++ b/substrate/bin/node/cli/src/chain_spec.rs @@ -27,7 +27,7 @@ use node_runtime::{ }; use node_runtime::Block; use node_runtime::constants::currency::*; -use sc_service; +use sc_service::ChainType; use hex_literal::hex; use sc_telemetry::TelemetryEndpoints; use grandpa_primitives::{AuthorityId as GrandpaId}; @@ -158,6 +158,7 @@ pub fn staging_testnet_config() -> ChainSpec { ChainSpec::from_genesis( "Staging Testnet", "staging_testnet", + ChainType::Live, staging_testnet_config_genesis, boot_nodes, Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)]) @@ -338,6 +339,7 @@ pub fn development_config() -> ChainSpec { ChainSpec::from_genesis( "Development", "dev", + ChainType::Development, development_config_genesis, vec![], None, @@ -364,6 +366,7 @@ pub fn local_testnet_config() -> ChainSpec { ChainSpec::from_genesis( "Local Testnet", "local_testnet", + ChainType::Local, local_testnet_genesis, vec![], None, @@ -396,6 +399,7 @@ pub(crate) mod tests { ChainSpec::from_genesis( "Integration Test", "test", + ChainType::Development, local_testnet_genesis_instant_single, vec![], None, @@ -410,6 +414,7 @@ pub(crate) mod tests { ChainSpec::from_genesis( "Integration Test", "test", + ChainType::Development, local_testnet_genesis, vec![], None, diff --git a/substrate/bin/utils/chain-spec-builder/Cargo.toml b/substrate/bin/utils/chain-spec-builder/Cargo.toml index 9b03dd17b7..bab393a86a 100644 --- a/substrate/bin/utils/chain-spec-builder/Cargo.toml +++ b/substrate/bin/utils/chain-spec-builder/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/paritytech/substrate/" [dependencies] ansi_term = "0.12.1" sc-keystore = { version = "2.0.0-alpha.5", path = "../../../client/keystore" } +sc-chain-spec = { version = "2.0.0-alpha.5", path = "../../../client/chain-spec" } node-cli = { version = "2.0.0-alpha.5", path = "../../node/cli" } sp-core = { version = "2.0.0-alpha.5", path = "../../../primitives/core" } rand = "0.7.2" diff --git a/substrate/bin/utils/chain-spec-builder/src/main.rs b/substrate/bin/utils/chain-spec-builder/src/main.rs index 5aa7e7fff7..1440187014 100644 --- a/substrate/bin/utils/chain-spec-builder/src/main.rs +++ b/substrate/bin/utils/chain-spec-builder/src/main.rs @@ -120,6 +120,7 @@ fn generate_chain_spec( let chain_spec = chain_spec::ChainSpec::from_genesis( "Custom", "custom", + sc_chain_spec::ChainType::Live, move || genesis_constructor(&authority_seeds, &endowed_accounts, &sudo_account), vec![], None, diff --git a/substrate/client/chain-spec/Cargo.toml b/substrate/client/chain-spec/Cargo.toml index 5d65cbd842..cf30ad6063 100644 --- a/substrate/client/chain-spec/Cargo.toml +++ b/substrate/client/chain-spec/Cargo.toml @@ -16,6 +16,7 @@ sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } +sp-chain-spec = { version = "2.0.0-alpha.5", path = "../../primitives/chain-spec" } sc-telemetry = { version = "2.0.0-alpha.5", path = "../telemetry" } [package.metadata.docs.rs] diff --git a/substrate/client/chain-spec/src/chain_spec.rs b/substrate/client/chain-spec/src/chain_spec.rs index a7cf1d8aac..9f3a10ee89 100644 --- a/substrate/client/chain-spec/src/chain_spec.rs +++ b/substrate/client/chain-spec/src/chain_spec.rs @@ -25,8 +25,7 @@ use serde::{Serialize, Deserialize}; use sp_core::storage::{StorageKey, StorageData, ChildInfo, Storage, StorageChild}; use sp_runtime::BuildStorage; use serde_json as json; -use crate::RuntimeGenesis; -use crate::extension::GetExtension; +use crate::{RuntimeGenesis, ChainType, extension::GetExtension, Properties}; use sc_network::config::MultiaddrWithPeerId; use sc_telemetry::TelemetryEndpoints; @@ -137,6 +136,8 @@ enum Genesis { struct ClientSpec { name: String, id: String, + #[serde(default)] + chain_type: ChainType, boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option, @@ -149,9 +150,6 @@ struct ClientSpec { genesis: serde::de::IgnoredAny, } -/// Arbitrary properties defined in chain spec as a JSON object -pub type Properties = json::map::Map; - /// A type denoting empty extensions. /// /// We use `Option` here since `()` is not flattenable by serde. @@ -219,6 +217,7 @@ impl ChainSpec { pub fn from_genesis G + 'static + Send + Sync>( name: &str, id: &str, + chain_type: ChainType, constructor: F, boot_nodes: Vec, telemetry_endpoints: Option, @@ -229,6 +228,7 @@ impl ChainSpec { let client_spec = ClientSpec { name: name.to_owned(), id: id.to_owned(), + chain_type, boot_nodes, telemetry_endpoints, protocol_id: protocol_id.map(str::to_owned), @@ -243,6 +243,11 @@ impl ChainSpec { genesis: GenesisSource::Factory(Arc::new(constructor)), } } + + /// Type of the chain. + fn chain_type(&self) -> ChainType { + self.client_spec.chain_type.clone() + } } impl ChainSpec { @@ -332,6 +337,10 @@ where ChainSpec::id(self) } + fn chain_type(&self) -> ChainType { + ChainSpec::chain_type(self) + } + fn telemetry_endpoints(&self) -> &Option { ChainSpec::telemetry_endpoints(self) } @@ -392,6 +401,7 @@ mod tests { ).unwrap(); assert_eq!(spec1.as_json(false), spec2.as_json(false)); + assert_eq!(spec2.chain_type(), ChainType::Live) } #[derive(Debug, Serialize, Deserialize)] diff --git a/substrate/client/chain-spec/src/lib.rs b/substrate/client/chain-spec/src/lib.rs index b7875fdbb4..de83e170e0 100644 --- a/substrate/client/chain-spec/src/lib.rs +++ b/substrate/client/chain-spec/src/lib.rs @@ -107,13 +107,13 @@ //! pub type MyChainSpec = GenericChainSpec; //! ``` - mod chain_spec; mod extension; -pub use chain_spec::{ChainSpec as GenericChainSpec, Properties, NoExtension}; +pub use chain_spec::{ChainSpec as GenericChainSpec, NoExtension}; pub use extension::{Group, Fork, Forks, Extension, GetExtension, get_extension}; pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; +pub use sp_chain_spec::{Properties, ChainType}; use serde::{Serialize, de::DeserializeOwned}; use sp_runtime::BuildStorage; @@ -124,12 +124,14 @@ use sc_telemetry::TelemetryEndpoints; pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} impl RuntimeGenesis for T {} -/// Common interface to `GenericChainSpec` +/// Common interface of a chain specification. pub trait ChainSpec: BuildStorage + Send { /// Spec name. fn name(&self) -> &str; /// Spec id. fn id(&self) -> &str; + /// Type of the chain. + fn chain_type(&self) -> ChainType; /// A list of bootnode addresses. fn boot_nodes(&self) -> &[MultiaddrWithPeerId]; /// Telemetry endpoints (if any) diff --git a/substrate/client/rpc-api/Cargo.toml b/substrate/client/rpc-api/Cargo.toml index c5043b5b07..10b4b1746e 100644 --- a/substrate/client/rpc-api/Cargo.toml +++ b/substrate/client/rpc-api/Cargo.toml @@ -21,6 +21,7 @@ parking_lot = "0.10.0" sp-core = { version = "2.0.0-alpha.5", path = "../../primitives/core" } sp-version = { version = "2.0.0-alpha.5", path = "../../primitives/version" } sp-runtime = { path = "../../primitives/runtime" , version = "2.0.0-alpha.5"} +sp-chain-spec = { path = "../../primitives/chain-spec" , version = "2.0.0-alpha.5"} serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" sp-transaction-pool = { version = "2.0.0-alpha.5", path = "../../primitives/transaction-pool" } diff --git a/substrate/client/rpc-api/src/system/helpers.rs b/substrate/client/rpc-api/src/system/helpers.rs index 80718cf487..46461d6988 100644 --- a/substrate/client/rpc-api/src/system/helpers.rs +++ b/substrate/client/rpc-api/src/system/helpers.rs @@ -18,10 +18,7 @@ use std::fmt; use serde::{Serialize, Deserialize}; -use serde_json::{Value, map::Map}; - -/// Node properties -pub type Properties = Map; +use sp_chain_spec::{Properties, ChainType}; /// Running node's static details. #[derive(Clone, Debug)] @@ -34,6 +31,8 @@ pub struct SystemInfo { pub chain_name: String, /// A custom set of properties defined in the chain spec. pub properties: Properties, + /// The type of this chain. + pub chain_type: ChainType, } /// Health struct returned by the RPC diff --git a/substrate/client/rpc-api/src/system/mod.rs b/substrate/client/rpc-api/src/system/mod.rs index f12a11e0b3..25f147b694 100644 --- a/substrate/client/rpc-api/src/system/mod.rs +++ b/substrate/client/rpc-api/src/system/mod.rs @@ -25,7 +25,7 @@ use futures::{future::BoxFuture, compat::Compat}; use self::error::Result as SystemResult; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; /// Substrate system RPC API @@ -39,13 +39,17 @@ pub trait SystemApi { #[rpc(name = "system_version")] fn system_version(&self) -> SystemResult; - /// Get the chain's type. Given as a string identifier. + /// Get the chain's name. Given as a string identifier. #[rpc(name = "system_chain")] fn system_chain(&self) -> SystemResult; + /// Get the chain's type. + #[rpc(name = "system_chainType")] + fn system_type(&self) -> SystemResult; + /// Get a custom set of properties as a JSON object, defined in the chain spec. #[rpc(name = "system_properties")] - fn system_properties(&self) -> SystemResult; + fn system_properties(&self) -> SystemResult; /// Return health status of the node. /// diff --git a/substrate/client/rpc/Cargo.toml b/substrate/client/rpc/Cargo.toml index 7092959b83..f852c452d7 100644 --- a/substrate/client/rpc/Cargo.toml +++ b/substrate/client/rpc/Cargo.toml @@ -27,6 +27,7 @@ sp-runtime = { version = "2.0.0-alpha.5", path = "../../primitives/runtime" } sp-utils = { version = "2.0.0-alpha.5", path = "../../primitives/utils" } sp-rpc = { version = "2.0.0-alpha.5", path = "../../primitives/rpc" } sp-state-machine = { version = "0.8.0-alpha.5", path = "../../primitives/state-machine" } +sp-chain-spec = { version = "2.0.0-alpha.5", path = "../../primitives/chain-spec" } sc-executor = { version = "0.8.0-alpha.5", path = "../executor" } sc-block-builder = { version = "0.8.0-alpha.5", path = "../../client/block-builder" } sc-keystore = { version = "2.0.0-alpha.5", path = "../keystore" } diff --git a/substrate/client/rpc/src/system/mod.rs b/substrate/client/rpc/src/system/mod.rs index 9565992cf4..e18d4d09a1 100644 --- a/substrate/client/rpc/src/system/mod.rs +++ b/substrate/client/rpc/src/system/mod.rs @@ -28,7 +28,7 @@ use sp_runtime::traits::{self, Header as HeaderT}; use self::error::Result; pub use sc_rpc_api::system::*; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; /// System API implementation @@ -82,7 +82,11 @@ impl SystemApi::Number> for Sy Ok(self.info.chain_name.clone()) } - fn system_properties(&self) -> Result { + fn system_type(&self) -> Result { + Ok(self.info.chain_type.clone()) + } + + fn system_properties(&self) -> Result { Ok(self.info.properties.clone()) } diff --git a/substrate/client/rpc/src/system/tests.rs b/substrate/client/rpc/src/system/tests.rs index d45894743c..f0331f50ed 100644 --- a/substrate/client/rpc/src/system/tests.rs +++ b/substrate/client/rpc/src/system/tests.rs @@ -105,6 +105,7 @@ fn api>>(sync: T) -> System { impl_version: "0.2.0".into(), chain_name: "testchain".into(), properties: Default::default(), + chain_type: Default::default(), }, tx) } @@ -117,7 +118,7 @@ fn wait_receiver(rx: Receiver) -> T { fn system_name_works() { assert_eq!( api(None).system_name().unwrap(), - "testclient".to_owned() + "testclient".to_owned(), ); } @@ -125,7 +126,7 @@ fn system_name_works() { fn system_version_works() { assert_eq!( api(None).system_version().unwrap(), - "0.2.0".to_owned() + "0.2.0".to_owned(), ); } @@ -133,7 +134,7 @@ fn system_version_works() { fn system_chain_works() { assert_eq!( api(None).system_chain().unwrap(), - "testchain".to_owned() + "testchain".to_owned(), ); } @@ -141,7 +142,15 @@ fn system_chain_works() { fn system_properties_works() { assert_eq!( api(None).system_properties().unwrap(), - serde_json::map::Map::new() + serde_json::map::Map::new(), + ); +} + +#[test] +fn system_type_works() { + assert_eq!( + api(None).system_type().unwrap(), + Default::default(), ); } diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index 0586a61a89..0eefbe730f 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -1016,6 +1016,7 @@ ServiceBuilder< impl_name: config.impl_name.into(), impl_version: config.impl_version.into(), properties: chain_spec.properties().clone(), + chain_type: chain_spec.chain_type().clone(), }; let subscriptions = sc_rpc::Subscriptions::new(Arc::new(tasks_builder.spawn_handle())); diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index 16b1d0d718..d5db64ea46 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -62,7 +62,7 @@ pub use self::builder::{ pub use config::{Configuration, Role, PruningMode, DatabaseConfig}; pub use sc_chain_spec::{ ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension, - NoExtension, + NoExtension, ChainType, }; pub use sp_transaction_pool::{TransactionPool, InPoolTransaction, error::IntoPoolError}; pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions; diff --git a/substrate/primitives/chain-spec/Cargo.toml b/substrate/primitives/chain-spec/Cargo.toml new file mode 100644 index 0000000000..62d64bf614 --- /dev/null +++ b/substrate/primitives/chain-spec/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "sp-chain-spec" +version = "2.0.0-alpha.5" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Substrate chain configurations types." + +[dependencies] +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" diff --git a/substrate/primitives/chain-spec/src/lib.rs b/substrate/primitives/chain-spec/src/lib.rs new file mode 100644 index 0000000000..13ebc09b6c --- /dev/null +++ b/substrate/primitives/chain-spec/src/lib.rs @@ -0,0 +1,42 @@ +// Copyright 2020 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 . + +//! Types and traits related to chain specifications. + +/// The type of a chain. +/// +/// This can be used by tools to determine the type of a chain for displaying +/// additional information or enabling additional features. +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)] +pub enum ChainType { + /// A development chain that runs mainly on one node. + Development, + /// A local chain that runs locally on multiple nodes for testing purposes. + Local, + /// A live chain. + Live, + /// Some custom chain type. + Custom(String), +} + +impl Default for ChainType { + fn default() -> Self { + Self::Live + } +} + +/// Arbitrary properties defined in chain spec as a JSON object +pub type Properties = serde_json::map::Map;