From 9e79dd238c95ade959df06d1bb1e270ca8b39dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 19 Sep 2019 16:27:57 +0200 Subject: [PATCH 01/17] Add some chainspec tests and make sure we validate it. --- core/service/res/chain_spec.json | 31 ++++ core/service/res/chain_spec2.json | 32 ++++ .../src/{ => chain_spec}/chain_spec.rs | 140 +++++++++++++----- core/service/src/chain_spec/extension.rs | 93 ++++++++++++ core/service/src/chain_spec/mod.rs | 21 +++ core/service/src/lib.rs | 2 +- core/telemetry/src/lib.rs | 2 +- 7 files changed, 281 insertions(+), 40 deletions(-) create mode 100644 core/service/res/chain_spec.json create mode 100644 core/service/res/chain_spec2.json rename core/service/src/{ => chain_spec}/chain_spec.rs (75%) create mode 100644 core/service/src/chain_spec/extension.rs create mode 100644 core/service/src/chain_spec/mod.rs diff --git a/core/service/res/chain_spec.json b/core/service/res/chain_spec.json new file mode 100644 index 0000000000000..673f35d507919 --- /dev/null +++ b/core/service/res/chain_spec.json @@ -0,0 +1,31 @@ +{ + "name": "Flaming Fir", + "id": "flaming-fir", + "properties": { + "tokenDecimals": 15, + "tokenSymbol": "FIR" + }, + "bootNodes": [ + "/ip4/35.246.224.91/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.210.11/tcp/30333/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.246.210.11/tcp/30334/ws/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.198.110.45/tcp/30333/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.110.45/tcp/30334/ws/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.114.154/tcp/30333/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6", + "/ip4/35.198.114.154/tcp/30334/ws/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6" + ], + "telemetryEndpoints": [ + ["wss://telemetry.polkadot.io/submit/", 0] + ], + "protocolId": "fir", + "consensusEngine": null, + "genesis": { + "raw": [ + { + "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106" + }, + {} + ] + } +} diff --git a/core/service/res/chain_spec2.json b/core/service/res/chain_spec2.json new file mode 100644 index 0000000000000..950a7fc827494 --- /dev/null +++ b/core/service/res/chain_spec2.json @@ -0,0 +1,32 @@ +{ + "name": "Flaming Fir", + "id": "flaming-fir", + "properties": { + "tokenDecimals": 15, + "tokenSymbol": "FIR" + }, + "bootNodes": [ + "/ip4/35.246.224.91/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.210.11/tcp/30333/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.246.210.11/tcp/30334/ws/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.198.110.45/tcp/30333/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.110.45/tcp/30334/ws/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.114.154/tcp/30333/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6", + "/ip4/35.198.114.154/tcp/30334/ws/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6" + ], + "telemetryEndpoints": [ + ["wss://telemetry.polkadot.io/submit/", 0] + ], + "protocolId": "fir", + "consensusEngine": null, + "myProperty": "Test Extension", + "genesis": { + "raw": [ + { + "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106" + }, + {} + ] + } +} diff --git a/core/service/src/chain_spec.rs b/core/service/src/chain_spec/chain_spec.rs similarity index 75% rename from core/service/src/chain_spec.rs rename to core/service/src/chain_spec/chain_spec.rs index 8b35b0bac9581..d0c65836c0552 100644 --- a/core/service/src/chain_spec.rs +++ b/core/service/src/chain_spec/chain_spec.rs @@ -98,28 +98,36 @@ enum Genesis { ), } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] -struct ChainSpecFile { +#[serde(deny_unknown_fields)] +struct ChainSpecFile { pub name: String, pub id: String, pub boot_nodes: Vec, pub telemetry_endpoints: Option, pub protocol_id: Option, - pub consensus_engine: Option, pub properties: Option, + #[serde(flatten)] + pub extensions: E, + // Never used, left only for backward compatibility. + consensus_engine: (), + #[serde(skip_serializing)] + genesis: serde::de::IgnoredAny, } /// Arbitrary properties defined in chain spec as a JSON object pub type Properties = json::map::Map; +type Empty = Option<()>; + /// A configuration of a chain. Can be used to build a genesis block. -pub struct ChainSpec { - spec: ChainSpecFile, +pub struct ChainSpec { + spec: ChainSpecFile, genesis: GenesisSource, } -impl Clone for ChainSpec { +impl Clone for ChainSpec { fn clone(&self) -> Self { ChainSpec { spec: self.spec.clone(), @@ -128,7 +136,7 @@ impl Clone for ChainSpec { } } -impl ChainSpec { +impl ChainSpec { /// A list of bootnode addresses. pub fn boot_nodes(&self) -> &[String] { &self.spec.boot_nodes @@ -154,14 +162,10 @@ impl ChainSpec { self.spec.protocol_id.as_ref().map(String::as_str) } - /// Name of the consensus engine. - pub fn consensus_engine(&self) -> Option<&str> { - self.spec.consensus_engine.as_ref().map(String::as_str) - } - /// Additional loosly-typed properties of the chain. + /// + /// Returns an empty JSON object if 'properties' not defined in config 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() } @@ -170,24 +174,9 @@ impl ChainSpec { self.spec.boot_nodes.push(addr.to_string()) } - /// Parse json content into a `ChainSpec` - pub fn from_json_bytes(json: impl Into>) -> Result { - let json = json.into(); - let spec = json::from_slice(json.as_ref()).map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(ChainSpec { - spec, - genesis: GenesisSource::Binary(json), - }) - } - - /// Parse json file into a `ChainSpec` - pub fn from_json_file(path: PathBuf) -> Result { - let file = File::open(&path).map_err(|e| format!("Error opening spec file: {}", e))?; - let spec = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(ChainSpec { - spec, - genesis: GenesisSource::File(path), - }) + /// Returns a reference to defined chain spec extensions. + pub fn extensions(&self) -> &E { + &self.spec.extensions } /// Create hardcoded spec. @@ -198,19 +187,21 @@ impl ChainSpec { boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option<&str>, - consensus_engine: Option<&str>, properties: Option, - ) -> Self - { + extensions: E, + ) -> Self { let spec = ChainSpecFile { name: name.to_owned(), id: id.to_owned(), boot_nodes: boot_nodes, telemetry_endpoints, protocol_id: protocol_id.map(str::to_owned), - consensus_engine: consensus_engine.map(str::to_owned), properties, + extensions, + consensus_engine: (), + genesis: Default::default(), }; + ChainSpec { spec, genesis: GenesisSource::Factory(constructor), @@ -218,13 +209,35 @@ impl ChainSpec { } } -impl ChainSpec { +impl ChainSpec { + /// Parse json content into a `ChainSpec` + pub fn from_json_bytes(json: impl Into>) -> Result { + let json = json.into(); + let spec = json::from_slice(json.as_ref()).map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + spec, + genesis: GenesisSource::Binary(json), + }) + } + + /// Parse json file into a `ChainSpec` + pub fn from_json_file(path: PathBuf) -> Result { + let file = File::open(&path).map_err(|e| format!("Error opening spec file: {}", e))?; + let spec = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + spec, + genesis: GenesisSource::File(path), + }) + } +} + +impl ChainSpec { /// Dump to json string. pub fn to_json(self, raw: bool) -> Result { #[derive(Serialize, Deserialize)] - struct Container { + struct Container { #[serde(flatten)] - spec: ChainSpecFile, + spec: ChainSpecFile, genesis: Genesis, }; @@ -254,3 +267,54 @@ impl ChainSpec { json::to_string_pretty(&spec).map_err(|e| format!("Error generating spec json: {}", e)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, Serialize, Deserialize)] + struct Genesis(HashMap); + + impl BuildStorage for Genesis { + fn assimilate_storage( + self, + storage: &mut (StorageOverlay, ChildrenStorageOverlay), + ) -> Result<(), String> { + storage.0.extend( + self.0.into_iter().map(|(a, b)| (a.into_bytes(), b.into_bytes())) + ); + Ok(()) + } + } + + type TestSpec = ChainSpec; + + #[test] + fn should_deserailize_example_chain_spec() { + let spec1 = TestSpec::from_json_bytes(Cow::Owned( + include_bytes!("../../res/chain_spec.json").to_vec() + )).unwrap(); + let spec2 = TestSpec::from_json_file( + PathBuf::from("./res/chain_spec.json") + ).unwrap(); + + assert_eq!(spec1.to_json(false), spec2.to_json(false)); + } + + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + struct Extension1 { + my_property: String, + } + + type TestSpec2 = ChainSpec; + + #[test] + fn should_deserialize_chain_spec_with_extensions() { + let spec = TestSpec2::from_json_bytes(Cow::Owned( + include_bytes!("../../res/chain_spec2.json").to_vec() + )).unwrap(); + + assert_eq!(spec.extensions().my_property, "Test Extension"); + } +} diff --git a/core/service/src/chain_spec/extension.rs b/core/service/src/chain_spec/extension.rs new file mode 100644 index 0000000000000..f6c2a773d5e33 --- /dev/null +++ b/core/service/src/chain_spec/extension.rs @@ -0,0 +1,93 @@ +// Copyright 2019 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 . + +//! Chain Spec extensions helpers. + +use std::collections::BTreeMap; + +/// A `ChainSpec` extension. +trait Extension: Clone { + /// An associated type containing fork definition. + type Fork: Fork + From; +} + +/// A `ChainSpec` extension fork definition. +/// +/// Basically should look the same as `Extension`, but +/// all parameters are optional. This allows changing +/// only one parameter as part of the fork. +/// The forks can be combined (summed up) to specify +/// a complete set of parameters +trait Fork: Clone { + /// A base `Extension` type. + type Base: Extension; + + /// Combine with another struct. + /// + /// All parameters set in `other` should override the + /// ones in the current struct. + fn combine_with(&mut self, other: &Self); + + /// Attempt to convert to the base type if all parameters are set. + fn to_base(self) -> Result; +} + +/// A collection of `ChainSpec` extensions. +pub trait Extensions { + /// Get an extension of specific type. + fn get(&self) -> Option<&T>; +} + + +pub struct Forks { + base: T, + forks: BTreeMap, +} + +impl Forks { + /// Return a set of parameters for `Extension` including all forks up to `block` (inclusive). + pub fn for_block(&self, block: BlockNumber) -> T { + let start = self.base.clone().into(); + + for fork in self.forks.range(..=block) { + start.combine_with(fork); + } + + start + .to_base() + .expect("We start from the `base` object, so it's always fully initialized; qed") + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(ChainSpecExtension)] + pub struct Extension1 { + pub test: u64, + } + + #[derive(ChainSpecExtension)] + pub struct Extension2 { + pub test: u8, + } + + extensions! { + ext1: Extension1, + ext2: Extension2, + } +} diff --git a/core/service/src/chain_spec/mod.rs b/core/service/src/chain_spec/mod.rs new file mode 100644 index 0000000000000..c89d05a4bb21f --- /dev/null +++ b/core/service/src/chain_spec/mod.rs @@ -0,0 +1,21 @@ +// Copyright 2019 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 . + +//! Substrate chain configurations. + +mod chain_spec; + +pub use chain_spec::{ChainSpec, Properties}; diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index 431776b31e9b4..faa0498a9e531 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -345,7 +345,7 @@ macro_rules! new_impl { chain_name: $config.chain_spec.name().into(), impl_name: $config.impl_name.into(), impl_version: $config.impl_version.into(), - properties: $config.chain_spec.properties(), + properties: $config.chain_spec.properties().clone(), }; $start_rpc( client.clone(), diff --git a/core/telemetry/src/lib.rs b/core/telemetry/src/lib.rs index 71a86defb6d3e..768fc2df84e6a 100644 --- a/core/telemetry/src/lib.rs +++ b/core/telemetry/src/lib.rs @@ -92,7 +92,7 @@ pub struct TelemetryConfig { /// maximum verbosity level. /// /// The URL string can be either a URL or a multiaddress. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TelemetryEndpoints(Vec<(String, u8)>); impl TelemetryEndpoints { From 5651aa4d8af6c59fb9de4c26b01da01860293155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 20 Sep 2019 10:35:26 +0200 Subject: [PATCH 02/17] Manual implementation of Extension + Forks definitions. --- core/service/src/chain_spec/extension.rs | 295 +++++++++++++++++++++-- core/service/src/chain_spec/mod.rs | 1 + 2 files changed, 279 insertions(+), 17 deletions(-) diff --git a/core/service/src/chain_spec/extension.rs b/core/service/src/chain_spec/extension.rs index f6c2a773d5e33..41dcedc06b267 100644 --- a/core/service/src/chain_spec/extension.rs +++ b/core/service/src/chain_spec/extension.rs @@ -16,12 +16,16 @@ //! Chain Spec extensions helpers. +use std::fmt::Debug; use std::collections::BTreeMap; /// A `ChainSpec` extension. -trait Extension: Clone { +pub trait Extension: Sized { /// An associated type containing fork definition. - type Fork: Fork + From; + type Fork: Fork; + + /// Convert to fork type. + fn to_fork(self) -> Self::Fork; } /// A `ChainSpec` extension fork definition. @@ -31,7 +35,7 @@ trait Extension: Clone { /// only one parameter as part of the fork. /// The forks can be combined (summed up) to specify /// a complete set of parameters -trait Fork: Clone { +pub trait Fork: Sized { /// A base `Extension` type. type Base: Extension; @@ -39,31 +43,102 @@ trait Fork: Clone { /// /// All parameters set in `other` should override the /// ones in the current struct. - fn combine_with(&mut self, other: &Self); + fn combine_with(&mut self, other: Self); /// Attempt to convert to the base type if all parameters are set. fn to_base(self) -> Result; } +macro_rules! impl_trivial { + () => {}; + ($A : ty) => { + impl_trivial!($A ,); + }; + ($A : ty , $( $B : ty ),*) => { + impl_trivial!($( $B ),*); + + impl Extension for $A { + type Fork = $A; + + fn to_fork(self) -> Self::Fork { + self + } + } + + impl Fork for $A { + type Base = $A; + + fn combine_with(&mut self, other: Self) { + *self = other; + } + + fn to_base(self) -> Result { + Ok(self) + } + } + } +} + +impl_trivial!(u8, u16, u32, u64, usize, String, Vec); + +impl Extension for Option { + type Fork = Option; + + fn to_fork(self) -> Self::Fork { + self.map(|a| a.to_fork()) + } +} + +impl Fork for Option { + type Base = Option; + + fn combine_with(&mut self, other: Self) { + *self = match (self.take(), other) { + (Some(mut a), Some(b)) => { + a.combine_with(b); + Some(a) + }, + (a, b) => a.or(b), + }; + } + + fn to_base(self) -> Result { + // TODO [ToDr] Handle error + Ok(self.map(|x| x.to_base().ok().unwrap())) + } +} + /// A collection of `ChainSpec` extensions. pub trait Extensions { /// Get an extension of specific type. - fn get(&self) -> Option<&T>; + fn get(&self) -> Option<&T>; } - -pub struct Forks { +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub struct Forks where + T::Fork: serde::Serialize + serde::de::DeserializeOwned, +{ + #[serde(flatten)] base: T, forks: BTreeMap, } -impl Forks { +impl Forks where + T::Fork: serde::Serialize + serde::de::DeserializeOwned + Clone + Debug, +{ + /// Create new fork definition given the base and the forks. + pub fn new(base: T, forks: BTreeMap) -> Self { + Self { base, forks } + } + /// Return a set of parameters for `Extension` including all forks up to `block` (inclusive). - pub fn for_block(&self, block: BlockNumber) -> T { - let start = self.base.clone().into(); + pub fn for_block(&self, block: B) -> T { + let mut start = self.base.clone().to_fork(); - for fork in self.forks.range(..=block) { - start.combine_with(fork); + println!("Starting: {:?}", start); + for (_, fork) in self.forks.range(..=block) { + start.combine_with(fork.clone()); + println!("Combined: {:?} + {:?}", start, fork); } start @@ -75,19 +150,205 @@ impl Forks { #[cfg(test)] mod tests { use super::*; + use serde::{Serialize, Deserialize}; - #[derive(ChainSpecExtension)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Extension1 { pub test: u64, } - #[derive(ChainSpecExtension)] + impl Extension for Extension1 { + type Fork = Extension1Fork; + + fn to_fork(self) -> Self::Fork { + Extension1Fork { + test: Some(self.test.to_fork()), + } + } + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct Extension1Fork { + pub test: Option, + } + + impl Fork for Extension1Fork { + type Base = Extension1; + + fn combine_with(&mut self, other: Self) { + self.test.combine_with(other.test); + } + + fn to_base(self) -> Result { + if self.test.is_none() { + Err(self) + } else { + Ok(Extension1 { + test: self.test.unwrap(), + }) + } + } + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Extension2 { pub test: u8, } - extensions! { - ext1: Extension1, - ext2: Extension2, + impl Extension for Extension2 { + type Fork = Extension2Fork; + + fn to_fork(self) -> Self::Fork { + Extension2Fork { + test: Some(self.test.to_fork()), + } + } + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct Extension2Fork { + pub test: Option, + } + + impl Fork for Extension2Fork { + type Base = Extension2; + + fn combine_with(&mut self, other: Self) { + self.test.combine_with(other.test) + } + + fn to_base(self) -> Result { + if self.test.is_none() { + Err(self) + } else { + Ok(Extension2 { + test: self.test.unwrap().to_base().unwrap(), + }) + } + } } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct Extensions { + pub ext1: Extension1, + pub ext2: Extension2, + } + + impl super::Extensions for Extensions { + fn get(&self) -> Option<&T> { + use std::any::{Any, TypeId}; + + match TypeId::of::() { + x if x == TypeId::of::() => Any::downcast_ref(&self.ext1), + x if x == TypeId::of::() => Any::downcast_ref(&self.ext2), + _ => None, + } + } + } + + impl Extension for Extensions { + type Fork = ExtensionsFork; + + fn to_fork(self) -> Self::Fork { + ExtensionsFork { + ext1: Some(self.ext1.to_fork()), + ext2: Some(self.ext2.to_fork()), + } + } + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct ExtensionsFork { + pub ext1: Option, + pub ext2: Option, + } + + impl Fork for ExtensionsFork { + type Base = Extensions; + + fn combine_with(&mut self, other: Self) { + self.ext1.combine_with(other.ext1); + self.ext2.combine_with(other.ext2); + } + + fn to_base(self) -> Result { + if self.ext1.is_none() || self.ext2.is_none() { + Err(self) + } else { + Ok(Extensions { + ext1: self.ext1.unwrap().to_base().unwrap(), + ext2: self.ext2.unwrap().to_base().unwrap(), + }) + } + } + } + + #[test] + fn forks_should_work_correctly() { + use super::Extensions as _ ; + + let forks: Forks = serde_json::from_str(r#" +{ + "ext1": { + "test": 15 + }, + "ext2": { + "test": 123 + }, + "forks": { + "1": { + "ext1": { "test": 5 } + }, + "2": { + "ext2": { "test": 5 } + }, + "5": { + "ext2": { "test": 1 } + } + } +} + "#).unwrap(); + assert_eq!(forks.for_block(0), Extensions { + ext1: Extension1 { test: 15 }, + ext2: Extension2 { test: 123 }, + }); + assert_eq!(forks.for_block(1), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 123 }, + }); + assert_eq!(forks.for_block(2), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 5 }, + }); + assert_eq!(forks.for_block(4), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 5 }, + }); + assert_eq!(forks.for_block(5), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 1 }, + }); + assert_eq!(forks.for_block(10), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 1 }, + }); + + assert!(forks.for_block(10).get::().is_some()); + } + + + // #[derive(ChainSpecExtension)] + // pub struct Extension1 { + // pub test: u64, + // } + // + // #[derive(ChainSpecExtension)] + // pub struct Extension2 { + // pub test: u8, + // } + // + // extensions! { + // ext1: Extension1, + // ext2: Extension2, + // } } diff --git a/core/service/src/chain_spec/mod.rs b/core/service/src/chain_spec/mod.rs index c89d05a4bb21f..1f4092fd2fba2 100644 --- a/core/service/src/chain_spec/mod.rs +++ b/core/service/src/chain_spec/mod.rs @@ -17,5 +17,6 @@ //! Substrate chain configurations. mod chain_spec; +mod extension; pub use chain_spec::{ChainSpec, Properties}; From 918d32697f28c446338f44a39c539776814fe94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 20 Sep 2019 13:15:41 +0200 Subject: [PATCH 03/17] Move chain spec to separate crate. --- Cargo.toml | 2 + core/chain-spec/Cargo.toml | 16 ++ core/chain-spec/derive/Cargo.toml | 17 ++ core/chain-spec/derive/src/impl_extension.rs | 144 +++++++++++++++++ .../mod.rs => chain-spec/derive/src/lib.rs} | 15 +- .../res/chain_spec.json | 0 .../res/chain_spec2.json | 0 .../src}/chain_spec.rs | 4 +- .../src}/extension.rs | 148 ++---------------- core/chain-spec/src/lib.rs | 32 ++++ core/service/Cargo.toml | 1 + core/service/src/chain_ops.rs | 3 +- core/service/src/config.rs | 2 +- core/service/src/lib.rs | 9 +- 14 files changed, 242 insertions(+), 151 deletions(-) create mode 100644 core/chain-spec/Cargo.toml create mode 100644 core/chain-spec/derive/Cargo.toml create mode 100644 core/chain-spec/derive/src/impl_extension.rs rename core/{service/src/chain_spec/mod.rs => chain-spec/derive/src/lib.rs} (68%) rename core/{service => chain-spec}/res/chain_spec.json (100%) rename core/{service => chain-spec}/res/chain_spec2.json (100%) rename core/{service/src/chain_spec => chain-spec/src}/chain_spec.rs (98%) rename core/{service/src/chain_spec => chain-spec/src}/extension.rs (62%) create mode 100644 core/chain-spec/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index bc9fd128ff145..581952352bb3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,8 @@ vergen = "3" members = [ "core/authority-discovery", "core/application-crypto", + "core/chain-spec", + "core/chain-spec/derive", "core/cli", "core/client", "core/client/db", diff --git a/core/chain-spec/Cargo.toml b/core/chain-spec/Cargo.toml new file mode 100644 index 0000000000000..7b7caf042e073 --- /dev/null +++ b/core/chain-spec/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "substrate-chain-spec" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +chain-spec-derive = { package = "substrate-chain-spec-derive", path = "./derive" } +network = { package = "substrate-network", path = "../../core/network" } +primitives = { package = "substrate-primitives", path = "../primitives" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +sr-primitives = { path = "../../core/sr-primitives" } +tel = { package = "substrate-telemetry", path = "../../core/telemetry" } + +[dev-dependencies] diff --git a/core/chain-spec/derive/Cargo.toml b/core/chain-spec/derive/Cargo.toml new file mode 100644 index 0000000000000..a1f3eacd148b4 --- /dev/null +++ b/core/chain-spec/derive/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "substrate-chain-spec-derive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +proc-macro-crate = "0.1.3" +proc-macro2 = "0.4" +quote = "0.6.12" +syn = "^0.15.30" + +[dev-dependencies] + diff --git a/core/chain-spec/derive/src/impl_extension.rs b/core/chain-spec/derive/src/impl_extension.rs new file mode 100644 index 0000000000000..fe8fd7134df25 --- /dev/null +++ b/core/chain-spec/derive/src/impl_extension.rs @@ -0,0 +1,144 @@ +// Copyright 2019 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 . + +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{DeriveInput, Ident, Error}; +use proc_macro_crate::crate_name; + +const CRATE_NAME: &str = "substrate-chain-spec"; + +pub fn impl_extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + let err = || { + let err = Error::new( + Span::call_site(), + "ChainSpecExtension is only avaible for structs with named fields." + ).to_compile_error(); + quote!( #err ).into() + }; + + let data = match &ast.data { + syn::Data::Struct(ref data) => data, + _ => return err(), + }; + + let fields = match &data.fields { + syn::Fields::Named(ref named) => named, + _ => return err(), + }; + + let name = &ast.ident; + let crate_name = match crate_name(CRATE_NAME) { + Ok(chain_spec_name) => chain_spec_name, + Err(e) => if std::env::var("CARGO_PKG_NAME").unwrap() == CRATE_NAME { + "crate".to_string() + } else { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + return quote!( #err ).into() + }, + }; + let crate_name = Ident::new(&crate_name, Span::call_site()); + + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); + let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); + let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); + + let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); + let to_fork = generate_base_to_fork(&fork_name, &field_names); + let combine_with = generate_combine_with(&field_names); + let to_base = generate_fork_to_base(name, &field_names); + + let gen = quote! { + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct #fork_name #ty_generics #where_clause { + #fork_fields + } + + impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { + type Fork = #fork_name #ty_generics; + + fn to_fork(self) -> Self::Fork { + use #crate_name::Extension; + #to_fork + } + } + + impl #impl_generics #crate_name::Fork for #fork_name #ty_generics #where_clause { + type Base = #name #ty_generics; + + fn combine_with(&mut self, other: Self) { + use #crate_name::Fork; + #combine_with + } + + fn to_base(self) -> Option { + use #crate_name::Fork; + #to_base + } + } + }; + + gen.into() +} + +fn generate_fork_fields( + crate_name: &Ident, + names: &[&Ident], + types: &[&syn::Type], +) -> TokenStream { + let crate_name = std::iter::repeat(crate_name); + quote! { + #( pub #names: Option<<#types as #crate_name::Extension>::Fork>, )* + } +} + +fn generate_base_to_fork( + fork_name: &Ident, + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + #fork_name { + #( #names: Some(self.#names2.to_fork()), )* + } + } +} + +fn generate_combine_with( + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + #( self.#names.combine_with(other.#names2); )* + } +} + +fn generate_fork_to_base( + fork: &Ident, + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + Some(#fork { + #( #names: self.#names2?.to_base()?, )* + }) + } +} + diff --git a/core/service/src/chain_spec/mod.rs b/core/chain-spec/derive/src/lib.rs similarity index 68% rename from core/service/src/chain_spec/mod.rs rename to core/chain-spec/derive/src/lib.rs index 1f4092fd2fba2..36e3e55b33d9d 100644 --- a/core/service/src/chain_spec/mod.rs +++ b/core/chain-spec/derive/src/lib.rs @@ -14,9 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Substrate chain configurations. +//! Macros to derive chain spec extension traits implementation. -mod chain_spec; -mod extension; +extern crate proc_macro; -pub use chain_spec::{ChainSpec, Properties}; +mod impl_extension; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ChainSpecExtension)] +pub fn extension_derive(input: TokenStream) -> TokenStream { + let ast = syn::parse(input).unwrap(); + impl_extension::impl_extension_derive(&ast) +} diff --git a/core/service/res/chain_spec.json b/core/chain-spec/res/chain_spec.json similarity index 100% rename from core/service/res/chain_spec.json rename to core/chain-spec/res/chain_spec.json diff --git a/core/service/res/chain_spec2.json b/core/chain-spec/res/chain_spec2.json similarity index 100% rename from core/service/res/chain_spec2.json rename to core/chain-spec/res/chain_spec2.json diff --git a/core/service/src/chain_spec/chain_spec.rs b/core/chain-spec/src/chain_spec.rs similarity index 98% rename from core/service/src/chain_spec/chain_spec.rs rename to core/chain-spec/src/chain_spec.rs index d0c65836c0552..ace3dfb8322f4 100644 --- a/core/service/src/chain_spec/chain_spec.rs +++ b/core/chain-spec/src/chain_spec.rs @@ -292,7 +292,7 @@ mod tests { #[test] fn should_deserailize_example_chain_spec() { let spec1 = TestSpec::from_json_bytes(Cow::Owned( - include_bytes!("../../res/chain_spec.json").to_vec() + include_bytes!("../res/chain_spec.json").to_vec() )).unwrap(); let spec2 = TestSpec::from_json_file( PathBuf::from("./res/chain_spec.json") @@ -312,7 +312,7 @@ mod tests { #[test] fn should_deserialize_chain_spec_with_extensions() { let spec = TestSpec2::from_json_bytes(Cow::Owned( - include_bytes!("../../res/chain_spec2.json").to_vec() + include_bytes!("../res/chain_spec2.json").to_vec() )).unwrap(); assert_eq!(spec.extensions().my_property, "Test Extension"); diff --git a/core/service/src/chain_spec/extension.rs b/core/chain-spec/src/extension.rs similarity index 62% rename from core/service/src/chain_spec/extension.rs rename to core/chain-spec/src/extension.rs index 41dcedc06b267..2c931c7e376bf 100644 --- a/core/service/src/chain_spec/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -19,6 +19,8 @@ use std::fmt::Debug; use std::collections::BTreeMap; +use serde::{Serialize, Deserialize, de::DeserializeOwned}; + /// A `ChainSpec` extension. pub trait Extension: Sized { /// An associated type containing fork definition. @@ -46,7 +48,7 @@ pub trait Fork: Sized { fn combine_with(&mut self, other: Self); /// Attempt to convert to the base type if all parameters are set. - fn to_base(self) -> Result; + fn to_base(self) -> Option; } macro_rules! impl_trivial { @@ -72,8 +74,8 @@ macro_rules! impl_trivial { *self = other; } - fn to_base(self) -> Result { - Ok(self) + fn to_base(self) -> Option { + Some(self) } } } @@ -102,9 +104,8 @@ impl Fork for Option { }; } - fn to_base(self) -> Result { - // TODO [ToDr] Handle error - Ok(self.map(|x| x.to_base().ok().unwrap())) + fn to_base(self) -> Option { + self.map(|x| x.to_base()) } } @@ -114,9 +115,9 @@ pub trait Extensions { fn get(&self) -> Option<&T>; } -#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct Forks where - T::Fork: serde::Serialize + serde::de::DeserializeOwned, + T::Fork: Serialize + DeserializeOwned, { #[serde(flatten)] base: T, @@ -124,7 +125,7 @@ pub struct Forks where } impl Forks where - T::Fork: serde::Serialize + serde::de::DeserializeOwned + Clone + Debug, + T::Fork: Serialize + DeserializeOwned + Clone + Debug, { /// Create new fork definition given the base and the forks. pub fn new(base: T, forks: BTreeMap) -> Self { @@ -135,10 +136,8 @@ impl Forks where pub fn for_block(&self, block: B) -> T { let mut start = self.base.clone().to_fork(); - println!("Starting: {:?}", start); for (_, fork) in self.forks.range(..=block) { start.combine_with(fork.clone()); - println!("Combined: {:?} + {:?}", start, fork); } start @@ -150,85 +149,19 @@ impl Forks where #[cfg(test)] mod tests { use super::*; - use serde::{Serialize, Deserialize}; + use chain_spec_derive::ChainSpecExtension; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] pub struct Extension1 { pub test: u64, } - impl Extension for Extension1 { - type Fork = Extension1Fork; - - fn to_fork(self) -> Self::Fork { - Extension1Fork { - test: Some(self.test.to_fork()), - } - } - } - - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub struct Extension1Fork { - pub test: Option, - } - - impl Fork for Extension1Fork { - type Base = Extension1; - - fn combine_with(&mut self, other: Self) { - self.test.combine_with(other.test); - } - - fn to_base(self) -> Result { - if self.test.is_none() { - Err(self) - } else { - Ok(Extension1 { - test: self.test.unwrap(), - }) - } - } - } - - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] pub struct Extension2 { pub test: u8, } - impl Extension for Extension2 { - type Fork = Extension2Fork; - - fn to_fork(self) -> Self::Fork { - Extension2Fork { - test: Some(self.test.to_fork()), - } - } - } - - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub struct Extension2Fork { - pub test: Option, - } - - impl Fork for Extension2Fork { - type Base = Extension2; - - fn combine_with(&mut self, other: Self) { - self.test.combine_with(other.test) - } - - fn to_base(self) -> Result { - if self.test.is_none() { - Err(self) - } else { - Ok(Extension2 { - test: self.test.unwrap().to_base().unwrap(), - }) - } - } - } - - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] pub struct Extensions { pub ext1: Extension1, pub ext2: Extension2, @@ -246,43 +179,6 @@ mod tests { } } - impl Extension for Extensions { - type Fork = ExtensionsFork; - - fn to_fork(self) -> Self::Fork { - ExtensionsFork { - ext1: Some(self.ext1.to_fork()), - ext2: Some(self.ext2.to_fork()), - } - } - } - - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub struct ExtensionsFork { - pub ext1: Option, - pub ext2: Option, - } - - impl Fork for ExtensionsFork { - type Base = Extensions; - - fn combine_with(&mut self, other: Self) { - self.ext1.combine_with(other.ext1); - self.ext2.combine_with(other.ext2); - } - - fn to_base(self) -> Result { - if self.ext1.is_none() || self.ext2.is_none() { - Err(self) - } else { - Ok(Extensions { - ext1: self.ext1.unwrap().to_base().unwrap(), - ext2: self.ext2.unwrap().to_base().unwrap(), - }) - } - } - } - #[test] fn forks_should_work_correctly() { use super::Extensions as _ ; @@ -335,20 +231,4 @@ mod tests { assert!(forks.for_block(10).get::().is_some()); } - - - // #[derive(ChainSpecExtension)] - // pub struct Extension1 { - // pub test: u64, - // } - // - // #[derive(ChainSpecExtension)] - // pub struct Extension2 { - // pub test: u8, - // } - // - // extensions! { - // ext1: Extension1, - // ext2: Extension2, - // } } diff --git a/core/chain-spec/src/lib.rs b/core/chain-spec/src/lib.rs new file mode 100644 index 0000000000000..f24f197d438a2 --- /dev/null +++ b/core/chain-spec/src/lib.rs @@ -0,0 +1,32 @@ +// Copyright 2019 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 . + +//! Substrate chain configurations. + +mod chain_spec; +mod extension; + +pub use chain_spec::{ChainSpec, Properties}; +pub use extension::{Extension, Extensions, Fork, Forks}; +pub use chain_spec_derive::ChainSpecExtension; + +use serde::{Serialize, de::DeserializeOwned}; +use sr_primitives::BuildStorage; + +/// A set of traits for the runtime genesis config. +pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} +impl RuntimeGenesis for T {} + diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index 7f17d83931564..b9af154a3080f 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -27,6 +27,7 @@ session = { package = "substrate-session", path = "../session" } app-crypto = { package = "substrate-application-crypto", path = "../application-crypto" } consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } network = { package = "substrate-network", path = "../../core/network" } +chain-spec = { package = "substrate-chain-spec", path = "../chain-spec" } client = { package = "substrate-client", path = "../../core/client" } client_db = { package = "substrate-client-db", path = "../../core/client/db", features = ["kvdb-rocksdb"] } codec = { package = "parity-scale-codec", version = "1.0.0" } diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index 3a3677798b6ad..226d9e9f8e6df 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -16,9 +16,8 @@ //! Chain utilities. -use crate::RuntimeGenesis; use crate::error; -use crate::chain_spec::ChainSpec; +use chain_spec::{ChainSpec, RuntimeGenesis}; #[macro_export] macro_rules! export_blocks { diff --git a/core/service/src/config.rs b/core/service/src/config.rs index 97eba357e3fea..e7d886dfbe567 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -22,7 +22,7 @@ pub use network::config::{ExtTransport, NetworkConfiguration, Roles}; use std::{path::PathBuf, net::SocketAddr}; use transaction_pool; -use crate::chain_spec::ChainSpec; +use chain_spec::ChainSpec; use primitives::crypto::Protected; use sr_primitives::BuildStorage; use serde::{Serialize, de::DeserializeOwned}; diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index faa0498a9e531..6ff3cd317edf5 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] -mod chain_spec; pub mod config; #[macro_use] pub mod chain_ops; @@ -31,7 +30,6 @@ use std::net::SocketAddr; use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Duration, Instant}; -use serde::{Serialize, de::DeserializeOwned}; use futures::sync::mpsc; use parking_lot::Mutex; @@ -43,14 +41,13 @@ use network::{NetworkService, NetworkState, specialization::NetworkSpecializatio use log::{log, warn, debug, error, Level}; use codec::{Encode, Decode}; use primitives::{Blake2Hasher, H256}; -use sr_primitives::BuildStorage; use sr_primitives::generic::BlockId; use sr_primitives::traits::NumberFor; pub use self::error::Error; pub use self::builder::{ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert}; pub use config::{Configuration, Roles, PruningMode}; -pub use chain_spec::{ChainSpec, Properties}; +pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis}; pub use transaction_pool::txpool::{ self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError }; @@ -100,10 +97,6 @@ pub struct NewService { marker: PhantomData, } -/// A set of traits for the runtime genesis config. -pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} -impl RuntimeGenesis for T {} - /// Alias for a an implementation of `futures::future::Executor`. pub type TaskExecutor = Arc + Send>> + Send + Sync>; From 7913800232e63541c307c691c34d2497e54ed50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 20 Sep 2019 18:26:42 +0200 Subject: [PATCH 04/17] Allow using ChainSpec with extensions. --- core/chain-spec/src/chain_spec.rs | 9 ++- core/chain-spec/src/extension.rs | 23 ++++++- core/chain-spec/src/lib.rs | 2 +- core/cli/src/lib.rs | 102 +++++++++++++++++------------- core/service/Cargo.toml | 2 +- core/service/src/builder.rs | 72 +++++++++++---------- core/service/src/chain_ops.rs | 7 +- core/service/src/config.rs | 16 +++-- core/service/src/lib.rs | 14 ++-- core/service/test/src/lib.rs | 63 ++++++++++-------- node-template/src/cli.rs | 13 ++-- node/cli/Cargo.toml | 1 + node/cli/src/chain_spec.rs | 16 +++-- node/cli/src/lib.rs | 16 +++-- node/cli/src/service.rs | 7 +- 15 files changed, 213 insertions(+), 150 deletions(-) diff --git a/core/chain-spec/src/chain_spec.rs b/core/chain-spec/src/chain_spec.rs index ace3dfb8322f4..486d3cdb43bc1 100644 --- a/core/chain-spec/src/chain_spec.rs +++ b/core/chain-spec/src/chain_spec.rs @@ -68,7 +68,7 @@ impl GenesisSource { } } -impl<'a, G: RuntimeGenesis> BuildStorage for &'a ChainSpec { +impl<'a, G: RuntimeGenesis, E> BuildStorage for &'a ChainSpec { fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { match self.genesis.resolve()? { Genesis::Runtime(gc) => gc.build_storage(), @@ -119,10 +119,13 @@ struct ChainSpecFile { /// Arbitrary properties defined in chain spec as a JSON object pub type Properties = json::map::Map; -type Empty = Option<()>; +/// A type denoting empty extensions. +/// +/// We use `Option` here since `()` is not flattenable by serde. +pub type NoExtension = Option<()>; /// A configuration of a chain. Can be used to build a genesis block. -pub struct ChainSpec { +pub struct ChainSpec { spec: ChainSpecFile, genesis: GenesisSource, } diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index 2c931c7e376bf..8885e8c1da324 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -81,7 +81,7 @@ macro_rules! impl_trivial { } } -impl_trivial!(u8, u16, u32, u64, usize, String, Vec); +impl_trivial!((), u8, u16, u32, u64, usize, String, Vec); impl Extension for Option { type Fork = Option; @@ -110,11 +110,19 @@ impl Fork for Option { } /// A collection of `ChainSpec` extensions. -pub trait Extensions { +pub trait Extensions: Extension + Serialize + DeserializeOwned + Clone { /// Get an extension of specific type. fn get(&self) -> Option<&T>; } +impl Extensions for () { + fn get(&self) -> Option<&T> { None } +} + +impl Extensions for Option<()> { + fn get(&self) -> Option<&T> { None } +} + #[derive(Debug, Serialize, Deserialize)] pub struct Forks where T::Fork: Serialize + DeserializeOwned, @@ -124,6 +132,17 @@ pub struct Forks where forks: BTreeMap, } +impl Default for Forks where + T::Fork: Serialize + DeserializeOwned, +{ + fn default() -> Self { + Self { + base: Default::default(), + forks: Default::default(), + } + } +} + impl Forks where T::Fork: Serialize + DeserializeOwned + Clone + Debug, { diff --git a/core/chain-spec/src/lib.rs b/core/chain-spec/src/lib.rs index f24f197d438a2..aabd3d5ad3c06 100644 --- a/core/chain-spec/src/lib.rs +++ b/core/chain-spec/src/lib.rs @@ -19,7 +19,7 @@ mod chain_spec; mod extension; -pub use chain_spec::{ChainSpec, Properties}; +pub use chain_spec::{ChainSpec, Properties, NoExtension}; pub use extension::{Extension, Extensions, Fork, Forks}; pub use chain_spec_derive::ChainSpecExtension; diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index 1fa4cabd6324b..c2198915bbc46 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -30,7 +30,7 @@ use client::ExecutionStrategies; use service::{ config::Configuration, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert, - RuntimeGenesis, PruningMode, ChainSpec, + RuntimeGenesis, ChainSpecExtensions, PruningMode, ChainSpec, }; use network::{ self, multiaddr::Protocol, @@ -121,8 +121,10 @@ fn generate_node_name() -> String { result } -fn load_spec(cli: &SharedParams, factory: F) -> error::Result> - where G: RuntimeGenesis, F: FnOnce(&str) -> Result>, String>, +fn load_spec(cli: &SharedParams, factory: F) -> error::Result> where + G: RuntimeGenesis, + E: ChainSpecExtensions, + F: FnOnce(&str) -> Result>, String>, { let chain_key = get_chain_key(cli); let spec = match factory(&chain_key)? { @@ -263,18 +265,19 @@ pub struct ParseAndPrepareRun<'a, RP> { impl<'a, RP> ParseAndPrepareRun<'a, RP> { /// Runs the command and runs the main client. - pub fn run( + pub fn run( self, spec_factory: S, - exit: E, + exit: Exit, run_service: RS, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, + where S: FnOnce(&str) -> Result>, String>, RP: StructOpt + Clone, C: Default, G: RuntimeGenesis, - E: IntoExit, - RS: FnOnce(E, RunCmd, RP, Configuration) -> Result<(), String> + E: ChainSpecExtensions, + Exit: IntoExit, + RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), String> { let config = create_run_node_config(self.params.left.clone(), spec_factory, self.impl_name, self.version)?; @@ -290,12 +293,13 @@ pub struct ParseAndPrepareBuildSpec<'a> { impl<'a> ParseAndPrepareBuildSpec<'a> { /// Runs the command and build the chain specs. - pub fn run( + pub fn run( self, spec_factory: S - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + G: RuntimeGenesis, + E: ChainSpecExtensions, { info!("Building chain spec"); let raw_output = self.params.raw; @@ -317,18 +321,19 @@ pub struct ParseAndPrepareExport<'a> { impl<'a> ParseAndPrepareExport<'a> { /// Runs the command and exports from the chain. - pub fn run_with_builder( + pub fn run_with_builder( self, builder: F, spec_factory: S, - exit: E, + exit: Exit, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - F: FnOnce(Configuration) -> Result, + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, B: ServiceBuilderExport, C: Default, G: RuntimeGenesis, - E: IntoExit + E: ChainSpecExtensions, + Exit: IntoExit { let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; @@ -355,18 +360,19 @@ pub struct ParseAndPrepareImport<'a> { impl<'a> ParseAndPrepareImport<'a> { /// Runs the command and imports to the chain. - pub fn run_with_builder( + pub fn run_with_builder( self, builder: F, spec_factory: S, - exit: E, + exit: Exit, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - F: FnOnce(Configuration) -> Result, + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, B: ServiceBuilderImport, C: Default, G: RuntimeGenesis, - E: IntoExit + E: ChainSpecExtensions, + Exit: IntoExit { let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; config.execution_strategies = ExecutionStrategies { @@ -398,14 +404,15 @@ pub struct ParseAndPreparePurge<'a> { impl<'a> ParseAndPreparePurge<'a> { /// Runs the command and purges the chain. - pub fn run( + pub fn run( self, spec_factory: S - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + G: RuntimeGenesis, + E: ChainSpecExtensions, { - let config = create_config_with_db_path::<(), _, _>(spec_factory, &self.params.shared_params, self.version)?; + let config = create_config_with_db_path::<(), _, _, _>(spec_factory, &self.params.shared_params, self.version)?; let db_path = config.database_path; if !self.params.yes { @@ -447,16 +454,18 @@ pub struct ParseAndPrepareRevert<'a> { impl<'a> ParseAndPrepareRevert<'a> { /// Runs the command and reverts the chain. - pub fn run_with_builder( + pub fn run_with_builder( self, builder: F, spec_factory: S - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - F: FnOnce(Configuration) -> Result, + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, B: ServiceBuilderRevert, C: Default, - G: RuntimeGenesis { + G: RuntimeGenesis, + E: ChainSpecExtensions, + { let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; let blocks = self.params.num; builder(config)?.revert_chain(blocks.into())?; @@ -519,8 +528,8 @@ fn parse_ed25519_secret(hex: &String) -> error::Result( - options: &mut Configuration, +fn fill_transaction_pool_configuration( + options: &mut Configuration, params: TransactionPoolParams, ) -> error::Result<()> { // ready queue @@ -594,8 +603,8 @@ fn input_keystore_password() -> Result { } /// Fill the password field of the given config instance. -fn fill_config_keystore_password( - config: &mut service::Configuration, +fn fill_config_keystore_password( + config: &mut service::Configuration, cli: &RunCmd, ) -> Result<(), String> { config.keystore_password = if cli.password_interactive { @@ -611,13 +620,14 @@ fn fill_config_keystore_password( Ok(()) } -fn create_run_node_config( +fn create_run_node_config( cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo -) -> error::Result> +) -> error::Result> where C: Default, G: RuntimeGenesis, - S: FnOnce(&str) -> Result>, String>, + E: ChainSpecExtensions, + S: FnOnce(&str) -> Result>, String>, { let spec = load_spec(&cli.shared_params, spec_factory)?; let mut config = service::Configuration::default_with_spec(spec.clone()); @@ -755,13 +765,14 @@ where // 9803-9874 Unassigned // 9926-9949 Unassigned -fn with_default_boot_node( - spec: &mut ChainSpec, +fn with_default_boot_node( + spec: &mut ChainSpec, cli: BuildSpecCmd, version: &VersionInfo, ) -> error::Result<()> where - G: RuntimeGenesis + G: RuntimeGenesis, + E: ChainSpecExtensions, { if spec.boot_nodes().is_empty() { let base_path = base_path(&cli.shared_params, version); @@ -780,13 +791,14 @@ where } /// Creates a configuration including the database path. -pub fn create_config_with_db_path( +pub fn create_config_with_db_path( spec_factory: S, cli: &SharedParams, version: &VersionInfo, -) -> error::Result> +) -> error::Result> where C: Default, G: RuntimeGenesis, - S: FnOnce(&str) -> Result>, String>, + E: ChainSpecExtensions, + S: FnOnce(&str) -> Result>, String>, { let spec = load_spec(cli, spec_factory)?; let base_path = base_path(cli, version); diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index b9af154a3080f..3e02254b64480 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -15,7 +15,7 @@ slog = {version = "^2", features = ["nested-values"]} tokio-executor = "0.1.7" tokio-timer = "0.2" exit-future = "0.1" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0" } serde_json = "1.0" sysinfo = "0.9.0" target_info = "0.1" diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index e6d2cdc89acff..84196688147f7 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -22,6 +22,7 @@ use client::{ BlockchainEvents, Client, runtime_api, backend::RemoteBackend, light::blockchain::RemoteBlockchain, }; +use chain_spec::{RuntimeGenesis, Extensions}; use codec::{Decode, Encode, IoReader}; use consensus_common::import_queue::ImportQueue; use futures::{prelude::*, sync::mpsc}; @@ -33,10 +34,9 @@ use network::{config::BoxFinalityProofRequestBuilder, specialization::NetworkSpe use parking_lot::{Mutex, RwLock}; use primitives::{Blake2Hasher, H256, Hasher}; use rpc::{self, system::SystemInfo}; -use sr_primitives::{BuildStorage, generic::BlockId}; +use sr_primitives::generic::BlockId; use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi, NumberFor, One, Zero, Header, SaturatedConversion}; use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; -use serde::{Serialize, de::DeserializeOwned}; use std::{io::{Read, Write, Seek}, marker::PhantomData, sync::Arc, sync::atomic::AtomicBool}; use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; use tel::{telemetry, SUBSTRATE_INFO}; @@ -60,10 +60,10 @@ use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool}; /// The order in which the `with_*` methods are called doesn't matter, as the correct binding of /// generics is done when you call `build`. /// -pub struct ServiceBuilder { - config: Configuration, + config: Configuration, client: Arc, backend: Arc, keystore: Arc>, @@ -126,16 +126,17 @@ type TLightCallExecutor = client::light::call_executor::GenesisC >, >; -impl ServiceBuilder<(), (), TCfg, TGen, (), (), (), (), (), (), (), (), (), (), ()> -where TGen: Serialize + DeserializeOwned + BuildStorage { +impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), (), ()> +where TGen: RuntimeGenesis, TCSExt: Extensions { /// Start the service builder with a configuration. pub fn new_full, TRtApi, TExecDisp: NativeExecutionDispatch>( - config: Configuration + config: Configuration ) -> Result, Arc>, (), @@ -194,12 +195,13 @@ where TGen: Serialize + DeserializeOwned + BuildStorage { /// Start the service builder with a configuration. pub fn new_light, TRtApi, TExecDisp: NativeExecutionDispatch + 'static>( - config: Configuration + config: Configuration ) -> Result, Arc>, (), @@ -262,8 +264,8 @@ where TGen: Serialize + DeserializeOwned + BuildStorage { } } -impl - ServiceBuilder + ServiceBuilder { /// Returns a reference to the client that was stored in this builder. @@ -284,8 +286,8 @@ impl( self, - select_chain_builder: impl FnOnce(&Configuration, &Arc) -> Result, Error> - ) -> Result, &Arc) -> Result, Error> + ) -> Result, Error> { let select_chain = select_chain_builder(&self.config, &self.backend)?; @@ -311,8 +313,8 @@ impl( self, - builder: impl FnOnce(&Configuration, &Arc) -> Result - ) -> Result, &Arc) -> Result + ) -> Result, Error> { self.with_opt_select_chain(|cfg, b| builder(cfg, b).map(Option::Some)) } @@ -320,9 +322,9 @@ impl( self, - builder: impl FnOnce(&Configuration, Arc, Option, Arc) + builder: impl FnOnce(&Configuration, Arc, Option, Arc) -> Result - ) -> Result Result, Error> where TSc: Clone { let import_queue = builder( @@ -354,8 +356,8 @@ impl( self, - network_protocol_builder: impl FnOnce(&Configuration) -> Result - ) -> Result) -> Result + ) -> Result, Error> { let network_protocol = network_protocol_builder(&self.config)?; @@ -387,6 +389,7 @@ impl( self, builder: impl FnOnce( - &Configuration, + &Configuration, Arc, Arc, Option, Option, Arc, ) -> Result<(UImpQu, Option), Error> - ) -> Result Result, Error> where TSc: Clone, TFchr: Clone { let (import_queue, fprb) = builder( @@ -490,14 +494,14 @@ impl( self, builder: impl FnOnce( - &Configuration, + &Configuration, Arc, Arc, Option, Option, Arc, ) -> Result<(UImpQu, UFprb), Error> - ) -> Result Result, Error> where TSc: Clone, TFchr: Clone { self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx| @@ -510,7 +514,7 @@ impl( self, transaction_pool_builder: impl FnOnce(transaction_pool::txpool::Options, Arc) -> Result - ) -> Result Result, Error> { let transaction_pool = transaction_pool_builder(self.config.transaction_pool.clone(), self.client.clone())?; @@ -537,7 +541,7 @@ impl( self, rpc_ext_builder: impl FnOnce(Arc, Arc) -> URpc - ) -> Result Result, Error> { let rpc_extensions = rpc_ext_builder(self.client.clone(), self.transaction_pool.clone()); @@ -565,7 +569,7 @@ impl, - ) -> Result Result, Error> { Ok(ServiceBuilder { config: self.config, @@ -706,8 +710,8 @@ pub trait ServiceBuilderRevert { ) -> Result<(), Error>; } -impl - ServiceBuilderImport for ServiceBuilder, +impl + ServiceBuilderImport for ServiceBuilder, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, Backend> where TBl: BlockT::Out>, @@ -728,8 +732,8 @@ where } } -impl - ServiceBuilderExport for ServiceBuilder, +impl + ServiceBuilderExport for ServiceBuilder, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, TBackend> where TBl: BlockT::Out>, @@ -751,8 +755,8 @@ where } } -impl - ServiceBuilderRevert for ServiceBuilder, +impl + ServiceBuilderRevert for ServiceBuilder, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, TBackend> where TBl: BlockT::Out>, @@ -770,12 +774,13 @@ where } } -impl +impl ServiceBuilder< TBl, TRtApi, TCfg, TGen, + TCSExt, Client, Arc>, TSc, @@ -797,7 +802,8 @@ ServiceBuilder< TBl: BlockT::Out>, TRtApi: 'static + Send + Sync, TCfg: Default, - TGen: Serialize + DeserializeOwned + BuildStorage, + TGen: RuntimeGenesis, + TCSExt: Extensions, TBackend: 'static + client::backend::Backend + Send, TExec: 'static + client::CallExecutor + Send + Sync + Clone, TSc: Clone, diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index 226d9e9f8e6df..5d6f7a5af9d3f 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -17,7 +17,7 @@ //! Chain utilities. use crate::error; -use chain_spec::{ChainSpec, RuntimeGenesis}; +use chain_spec::{ChainSpec, RuntimeGenesis, Extensions}; #[macro_export] macro_rules! export_blocks { @@ -218,8 +218,9 @@ macro_rules! revert_chain { } /// Build a chain spec json -pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result - where G: RuntimeGenesis, +pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result where + G: RuntimeGenesis, + E: Extensions, { Ok(spec.to_json(raw)?) } diff --git a/core/service/src/config.rs b/core/service/src/config.rs index e7d886dfbe567..98b719eb5eec8 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -22,16 +22,14 @@ pub use network::config::{ExtTransport, NetworkConfiguration, Roles}; use std::{path::PathBuf, net::SocketAddr}; use transaction_pool; -use chain_spec::ChainSpec; +use chain_spec::{ChainSpec, RuntimeGenesis, Extensions, NoExtension}; use primitives::crypto::Protected; -use sr_primitives::BuildStorage; -use serde::{Serialize, de::DeserializeOwned}; use target_info::Target; use tel::TelemetryEndpoints; /// Service configuration. #[derive(Clone)] -pub struct Configuration { +pub struct Configuration { /// Implementation name pub impl_name: &'static str, /// Implementation version @@ -57,7 +55,7 @@ pub struct Configuration { /// Pruning settings. pub pruning: PruningMode, /// Chain configuration. - pub chain_spec: ChainSpec, + pub chain_spec: ChainSpec, /// Custom configuration. pub custom: C, /// Node name. @@ -95,9 +93,13 @@ pub struct Configuration { pub dev_key_seed: Option, } -impl Configuration { +impl Configuration where + C: Default, + G: RuntimeGenesis, + E: Extensions, +{ /// Create default config for given chain spec. - pub fn default_with_spec(chain_spec: ChainSpec) -> Self { + pub fn default_with_spec(chain_spec: ChainSpec) -> Self { let mut configuration = Configuration { impl_name: "parity-substrate", impl_version: "0.0.0", diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index 6ff3cd317edf5..d98ac44393335 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -47,7 +47,7 @@ use sr_primitives::traits::NumberFor; pub use self::error::Error; pub use self::builder::{ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert}; pub use config::{Configuration, Roles, PruningMode}; -pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis}; +pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extensions as ChainSpecExtensions}; pub use transaction_pool::txpool::{ self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError }; @@ -794,8 +794,8 @@ impl Drop for /// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. #[cfg(not(target_os = "unknown"))] -fn start_rpc_servers rpc_servers::RpcHandler>( - config: &Configuration, +fn start_rpc_servers rpc_servers::RpcHandler>( + config: &Configuration, mut gen_handler: H ) -> Result, error::Error> { fn maybe_start_server(address: Option, mut start: F) -> Result, io::Error> @@ -835,8 +835,8 @@ fn start_rpc_servers rpc_servers::RpcHandler> /// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. #[cfg(target_os = "unknown")] -fn start_rpc_servers components::RpcHandler>( - _: &Configuration, +fn start_rpc_servers components::RpcHandler>( + _: &Configuration, _: H ) -> Result, error::Error> { Ok(Box::new(())) @@ -877,7 +877,7 @@ fn transactions_to_propagate(pool: &TransactionPool) where PoolApi: ChainApi, B: BlockT, - H: std::hash::Hash + Eq + sr_primitives::traits::Member + serde::Serialize, + H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, E: txpool::error::IntoPoolError + From, { pool.ready() @@ -896,7 +896,7 @@ where C: network::ClientHandle + Send + Sync, PoolApi: ChainApi, B: BlockT, - H: std::hash::Hash + Eq + sr_primitives::traits::Member + serde::Serialize, + H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, E: txpool::error::IntoPoolError + From, { fn transactions(&self) -> Vec<(H, ::Extrinsic)> { diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index 870f287bff8f2..a271dfe173d36 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -41,12 +41,12 @@ use consensus::{BlockImportParams, BlockImport}; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); -struct TestNet { +struct TestNet { runtime: Runtime, authority_nodes: Vec<(usize, SyncService, U, Multiaddr)>, full_nodes: Vec<(usize, SyncService, U, Multiaddr)>, light_nodes: Vec<(usize, SyncService, Multiaddr)>, - chain_spec: ChainSpec, + chain_spec: ChainSpec, base_port: u16, nodes: usize, } @@ -81,7 +81,7 @@ impl> Future for SyncService { } } -impl TestNet +impl TestNet where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static { pub fn run_until_all_full( @@ -126,14 +126,14 @@ where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static } } -fn node_config ( +fn node_config ( index: usize, - spec: &ChainSpec, + spec: &ChainSpec, role: Roles, key_seed: Option, base_port: u16, root: &TempDir, -) -> Configuration<(), G> +) -> Configuration<(), G, E> { let root = root.path().join(format!("node-{}", index)); @@ -195,18 +195,22 @@ fn node_config ( } } -impl TestNet where +impl TestNet where F: AbstractService, L: AbstractService, + E: Clone, { fn new( temp: &TempDir, - spec: ChainSpec, - full: impl Iterator) -> Result<(F, U), Error>>, - light: impl Iterator) -> Result>, - authorities: impl Iterator) -> Result<(F, U), Error>)>, + spec: ChainSpec, + full: impl Iterator) -> Result<(F, U), Error>>, + light: impl Iterator) -> Result>, + authorities: impl Iterator) -> Result<(F, U), Error> + )>, base_port: u16 - ) -> TestNet { + ) -> TestNet { let _ = env_logger::try_init(); fdlimit::raise_fd_limit(); let runtime = Runtime::new().expect("Error creating tokio runtime"); @@ -226,9 +230,9 @@ impl TestNet where fn insert_nodes( &mut self, temp: &TempDir, - full: impl Iterator) -> Result<(F, U), Error>>, - light: impl Iterator) -> Result>, - authorities: impl Iterator) -> Result<(F, U), Error>)> + full: impl Iterator) -> Result<(F, U), Error>>, + light: impl Iterator) -> Result>, + authorities: impl Iterator) -> Result<(F, U), Error>)> ) { let executor = self.runtime.executor(); @@ -276,10 +280,11 @@ impl TestNet where } } -pub fn connectivity(spec: ChainSpec, full_builder: Fb, light_builder: Lb) where - Fb: Fn(Configuration<(), G>) -> Result, +pub fn connectivity(spec: ChainSpec, full_builder: Fb, light_builder: Lb) where + E: Clone, + Fb: Fn(Configuration<(), G, E>) -> Result, F: AbstractService, - Lb: Fn(Configuration<(), G>) -> Result, + Lb: Fn(Configuration<(), G, E>) -> Result, L: AbstractService, { const NUM_FULL_NODES: usize = 5; @@ -360,20 +365,21 @@ pub fn connectivity(spec: ChainSpec, full_builder: Fb, light } } -pub fn sync( - spec: ChainSpec, +pub fn sync( + spec: ChainSpec, full_builder: Fb, light_builder: Lb, mut block_factory: B, - mut extrinsic_factory: E + mut extrinsic_factory: ExF, ) where - Fb: Fn(Configuration<(), G>) -> Result<(F, U), Error>, + Fb: Fn(Configuration<(), G, E>) -> Result<(F, U), Error>, F: AbstractService, - Lb: Fn(Configuration<(), G>) -> Result, + Lb: Fn(Configuration<(), G, E>) -> Result, L: AbstractService, B: FnMut(&F, &U) -> BlockImportParams, - E: FnMut(&F, &U) -> ::Extrinsic, + ExF: FnMut(&F, &U) -> ::Extrinsic, U: Clone + Send + 'static, + E: Clone, { const NUM_FULL_NODES: usize = 10; // FIXME: BABE light client support is currently not working. @@ -431,16 +437,17 @@ pub fn sync( ); } -pub fn consensus( - spec: ChainSpec, +pub fn consensus( + spec: ChainSpec, full_builder: Fb, light_builder: Lb, authorities: impl IntoIterator ) where - Fb: Fn(Configuration<(), G>) -> Result, + Fb: Fn(Configuration<(), G, E>) -> Result, F: AbstractService, - Lb: Fn(Configuration<(), G>) -> Result, + Lb: Fn(Configuration<(), G, E>) -> Result, L: AbstractService, + E: Clone, { const NUM_FULL_NODES: usize = 10; const NUM_LIGHT_NODES: usize = 10; diff --git a/node-template/src/cli.rs b/node-template/src/cli.rs index f6edbb2cc3ee3..6a0b0dd706c2d 100644 --- a/node-template/src/cli.rs +++ b/node-template/src/cli.rs @@ -4,7 +4,7 @@ use std::cell::RefCell; use tokio::runtime::Runtime; pub use substrate_cli::{VersionInfo, IntoExit, error}; use substrate_cli::{informant, parse_and_prepare, ParseAndPrepare, NoCustom}; -use substrate_service::{AbstractService, Roles as ServiceRoles}; +use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration}; use crate::chain_spec; use log::info; @@ -14,9 +14,10 @@ pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> T: Into + Clone, E: IntoExit, { + type Config = Configuration<(), T>; match parse_and_prepare::(&version, "substrate-node", args) { - ParseAndPrepare::Run(cmd) => cmd.run::<(), _, _, _, _>(load_spec, exit, - |exit, _cli_args, _custom_args, config| { + ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, + |exit, _cli_args, _custom_args, config: Config<_>| { info!("{}", version.name); info!(" version {}", config.full_version()); info!(" by {}, 2017, 2018", version.author); @@ -38,12 +39,12 @@ pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> }.map_err(|e| format!("{:?}", e)) }), ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder::<(), _, _, _, _, _>(|config| + ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder::<(), _, _, _, _, _>(|config| + ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder::<(), _, _, _, _>(|config| + ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(_) => Ok(()) }?; diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index 68232800f2023..7cba8a43e2a85 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -25,6 +25,7 @@ hex-literal = "0.2" substrate-rpc = { package = "substrate-rpc", path = "../../core/rpc" } substrate-basic-authorship = { path = "../../core/basic-authorship" } substrate-service = { path = "../../core/service" } +chain-spec = { package = "substrate-chain-spec", path = "../../core/chain-spec" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } network = { package = "substrate-network", path = "../../core/network" } babe = { package = "substrate-consensus-babe", path = "../../core/consensus/babe" } diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 00bcb2577613d..6f5a7a96390ac 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -17,14 +17,12 @@ //! Substrate chain configurations. use primitives::{Pair, Public, crypto::UncheckedInto}; -pub use node_primitives::{AccountId, Balance}; use node_runtime::{ AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, }; use node_runtime::constants::{time::*, currency::*}; -pub use node_runtime::GenesisConfig; use substrate_service; use hex_literal::hex; use substrate_telemetry::TelemetryEndpoints; @@ -33,11 +31,19 @@ use babe_primitives::{AuthorityId as BabeId}; use im_online::sr25519::{AuthorityId as ImOnlineId}; use sr_primitives::Perbill; +pub use node_primitives::{AccountId, Balance}; +pub use node_runtime::GenesisConfig; + const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; -/// Specialized `ChainSpec`. -pub type ChainSpec = substrate_service::ChainSpec; +//pub type Extensions = chain_spec::Forks>; +pub type Extensions = Option<()>; +/// Specialized `ChainSpec`. +pub type ChainSpec = substrate_service::ChainSpec< + GenesisConfig, + Extensions, +>; /// Flaming Fir testnet generator pub fn flaming_fir_config() -> Result { ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) @@ -191,7 +197,7 @@ pub fn staging_testnet_config() -> ChainSpec { Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), None, None, - None, + Default::default(), ) } diff --git a/node/cli/src/lib.rs b/node/cli/src/lib.rs index b7679be1764e0..a4deed37c1e37 100644 --- a/node/cli/src/lib.rs +++ b/node/cli/src/lib.rs @@ -28,7 +28,7 @@ mod factory_impl; use tokio::prelude::Future; use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; pub use cli::{VersionInfo, IntoExit, NoCustom, SharedParams, ExecutionStrategyParam}; -use substrate_service::{AbstractService, Roles as ServiceRoles}; +use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration}; use log::info; use structopt::{StructOpt, clap::App}; use cli::{AugmentClap, GetLogFilter, parse_and_prepare, ParseAndPrepare}; @@ -158,9 +158,11 @@ pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Resul T: Into + Clone, E: IntoExit, { + type Config = Configuration<(), A, B>; + match parse_and_prepare::(&version, "substrate-node", args) { - ParseAndPrepare::Run(cmd) => cmd.run::<(), _, _, _, _>(load_spec, exit, - |exit, _cli_args, _custom_args, config| { + ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, + |exit, _cli_args, _custom_args, config: Config<_, _>| { info!("{}", version.name); info!(" version {}", config.full_version()); info!(" by Parity Technologies, 2017-2019"); @@ -183,15 +185,15 @@ pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Resul }.map_err(|e| format!("{:?}", e)) }), ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder::<(), _, _, _, _, _>(|config| + ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder::<(), _, _, _, _, _>(|config| + ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder::<(), _, _, _, _>(|config| + ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { - let mut config = cli::create_config_with_db_path::<(), _, _>( + let mut config: Config<_, _> = cli::create_config_with_db_path( load_spec, &cli_args.shared_params, &version, diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index b1d13480697f8..19cbb9b420763 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -211,14 +211,17 @@ macro_rules! new_full { }} } +/// A specialized configuration object for setting up the node.. +pub type NodeConfiguration = Configuration; + /// Builds a new service for a full client. -pub fn new_full(config: Configuration) +pub fn new_full(config: NodeConfiguration) -> Result { new_full!(config).map(|(service, _)| service) } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) +pub fn new_light(config: NodeConfiguration) -> Result { use futures::Future; From 21e3ac06b54d4f5fab4090a9637178ea98e1db80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 Sep 2019 14:14:26 +0200 Subject: [PATCH 05/17] Renames. --- .../src/{impl_extension.rs => impl_group.rs} | 10 +- core/chain-spec/derive/src/lib.rs | 13 ++- core/chain-spec/src/extension.rs | 95 +++++++++++-------- core/chain-spec/src/lib.rs | 2 +- core/cli/src/lib.rs | 22 ++--- core/service/src/builder.rs | 6 +- core/service/src/chain_ops.rs | 4 +- core/service/src/config.rs | 4 +- core/service/src/lib.rs | 2 +- 9 files changed, 90 insertions(+), 68 deletions(-) rename core/chain-spec/derive/src/{impl_extension.rs => impl_group.rs} (91%) diff --git a/core/chain-spec/derive/src/impl_extension.rs b/core/chain-spec/derive/src/impl_group.rs similarity index 91% rename from core/chain-spec/derive/src/impl_extension.rs rename to core/chain-spec/derive/src/impl_group.rs index fe8fd7134df25..b723e914de241 100644 --- a/core/chain-spec/derive/src/impl_extension.rs +++ b/core/chain-spec/derive/src/impl_group.rs @@ -21,11 +21,11 @@ use proc_macro_crate::crate_name; const CRATE_NAME: &str = "substrate-chain-spec"; -pub fn impl_extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { +pub fn impl_group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { let err = || { let err = Error::new( Span::call_site(), - "ChainSpecExtension is only avaible for structs with named fields." + "ChainSpecGroup is only avaible for structs with named fields." ).to_compile_error(); quote!( #err ).into() }; @@ -68,11 +68,11 @@ pub fn impl_extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { #fork_fields } - impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { + impl #impl_generics #crate_name::Group for #name #ty_generics #where_clause { type Fork = #fork_name #ty_generics; fn to_fork(self) -> Self::Fork { - use #crate_name::Extension; + use #crate_name::Group; #to_fork } } @@ -102,7 +102,7 @@ fn generate_fork_fields( ) -> TokenStream { let crate_name = std::iter::repeat(crate_name); quote! { - #( pub #names: Option<<#types as #crate_name::Extension>::Fork>, )* + #( pub #names: Option<<#types as #crate_name::Group>::Fork>, )* } } diff --git a/core/chain-spec/derive/src/lib.rs b/core/chain-spec/derive/src/lib.rs index 36e3e55b33d9d..cad9bd2de4cba 100644 --- a/core/chain-spec/derive/src/lib.rs +++ b/core/chain-spec/derive/src/lib.rs @@ -18,12 +18,17 @@ extern crate proc_macro; -mod impl_extension; +mod impl_group; use proc_macro::TokenStream; -#[proc_macro_derive(ChainSpecExtension)] -pub fn extension_derive(input: TokenStream) -> TokenStream { +#[proc_macro_derive(ChainSpecGroup)] +pub fn group_derive(input: TokenStream) -> TokenStream { let ast = syn::parse(input).unwrap(); - impl_extension::impl_extension_derive(&ast) + impl_group::impl_group_derive(&ast) +} + +#[proc_macro_derive(ChainSpecExtension)] +pub fn extensions_derive(input: TokenStream) -> TokenStream { + unimplemented!() } diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index 8885e8c1da324..b4c53f9ab9566 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -22,7 +22,7 @@ use std::collections::BTreeMap; use serde::{Serialize, Deserialize, de::DeserializeOwned}; /// A `ChainSpec` extension. -pub trait Extension: Sized { +pub trait Group: Sized { /// An associated type containing fork definition. type Fork: Fork; @@ -32,14 +32,14 @@ pub trait Extension: Sized { /// A `ChainSpec` extension fork definition. /// -/// Basically should look the same as `Extension`, but +/// Basically should look the same as `Group`, but /// all parameters are optional. This allows changing /// only one parameter as part of the fork. /// The forks can be combined (summed up) to specify /// a complete set of parameters pub trait Fork: Sized { - /// A base `Extension` type. - type Base: Extension; + /// A base `Group` type. + type Base: Group; /// Combine with another struct. /// @@ -59,7 +59,7 @@ macro_rules! impl_trivial { ($A : ty , $( $B : ty ),*) => { impl_trivial!($( $B ),*); - impl Extension for $A { + impl Group for $A { type Fork = $A; fn to_fork(self) -> Self::Fork { @@ -83,7 +83,7 @@ macro_rules! impl_trivial { impl_trivial!((), u8, u16, u32, u64, usize, String, Vec); -impl Extension for Option { +impl Group for Option { type Fork = Option; fn to_fork(self) -> Self::Fork { @@ -110,21 +110,21 @@ impl Fork for Option { } /// A collection of `ChainSpec` extensions. -pub trait Extensions: Extension + Serialize + DeserializeOwned + Clone { +pub trait Extension: Group + Serialize + DeserializeOwned + Clone { /// Get an extension of specific type. - fn get(&self) -> Option<&T>; + fn get(&self) -> Option<&T>; } -impl Extensions for () { - fn get(&self) -> Option<&T> { None } +impl Extension for () { + fn get(&self) -> Option<&T> { None } } -impl Extensions for Option<()> { - fn get(&self) -> Option<&T> { None } +impl Extension for Option<()> { + fn get(&self) -> Option<&T> { None } } #[derive(Debug, Serialize, Deserialize)] -pub struct Forks where +pub struct Forks where T::Fork: Serialize + DeserializeOwned, { #[serde(flatten)] @@ -132,7 +132,7 @@ pub struct Forks where forks: BTreeMap, } -impl Default for Forks where +impl Default for Forks where T::Fork: Serialize + DeserializeOwned, { fn default() -> Self { @@ -143,7 +143,7 @@ impl Default for Forks where } } -impl Forks where +impl Forks where T::Fork: Serialize + DeserializeOwned + Clone + Debug, { /// Create new fork definition given the base and the forks. @@ -151,8 +151,8 @@ impl Forks where Self { base, forks } } - /// Return a set of parameters for `Extension` including all forks up to `block` (inclusive). - pub fn for_block(&self, block: B) -> T { + /// Return a set of parameters for `Group` including all forks up to `block` (inclusive). + pub fn at_block(&self, block: B) -> T { let mut start = self.base.clone().to_fork(); for (_, fork) in self.forks.range(..=block) { @@ -168,14 +168,14 @@ impl Forks where #[cfg(test)] mod tests { use super::*; - use chain_spec_derive::ChainSpecExtension; + use chain_spec_derive::{ChainSpecGroup, ChainSpecExtension}; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] pub struct Extension1 { pub test: u64, } - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] pub struct Extension2 { pub test: u8, } @@ -186,24 +186,34 @@ mod tests { pub ext2: Extension2, } - impl super::Extensions for Extensions { - fn get(&self) -> Option<&T> { - use std::any::{Any, TypeId}; - - match TypeId::of::() { - x if x == TypeId::of::() => Any::downcast_ref(&self.ext1), - x if x == TypeId::of::() => Any::downcast_ref(&self.ext2), - _ => None, - } - } + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + pub struct Ext2 { + pub non_fork: Extension1, + #[serde(flatten)] + pub forks: Forks, } + // impl super::Extension for Extensions { + // fn get(&self) -> Option<&T> { + // use std::any::{Any, TypeId}; + // + // match TypeId::of::() { + // x if x == TypeId::of::() => Any::downcast_ref(&self.ext1), + // x if x == TypeId::of::() => Any::downcast_ref(&self.ext2), + // _ => None, + // } + // } + // } + #[test] fn forks_should_work_correctly() { - use super::Extensions as _ ; + use super::Extension as _ ; - let forks: Forks = serde_json::from_str(r#" + let ext: Ext2 = serde_json::from_str(r#" { + "non_fork": { + "test": 11 + }, "ext1": { "test": 15 }, @@ -223,31 +233,38 @@ mod tests { } } "#).unwrap(); - assert_eq!(forks.for_block(0), Extensions { + + assert_eq!(ext.get::(), Extension1 { + test: 11 + }); + + // get forks definition + let forks = ext.get::>().unwrap(); + assert_eq!(forks.at_block(0), Extensions { ext1: Extension1 { test: 15 }, ext2: Extension2 { test: 123 }, }); - assert_eq!(forks.for_block(1), Extensions { + assert_eq!(forks.at_block(1), Extensions { ext1: Extension1 { test: 5 }, ext2: Extension2 { test: 123 }, }); - assert_eq!(forks.for_block(2), Extensions { + assert_eq!(forks.at_block(2), Extensions { ext1: Extension1 { test: 5 }, ext2: Extension2 { test: 5 }, }); - assert_eq!(forks.for_block(4), Extensions { + assert_eq!(forks.at_block(4), Extensions { ext1: Extension1 { test: 5 }, ext2: Extension2 { test: 5 }, }); - assert_eq!(forks.for_block(5), Extensions { + assert_eq!(forks.at_block(5), Extensions { ext1: Extension1 { test: 5 }, ext2: Extension2 { test: 1 }, }); - assert_eq!(forks.for_block(10), Extensions { + assert_eq!(forks.at_block(10), Extensions { ext1: Extension1 { test: 5 }, ext2: Extension2 { test: 1 }, }); - assert!(forks.for_block(10).get::().is_some()); + assert!(forks.at_block(10).get::().is_some()); } } diff --git a/core/chain-spec/src/lib.rs b/core/chain-spec/src/lib.rs index aabd3d5ad3c06..7f4604a224bb1 100644 --- a/core/chain-spec/src/lib.rs +++ b/core/chain-spec/src/lib.rs @@ -20,7 +20,7 @@ mod chain_spec; mod extension; pub use chain_spec::{ChainSpec, Properties, NoExtension}; -pub use extension::{Extension, Extensions, Fork, Forks}; +pub use extension::{Group, Fork, Forks, Extension}; pub use chain_spec_derive::ChainSpecExtension; use serde::{Serialize, de::DeserializeOwned}; diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index c2198915bbc46..0635dda492a31 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -30,7 +30,7 @@ use client::ExecutionStrategies; use service::{ config::Configuration, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert, - RuntimeGenesis, ChainSpecExtensions, PruningMode, ChainSpec, + RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec, }; use network::{ self, multiaddr::Protocol, @@ -123,7 +123,7 @@ fn generate_node_name() -> String { fn load_spec(cli: &SharedParams, factory: F) -> error::Result> where G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, F: FnOnce(&str) -> Result>, String>, { let chain_key = get_chain_key(cli); @@ -275,7 +275,7 @@ impl<'a, RP> ParseAndPrepareRun<'a, RP> { RP: StructOpt + Clone, C: Default, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, Exit: IntoExit, RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), String> { @@ -299,7 +299,7 @@ impl<'a> ParseAndPrepareBuildSpec<'a> { ) -> error::Result<()> where S: FnOnce(&str) -> Result>, String>, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, { info!("Building chain spec"); let raw_output = self.params.raw; @@ -332,7 +332,7 @@ impl<'a> ParseAndPrepareExport<'a> { B: ServiceBuilderExport, C: Default, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, Exit: IntoExit { let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; @@ -371,7 +371,7 @@ impl<'a> ParseAndPrepareImport<'a> { B: ServiceBuilderImport, C: Default, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, Exit: IntoExit { let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; @@ -410,7 +410,7 @@ impl<'a> ParseAndPreparePurge<'a> { ) -> error::Result<()> where S: FnOnce(&str) -> Result>, String>, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, { let config = create_config_with_db_path::<(), _, _, _>(spec_factory, &self.params.shared_params, self.version)?; let db_path = config.database_path; @@ -464,7 +464,7 @@ impl<'a> ParseAndPrepareRevert<'a> { B: ServiceBuilderRevert, C: Default, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, { let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; let blocks = self.params.num; @@ -626,7 +626,7 @@ fn create_run_node_config( where C: Default, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, S: FnOnce(&str) -> Result>, String>, { let spec = load_spec(&cli.shared_params, spec_factory)?; @@ -772,7 +772,7 @@ fn with_default_boot_node( ) -> error::Result<()> where G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, { if spec.boot_nodes().is_empty() { let base_path = base_path(&cli.shared_params, version); @@ -797,7 +797,7 @@ pub fn create_config_with_db_path( where C: Default, G: RuntimeGenesis, - E: ChainSpecExtensions, + E: ChainSpecExtension, S: FnOnce(&str) -> Result>, String>, { let spec = load_spec(cli, spec_factory)?; diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index 9fdab4994a576..77245706cd637 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -22,7 +22,7 @@ use client::{ BlockchainEvents, Client, runtime_api, backend::RemoteBackend, light::blockchain::RemoteBlockchain, }; -use chain_spec::{RuntimeGenesis, Extensions}; +use chain_spec::{RuntimeGenesis, Extension}; use codec::{Decode, Encode, IoReader}; use consensus_common::import_queue::ImportQueue; use futures::{prelude::*, sync::mpsc}; @@ -129,7 +129,7 @@ type TLightCallExecutor = client::light::call_executor::GenesisC >; impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), (), ()> -where TGen: RuntimeGenesis, TCSExt: Extensions { +where TGen: RuntimeGenesis, TCSExt: Extension { /// Start the service builder with a configuration. pub fn new_full, TRtApi, TExecDisp: NativeExecutionDispatch>( config: Configuration @@ -805,7 +805,7 @@ ServiceBuilder< TRtApi: 'static + Send + Sync, TCfg: Default, TGen: RuntimeGenesis, - TCSExt: Extensions, + TCSExt: Extension, TBackend: 'static + client::backend::Backend + Send, TExec: 'static + client::CallExecutor + Send + Sync + Clone, TSc: Clone, diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index 5d6f7a5af9d3f..66ce4ee5470c0 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -17,7 +17,7 @@ //! Chain utilities. use crate::error; -use chain_spec::{ChainSpec, RuntimeGenesis, Extensions}; +use chain_spec::{ChainSpec, RuntimeGenesis, Extension}; #[macro_export] macro_rules! export_blocks { @@ -220,7 +220,7 @@ macro_rules! revert_chain { /// Build a chain spec json pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result where G: RuntimeGenesis, - E: Extensions, + E: Extension, { Ok(spec.to_json(raw)?) } diff --git a/core/service/src/config.rs b/core/service/src/config.rs index 98b719eb5eec8..c4690e53f7995 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -22,7 +22,7 @@ pub use network::config::{ExtTransport, NetworkConfiguration, Roles}; use std::{path::PathBuf, net::SocketAddr}; use transaction_pool; -use chain_spec::{ChainSpec, RuntimeGenesis, Extensions, NoExtension}; +use chain_spec::{ChainSpec, RuntimeGenesis, Extension, NoExtension}; use primitives::crypto::Protected; use target_info::Target; use tel::TelemetryEndpoints; @@ -96,7 +96,7 @@ pub struct Configuration { impl Configuration where C: Default, G: RuntimeGenesis, - E: Extensions, + E: Extension, { /// Create default config for given chain spec. pub fn default_with_spec(chain_spec: ChainSpec) -> Self { diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index d98ac44393335..561fd7cd679a3 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -47,7 +47,7 @@ use sr_primitives::traits::NumberFor; pub use self::error::Error; pub use self::builder::{ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert}; pub use config::{Configuration, Roles, PruningMode}; -pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extensions as ChainSpecExtensions}; +pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; pub use transaction_pool::txpool::{ self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError }; From 44228a2fa7a71adca958521cb9f8b79c40aeac3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 Sep 2019 14:45:31 +0200 Subject: [PATCH 06/17] Implement Extension derive. --- .../derive/src/{impl_group.rs => impls.rs} | 46 ++++++++++++++++++- core/chain-spec/derive/src/lib.rs | 9 ++-- core/chain-spec/src/extension.rs | 12 ----- 3 files changed, 50 insertions(+), 17 deletions(-) rename core/chain-spec/derive/src/{impl_group.rs => impls.rs} (72%) diff --git a/core/chain-spec/derive/src/impl_group.rs b/core/chain-spec/derive/src/impls.rs similarity index 72% rename from core/chain-spec/derive/src/impl_group.rs rename to core/chain-spec/derive/src/impls.rs index b723e914de241..4a2ef77132cd5 100644 --- a/core/chain-spec/derive/src/impl_group.rs +++ b/core/chain-spec/derive/src/impls.rs @@ -21,7 +21,43 @@ use proc_macro_crate::crate_name; const CRATE_NAME: &str = "substrate-chain-spec"; -pub fn impl_group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { +/// Implements `Extension's` `Group` accessor. +/// +/// The struct that derives this implementation will be usable within the `ChainSpec` file. +/// The derive implements a by-type accessor method. +pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + // the extension needs to be a group as well, so we call `derive` + // and only add the `Extension` implementation. + derive(ast, Some(Box::new(|crate_name, name, generics: &syn::Generics, field_names, field_types| { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { + fn get(&self) -> Option<&T> { + use std::any::{Any, TypeId}; + + match TypeId::of::() { + #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) )*, + _ => None, + } + } + } + } + }))) +} + + +/// Implements required traits and creates `Fork` structs for `ChainSpec` custom parameter group. +pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + derive(ast, None) +} + +pub fn derive( + ast: &DeriveInput, + extra: Option TokenStream>> +) -> proc_macro::TokenStream { let err = || { let err = Error::new( Span::call_site(), @@ -57,11 +93,17 @@ pub fn impl_group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); + let extra = match extra { + Some(x) => (&*x)(&crate_name, &name, &ast.generics, &field_names, &field_types), + None => quote! {} + }; + let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); let to_fork = generate_base_to_fork(&fork_name, &field_names); let combine_with = generate_combine_with(&field_names); let to_base = generate_fork_to_base(name, &field_names); + let gen = quote! { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct #fork_name #ty_generics #where_clause { @@ -90,6 +132,8 @@ pub fn impl_group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { #to_base } } + + #extra }; gen.into() diff --git a/core/chain-spec/derive/src/lib.rs b/core/chain-spec/derive/src/lib.rs index cad9bd2de4cba..1f515a72ad05a 100644 --- a/core/chain-spec/derive/src/lib.rs +++ b/core/chain-spec/derive/src/lib.rs @@ -18,17 +18,18 @@ extern crate proc_macro; -mod impl_group; +mod impls; use proc_macro::TokenStream; #[proc_macro_derive(ChainSpecGroup)] pub fn group_derive(input: TokenStream) -> TokenStream { - let ast = syn::parse(input).unwrap(); - impl_group::impl_group_derive(&ast) + let ast = syn::parse(input).expect("Invalid AST"); + impls::group_derive(&ast) } #[proc_macro_derive(ChainSpecExtension)] pub fn extensions_derive(input: TokenStream) -> TokenStream { - unimplemented!() + let ast = syn::parse(input).expect("Invalid AST"); + impls::extension_derive(&ast) } diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index b4c53f9ab9566..9143bff0409e1 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -193,18 +193,6 @@ mod tests { pub forks: Forks, } - // impl super::Extension for Extensions { - // fn get(&self) -> Option<&T> { - // use std::any::{Any, TypeId}; - // - // match TypeId::of::() { - // x if x == TypeId::of::() => Any::downcast_ref(&self.ext1), - // x if x == TypeId::of::() => Any::downcast_ref(&self.ext2), - // _ => None, - // } - // } - // } - #[test] fn forks_should_work_correctly() { use super::Extension as _ ; From d43f4215b0587269ddc0b36dd38815b99579ad0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 Sep 2019 16:16:20 +0200 Subject: [PATCH 07/17] Implement Extension for Forks. --- Cargo.lock | 161 ++++++++++++++++------------ core/chain-spec/Cargo.toml | 5 +- core/chain-spec/derive/src/impls.rs | 104 ++++++++---------- core/chain-spec/src/extension.rs | 78 ++++++++------ 4 files changed, 190 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c852d480edd5d..58204687b8800 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -285,7 +285,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -357,7 +357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -522,7 +522,7 @@ dependencies = [ "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -627,7 +627,7 @@ dependencies = [ "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -797,7 +797,7 @@ name = "erased-serde" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1367,7 +1367,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1375,7 +1375,7 @@ name = "impl-serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1449,7 +1449,7 @@ dependencies = [ "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1463,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1509,7 +1509,7 @@ dependencies = [ "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2345,6 +2345,7 @@ dependencies = [ "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-authority-discovery 2.0.0", "substrate-basic-authorship 2.0.0", + "substrate-chain-spec 2.0.0", "substrate-cli 2.0.0", "substrate-client 2.0.0", "substrate-consensus-babe 2.0.0", @@ -2401,7 +2402,7 @@ version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-client 2.0.0", @@ -2423,7 +2424,7 @@ dependencies = [ "node-runtime 2.0.0", "node-testing 2.0.0", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-keyring 2.0.0", @@ -2454,7 +2455,7 @@ dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", "sr-std 2.0.0", @@ -2529,7 +2530,7 @@ version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -2737,7 +2738,7 @@ dependencies = [ "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2765,7 +2766,7 @@ dependencies = [ "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec-derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3581,7 +3582,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3596,7 +3597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.97" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3619,7 +3620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3713,7 +3714,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3840,7 +3841,7 @@ dependencies = [ "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-std 2.0.0", @@ -3883,7 +3884,7 @@ version = "2.0.0" dependencies = [ "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", ] @@ -3893,7 +3894,7 @@ name = "srml-assets" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3909,7 +3910,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3928,7 +3929,7 @@ name = "srml-authority-discovery" version = "0.1.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -3964,7 +3965,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -3984,7 +3985,7 @@ version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4001,7 +4002,7 @@ dependencies = [ "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4021,7 +4022,7 @@ dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.40.2 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-sandbox 2.0.0", @@ -4041,7 +4042,7 @@ version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4058,7 +4059,7 @@ dependencies = [ "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4074,7 +4075,7 @@ version = "2.0.0" dependencies = [ "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4090,7 +4091,7 @@ name = "srml-example" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4106,7 +4107,7 @@ version = "2.0.0" dependencies = [ "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4123,7 +4124,7 @@ version = "2.0.0" dependencies = [ "impl-trait-for-tuples 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4138,7 +4139,7 @@ name = "srml-generic-asset" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4152,7 +4153,7 @@ name = "srml-grandpa" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -4170,7 +4171,7 @@ name = "srml-im-online" version = "0.1.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -4190,7 +4191,7 @@ dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4205,7 +4206,7 @@ name = "srml-membership" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4219,7 +4220,7 @@ name = "srml-metadata" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", "substrate-primitives 2.0.0", ] @@ -4229,7 +4230,7 @@ name = "srml-offences" version = "1.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -4245,7 +4246,7 @@ name = "srml-scored-pool" version = "1.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4263,7 +4264,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -4282,7 +4283,7 @@ version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-staking-primitives 2.0.0", @@ -4323,7 +4324,7 @@ name = "srml-sudo" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4342,7 +4343,7 @@ dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4390,7 +4391,7 @@ version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "srml-support 2.0.0", "substrate-inherents 2.0.0", @@ -4406,7 +4407,7 @@ dependencies = [ "impl-trait-for-tuples 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4421,7 +4422,7 @@ version = "2.0.0" dependencies = [ "impl-trait-for-tuples 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4436,7 +4437,7 @@ name = "srml-treasury" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4553,7 +4554,7 @@ name = "substrate-application-crypto" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4624,6 +4625,29 @@ dependencies = [ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-chain-spec" +version = "2.0.0" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "substrate-chain-spec-derive 2.0.0", + "substrate-network 2.0.0", + "substrate-primitives 2.0.0", + "substrate-telemetry 2.0.0", +] + +[[package]] +name = "substrate-chain-spec-derive" +version = "2.0.0" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-cli" version = "2.0.0" @@ -4984,7 +5008,7 @@ name = "substrate-finality-grandpa-primitives" version = "2.0.0" dependencies = [ "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", @@ -5052,7 +5076,7 @@ dependencies = [ "quickcheck 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5168,7 +5192,7 @@ dependencies = [ "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5223,7 +5247,7 @@ dependencies = [ "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "sr-version 2.0.0", "substrate-primitives 2.0.0", @@ -5235,7 +5259,7 @@ dependencies = [ name = "substrate-rpc-primitives" version = "2.0.0" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 2.0.0", ] @@ -5248,7 +5272,7 @@ dependencies = [ "jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-ws-server 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", ] @@ -5269,7 +5293,7 @@ dependencies = [ name = "substrate-serializer" version = "2.0.0" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5289,7 +5313,7 @@ dependencies = [ "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", @@ -5297,6 +5321,7 @@ dependencies = [ "substrate-application-crypto 2.0.0", "substrate-authority-discovery 2.0.0", "substrate-authority-discovery-primitives 2.0.0", + "substrate-chain-spec 2.0.0", "substrate-client 2.0.0", "substrate-client-db 2.0.0", "substrate-consensus-babe-primitives 2.0.0", @@ -5389,7 +5414,7 @@ dependencies = [ "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5423,7 +5448,7 @@ dependencies = [ "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -5472,7 +5497,7 @@ dependencies = [ "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime 2.0.0", @@ -5686,7 +5711,7 @@ name = "tinytemplate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5908,7 +5933,7 @@ name = "toml" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5986,7 +6011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6161,7 +6186,7 @@ name = "wabt" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6853,7 +6878,7 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" -"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" "checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" diff --git a/core/chain-spec/Cargo.toml b/core/chain-spec/Cargo.toml index 7b7caf042e073..d3111b094dffc 100644 --- a/core/chain-spec/Cargo.toml +++ b/core/chain-spec/Cargo.toml @@ -6,10 +6,11 @@ edition = "2018" [dependencies] chain-spec-derive = { package = "substrate-chain-spec-derive", path = "./derive" } +impl-trait-for-tuples = "0.1.1" network = { package = "substrate-network", path = "../../core/network" } primitives = { package = "substrate-primitives", path = "../primitives" } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.40" sr-primitives = { path = "../../core/sr-primitives" } tel = { package = "substrate-telemetry", path = "../../core/telemetry" } diff --git a/core/chain-spec/derive/src/impls.rs b/core/chain-spec/derive/src/impls.rs index 4a2ef77132cd5..cdad6fd53dcb9 100644 --- a/core/chain-spec/derive/src/impls.rs +++ b/core/chain-spec/derive/src/impls.rs @@ -26,37 +26,73 @@ const CRATE_NAME: &str = "substrate-chain-spec"; /// The struct that derives this implementation will be usable within the `ChainSpec` file. /// The derive implements a by-type accessor method. pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { - // the extension needs to be a group as well, so we call `derive` - // and only add the `Extension` implementation. - derive(ast, Some(Box::new(|crate_name, name, generics: &syn::Generics, field_names, field_types| { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types| { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { - fn get(&self) -> Option<&T> { + fn get(&self) -> Option<&T> { use std::any::{Any, TypeId}; match TypeId::of::() { - #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) )*, + #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) ),*, _ => None, } } } } - }))) + }) } /// Implements required traits and creates `Fork` structs for `ChainSpec` custom parameter group. pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { - derive(ast, None) + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types| { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); + + let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); + let to_fork = generate_base_to_fork(&fork_name, &field_names); + let combine_with = generate_combine_with(&field_names); + let to_base = generate_fork_to_base(name, &field_names); + + quote! { + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + pub struct #fork_name #ty_generics #where_clause { + #fork_fields + } + + impl #impl_generics #crate_name::Group for #name #ty_generics #where_clause { + type Fork = #fork_name #ty_generics; + + fn to_fork(self) -> Self::Fork { + use #crate_name::Group; + #to_fork + } + } + + impl #impl_generics #crate_name::Fork for #fork_name #ty_generics #where_clause { + type Base = #name #ty_generics; + + fn combine_with(&mut self, other: Self) { + use #crate_name::Fork; + #combine_with + } + + fn to_base(self) -> Option { + use #crate_name::Fork; + #to_base + } + } + } + }) } pub fn derive( ast: &DeriveInput, - extra: Option TokenStream>> + derive: impl Fn( + &Ident, &Ident, &syn::Generics, Vec<&Ident>, Vec<&syn::Type> + ) -> TokenStream, ) -> proc_macro::TokenStream { let err = || { let err = Error::new( @@ -87,56 +123,10 @@ pub fn derive( }, }; let crate_name = Ident::new(&crate_name, Span::call_site()); - - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); - let extra = match extra { - Some(x) => (&*x)(&crate_name, &name, &ast.generics, &field_names, &field_types), - None => quote! {} - }; - - let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); - let to_fork = generate_base_to_fork(&fork_name, &field_names); - let combine_with = generate_combine_with(&field_names); - let to_base = generate_fork_to_base(name, &field_names); - - - let gen = quote! { - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] - pub struct #fork_name #ty_generics #where_clause { - #fork_fields - } - - impl #impl_generics #crate_name::Group for #name #ty_generics #where_clause { - type Fork = #fork_name #ty_generics; - - fn to_fork(self) -> Self::Fork { - use #crate_name::Group; - #to_fork - } - } - - impl #impl_generics #crate_name::Fork for #fork_name #ty_generics #where_clause { - type Base = #name #ty_generics; - - fn combine_with(&mut self, other: Self) { - use #crate_name::Fork; - #combine_with - } - - fn to_base(self) -> Option { - use #crate_name::Fork; - #to_base - } - } - - #extra - }; - - gen.into() + derive(&crate_name, name, &ast.generics, field_names, field_types).into() } fn generate_fork_fields( diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index 9143bff0409e1..a44b1d8f22b4c 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -110,26 +110,23 @@ impl Fork for Option { } /// A collection of `ChainSpec` extensions. -pub trait Extension: Group + Serialize + DeserializeOwned + Clone { +pub trait Extension: Serialize + DeserializeOwned + Clone { /// Get an extension of specific type. - fn get(&self) -> Option<&T>; + fn get(&self) -> Option<&T>; } -impl Extension for () { - fn get(&self) -> Option<&T> { None } +impl Extension for crate::NoExtension { + fn get(&self) -> Option<&T> { None } } -impl Extension for Option<()> { - fn get(&self) -> Option<&T> { None } -} - -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(deny_unknown_fields)] pub struct Forks where T::Fork: Serialize + DeserializeOwned, { + forks: BTreeMap, #[serde(flatten)] base: T, - forks: BTreeMap, } impl Default for Forks where @@ -165,32 +162,51 @@ impl Forks where } } +impl Extension for Forks where + B: Ord + Clone + Serialize + DeserializeOwned, + E: Extension + Group + Clone + 'static, + E::Fork: Serialize + DeserializeOwned + Clone, +{ + fn get(&self) -> Option<&T> { + use std::any::{TypeId, Any}; + + match TypeId::of::() { + x if x == TypeId::of::() => Any::downcast_ref(&self.base), + _ => self.base.get(), + } + } +} + #[cfg(test)] mod tests { use super::*; use chain_spec_derive::{ChainSpecGroup, ChainSpecExtension}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] + #[serde(deny_unknown_fields)] pub struct Extension1 { pub test: u64, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] + #[serde(deny_unknown_fields)] pub struct Extension2 { pub test: u8, } - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] + #[serde(deny_unknown_fields)] pub struct Extensions { pub ext1: Extension1, pub ext2: Extension2, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + #[serde(deny_unknown_fields)] pub struct Ext2 { - pub non_fork: Extension1, #[serde(flatten)] - pub forks: Forks, + ext1: Extension1, + forkable: Forks, } #[test] @@ -199,32 +215,32 @@ mod tests { let ext: Ext2 = serde_json::from_str(r#" { - "non_fork": { - "test": 11 - }, - "ext1": { - "test": 15 - }, - "ext2": { - "test": 123 - }, - "forks": { - "1": { - "ext1": { "test": 5 } + "test": 11, + "forkable": { + "ext1": { + "test": 15 }, - "2": { - "ext2": { "test": 5 } + "ext2": { + "test": 123 }, - "5": { - "ext2": { "test": 1 } + "forks": { + "1": { + "ext1": { "test": 5 } + }, + "2": { + "ext2": { "test": 5 } + }, + "5": { + "ext2": { "test": 1 } + } } } } "#).unwrap(); - assert_eq!(ext.get::(), Extension1 { + assert_eq!(ext.get::(), Some(&Extension1 { test: 11 - }); + })); // get forks definition let forks = ext.get::>().unwrap(); From 0a903d27699d3c26d75d94e7548bd41bda478c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 24 Sep 2019 12:33:34 +0200 Subject: [PATCH 08/17] Support specifying fork blocks. --- core/chain-spec/src/extension.rs | 23 +++++++++++++++ core/client/db/src/lib.rs | 5 ++-- core/client/src/client.rs | 25 ++++++++++++++-- core/client/src/lib.rs | 2 +- core/client/src/light/mod.rs | 2 +- core/consensus/babe/src/lib.rs | 3 +- core/consensus/common/src/block_import.rs | 4 ++- core/consensus/common/src/import_queue.rs | 2 +- core/finality-grandpa/src/import.rs | 3 +- core/finality-grandpa/src/light_import.rs | 6 ++-- core/network/src/test/mod.rs | 9 ++++-- core/service/src/builder.rs | 7 +++++ core/test-client/src/lib.rs | 1 + node/cli/Cargo.toml | 1 + node/cli/src/chain_spec.rs | 35 +++++++++++++++++++---- 15 files changed, 108 insertions(+), 20 deletions(-) diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index a44b1d8f22b4c..0b573949601ef 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -162,6 +162,29 @@ impl Forks where } } +impl Forks where + T::Fork: Serialize + DeserializeOwned + Extension, +{ + /// Get forks definition for a subset of this extension. + /// + /// Returns the `Forks` struct, but limited to a particular type + /// within the extension. + pub fn for_type(&self) -> Option> where + X: Group + Clone + 'static, + X::Fork: Serialize + DeserializeOwned + Clone, + { + let base = self.base.get::()?.clone(); + let forks = self.forks.iter().filter_map(|(k, v)| { + Some((k.clone(), v.get::()?.clone())) + }).collect(); + + Some(Forks { + base, + forks, + }) + } +} + impl Extension for Forks where B: Ord + Clone + Serialize + DeserializeOwned, E: Extension + Group + Clone + 'static, diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs index 62cc8027c2afe..ae1085bf7afaa 100644 --- a/core/client/db/src/lib.rs +++ b/core/client/db/src/lib.rs @@ -40,7 +40,7 @@ use std::collections::{HashMap, HashSet}; use client::backend::NewBlockState; use client::blockchain::{well_known_cache_keys, HeaderBackend}; -use client::ExecutionStrategies; +use client::{ForkBlocks, ExecutionStrategies}; use client::backend::{StorageCollection, ChildStorageCollection}; use codec::{Decode, Encode}; use hash_db::{Hasher, Prefix}; @@ -206,6 +206,7 @@ pub fn new_client( settings: DatabaseSettings, executor: E, genesis_storage: S, + fork_blocks: ForkBlocks, execution_strategies: ExecutionStrategies, keystore: Option, ) -> Result<( @@ -227,7 +228,7 @@ pub fn new_client( let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); let executor = client::LocalCallExecutor::new(backend.clone(), executor, keystore); Ok(( - client::Client::new(backend.clone(), executor, genesis_storage, execution_strategies)?, + client::Client::new(backend.clone(), executor, genesis_storage, fork_blocks, execution_strategies)?, backend, )) } diff --git a/core/client/src/client.rs b/core/client/src/client.rs index acba5fa824aab..3a53db11b2cbd 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -87,6 +87,8 @@ type StorageUpdate = < >::State as state_machine::Backend>::Transaction; type ChangesUpdate = ChangesTrieTransaction>; +pub type ForkBlocks = HashMap, ::Hash>; + /// Execution strategies settings. #[derive(Debug, Clone)] pub struct ExecutionStrategies { @@ -123,6 +125,7 @@ pub struct Client where Block: BlockT { finality_notification_sinks: Mutex>>>, // holds the block hash currently being imported. TODO: replace this with block queue importing_block: RwLock>, + fork_blocks: ForkBlocks, execution_strategies: ExecutionStrategies, _phantom: PhantomData, } @@ -278,7 +281,7 @@ pub fn new_with_backend( B: backend::LocalBackend { let call_executor = LocalCallExecutor::new(backend.clone(), executor, keystore); - Client::new(backend, call_executor, build_genesis_storage, Default::default()) + Client::new(backend, call_executor, build_genesis_storage, Default::default(), Default::default()) } /// Figure out the block type for a given type (for now, just a `Client`). @@ -305,6 +308,7 @@ impl Client where backend: Arc, executor: E, build_genesis_storage: S, + fork_blocks: ForkBlocks, execution_strategies: ExecutionStrategies ) -> error::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { @@ -333,6 +337,7 @@ impl Client where import_notification_sinks: Default::default(), finality_notification_sinks: Default::default(), importing_block: Default::default(), + fork_blocks, execution_strategies, _phantom: Default::default(), }) @@ -1508,8 +1513,22 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client, parent_hash: Block::Hash, ) -> Result { + + if let Some(h) = self.fork_blocks.get(&number) { + if &hash != h { + trace!( + "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", + hash, + h, + number + ); + return Ok(ImportResult::KnownBad); + } + } + match self.block_status(&BlockId::Hash(parent_hash)) .map_err(|e| ConsensusError::ClientImport(e.to_string()))? { @@ -1526,6 +1545,7 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client return Ok(ImportResult::KnownBad), } + Ok(ImportResult::imported(false)) } } @@ -1548,9 +1568,10 @@ impl consensus::BlockImport for Client fn check_block( &mut self, hash: Block::Hash, + number: NumberFor, parent_hash: Block::Hash, ) -> Result { - (&*self).check_block(hash, parent_hash) + (&*self).check_block(hash, number, parent_hash) } } diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs index 636a1e4df61da..25da98e128074 100644 --- a/core/client/src/lib.rs +++ b/core/client/src/lib.rs @@ -115,7 +115,7 @@ pub use crate::client::{ new_in_mem, BlockBody, BlockStatus, ImportNotifications, FinalityNotifications, BlockchainEvents, BlockImportNotification, Client, ClientInfo, ExecutionStrategies, FinalityNotification, - LongestChain, BlockOf, ProvideUncles, + LongestChain, BlockOf, ProvideUncles, ForkBlocks, utils, apply_aux, }; #[cfg(feature = "std")] diff --git a/core/client/src/light/mod.rs b/core/client/src/light/mod.rs index 03b7dcff8564c..c9d2e6040be2b 100644 --- a/core/client/src/light/mod.rs +++ b/core/client/src/light/mod.rs @@ -67,7 +67,7 @@ pub fn new_light( { let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, None); let executor = GenesisCallExecutor::new(backend.clone(), local_executor); - Client::new(backend, executor, genesis_storage, Default::default()) + Client::new(backend, executor, genesis_storage, Default::default(), Default::default()) } /// Create an instance of fetch data checker. diff --git a/core/consensus/babe/src/lib.rs b/core/consensus/babe/src/lib.rs index 7816f81d47a4d..7fe4d34ec5930 100644 --- a/core/consensus/babe/src/lib.rs +++ b/core/consensus/babe/src/lib.rs @@ -1446,9 +1446,10 @@ impl BlockImport for BabeBlockImport, parent_hash: Block::Hash, ) -> Result { - self.inner.check_block(hash, parent_hash).map_err(Into::into) + self.inner.check_block(hash, number, parent_hash).map_err(Into::into) } } diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index bcafb352cd10b..a46b77f90c84a 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -172,6 +172,7 @@ pub trait BlockImport { fn check_block( &mut self, hash: B::Hash, + number: NumberFor, parent_hash: B::Hash, ) -> Result; @@ -193,9 +194,10 @@ where for<'r> &'r T: BlockImport fn check_block( &mut self, hash: B::Hash, + number: NumberFor, parent_hash: B::Hash, ) -> Result { - (&**self).check_block(hash, parent_hash) + (&**self).check_block(hash, number, parent_hash) } fn import_block( diff --git a/core/consensus/common/src/import_queue.rs b/core/consensus/common/src/import_queue.rs index 533df2b179abd..6c1ae859f6595 100644 --- a/core/consensus/common/src/import_queue.rs +++ b/core/consensus/common/src/import_queue.rs @@ -217,7 +217,7 @@ pub fn import_single_block>( } }; - match import_error(import_handle.check_block(hash, parent))? { + match import_error(import_handle.check_block(hash, number, parent))? { BlockImportResult::ImportedUnknown { .. } => (), r => return Ok(r), // Any other successful result means that the block is already imported. } diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs index 8f7124b3d3ab2..6fa17382a5ce3 100644 --- a/core/finality-grandpa/src/import.rs +++ b/core/finality-grandpa/src/import.rs @@ -515,9 +515,10 @@ impl, RA, PRA, SC> BlockImport fn check_block( &mut self, hash: Block::Hash, + number: NumberFor, parent_hash: Block::Hash, ) -> Result { - self.inner.check_block(hash, parent_hash) + self.inner.check_block(hash, number, parent_hash) } } diff --git a/core/finality-grandpa/src/light_import.rs b/core/finality-grandpa/src/light_import.rs index 053daa81a8798..d16b5b17c6d5a 100644 --- a/core/finality-grandpa/src/light_import.rs +++ b/core/finality-grandpa/src/light_import.rs @@ -143,9 +143,10 @@ impl, RA> BlockImport fn check_block( &mut self, hash: Block::Hash, + number: NumberFor, parent_hash: Block::Hash, ) -> Result { - self.client.check_block(hash, parent_hash) + self.client.check_block(hash, number, parent_hash) } } @@ -592,9 +593,10 @@ pub mod tests { fn check_block( &mut self, hash: Block::Hash, + number: NumberFor, parent_hash: Block::Hash, ) -> Result { - self.0.check_block(hash, parent_hash) + self.0.check_block(hash, number, parent_hash) } } diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index 8cceeeaae6543..af672a24302b6 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -420,8 +420,13 @@ impl Clone for BlockImportAdapter { impl> BlockImport for BlockImportAdapter { type Error = T::Error; - fn check_block(&mut self, hash: Hash, parent_hash: Hash) -> Result { - self.0.lock().check_block(hash, parent_hash) + fn check_block( + &mut self, + hash: Hash, + number: NumberFor, + parent_hash: Hash, + ) -> Result { + self.0.lock().check_block(hash, number, parent_hash) } fn import_block( diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index 77245706cd637..75c4308a7bbeb 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -164,10 +164,17 @@ where TGen: RuntimeGenesis, TCSExt: Extension { let executor = NativeExecutor::::new(config.default_heap_pages); + let fork_blocks = config.chain_spec + .extensions() + .get::>() + .cloned() + .unwrap_or_default(); + let (client, backend) = client_db::new_client( db_settings, executor, &config.chain_spec, + fork_blocks, config.execution_strategies.clone(), Some(keystore.clone()), )?; diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs index 3ce5bec4fb4ad..a2baf11be2e84 100644 --- a/core/test-client/src/lib.rs +++ b/core/test-client/src/lib.rs @@ -187,6 +187,7 @@ impl TestClientBuilder self.backend.clone(), executor, storage, + Default::default(), self.execution_strategies, ).expect("Creates new client"); diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index 6d6ab4d9a055f..361e57a612ef4 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -49,6 +49,7 @@ support = { package = "srml-support", path = "../../srml/support", default-featu im_online = { package = "srml-im-online", path = "../../srml/im-online", default-features = false } sr-authority-discovery = { package = "srml-authority-discovery", path = "../../srml/authority-discovery", default-features = false } authority-discovery = { package = "substrate-authority-discovery", path = "../../core/authority-discovery"} +serde = { version = "1.0", features = [ "derive" ] } [dev-dependencies] keystore = { package = "substrate-keystore", path = "../../core/keystore" } diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 6f5a7a96390ac..633607427925d 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -16,12 +16,15 @@ //! Substrate chain configurations. +use chain_spec::ChainSpecExtension; use primitives::{Pair, Public, crypto::UncheckedInto}; +use serde::{Serialize, Deserialize}; use node_runtime::{ AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, }; +use node_runtime::Block; use node_runtime::constants::{time::*, currency::*}; use substrate_service; use hex_literal::hex; @@ -36,8 +39,10 @@ pub use node_runtime::GenesisConfig; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; -//pub type Extensions = chain_spec::Forks>; -pub type Extensions = Option<()>; +#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] +pub struct Extensions { + pub fork_blocks: client::ForkBlocks, +} /// Specialized `ChainSpec`. pub type ChainSpec = substrate_service::ChainSpec< @@ -333,7 +338,16 @@ fn development_config_genesis() -> GenesisConfig { /// Development config (single validator Alice) pub fn development_config() -> ChainSpec { - ChainSpec::from_genesis("Development", "dev", development_config_genesis, vec![], None, None, None, None) + ChainSpec::from_genesis( + "Development", + "dev", + development_config_genesis, + vec![], + None, + None, + None, + Default::default(), + ) } fn local_testnet_genesis() -> GenesisConfig { @@ -350,7 +364,16 @@ 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, None) + ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + local_testnet_genesis, + vec![], + None, + None, + None, + Default::default(), + ) } #[cfg(test)] @@ -380,7 +403,7 @@ pub(crate) mod tests { None, None, None, - None, + Default::default(), ) } @@ -394,7 +417,7 @@ pub(crate) mod tests { None, None, None, - None, + Default::default(), ) } From 57f856f638fbdbf2d7740528a69c97e60d4ee043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 24 Sep 2019 12:50:10 +0200 Subject: [PATCH 09/17] make for_blocks work --- core/chain-spec/derive/src/impls.rs | 2 +- core/chain-spec/derive/src/lib.rs | 12 ++++++++---- core/chain-spec/src/extension.rs | 9 +++++++-- test-utils/chain-spec-builder/src/main.rs | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/core/chain-spec/derive/src/impls.rs b/core/chain-spec/derive/src/impls.rs index cdad6fd53dcb9..f0c3b15fae429 100644 --- a/core/chain-spec/derive/src/impls.rs +++ b/core/chain-spec/derive/src/impls.rs @@ -57,7 +57,7 @@ pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { let to_base = generate_fork_to_base(name, &field_names); quote! { - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] pub struct #fork_name #ty_generics #where_clause { #fork_fields } diff --git a/core/chain-spec/derive/src/lib.rs b/core/chain-spec/derive/src/lib.rs index 1f515a72ad05a..a06e6ba477e73 100644 --- a/core/chain-spec/derive/src/lib.rs +++ b/core/chain-spec/derive/src/lib.rs @@ -24,12 +24,16 @@ use proc_macro::TokenStream; #[proc_macro_derive(ChainSpecGroup)] pub fn group_derive(input: TokenStream) -> TokenStream { - let ast = syn::parse(input).expect("Invalid AST"); - impls::group_derive(&ast) + match syn::parse(input) { + Ok(ast) => impls::group_derive(&ast), + Err(e) => e.to_compile_error().into(), + } } #[proc_macro_derive(ChainSpecExtension)] pub fn extensions_derive(input: TokenStream) -> TokenStream { - let ast = syn::parse(input).expect("Invalid AST"); - impls::extension_derive(&ast) + match syn::parse(input) { + Ok(ast) => impls::extension_derive(&ast), + Err(e) => e.to_compile_error().into(), + } } diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index 0b573949601ef..e48eced7c2c18 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -175,7 +175,7 @@ impl Forks where { let base = self.base.get::()?.clone(); let forks = self.forks.iter().filter_map(|(k, v)| { - Some((k.clone(), v.get::()?.clone())) + Some((k.clone(), v.get::>()?.clone()?)) }).collect(); Some(Forks { @@ -291,7 +291,12 @@ mod tests { ext1: Extension1 { test: 5 }, ext2: Extension2 { test: 1 }, }); - assert!(forks.at_block(10).get::().is_some()); + + // filter forks for `Extension2` + let ext2 = forks.for_type::().unwrap(); + assert_eq!(ext2.at_block(0), Extension2 { test: 123 }); + assert_eq!(ext2.at_block(2), Extension2 { test: 5 }); + assert_eq!(ext2.at_block(10), Extension2 { test: 1 }); } } diff --git a/test-utils/chain-spec-builder/src/main.rs b/test-utils/chain-spec-builder/src/main.rs index 13b4cc38a1646..8f59c7349363f 100644 --- a/test-utils/chain-spec-builder/src/main.rs +++ b/test-utils/chain-spec-builder/src/main.rs @@ -38,7 +38,7 @@ fn generate_chain_spec() -> String { None, None, None, - None, + Default::default(), ); build_spec(chain_spec, false).unwrap() } From 08fb6da77b7cbfe646cf379af8da3c651d104ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 24 Sep 2019 18:44:10 +0200 Subject: [PATCH 10/17] Support forks correctly. --- core/chain-spec/derive/Cargo.toml | 6 +- core/chain-spec/derive/src/impls.rs | 22 ++++++-- core/chain-spec/derive/src/lib.rs | 2 +- core/chain-spec/src/extension.rs | 86 +++++++++++++++++++++++------ 4 files changed, 90 insertions(+), 26 deletions(-) diff --git a/core/chain-spec/derive/Cargo.toml b/core/chain-spec/derive/Cargo.toml index a1f3eacd148b4..fab6cd5d1d2f5 100644 --- a/core/chain-spec/derive/Cargo.toml +++ b/core/chain-spec/derive/Cargo.toml @@ -9,9 +9,9 @@ proc-macro = true [dependencies] proc-macro-crate = "0.1.3" -proc-macro2 = "0.4" -quote = "0.6.12" -syn = "^0.15.30" +proc-macro2 = "1.0.1" +quote = "1.0.2" +syn = "1.0.5" [dev-dependencies] diff --git a/core/chain-spec/derive/src/impls.rs b/core/chain-spec/derive/src/impls.rs index f0c3b15fae429..043278a9209ef 100644 --- a/core/chain-spec/derive/src/impls.rs +++ b/core/chain-spec/derive/src/impls.rs @@ -20,17 +20,28 @@ use syn::{DeriveInput, Ident, Error}; use proc_macro_crate::crate_name; const CRATE_NAME: &str = "substrate-chain-spec"; +const ATTRIBUTE_NAME: &str = "forks"; /// Implements `Extension's` `Group` accessor. /// /// The struct that derives this implementation will be usable within the `ChainSpec` file. /// The derive implements a by-type accessor method. pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { - derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types| { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, fields| { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let forks = fields.named.iter().find_map(|f| { + if f.attrs.iter().any(|attr| attr.path.is_ident(ATTRIBUTE_NAME)) { + let typ = &f.ty; + Some(quote! { #typ }) + } else { + None + } + }).unwrap_or_else(|| quote! { #crate_name::NoExtension }); quote! { impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { + type Forks = #forks; + fn get(&self) -> Option<&T> { use std::any::{Any, TypeId}; @@ -47,7 +58,7 @@ pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { /// Implements required traits and creates `Fork` structs for `ChainSpec` custom parameter group. pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { - derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types| { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, _fields| { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); @@ -91,7 +102,7 @@ pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { pub fn derive( ast: &DeriveInput, derive: impl Fn( - &Ident, &Ident, &syn::Generics, Vec<&Ident>, Vec<&syn::Type> + &Ident, &Ident, &syn::Generics, Vec<&Ident>, Vec<&syn::Type>, &syn::FieldsNamed, ) -> TokenStream, ) -> proc_macro::TokenStream { let err = || { @@ -112,10 +123,11 @@ pub fn derive( _ => return err(), }; + const PROOF: &str = "CARGO_PKG_NAME always defined when compiling; qed"; let name = &ast.ident; let crate_name = match crate_name(CRATE_NAME) { Ok(chain_spec_name) => chain_spec_name, - Err(e) => if std::env::var("CARGO_PKG_NAME").unwrap() == CRATE_NAME { + Err(e) => if std::env::var("CARGO_PKG_NAME").expect(PROOF) == CRATE_NAME { "crate".to_string() } else { let err = Error::new(Span::call_site(), &e).to_compile_error(); @@ -126,7 +138,7 @@ pub fn derive( let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); - derive(&crate_name, name, &ast.generics, field_names, field_types).into() + derive(&crate_name, name, &ast.generics, field_names, field_types, fields).into() } fn generate_fork_fields( diff --git a/core/chain-spec/derive/src/lib.rs b/core/chain-spec/derive/src/lib.rs index a06e6ba477e73..bcd50c1021785 100644 --- a/core/chain-spec/derive/src/lib.rs +++ b/core/chain-spec/derive/src/lib.rs @@ -30,7 +30,7 @@ pub fn group_derive(input: TokenStream) -> TokenStream { } } -#[proc_macro_derive(ChainSpecExtension)] +#[proc_macro_derive(ChainSpecExtension, attributes(forks))] pub fn extensions_derive(input: TokenStream) -> TokenStream { match syn::parse(input) { Ok(ast) => impls::extension_derive(&ast), diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index e48eced7c2c18..8391aaf3c9a34 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -22,7 +22,7 @@ use std::collections::BTreeMap; use serde::{Serialize, Deserialize, de::DeserializeOwned}; /// A `ChainSpec` extension. -pub trait Group: Sized { +pub trait Group: Clone + Sized { /// An associated type containing fork definition. type Fork: Fork; @@ -37,7 +37,7 @@ pub trait Group: Sized { /// only one parameter as part of the fork. /// The forks can be combined (summed up) to specify /// a complete set of parameters -pub trait Fork: Sized { +pub trait Fork: Serialize + DeserializeOwned + Clone + Sized { /// A base `Group` type. type Base: Group; @@ -111,27 +111,47 @@ impl Fork for Option { /// A collection of `ChainSpec` extensions. pub trait Extension: Serialize + DeserializeOwned + Clone { + type Forks: IsForks; + /// Get an extension of specific type. fn get(&self) -> Option<&T>; + + /// Get forkable extensions of specific type. + fn forks(&self) -> Option> where + BlockNumber: Ord + Clone + 'static, + T: Group + 'static, + <::Extension as Group>::Fork: Extension, + { + self.get::::Extension>>()? + .for_type() + } } impl Extension for crate::NoExtension { + type Forks = Self; + fn get(&self) -> Option<&T> { None } } +pub trait IsForks { + type BlockNumber: Ord + 'static; + type Extension: Extension + Group + 'static; +} + +impl IsForks for Option<()> { + type BlockNumber = u64; + type Extension = Self; +} + #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(deny_unknown_fields)] -pub struct Forks where - T::Fork: Serialize + DeserializeOwned, -{ +pub struct Forks { forks: BTreeMap, #[serde(flatten)] base: T, } -impl Default for Forks where - T::Fork: Serialize + DeserializeOwned, -{ +impl Default for Forks { fn default() -> Self { Self { base: Default::default(), @@ -140,8 +160,8 @@ impl Default for Forks where } } -impl Forks where - T::Fork: Serialize + DeserializeOwned + Clone + Debug, +impl Forks where + T::Fork: Debug, { /// Create new fork definition given the base and the forks. pub fn new(base: T, forks: BTreeMap) -> Self { @@ -162,16 +182,23 @@ impl Forks where } } -impl Forks where - T::Fork: Serialize + DeserializeOwned + Extension, +impl IsForks for Forks where + B: Ord + 'static, + T: Group + Extension + 'static, +{ + type BlockNumber = B; + type Extension = T; +} + +impl Forks where + T::Fork: Extension, { /// Get forks definition for a subset of this extension. /// /// Returns the `Forks` struct, but limited to a particular type /// within the extension. pub fn for_type(&self) -> Option> where - X: Group + Clone + 'static, - X::Fork: Serialize + DeserializeOwned + Clone, + X: Group + 'static, { let base = self.base.get::()?.clone(); let forks = self.forks.iter().filter_map(|(k, v)| { @@ -186,10 +213,11 @@ impl Forks where } impl Extension for Forks where - B: Ord + Clone + Serialize + DeserializeOwned, - E: Extension + Group + Clone + 'static, - E::Fork: Serialize + DeserializeOwned + Clone, + B: Serialize + DeserializeOwned + Ord + Clone + 'static, + E: Extension + Group + 'static, { + type Forks = Self; + fn get(&self) -> Option<&T> { use std::any::{TypeId, Any}; @@ -198,6 +226,21 @@ impl Extension for Forks where _ => self.base.get(), } } + + fn forks(&self) -> Option> where + BlockNumber: Ord + Clone + 'static, + T: Group + 'static, + <::Extension as Group>::Fork: Extension, + { + use std::any::{TypeId, Any}; + + if TypeId::of::() == TypeId::of::() { + Any::downcast_ref(&self.for_type::()?).cloned() + } else { + self.get::::Extension>>()? + .for_type() + } + } } #[cfg(test)] @@ -229,6 +272,7 @@ mod tests { pub struct Ext2 { #[serde(flatten)] ext1: Extension1, + #[forks] forkable: Forks, } @@ -298,5 +342,13 @@ mod tests { assert_eq!(ext2.at_block(0), Extension2 { test: 123 }); assert_eq!(ext2.at_block(2), Extension2 { test: 5 }); assert_eq!(ext2.at_block(10), Extension2 { test: 1 }); + + // make sure that it can return forks correctly + let ext2_2 = forks.forks::().unwrap(); + assert_eq!(ext2, ext2_2); + + // also ext should be able to return forks correctly: + let ext2_3 = ext.forks::().unwrap(); + assert_eq!(ext2_2, ext2_3); } } From dd258d22d05ad32a07d75edd14c9b216d6303123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 25 Sep 2019 13:53:56 +0200 Subject: [PATCH 11/17] Add a bunch of docs. --- Cargo.lock | 8 ++- core/chain-spec/derive/src/impls.rs | 3 +- core/chain-spec/src/extension.rs | 13 +++- core/chain-spec/src/lib.rs | 94 ++++++++++++++++++++++++++++- core/client/src/lib.rs | 3 +- 5 files changed, 113 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58204687b8800..327680a8c2222 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2331,6 +2331,7 @@ dependencies = [ "node-runtime 2.0.0", "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "srml-authority-discovery 0.1.0", @@ -4629,6 +4630,7 @@ dependencies = [ name = "substrate-chain-spec" version = "2.0.0" dependencies = [ + "impl-trait-for-tuples 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", @@ -4643,9 +4645,9 @@ name = "substrate-chain-spec-derive" version = "2.0.0" dependencies = [ "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/core/chain-spec/derive/src/impls.rs b/core/chain-spec/derive/src/impls.rs index 043278a9209ef..fe6e963286dce 100644 --- a/core/chain-spec/derive/src/impls.rs +++ b/core/chain-spec/derive/src/impls.rs @@ -128,7 +128,8 @@ pub fn derive( let crate_name = match crate_name(CRATE_NAME) { Ok(chain_spec_name) => chain_spec_name, Err(e) => if std::env::var("CARGO_PKG_NAME").expect(PROOF) == CRATE_NAME { - "crate".to_string() + // we return the name of the crate here instead of `crate` to support doc tests. + CRATE_NAME.replace("-", "_") } else { let err = Error::new(Span::call_site(), &e).to_compile_error(); return quote!( #err ).into() diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs index 8391aaf3c9a34..bf98ced04d63f 100644 --- a/core/chain-spec/src/extension.rs +++ b/core/chain-spec/src/extension.rs @@ -22,6 +22,8 @@ use std::collections::BTreeMap; use serde::{Serialize, Deserialize, de::DeserializeOwned}; /// A `ChainSpec` extension. +/// +/// This trait is implemented automatically by `ChainSpecGroup` macro. pub trait Group: Clone + Sized { /// An associated type containing fork definition. type Fork: Fork; @@ -110,6 +112,9 @@ impl Fork for Option { } /// A collection of `ChainSpec` extensions. +/// +/// This type can be passed around and allows the core +/// modules to request a strongly-typed, but optional configuration. pub trait Extension: Serialize + DeserializeOwned + Clone { type Forks: IsForks; @@ -120,6 +125,7 @@ pub trait Extension: Serialize + DeserializeOwned + Clone { fn forks(&self) -> Option> where BlockNumber: Ord + Clone + 'static, T: Group + 'static, + ::Extension: Extension, <::Extension as Group>::Fork: Extension, { self.get::::Extension>>()? @@ -135,7 +141,7 @@ impl Extension for crate::NoExtension { pub trait IsForks { type BlockNumber: Ord + 'static; - type Extension: Extension + Group + 'static; + type Extension: Group + 'static; } impl IsForks for Option<()> { @@ -184,7 +190,7 @@ impl Forks where impl IsForks for Forks where B: Ord + 'static, - T: Group + Extension + 'static, + T: Group + 'static, { type BlockNumber = B; type Extension = T; @@ -230,6 +236,7 @@ impl Extension for Forks where fn forks(&self) -> Option> where BlockNumber: Ord + Clone + 'static, T: Group + 'static, + ::Extension: Extension, <::Extension as Group>::Fork: Extension, { use std::any::{TypeId, Any}; @@ -247,6 +254,8 @@ impl Extension for Forks where mod tests { use super::*; use chain_spec_derive::{ChainSpecGroup, ChainSpecExtension}; + // Make the proc macro work for tests and doc tests. + use crate as substrate_chain_spec; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] #[serde(deny_unknown_fields)] diff --git a/core/chain-spec/src/lib.rs b/core/chain-spec/src/lib.rs index 7f4604a224bb1..88184b9706dd2 100644 --- a/core/chain-spec/src/lib.rs +++ b/core/chain-spec/src/lib.rs @@ -15,13 +15,105 @@ // along with Substrate. If not, see . //! Substrate chain configurations. +//! +//! This crate contains structs and utilities to declare +//! a runtime-specific configuration file (a.k.a chain spec). +//! +//! Basic chain spec type containing all required parameters is +//! [`ChainSpec`](./struct.ChainSpec.html). It can be extended with +//! additional options that contain configuration specific to your chain. +//! Usually the extension is going to be an amalgamate of types exposed +//! by Substrate core modules. To allow the core modules to retrieve +//! their configuration from your extension you should use `ChainSpecExtension` +//! macro exposed by this crate. +//! +//! ```rust +//! use std::collections::HashMap; +//! use serde::{Serialize, Deserialize}; +//! use substrate_chain_spec::{ChainSpec, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! pub struct MyExtension { +//! pub known_blocks: HashMap, +//! } +//! +//! pub type MyChainSpec = ChainSpec; +//! ``` +//! +//! Some parameters may require different values depending on the +//! current blockchain height (a.k.a. forks). You can use `ChainSpecGroup` +//! macro and provided [`Forks`](./struct.Forks.html) structure to put +//! such parameters to your chain spec. +//! This will allow to override a single parameter starting at specific +//! block number. +//! +//! ```rust +//! use serde::{Serialize, Deserialize}; +//! use substrate_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct ClientParams { +//! max_block_size: usize, +//! max_extrinsic_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct PoolParams { +//! max_transaction_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +//! pub struct Extension { +//! pub client: ClientParams, +//! pub pool: PoolParams, +//! } +//! +//! pub type BlockNumber = u64; +//! +//! /// A chain spec supporting forkable `ClientParams`. +//! pub type MyChainSpec1 = ChainSpec>; +//! +//! /// A chain spec supporting forkable `Extension`. +//! pub type MyChainSpec2 = ChainSpec>; +//! ``` +//! +//! It's also possible to have a set of parameters that is allowed to change +//! with block numbers (i.e. is forkable), and another set that is not subject to changes. +//! This is also possible by declaring an extension that contains `Forks` within it. +//! +//! +//! ```rust +//! use serde::{Serialize, Deserialize}; +//! use substrate_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct ClientParams { +//! max_block_size: usize, +//! max_extrinsic_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct PoolParams { +//! max_transaction_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! pub struct Extension { +//! pub client: ClientParams, +//! #[forks] +//! pub pool: Forks, +//! } +//! +//! pub type MyChainSpec = ChainSpec; +//! ``` + mod chain_spec; mod extension; pub use chain_spec::{ChainSpec, Properties, NoExtension}; pub use extension::{Group, Fork, Forks, Extension}; -pub use chain_spec_derive::ChainSpecExtension; +pub use chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; use serde::{Serialize, de::DeserializeOwned}; use sr_primitives::BuildStorage; diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs index 25da98e128074..13c2622f43396 100644 --- a/core/client/src/lib.rs +++ b/core/client/src/lib.rs @@ -67,7 +67,8 @@ //! ), //! // This parameter provides the storage for the chain genesis. //! <(StorageOverlay, ChildrenStorageOverlay)>::default(), -//! Default::default() +//! Default::default(), +//! Default::default(), //! ); //! ``` //! From ba1b9a883f48feeb3786f10ddf5f86a1bd4467f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 25 Sep 2019 13:55:33 +0200 Subject: [PATCH 12/17] Make fork blocks optional. --- core/client/src/client.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/client/src/client.rs b/core/client/src/client.rs index 3a53db11b2cbd..e2d826810546a 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -87,7 +87,7 @@ type StorageUpdate = < >::State as state_machine::Backend>::Transaction; type ChangesUpdate = ChangesTrieTransaction>; -pub type ForkBlocks = HashMap, ::Hash>; +pub type ForkBlocks = Option, ::Hash>>; /// Execution strategies settings. #[derive(Debug, Clone)] @@ -1517,7 +1517,7 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client Result { - if let Some(h) = self.fork_blocks.get(&number) { + if let Some(h) = self.fork_blocks.as_ref().and_then(|x| x.get(&number)) { if &hash != h { trace!( "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", From 7762d42d636198ecbc03c3d36d0f8d6e73f26514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 25 Sep 2019 15:02:17 +0200 Subject: [PATCH 13/17] Add missing docs. --- core/service/src/chain_ops.rs | 3 +++ node/cli/src/chain_spec.rs | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index 66ce4ee5470c0..92f8518bf3974 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -19,6 +19,7 @@ use crate::error; use chain_spec::{ChainSpec, RuntimeGenesis, Extension}; +/// Generates a method to export blocks. #[macro_export] macro_rules! export_blocks { ($client:ident, $exit:ident, $output:ident, $from:ident, $to:ident, $json:ident) => {{ @@ -74,6 +75,7 @@ macro_rules! export_blocks { }} } +/// Generates a method to import blocks. #[macro_export] macro_rules! import_blocks { ($block:ty, $client:ident, $queue:ident, $exit:ident, $input:ident) => {{ @@ -202,6 +204,7 @@ macro_rules! import_blocks { }} } +/// Generates a method to revert chain given number of blocks and client variables. #[macro_export] macro_rules! revert_chain { ($client:ident, $blocks:ident) => {{ diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 633607427925d..c928db3eaba98 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -39,8 +39,13 @@ pub use node_runtime::GenesisConfig; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; +/// Node `ChainSpec` extensions. +/// +/// Additional parameters for some Substrate core modules, +/// customizable from the chain spec. #[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] pub struct Extensions { + /// Block numbers with known hashes. pub fork_blocks: client::ForkBlocks, } From 3171fc5063f9f32bb564da4076d42375fa2d03fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 25 Sep 2019 15:15:34 +0200 Subject: [PATCH 14/17] Fix build. --- core/client/src/client.rs | 3 +++ core/consensus/babe/src/lib.rs | 2 +- core/consensus/babe/src/tests.rs | 5 +++-- core/consensus/common/src/block_import.rs | 3 ++- core/service/test/src/lib.rs | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/core/client/src/client.rs b/core/client/src/client.rs index e95dfb9dc992c..462dac880f468 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -87,6 +87,9 @@ type StorageUpdate = < >::State as state_machine::Backend>::Transaction; type ChangesUpdate = ChangesTrieTransaction>; +/// Expected hashes of blocks at given heights. +/// +/// This may be used as chain spec extension to filter out known, unwanted forks. pub type ForkBlocks = Option, ::Hash>>; /// Execution strategies settings. diff --git a/core/consensus/babe/src/lib.rs b/core/consensus/babe/src/lib.rs index 0383f63d9af30..af4ad04051ff6 100644 --- a/core/consensus/babe/src/lib.rs +++ b/core/consensus/babe/src/lib.rs @@ -68,7 +68,7 @@ use consensus_common::import_queue::{ }; use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification}; use sr_primitives::traits::{ - Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, + Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, NumberFor, Zero, }; use keystore::KeyStorePtr; diff --git a/core/consensus/babe/src/tests.rs b/core/consensus/babe/src/tests.rs index 70c7738dec8e7..d64bd38a9fc31 100644 --- a/core/consensus/babe/src/tests.rs +++ b/core/consensus/babe/src/tests.rs @@ -30,7 +30,7 @@ use consensus_common::import_queue::{ use network::test::*; use network::test::{Block as TestBlock, PeersClient}; use network::config::BoxFinalityProofRequestBuilder; -use sr_primitives::{generic::DigestItem, traits::{Block as BlockT, DigestFor}}; +use sr_primitives::{generic::DigestItem, traits::{Block as BlockT, DigestFor, NumberFor}}; use network::config::ProtocolConfig; use tokio::runtime::current_thread; use client::BlockchainEvents; @@ -180,9 +180,10 @@ impl> BlockImport for PanickingBlockImport< fn check_block( &mut self, hash: Hash, + number: NumberFor, parent_hash: Hash, ) -> Result { - Ok(self.0.check_block(hash, parent_hash).expect("checking block failed")) + Ok(self.0.check_block(hash, number, parent_hash).expect("checking block failed")) } } diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index e06ac19bd23e0..f901a74b898d1 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -194,9 +194,10 @@ impl BlockImport for crate::import_queue::BoxBlockImport { fn check_block( &mut self, hash: B::Hash, + number: NumberFor, parent_hash: B::Hash, ) -> Result { - (**self).check_block(hash, parent_hash) + (**self).check_block(hash, number, parent_hash) } /// Import a block. diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index 08618d97efbe2..0540210b40a0b 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -279,7 +279,7 @@ impl TestNet where } pub fn connectivity( - spec: ChainSpec, + spec: ChainSpec, full_builder: Fb, light_builder: Lb, light_node_interconnectivity: bool, // should normally be false, unless the light nodes From 713c2b352748c2b0cbefd46d4b3ebcf6646f17af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 27 Sep 2019 16:34:02 +0200 Subject: [PATCH 15/17] Use struct for check_block params. --- core/client/src/client.rs | 13 ++++------- core/consensus/babe/src/lib.rs | 10 ++++---- core/consensus/babe/src/tests.rs | 6 ++--- core/consensus/common/src/block_import.rs | 28 +++++++++++++---------- core/consensus/common/src/import_queue.rs | 9 ++++---- core/consensus/common/src/lib.rs | 2 +- core/finality-grandpa/src/import.rs | 16 ++++++------- core/finality-grandpa/src/light_import.rs | 14 ++++-------- core/network/src/test/mod.rs | 8 +++---- 9 files changed, 48 insertions(+), 58 deletions(-) diff --git a/core/client/src/client.rs b/core/client/src/client.rs index 462dac880f468..8b7d2dc9952e8 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -47,7 +47,7 @@ use state_machine::{ }; use executor::{RuntimeVersion, RuntimeInfo}; use consensus::{ - Error as ConsensusError, BlockStatus, BlockImportParams, + Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, ImportResult, BlockOrigin, ForkChoiceStrategy, SelectChain, self, }; @@ -1507,10 +1507,9 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { + let BlockCheckParams { hash, number, parent_hash } = block; if let Some(h) = self.fork_blocks.as_ref().and_then(|x| x.get(&number)) { if &hash != h { @@ -1562,11 +1561,9 @@ impl consensus::BlockImport for Client fn check_block( &mut self, - hash: Block::Hash, - number: NumberFor, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - (&*self).check_block(hash, number, parent_hash) + (&*self).check_block(block) } } diff --git a/core/consensus/babe/src/lib.rs b/core/consensus/babe/src/lib.rs index af4ad04051ff6..800caf9d2bb24 100644 --- a/core/consensus/babe/src/lib.rs +++ b/core/consensus/babe/src/lib.rs @@ -68,7 +68,7 @@ use consensus_common::import_queue::{ }; use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification}; use sr_primitives::traits::{ - Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, NumberFor, + Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, Zero, }; use keystore::KeyStorePtr; @@ -89,7 +89,7 @@ use schnorrkel::{ }, }; use consensus_common::{ - self, BlockImport, Environment, Proposer, + self, BlockImport, Environment, Proposer, BlockCheckParams, ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, }; use srml_babe::{ @@ -1367,11 +1367,9 @@ impl BlockImport for BabeBlockImport, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.inner.check_block(hash, number, parent_hash).map_err(Into::into) + self.inner.check_block(block).map_err(Into::into) } } diff --git a/core/consensus/babe/src/tests.rs b/core/consensus/babe/src/tests.rs index d64bd38a9fc31..85c3101e5e764 100644 --- a/core/consensus/babe/src/tests.rs +++ b/core/consensus/babe/src/tests.rs @@ -179,11 +179,9 @@ impl> BlockImport for PanickingBlockImport< fn check_block( &mut self, - hash: Hash, - number: NumberFor, - parent_hash: Hash, + block: BlockCheckParams, ) -> Result { - Ok(self.0.check_block(hash, number, parent_hash).expect("checking block failed")) + Ok(self.0.check_block(block).expect("checking block failed")) } } diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index f901a74b898d1..4342ee38df10a 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -90,7 +90,17 @@ pub enum ForkChoiceStrategy { Custom(bool), } -/// Data required to import a Block +/// Data required to check validity of a Block. +pub struct BlockCheckParams { + /// Hash of the block that we verify. + pub hash: Block::Hash, + /// Block number of the block that we verify. + pub number: NumberFor, + /// Parent hash of the block that we verify. + pub parent_hash: Block::Hash, +} + +/// Data required to import a Block. pub struct BlockImportParams { /// Origin of the Block pub origin: BlockOrigin, @@ -172,9 +182,7 @@ pub trait BlockImport { /// Check block preconditions. fn check_block( &mut self, - hash: B::Hash, - number: NumberFor, - parent_hash: B::Hash, + block: BlockCheckParams, ) -> Result; /// Import a block. @@ -193,11 +201,9 @@ impl BlockImport for crate::import_queue::BoxBlockImport { /// Check block preconditions. fn check_block( &mut self, - hash: B::Hash, - number: NumberFor, - parent_hash: B::Hash, + block: BlockCheckParams, ) -> Result { - (**self).check_block(hash, number, parent_hash) + (**self).check_block(block) } /// Import a block. @@ -219,11 +225,9 @@ where for<'r> &'r T: BlockImport fn check_block( &mut self, - hash: B::Hash, - number: NumberFor, - parent_hash: B::Hash, + block: BlockCheckParams, ) -> Result { - (&**self).check_block(hash, number, parent_hash) + (&**self).check_block(block) } fn import_block( diff --git a/core/consensus/common/src/import_queue.rs b/core/consensus/common/src/import_queue.rs index aca584d874bf0..dc1678fcf189d 100644 --- a/core/consensus/common/src/import_queue.rs +++ b/core/consensus/common/src/import_queue.rs @@ -30,7 +30,7 @@ use sr_primitives::{Justification, traits::{Block as BlockT, Header as _, Number use crate::error::Error as ConsensusError; use crate::block_import::{ BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, - FinalityProofImport, + BlockCheckParams, FinalityProofImport, }; pub use basic_queue::BasicQueue; @@ -194,7 +194,7 @@ pub fn import_single_block>( let number = header.number().clone(); let hash = header.hash(); - let parent = header.parent_hash().clone(); + let parent_hash = header.parent_hash().clone(); let import_error = |e| { match e { @@ -204,7 +204,7 @@ pub fn import_single_block>( }, Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux, peer.clone())), Ok(ImportResult::UnknownParent) => { - debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); + debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent_hash); Err(BlockImportError::UnknownParent) }, Ok(ImportResult::KnownBad) => { @@ -217,8 +217,7 @@ pub fn import_single_block>( } } }; - - match import_error(import_handle.check_block(hash, number, parent))? { + match import_error(import_handle.check_block(BlockCheckParams { hash, number, parent_hash }))? { BlockImportResult::ImportedUnknown { .. } => (), r => return Ok(r), // Any other successful result means that the block is already imported. } diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs index d0f42d8b33af0..154ea7bb52f7c 100644 --- a/core/consensus/common/src/lib.rs +++ b/core/consensus/common/src/lib.rs @@ -48,7 +48,7 @@ const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; pub use self::error::Error; pub use block_import::{ - BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, + BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams, ImportResult, JustificationImport, FinalityProofImport, }; pub use select_chain::SelectChain; diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs index 22a12db899dbe..758f6f18dbb01 100644 --- a/core/finality-grandpa/src/import.rs +++ b/core/finality-grandpa/src/import.rs @@ -27,7 +27,7 @@ use client::backend::Backend; use client::utils::is_descendent_of; use consensus_common::{ BlockImport, Error as ConsensusError, - BlockImportParams, ImportResult, JustificationImport, + BlockCheckParams, BlockImportParams, ImportResult, JustificationImport, SelectChain, }; use fg_primitives::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog}; @@ -386,9 +386,11 @@ impl, RA, SC> BlockImport { type Error = ConsensusError; - fn import_block(&mut self, mut block: BlockImportParams, new_cache: HashMap>) - -> Result - { + fn import_block( + &mut self, + mut block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { let hash = block.post_header().hash(); let number = block.header.number().clone(); @@ -500,11 +502,9 @@ impl, RA, SC> BlockImport fn check_block( &mut self, - hash: Block::Hash, - number: NumberFor, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.inner.check_block(hash, number, parent_hash) + self.inner.check_block(block) } } diff --git a/core/finality-grandpa/src/light_import.rs b/core/finality-grandpa/src/light_import.rs index d16b5b17c6d5a..30af3a06d3f76 100644 --- a/core/finality-grandpa/src/light_import.rs +++ b/core/finality-grandpa/src/light_import.rs @@ -30,7 +30,7 @@ use codec::{Encode, Decode}; use consensus_common::{ import_queue::Verifier, BlockOrigin, BlockImport, FinalityProofImport, BlockImportParams, ImportResult, ImportedAux, - Error as ConsensusError, + BlockCheckParams, Error as ConsensusError, }; use network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; use sr_primitives::Justification; @@ -142,11 +142,9 @@ impl, RA> BlockImport fn check_block( &mut self, - hash: Block::Hash, - number: NumberFor, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.client.check_block(hash, number, parent_hash) + self.client.check_block(block) } } @@ -592,11 +590,9 @@ pub mod tests { fn check_block( &mut self, - hash: Block::Hash, - number: NumberFor, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.0.check_block(hash, number, parent_hash) + self.0.check_block(block) } } diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index cb78396f8a646..c988a2273838e 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -44,7 +44,7 @@ use consensus::import_queue::{ }; use consensus::block_import::{BlockImport, ImportResult}; use consensus::Error as ConsensusError; -use consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, JustificationImport}; +use consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport}; use futures::prelude::*; use futures03::{StreamExt as _, TryStreamExt as _}; use crate::{NetworkWorker, NetworkService, config::ProtocolId}; @@ -423,11 +423,9 @@ impl> BlockImport for BlockImportAdapter, - parent_hash: Hash, + block: BlockCheckParams, ) -> Result { - self.0.lock().check_block(hash, number, parent_hash) + self.0.lock().check_block(block) } fn import_block( From 8e688f56c7991c60fbd62920bb80f28e8abbc610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 27 Sep 2019 22:14:48 +0200 Subject: [PATCH 16/17] Fix tests? --- core/sr-api-macros/tests/ui/declaring_old_block.stderr | 2 +- .../tests/ui/declaring_own_block_with_different_name.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 999a50cc96977..181aa2a3ca783 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` on by default + = note: #[warn(unused_imports)] on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index ec033f2e09d23..a591d0448c50d 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` on by default + = note: #[warn(unused_imports)] on by default From 4a0892fed35d0722daf55dc84fa8460915a8703b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 28 Sep 2019 13:44:39 +0200 Subject: [PATCH 17/17] Clean up. --- core/chain-spec/src/chain_spec.rs | 28 ++++++++++++------- core/cli/src/lib.rs | 23 ++++++++++----- core/service/src/builder.rs | 16 +++++++---- .../tests/ui/declaring_old_block.stderr | 2 +- ...aring_own_block_with_different_name.stderr | 2 +- node/runtime/src/lib.rs | 2 +- 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/core/chain-spec/src/chain_spec.rs b/core/chain-spec/src/chain_spec.rs index 486d3cdb43bc1..b4c57f1e0365c 100644 --- a/core/chain-spec/src/chain_spec.rs +++ b/core/chain-spec/src/chain_spec.rs @@ -53,14 +53,15 @@ impl GenesisSource { match self { GenesisSource::File(path) => { - let file = File::open(path).map_err(|e| format!("Error opening spec file: {}", e))?; - let genesis: GenesisContainer = - json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + let file = File::open(path) + .map_err(|e| format!("Error opening spec file: {}", e))?; + let genesis: GenesisContainer = json::from_reader(file) + .map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(genesis.genesis) }, GenesisSource::Binary(buf) => { - let genesis: GenesisContainer = - json::from_reader(buf.as_ref()).map_err(|e| format!("Error parsing embedded file: {}", e))?; + let genesis: GenesisContainer = json::from_reader(buf.as_ref()) + .map_err(|e| format!("Error parsing embedded file: {}", e))?; Ok(genesis.genesis) }, GenesisSource::Factory(f) => Ok(Genesis::Runtime(f())), @@ -82,7 +83,10 @@ impl<'a, G: RuntimeGenesis, E> BuildStorage for &'a ChainSpec { } } - fn assimilate_storage(self, _: &mut (StorageOverlay, ChildrenStorageOverlay)) -> Result<(), String> { + fn assimilate_storage( + self, + _: &mut (StorageOverlay, ChildrenStorageOverlay) + ) -> Result<(), String> { Err("`assimilate_storage` not implemented for `ChainSpec`.".into()) } } @@ -216,7 +220,8 @@ impl ChainSpec { /// Parse json content into a `ChainSpec` pub fn from_json_bytes(json: impl Into>) -> Result { let json = json.into(); - let spec = json::from_slice(json.as_ref()).map_err(|e| format!("Error parsing spec file: {}", e))?; + let spec = json::from_slice(json.as_ref()) + .map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(ChainSpec { spec, genesis: GenesisSource::Binary(json), @@ -225,8 +230,10 @@ impl ChainSpec { /// Parse json file into a `ChainSpec` pub fn from_json_file(path: PathBuf) -> Result { - let file = File::open(&path).map_err(|e| format!("Error opening spec file: {}", e))?; - let spec = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + let file = File::open(&path) + .map_err(|e| format!("Error opening spec file: {}", e))?; + let spec = json::from_reader(file) + .map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(ChainSpec { spec, genesis: GenesisSource::File(path), @@ -267,7 +274,8 @@ impl ChainSpec { spec: self.spec, genesis, }; - json::to_string_pretty(&spec).map_err(|e| format!("Error generating spec json: {}", e)) + json::to_string_pretty(&spec) + .map_err(|e| format!("Error generating spec json: {}", e)) } } diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index 0635dda492a31..62a2f8ee6c872 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -33,8 +33,11 @@ use service::{ RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec, }; use network::{ - self, multiaddr::Protocol, - config::{NetworkConfiguration, TransportConfig, NonReservedPeerMode, NodeKeyConfig, build_multiaddr}, + self, + multiaddr::Protocol, + config::{ + NetworkConfiguration, TransportConfig, NonReservedPeerMode, NodeKeyConfig, build_multiaddr + }, }; use primitives::H256; @@ -279,7 +282,9 @@ impl<'a, RP> ParseAndPrepareRun<'a, RP> { Exit: IntoExit, RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), String> { - let config = create_run_node_config(self.params.left.clone(), spec_factory, self.impl_name, self.version)?; + let config = create_run_node_config( + self.params.left.clone(), spec_factory, self.impl_name, self.version + )?; run_service(exit, self.params.left, self.params.right, config).map_err(Into::into) } @@ -412,7 +417,9 @@ impl<'a> ParseAndPreparePurge<'a> { G: RuntimeGenesis, E: ChainSpecExtension, { - let config = create_config_with_db_path::<(), _, _, _>(spec_factory, &self.params.shared_params, self.version)?; + let config = create_config_with_db_path::<(), _, _, _>( + spec_factory, &self.params.shared_params, self.version + )?; let db_path = config.database_path; if !self.params.yes { @@ -466,7 +473,9 @@ impl<'a> ParseAndPrepareRevert<'a> { G: RuntimeGenesis, E: ChainSpecExtension, { - let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; + let config = create_config_with_db_path( + spec_factory, &self.params.shared_params, self.version + )?; let blocks = self.params.num; builder(config)?.revert_chain(blocks.into())?; Ok(()) @@ -666,8 +675,8 @@ where config.pruning = match cli.pruning { Some(ref s) if s == "archive" => PruningMode::ArchiveAll, None => PruningMode::default(), - Some(s) => PruningMode::keep_blocks( - s.parse().map_err(|_| error::Error::Input("Invalid pruning mode specified".to_string()))? + Some(s) => PruningMode::keep_blocks(s.parse() + .map_err(|_| error::Error::Input("Invalid pruning mode specified".to_string()))? ), }; diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs index 75c4308a7bbeb..3317ab23cd797 100644 --- a/core/service/src/builder.rs +++ b/core/service/src/builder.rs @@ -295,7 +295,9 @@ impl( self, - select_chain_builder: impl FnOnce(&Configuration, &Arc) -> Result, Error> + select_chain_builder: impl FnOnce( + &Configuration, &Arc + ) -> Result, Error> ) -> Result, Error> { let select_chain = select_chain_builder(&self.config, &self.backend)?; @@ -719,10 +721,14 @@ pub trait ServiceBuilderRevert { ) -> Result<(), Error>; } -impl - ServiceBuilderImport for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, Backend> -where +impl< + TBl, TRtApi, TCfg, TGen, TCSExt, TBackend, + TExec, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, + TExPool, TRpc, TRpcB, Backend +> ServiceBuilderImport for ServiceBuilder< + TBl, TRtApi, TCfg, TGen, TCSExt, Client, + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TRpcB, Backend +> where TBl: BlockT::Out>, TBackend: 'static + client::backend::Backend + Send, TExec: 'static + client::CallExecutor + Send + Sync + Clone, diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 181aa2a3ca783..999a50cc96977 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index a591d0448c50d..ec033f2e09d23 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 337e1ac35810c..627f4b6731c25 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -85,7 +85,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 165, - impl_version: 166, + impl_version: 167, apis: RUNTIME_API_VERSIONS, };