ChainSpec extensions (#3692)

* Add some chainspec tests and make sure we validate it.

* Manual implementation of Extension + Forks definitions.

* Move chain spec to separate crate.

* Allow using ChainSpec with extensions.

* Renames.

* Implement Extension derive.

* Implement Extension for Forks.

* Support specifying fork blocks.

* make for_blocks work

* Support forks correctly.

* Add a bunch of docs.

* Make fork blocks optional.

* Add missing docs.

* Fix build.

* Use struct for check_block params.

* Fix tests?

* Clean up.
This commit is contained in:
Tomasz Drwięga
2019-09-28 19:05:36 +02:00
committed by Gavin Wood
parent c555b9bf88
commit 667ee95f5d
39 changed files with 1368 additions and 336 deletions
+72 -51
View File
@@ -30,11 +30,14 @@ use client::ExecutionStrategies;
use service::{
config::Configuration,
ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert,
RuntimeGenesis, PruningMode, ChainSpec,
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;
@@ -121,8 +124,10 @@ fn generate_node_name() -> String {
result
}
fn load_spec<F, G>(cli: &SharedParams, factory: F) -> error::Result<ChainSpec<G>>
where G: RuntimeGenesis, F: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
fn load_spec<F, G, E>(cli: &SharedParams, factory: F) -> error::Result<ChainSpec<G, E>> where
G: RuntimeGenesis,
E: ChainSpecExtension,
F: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
{
let chain_key = get_chain_key(cli);
let spec = match factory(&chain_key)? {
@@ -263,20 +268,23 @@ pub struct ParseAndPrepareRun<'a, RP> {
impl<'a, RP> ParseAndPrepareRun<'a, RP> {
/// Runs the command and runs the main client.
pub fn run<C, G, S, E, RS>(
pub fn run<C, G, E, S, Exit, RS>(
self,
spec_factory: S,
exit: E,
exit: Exit,
run_service: RS,
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
where S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
RP: StructOpt + Clone,
C: Default,
G: RuntimeGenesis,
E: IntoExit,
RS: FnOnce(E, RunCmd, RP, Configuration<C, G>) -> Result<(), String>
E: ChainSpecExtension,
Exit: IntoExit,
RS: FnOnce(Exit, RunCmd, RP, Configuration<C, G, E>) -> 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)
}
@@ -290,12 +298,13 @@ pub struct ParseAndPrepareBuildSpec<'a> {
impl<'a> ParseAndPrepareBuildSpec<'a> {
/// Runs the command and build the chain specs.
pub fn run<G, S>(
pub fn run<G, S, E>(
self,
spec_factory: S
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
G: RuntimeGenesis
) -> error::Result<()> where
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
G: RuntimeGenesis,
E: ChainSpecExtension,
{
info!("Building chain spec");
let raw_output = self.params.raw;
@@ -317,18 +326,19 @@ pub struct ParseAndPrepareExport<'a> {
impl<'a> ParseAndPrepareExport<'a> {
/// Runs the command and exports from the chain.
pub fn run_with_builder<C, G, F, B, S, E>(
pub fn run_with_builder<C, G, E, F, B, S, Exit>(
self,
builder: F,
spec_factory: S,
exit: E,
exit: Exit,
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
F: FnOnce(Configuration<C, G>) -> Result<B, error::Error>,
where S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderExport,
C: Default,
G: RuntimeGenesis,
E: IntoExit
E: ChainSpecExtension,
Exit: IntoExit
{
let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?;
@@ -355,18 +365,19 @@ pub struct ParseAndPrepareImport<'a> {
impl<'a> ParseAndPrepareImport<'a> {
/// Runs the command and imports to the chain.
pub fn run_with_builder<C, G, F, B, S, E>(
pub fn run_with_builder<C, G, E, F, B, S, Exit>(
self,
builder: F,
spec_factory: S,
exit: E,
exit: Exit,
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
F: FnOnce(Configuration<C, G>) -> Result<B, error::Error>,
where S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderImport,
C: Default,
G: RuntimeGenesis,
E: IntoExit
E: ChainSpecExtension,
Exit: IntoExit
{
let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?;
config.execution_strategies = ExecutionStrategies {
@@ -398,14 +409,17 @@ pub struct ParseAndPreparePurge<'a> {
impl<'a> ParseAndPreparePurge<'a> {
/// Runs the command and purges the chain.
pub fn run<G, S>(
pub fn run<G, E, S>(
self,
spec_factory: S
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
G: RuntimeGenesis
) -> error::Result<()> where
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
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 {
@@ -447,17 +461,21 @@ pub struct ParseAndPrepareRevert<'a> {
impl<'a> ParseAndPrepareRevert<'a> {
/// Runs the command and reverts the chain.
pub fn run_with_builder<C, G, F, B, S>(
pub fn run_with_builder<C, G, E, F, B, S>(
self,
builder: F,
spec_factory: S
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
F: FnOnce(Configuration<C, G>) -> Result<B, error::Error>,
) -> error::Result<()> where
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderRevert,
C: Default,
G: RuntimeGenesis {
let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?;
G: RuntimeGenesis,
E: ChainSpecExtension,
{
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(())
@@ -519,8 +537,8 @@ fn parse_ed25519_secret(hex: &String) -> error::Result<network::config::Ed25519S
}
/// Fill the given `PoolConfiguration` by looking at the cli parameters.
fn fill_transaction_pool_configuration<C, G>(
options: &mut Configuration<C, G>,
fn fill_transaction_pool_configuration<C, G, E>(
options: &mut Configuration<C, G, E>,
params: TransactionPoolParams,
) -> error::Result<()> {
// ready queue
@@ -595,8 +613,8 @@ fn input_keystore_password() -> Result<String, String> {
}
/// Fill the password field of the given config instance.
fn fill_config_keystore_password<C, G>(
config: &mut service::Configuration<C, G>,
fn fill_config_keystore_password<C, G, E>(
config: &mut service::Configuration<C, G, E>,
cli: &RunCmd,
) -> Result<(), String> {
config.keystore_password = if cli.password_interactive {
@@ -612,13 +630,14 @@ fn fill_config_keystore_password<C, G>(
Ok(())
}
fn create_run_node_config<C, G, S>(
fn create_run_node_config<C, G, E, S>(
cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo
) -> error::Result<Configuration<C, G>>
) -> error::Result<Configuration<C, G, E>>
where
C: Default,
G: RuntimeGenesis,
S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
E: ChainSpecExtension,
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
{
let spec = load_spec(&cli.shared_params, spec_factory)?;
let mut config = service::Configuration::default_with_spec(spec.clone());
@@ -657,8 +676,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()))?
),
};
@@ -756,13 +775,14 @@ where
// 9803-9874 Unassigned
// 9926-9949 Unassigned
fn with_default_boot_node<G>(
spec: &mut ChainSpec<G>,
fn with_default_boot_node<G, E>(
spec: &mut ChainSpec<G, E>,
cli: BuildSpecCmd,
version: &VersionInfo,
) -> error::Result<()>
where
G: RuntimeGenesis
G: RuntimeGenesis,
E: ChainSpecExtension,
{
if spec.boot_nodes().is_empty() {
let base_path = base_path(&cli.shared_params, version);
@@ -781,13 +801,14 @@ where
}
/// Creates a configuration including the database path.
pub fn create_config_with_db_path<C, G, S>(
pub fn create_config_with_db_path<C, G, E, S>(
spec_factory: S, cli: &SharedParams, version: &VersionInfo,
) -> error::Result<Configuration<C, G>>
) -> error::Result<Configuration<C, G, E>>
where
C: Default,
G: RuntimeGenesis,
S: FnOnce(&str) -> Result<Option<ChainSpec<G>>, String>,
E: ChainSpecExtension,
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
{
let spec = load_spec(cli, spec_factory)?;
let base_path = base_path(cli, version);