diff --git a/Cargo.lock b/Cargo.lock index 4895aef6e1..7310f44ccd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2183,6 +2183,7 @@ name = "cumulus-test-service" version = "0.1.0" dependencies = [ "async-trait", + "clap 3.1.17", "criterion", "cumulus-client-cli", "cumulus-client-consensus-common", @@ -2201,8 +2202,10 @@ dependencies = [ "futures 0.3.21", "jsonrpsee", "pallet-transaction-payment", + "parachains-common", "parity-scale-codec", "parking_lot 0.12.0", + "polkadot-cli", "polkadot-primitives", "polkadot-service", "polkadot-test-service", @@ -2217,6 +2220,7 @@ dependencies = [ "sc-network", "sc-rpc", "sc-service", + "sc-telemetry", "sc-tracing", "sc-transaction-pool", "sc-transaction-pool-api", @@ -2234,6 +2238,7 @@ dependencies = [ "substrate-test-client", "substrate-test-utils", "tokio", + "tracing", "url", ] diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 0c1cb4f6be..a30ef306c1 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -150,15 +150,8 @@ pub struct RunCmd { long, parse(try_from_str), validator = validate_relay_chain_url, - conflicts_with = "collator", - conflicts_with = "validator", - conflicts_with = "alice", - conflicts_with = "bob", - conflicts_with = "charlie", - conflicts_with = "dave", - conflicts_with = "eve", - conflicts_with = "ferdie" - )] + conflicts_with_all = &["alice", "bob", "charlie", "dave", "eve", "ferdie", "one", "two"] ) + ] pub relay_chain_rpc_url: Option, } diff --git a/test/service/Cargo.toml b/test/service/Cargo.toml index 0008b0f13a..8d9ddad4a5 100644 --- a/test/service/Cargo.toml +++ b/test/service/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" +[[bin]] +name = "test-parachain" +path = "src/main.rs" + [dependencies] async-trait = "0.1.53" codec = { package = "parity-scale-codec", version = "3.0.0" } @@ -30,6 +34,7 @@ sc-service = { git = "https://github.com/paritytech/substrate", branch = "master sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -37,18 +42,23 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +clap = { version = "3.1", features = ["derive"] } +tracing = "0.1.25" # Polkadot polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } # Cumulus cumulus-client-cli = { path = "../../client/cli" } +parachains-common = { path = "../../polkadot-parachains/parachains-common" } cumulus-client-consensus-common = { path = "../../client/consensus/common" } cumulus-client-consensus-relay-chain = { path = "../../client/consensus/relay-chain" } cumulus-client-network = { path = "../../client/network" } diff --git a/test/service/src/cli.rs b/test/service/src/cli.rs new file mode 100644 index 0000000000..13995d6ed3 --- /dev/null +++ b/test/service/src/cli.rs @@ -0,0 +1,344 @@ +// Copyright 2022 Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +use clap::{Parser, Subcommand}; +use polkadot_service::{ChainSpec, ParaId, PrometheusConfig}; +use sc_cli::{ + CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, + Result as CliResult, RuntimeVersion, SharedParams, SubstrateCli, +}; +use sc_service::BasePath; +use std::{net::SocketAddr, path::PathBuf}; + +#[derive(Debug, Parser)] +pub struct ExportGenesisStateCommand { + #[clap(default_value_t = 2000u32)] + pub parachain_id: u32, + + /// Output file name or stdout if unspecified. + #[clap(parse(from_os_str))] + pub output: Option, + + /// Write output in binary. Default is to write in hex. + #[clap(short, long)] + pub raw: bool, + + /// The name of the chain for that the genesis state should be exported. + #[clap(long)] + pub chain: Option, +} + +/// Command for exporting the genesis wasm file. +#[derive(Debug, Parser)] +pub struct ExportGenesisWasmCommand { + #[clap(default_value_t = 2000u32)] + pub parachain_id: u32, + + /// Output file name or stdout if unspecified. + #[clap(parse(from_os_str))] + pub output: Option, + + /// Write output in binary. Default is to write in hex. + #[clap(short, long)] + pub raw: bool, + + /// The name of the chain for that the genesis wasm file should be exported. + #[clap(long)] + pub chain: Option, +} +#[derive(Subcommand, Debug)] +pub enum Commands { + #[clap(name = "export-genesis-wasm")] + ExportGenesisWasm(ExportGenesisWasmCommand), + + #[clap(name = "export-genesis-state")] + ExportGenesisState(ExportGenesisStateCommand), + + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), +} + +#[derive(Debug, Parser)] +#[clap( + version, + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] +pub struct TestCollatorCli { + #[clap(subcommand)] + pub subcommand: Option, + + #[clap(flatten)] + pub run: cumulus_client_cli::RunCmd, + + #[clap(default_value_t = 2000u32)] + pub parachain_id: u32, + + /// Relay chain arguments + #[clap(raw = true, conflicts_with = "relay-chain-rpc-url")] + pub relaychain_args: Vec, + + #[clap(long)] + pub use_null_consensus: bool, + + #[clap(long)] + pub disable_block_announcements: bool, +} + +#[derive(Debug)] +pub struct RelayChainCli { + /// The actual relay chain cli object. + pub base: polkadot_cli::RunCmd, + + /// Optional chain id that should be passed to the relay chain. + pub chain_id: Option, + + /// The base path that should be used by the relay chain. + pub base_path: Option, +} + +impl RelayChainCli { + /// Parse the relay chain CLI parameters using the para chain `Configuration`. + pub fn new<'a>( + para_config: &sc_service::Configuration, + relay_chain_args: impl Iterator, + ) -> Self { + let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); + Self { base_path, chain_id: None, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } + } +} + +impl CliConfiguration for RelayChainCli { + fn shared_params(&self) -> &SharedParams { + self.base.base.shared_params() + } + + fn import_params(&self) -> Option<&ImportParams> { + self.base.base.import_params() + } + + fn network_params(&self) -> Option<&NetworkParams> { + self.base.base.network_params() + } + + fn keystore_params(&self) -> Option<&KeystoreParams> { + self.base.base.keystore_params() + } + + fn base_path(&self) -> CliResult> { + Ok(self + .shared_params() + .base_path() + .or_else(|| self.base_path.clone().map(Into::into))) + } + + fn rpc_http(&self, default_listen_port: u16) -> CliResult> { + self.base.base.rpc_http(default_listen_port) + } + + fn rpc_ipc(&self) -> CliResult> { + self.base.base.rpc_ipc() + } + + fn rpc_ws(&self, default_listen_port: u16) -> CliResult> { + self.base.base.rpc_ws(default_listen_port) + } + + fn prometheus_config( + &self, + default_listen_port: u16, + chain_spec: &Box, + ) -> CliResult> { + self.base.base.prometheus_config(default_listen_port, chain_spec) + } + + fn init( + &self, + _support_url: &String, + _impl_version: &String, + _logger_hook: F, + _config: &sc_service::Configuration, + ) -> CliResult<()> + where + F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), + { + unreachable!("PolkadotCli is never initialized; qed"); + } + + fn chain_id(&self, is_dev: bool) -> CliResult { + let chain_id = self.base.base.chain_id(is_dev)?; + + Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) + } + + fn role(&self, is_dev: bool) -> CliResult { + self.base.base.role(is_dev) + } + + fn transaction_pool(&self) -> CliResult { + self.base.base.transaction_pool() + } + + fn state_cache_child_ratio(&self) -> CliResult> { + self.base.base.state_cache_child_ratio() + } + + fn rpc_methods(&self) -> CliResult { + self.base.base.rpc_methods() + } + + fn rpc_ws_max_connections(&self) -> CliResult> { + self.base.base.rpc_ws_max_connections() + } + + fn rpc_cors(&self, is_dev: bool) -> CliResult>> { + self.base.base.rpc_cors(is_dev) + } + + fn default_heap_pages(&self) -> CliResult> { + self.base.base.default_heap_pages() + } + + fn force_authoring(&self) -> CliResult { + self.base.base.force_authoring() + } + + fn disable_grandpa(&self) -> CliResult { + self.base.base.disable_grandpa() + } + + fn max_runtime_instances(&self) -> CliResult> { + self.base.base.max_runtime_instances() + } + + fn announce_block(&self) -> CliResult { + self.base.base.announce_block() + } + + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> CliResult> { + self.base.base.telemetry_endpoints(chain_spec) + } + + fn node_name(&self) -> CliResult { + self.base.base.node_name() + } +} + +impl DefaultConfigurationValues for RelayChainCli { + fn p2p_listen_port() -> u16 { + 30334 + } + + fn rpc_ws_listen_port() -> u16 { + 9945 + } + + fn rpc_http_listen_port() -> u16 { + 9934 + } + + fn prometheus_listen_port() -> u16 { + 9616 + } +} + +impl SubstrateCli for TestCollatorCli { + fn impl_name() -> String { + "Cumulus zombienet test parachain".into() + } + + fn impl_version() -> String { + String::new() + } + + fn description() -> String { + format!( + "Cumulus zombienet test parachain\n\nThe command-line arguments provided first will be \ + passed to the parachain node, while the arguments provided after -- will be passed \ + to the relaychain node.\n\n\ + {} [parachain-args] -- [relaychain-args]", + Self::executable_name() + ) + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/paritytech/cumulus/issues/new".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, _: &str) -> std::result::Result, String> { + Ok(Box::new(cumulus_test_service::get_chain_spec(ParaId::from(self.parachain_id))) + as Box<_>) + } + + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &cumulus_test_service::runtime::VERSION + } +} + +impl SubstrateCli for RelayChainCli { + fn impl_name() -> String { + "Polkadot collator".into() + } + + fn impl_version() -> String { + String::new() + } + + fn description() -> String { + format!( + "Polkadot collator\n\nThe command-line arguments provided first will be \ + passed to the parachain node, while the arguments provided after -- will be passed \ + to the relay chain node.\n\n\ + {} [parachain-args] -- [relay_chain-args]", + Self::executable_name() + ) + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/paritytech/cumulus/issues/new".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> std::result::Result, String> { + ::from_iter( + [RelayChainCli::executable_name().to_string()].iter(), + ) + .load_spec(id) + } + + fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion { + polkadot_cli::Cli::native_runtime_version(chain_spec) + } +} diff --git a/test/service/src/lib.rs b/test/service/src/lib.rs index 3c2d44a9e1..cf87fd826a 100644 --- a/test/service/src/lib.rs +++ b/test/service/src/lib.rs @@ -208,7 +208,7 @@ async fn build_relay_chain_interface( /// /// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with(parachain_config.network.node_name.as_str())] -async fn start_node_impl( +pub async fn start_node_impl( parachain_config: Configuration, collator_key: Option, relay_chain_config: Configuration, @@ -396,7 +396,8 @@ pub struct TestNode { pub transaction_pool: TransactionPool, } -enum Consensus { +#[allow(missing_docs)] +pub enum Consensus { /// Use the relay-chain provided consensus. RelayChain, /// Use the null consensus that will never produce any block. diff --git a/test/service/src/main.rs b/test/service/src/main.rs new file mode 100644 index 0000000000..791621dafa --- /dev/null +++ b/test/service/src/main.rs @@ -0,0 +1,178 @@ +// Copyright 2022 Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . +mod cli; + +use clap::Parser; +use cli::{Commands, RelayChainCli, TestCollatorCli}; +use cumulus_client_service::genesis::generate_genesis_block; +use cumulus_primitives_core::{relay_chain::v2::CollatorPair, ParaId}; +use cumulus_test_service::AnnounceBlockFn; +use polkadot_service::runtime_traits::AccountIdConversion; +use sc_cli::{CliConfiguration, SubstrateCli}; +use sp_core::{hexdisplay::HexDisplay, Encode, Pair}; +use sp_runtime::traits::Block; +use std::{io::Write, sync::Arc}; + +fn extract_genesis_wasm(chain_spec: &Box) -> Result, String> { + let mut storage = chain_spec.build_storage()?; + + storage + .top + .remove(sp_core::storage::well_known_keys::CODE) + .ok_or_else(|| "Could not find wasm file in genesis state!".into()) +} + +pub fn wrap_announce_block() -> Box AnnounceBlockFn> { + tracing::info!("Block announcements disabled."); + Box::new(|_| { + // Never announce any block + Arc::new(|_, _| {}) + }) +} + +fn main() -> Result<(), sc_cli::Error> { + let cli = TestCollatorCli::parse(); + + match &cli.subcommand { + Some(Commands::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + }, + Some(Commands::ExportGenesisState(params)) => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); + let _ = builder.init(); + + let parachain_id = ParaId::from(params.parachain_id); + let spec = Box::new(cumulus_test_service::get_chain_spec(parachain_id)) as Box<_>; + let state_version = cumulus_test_service::runtime::VERSION.state_version(); + + let block: parachains_common::Block = generate_genesis_block(&spec, state_version)?; + let raw_header = block.header().encode(); + let output_buf = if params.raw { + raw_header + } else { + format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() + }; + + if let Some(output) = ¶ms.output { + std::fs::write(output, output_buf)?; + } else { + std::io::stdout().write_all(&output_buf)?; + } + + Ok(()) + }, + Some(Commands::ExportGenesisWasm(params)) => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); + let _ = builder.init(); + + let parachain_id = ParaId::from(params.parachain_id); + let spec = Box::new(cumulus_test_service::get_chain_spec(parachain_id)) as Box<_>; + let raw_wasm_blob = extract_genesis_wasm(&spec)?; + let output_buf = if params.raw { + raw_wasm_blob + } else { + format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() + }; + + if let Some(output) = ¶ms.output { + std::fs::write(output, output_buf)?; + } else { + std::io::stdout().write_all(&output_buf)?; + } + + Ok(()) + }, + None => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_colors(true); + let _ = builder.init(); + + let collator_options = cli.run.collator_options(); + let tokio_runtime = sc_cli::build_runtime()?; + let tokio_handle = tokio_runtime.handle(); + let config = cli + .run + .normalize() + .create_configuration(&cli, tokio_handle.clone()) + .expect("Should be able to generate config"); + + let parachain_id = ParaId::from(cli.parachain_id); + let polkadot_cli = RelayChainCli::new( + &config, + [RelayChainCli::executable_name().to_string()] + .iter() + .chain(cli.relaychain_args.iter()), + ); + + let parachain_account = + AccountIdConversion::::into_account( + ¶chain_id, + ); + + let state_version = + RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); + + let block: parachains_common::Block = + generate_genesis_block(&config.chain_spec, state_version) + .map_err(|e| format!("{:?}", e))?; + let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); + + let tokio_handle = config.tokio_handle.clone(); + let polkadot_config = + SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, tokio_handle) + .map_err(|err| format!("Relay chain argument error: {}", err))?; + + tracing::info!("Parachain id: {:?}", parachain_id); + tracing::info!("Parachain Account: {}", parachain_account); + tracing::info!("Parachain genesis state: {}", genesis_state); + tracing::info!( + "Is collating: {}", + if config.role.is_authority() { "yes" } else { "no" } + ); + + let collator_key = Some(CollatorPair::generate().0); + + let consensus = cli + .use_null_consensus + .then(|| { + tracing::info!("Using null consensus."); + cumulus_test_service::Consensus::Null + }) + .unwrap_or(cumulus_test_service::Consensus::RelayChain); + + let (mut task_manager, _, _, _, _) = tokio_runtime + .block_on(cumulus_test_service::start_node_impl( + config, + collator_key, + polkadot_config, + parachain_id, + cli.disable_block_announcements.then(wrap_announce_block), + |_| Ok(jsonrpsee::RpcModule::new(())), + consensus, + collator_options, + )) + .expect("could not create Cumulus test service"); + + tokio_runtime + .block_on(task_manager.future()) + .expect("Could not run service to completion"); + Ok(()) + }, + } +} diff --git a/zombienet_tests/0001-sync_blocks_from_tip_without_connected_collator.feature b/zombienet_tests/0001-sync_blocks_from_tip_without_connected_collator.feature new file mode 100644 index 0000000000..6f84041c07 --- /dev/null +++ b/zombienet_tests/0001-sync_blocks_from_tip_without_connected_collator.feature @@ -0,0 +1,17 @@ +Description: Small Network test +Network: ./0001-sync_blocks_from_tip_without_connected_collator.toml +Creds: config + + +alice: is up +bob: is up +charlie: is up +dave: is up +ferdie: is up +eve: is up + +alice: parachain 2000 is registered within 225 seconds +alice: parachain 2000 block height is at least 10 within 250 seconds + +ferdie: reports block height is at least 12 within 250 seconds +eve: reports block height is at least 12 within 250 seconds diff --git a/zombienet_tests/0001-sync_blocks_from_tip_without_connected_collator.toml b/zombienet_tests/0001-sync_blocks_from_tip_without_connected_collator.toml new file mode 100644 index 0000000000..8f2d8a3a8c --- /dev/null +++ b/zombienet_tests/0001-sync_blocks_from_tip_without_connected_collator.toml @@ -0,0 +1,52 @@ +[relaychain] +default_image = "docker.io/paritypr/polkadot-debug:master" +default_command = "polkadot" +default_args = [ "-lparachain=debug" ] + +chain = "rococo-local" + + [[relaychain.nodes]] + name = "alice" + validator = true + + [[relaychain.nodes]] + name = "bob" + image = "docker.io/paritypr/polkadot-debug:5236-0.9.18-c55660e9-be16bd72" + validator = true + args = ["--database=paritydb-experimental"] + +[[parachains]] +id = 2000 +cumulus_based = true + + # run charlie as parachain collator + [[parachains.collators]] + name = "charlie" + validator = true + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["-lparachain=debug"] + + # run dave as parachain full node + [[parachains.collators]] + name = "dave" + validator = false + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["-lparachain=debug"] + + # run eve as parachain full node that is only connected to dave + [[parachains.collators]] + name = "eve" + validator = false + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["--reserved-only", "--reserved-nodes {{'dave'|zombie}}"] + + # run ferdie as parachain full node that is only connected to dave + [[parachains.collators]] + name = "ferdie" + validator = false + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["--reserved-only", "--reserved-nodes {{'dave'|zombie}}"] \ No newline at end of file diff --git a/zombienet_tests/0002-pov_recovery.feature b/zombienet_tests/0002-pov_recovery.feature new file mode 100644 index 0000000000..5f33c5ff4a --- /dev/null +++ b/zombienet_tests/0002-pov_recovery.feature @@ -0,0 +1,13 @@ +Description: Small Network test +Network: ./0002-pov_recovery.toml +Creds: config + + +alice: is up +bob: is up +charlie: is up +dave: is up +eve: is up +alice: parachain 2000 is registered within 225 seconds +dave: reports block height is at least 7 within 250 seconds +eve: reports block height is at least 7 within 250 seconds diff --git a/zombienet_tests/0002-pov_recovery.toml b/zombienet_tests/0002-pov_recovery.toml new file mode 100644 index 0000000000..5913cf8275 --- /dev/null +++ b/zombienet_tests/0002-pov_recovery.toml @@ -0,0 +1,46 @@ +[relaychain] +default_image = "docker.io/paritypr/polkadot-debug:master" +default_command = "polkadot" +default_args = [ "-lparachain=debug" ] + +chain = "rococo-local" + + [[relaychain.nodes]] + name = "alice" + validator = true + + [[relaychain.nodes]] + name = "bob" + image = "docker.io/paritypr/polkadot-debug:5236-0.9.18-c55660e9-be16bd72" + validator = true + args = ["--database=paritydb-experimental"] + +[[parachains]] +id = 2000 +cumulus_based = true + + # run charlie as parachain collator + [[parachains.collators]] + name = "charlie" + validator = true + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["-lparachain=debug"] + + # Run dave as parachain collator and eve as parachain full node + # + # They will need to recover the pov blocks through availability recovery. + [[parachains.collators]] + name = "dave" + validator = true + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["--reserved-only", "--reserved-nodes {{'charlie'|zombie}}", "--use-null-consensus", "--disable-block-announcements"] + + # run eve as parachain full node that is only connected to dave + [[parachains.collators]] + name = "eve" + validator = false + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["--reserved-only", "--reserved-nodes {{'charlie'|zombie}}", "--use-null-consensus", "--disable-block-announcements"] diff --git a/zombienet_tests/0003-test_full_node_catching_up.feature b/zombienet_tests/0003-test_full_node_catching_up.feature new file mode 100644 index 0000000000..f7e5e4df3a --- /dev/null +++ b/zombienet_tests/0003-test_full_node_catching_up.feature @@ -0,0 +1,13 @@ +Description: Small Network test +Network: ./0003-test_full_node_catching_up.toml +Creds: config + + +alice: is up +bob: is up +charlie: is up +dave: is up +eve: is up +alice: parachain 2000 is registered within 225 seconds +dave: reports block height is at least 7 within 250 seconds +eve: reports block height is at least 7 within 250 seconds diff --git a/zombienet_tests/0003-test_full_node_catching_up.toml b/zombienet_tests/0003-test_full_node_catching_up.toml new file mode 100644 index 0000000000..59ec912181 --- /dev/null +++ b/zombienet_tests/0003-test_full_node_catching_up.toml @@ -0,0 +1,44 @@ +[relaychain] +default_image = "docker.io/paritypr/polkadot-debug:master" +default_command = "polkadot" +default_args = [ "-lparachain=debug" ] + +chain = "rococo-local" + + [[relaychain.nodes]] + name = "alice" + validator = true + + [[relaychain.nodes]] + name = "bob" + image = "docker.io/paritypr/polkadot-debug:5236-0.9.18-c55660e9-be16bd72" + validator = true + args = ["--database=paritydb-experimental"] + +[[parachains]] +id = 2000 +cumulus_based = true + + # run charlie as parachain collator + [[parachains.collators]] + name = "charlie" + validator = true + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["-lparachain=debug"] + + # run cumulus dave (a parachain full node) and wait for it to sync some blocks + [[parachains.collators]] + name = "dave" + validator = false + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["--reserved-only", "--reserved-nodes {{'charlie'|zombie}}"] + + # run cumulus eve (a parachain full node) and wait for it to sync some blocks + [[parachains.collators]] + name = "eve" + validator = false + image = "docker.io/parity/polkadot-collator:latest" + command = "test-collator" + args = ["--reserved-only", "--reserved-nodes {{'charlie'|zombie}}"]