diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index c17744a472..f62c803817 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -3325,6 +3325,7 @@ dependencies = [ "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)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-client 0.1.0", diff --git a/substrate/core/rpc/Cargo.toml b/substrate/core/rpc/Cargo.toml index 3f35394c91..0a1c95bb5e 100644 --- a/substrate/core/rpc/Cargo.toml +++ b/substrate/core/rpc/Cargo.toml @@ -11,6 +11,7 @@ jsonrpc-pubsub = { git="https://github.com/paritytech/jsonrpc.git" } log = "0.4" parking_lot = "0.4" parity-codec = "2.1" +serde_json = "1.0" substrate-client = { path = "../client" } substrate-executor = { path = "../executor" } substrate-transaction-pool = { path = "../transaction-pool" } diff --git a/substrate/core/rpc/src/system/mod.rs b/substrate/core/rpc/src/system/mod.rs index 78fd7dda87..44f9033a2d 100644 --- a/substrate/core/rpc/src/system/mod.rs +++ b/substrate/core/rpc/src/system/mod.rs @@ -37,5 +37,9 @@ build_rpc_trait! { /// Get the chain's type. Given as a string identifier. #[rpc(name = "system_chain")] fn system_chain(&self) -> Result; + + /// Get a custom set of properties as a JSON object, defined in the chain spec. + #[rpc(name = "system_properties")] + fn system_properties(&self) -> Result>; } } diff --git a/substrate/core/rpc/src/system/tests.rs b/substrate/core/rpc/src/system/tests.rs index 95f37e79c8..0a1222c068 100644 --- a/substrate/core/rpc/src/system/tests.rs +++ b/substrate/core/rpc/src/system/tests.rs @@ -27,6 +27,9 @@ impl SystemApi for () { fn system_chain(&self) -> Result { Ok("testchain".into()) } + fn system_properties(&self) -> Result> { + Ok(serde_json::map::Map::new()) + } } #[test] @@ -52,3 +55,11 @@ fn system_chain_works() { "testchain".to_owned() ); } + +#[test] +fn system_properties_works() { + assert_eq!( + SystemApi::system_properties(&()).unwrap(), + serde_json::map::Map::new() + ); +} diff --git a/substrate/core/service/src/chain_spec.rs b/substrate/core/service/src/chain_spec.rs index 1b9cad490a..bc3ebf63cb 100644 --- a/substrate/core/service/src/chain_spec.rs +++ b/substrate/core/service/src/chain_spec.rs @@ -88,8 +88,12 @@ struct ChainSpecFile { pub telemetry_url: Option, pub protocol_id: Option, pub consensus_engine: Option, + pub properties: Option, } +/// Arbitrary properties defined in chain spec as a JSON object +pub type Properties = json::map::Map; + /// A configuration of a chain. Can be used to build a genesis block. pub struct ChainSpec { spec: ChainSpecFile, @@ -130,6 +134,11 @@ impl ChainSpec { self.spec.consensus_engine.as_ref().map(String::as_str) } + pub fn properties(&self) -> Properties { + // Return an empty JSON object if 'properties' not defined in config + self.spec.properties.as_ref().unwrap_or(&json::map::Map::new()).clone() + } + /// Parse json content into a `ChainSpec` pub fn from_embedded(json: &'static [u8]) -> Result { let spec = json::from_slice(json).map_err(|e| format!("Error parsing spec file: {}", e))?; @@ -158,6 +167,7 @@ impl ChainSpec { telemetry_url: Option<&str>, protocol_id: Option<&str>, consensus_engine: Option<&str>, + properties: Option, ) -> Self { let spec = ChainSpecFile { @@ -167,6 +177,7 @@ impl ChainSpec { telemetry_url: telemetry_url.map(str::to_owned), protocol_id: protocol_id.map(str::to_owned), consensus_engine: consensus_engine.map(str::to_owned), + properties, }; ChainSpec { spec, diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index 3b817e4ced..07dbf9addb 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -78,7 +78,7 @@ use codec::{Encode, Decode}; pub use self::error::{ErrorKind, Error}; pub use config::{Configuration, Roles, PruningMode}; -pub use chain_spec::ChainSpec; +pub use chain_spec::{ChainSpec, Properties}; pub use transaction_pool::txpool::{self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError}; pub use client::ExecutionStrategy; @@ -235,6 +235,7 @@ impl Service // RPC let rpc_config = RpcConfig { chain_name: config.chain_spec.name().to_string(), + properties: config.chain_spec.properties().clone(), impl_name: config.impl_name, impl_version: config.impl_version, }; @@ -378,6 +379,7 @@ fn maybe_start_server(address: Option, start: F) -> Result substrate_rpc::system::error::Result { Ok(self.chain_name.clone()) } + + fn system_properties(&self) -> substrate_rpc::system::error::Result { + Ok(self.properties.clone()) + } } /// Transaction pool adapter. diff --git a/substrate/node/cli/res/bbq-birch.json b/substrate/node/cli/res/bbq-birch.json index 7504b7e8ca..ebd6b19fbd 100644 --- a/substrate/node/cli/res/bbq-birch.json +++ b/substrate/node/cli/res/bbq-birch.json @@ -1,6 +1,9 @@ { "name": "BBQ Birch", "id": "bbq-birch", + "properties": { + "tokenSymbol": "BBQ" + }, "telemetryUrl": "wss://telemetry.polkadot.io/submit/", "protocolId": null, "bootNodes": [ diff --git a/substrate/node/cli/src/chain_spec.rs b/substrate/node/cli/src/chain_spec.rs index 5058f0de60..a3fd6e0863 100644 --- a/substrate/node/cli/src/chain_spec.rs +++ b/substrate/node/cli/src/chain_spec.rs @@ -140,6 +140,7 @@ pub fn staging_testnet_config() -> ChainSpec { Some(STAGING_TELEMETRY_URL.into()), None, None, + None, ) } @@ -240,7 +241,7 @@ fn development_config_genesis() -> GenesisConfig { /// Development config (single validator Alice) pub fn development_config() -> ChainSpec { - ChainSpec::from_genesis("Development", "development", development_config_genesis, vec![], None, None, None) + ChainSpec::from_genesis("Development", "development", development_config_genesis, vec![], None, None, None, None) } fn local_testnet_genesis() -> GenesisConfig { @@ -254,7 +255,7 @@ fn local_testnet_genesis() -> GenesisConfig { /// Local testnet config (multivalidator Alice + Bob) pub fn local_testnet_config() -> ChainSpec { - ChainSpec::from_genesis("Local Testnet", "local_testnet", local_testnet_genesis, vec![], None, None, None) + ChainSpec::from_genesis("Local Testnet", "local_testnet", local_testnet_genesis, vec![], None, None, None, None) } #[cfg(test)] @@ -271,7 +272,7 @@ mod tests { /// 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) + ChainSpec::from_genesis("Integration Test", "test", local_testnet_genesis_instant, vec![], None, None, None, None) } #[test]