mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 04:41:03 +00:00
Fix integration test (#124)
This commit is contained in:
Generated
+296
-319
File diff suppressed because it is too large
Load Diff
@@ -14,24 +14,24 @@ cumulus-runtime = { path = "../runtime", default-features = false }
|
||||
parachain = { package = "polkadot-parachain", git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch", default-features = false }
|
||||
|
||||
# Substrate dependencies
|
||||
frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", version = "2.0.0-dev", default-features = false }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", version = "2.0.0-dev", default-features = false }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
|
||||
# Other Dependencies
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"]}
|
||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
sp-externalities = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
substrate-test-runtime-client = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "cumulus-branch", default-features = false }
|
||||
sp-externalities = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
substrate-test-runtime-client = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ['std']
|
||||
|
||||
@@ -49,10 +49,11 @@ cumulus-primitives = { path = "../../primitives" }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
@@ -60,21 +61,17 @@ substrate-build-script-utils = { git = "https://github.com/paritytech/substrate"
|
||||
[dev-dependencies]
|
||||
assert_cmd = "0.12"
|
||||
nix = "0.17"
|
||||
tempfile = "3.1"
|
||||
jsonrpsee = "0.1"
|
||||
async-std = { version = "1.2.0", features = [ "attributes" ] }
|
||||
hex = "0.4"
|
||||
serde_json = "1.0"
|
||||
rand = "0.7.3"
|
||||
tokio = { version = "0.2.13", features = ["macros"] }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-test-runtime = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-test-runtime-client = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||
|
||||
# Substrate dependencies
|
||||
substrate-test-runtime-client = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
sp-version = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
substrate-test-runtime-client = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
|
||||
|
||||
@@ -28,12 +28,6 @@ pub enum Subcommand {
|
||||
/// Export the genesis state of the parachain.
|
||||
#[structopt(name = "export-genesis-state")]
|
||||
ExportGenesisState(ExportGenesisStateCommand),
|
||||
|
||||
/// Run Polkadot for testing purpose
|
||||
Polkadot(polkadot_cli::Cli),
|
||||
|
||||
#[structopt(name = "validation-worker", setting = structopt::clap::AppSettings::Hidden)]
|
||||
PolkadotValidationWorker(polkadot_cli::ValidationWorkerCommand),
|
||||
}
|
||||
|
||||
/// Command for exporting the genesis state of the parachain
|
||||
|
||||
@@ -115,7 +115,8 @@ impl SubstrateCli for PolkadotCli {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_genesis_state(para_id: ParaId) -> Result<Block> {
|
||||
/// Generate the genesis block
|
||||
pub fn generate_genesis_state(para_id: ParaId) -> Result<Block> {
|
||||
let storage = (&chain_spec::get_chain_spec(para_id)).build_storage()?;
|
||||
|
||||
let child_roots = storage.children_default.iter().map(|(sk, child_content)| {
|
||||
@@ -156,7 +157,7 @@ pub fn run() -> Result<()> {
|
||||
})
|
||||
}
|
||||
Some(Subcommand::ExportGenesisState(params)) => {
|
||||
sc_cli::init_logger("", &<sc_cli::LogRotationOpt as structopt::StructOpt>::from_args())?;
|
||||
sc_cli::init_logger("");
|
||||
|
||||
let block = generate_genesis_state(params.parachain_id.into())?;
|
||||
let header_hex = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
|
||||
@@ -169,37 +170,6 @@ pub fn run() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Some(Subcommand::Polkadot(polkadot_cli)) => {
|
||||
let runner = polkadot_cli.create_runner(&polkadot_cli.run.base)?;
|
||||
let authority_discovery_enabled = polkadot_cli.run.authority_discovery_enabled;
|
||||
let grandpa_pause = if polkadot_cli.run.grandpa_pause.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
polkadot_cli.run.grandpa_pause[0],
|
||||
polkadot_cli.run.grandpa_pause[1],
|
||||
))
|
||||
};
|
||||
|
||||
runner.run_node_until_exit(|config| match config.role {
|
||||
Role::Light => polkadot_service::polkadot_new_light(config).map(|r| r.0),
|
||||
_ => polkadot_service::polkadot_new_full(
|
||||
config,
|
||||
None,
|
||||
None,
|
||||
authority_discovery_enabled,
|
||||
6000,
|
||||
grandpa_pause,
|
||||
)
|
||||
.map(|(s, _, _)| s),
|
||||
})
|
||||
}
|
||||
Some(Subcommand::PolkadotValidationWorker(cmd)) => {
|
||||
sc_cli::init_logger("", &<sc_cli::LogRotationOpt as structopt::StructOpt>::from_args())?;
|
||||
polkadot_service::run_validation_worker(&cmd.mem_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
let runner = cli.create_runner(&*cli.run)?;
|
||||
|
||||
@@ -238,6 +208,7 @@ pub fn run() -> Result<()> {
|
||||
info!("Parachain genesis state: {}", genesis_state);
|
||||
|
||||
crate::service::run_collator(config, key, polkadot_config, id)
|
||||
.map(|x| x.task_manager)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use codec::Encode;
|
||||
use futures::{
|
||||
future::{self, FutureExt},
|
||||
pin_mut, select,
|
||||
};
|
||||
use polkadot_primitives::parachain::{Id as ParaId, Info, Scheduling};
|
||||
use polkadot_runtime_common::registrar;
|
||||
use polkadot_test_runtime_client::Sr25519Keyring;
|
||||
use sc_client_api::execution_extensions::ExecutionStrategies;
|
||||
use sc_informant::OutputFormat;
|
||||
use sc_network::{config::TransportConfig, multiaddr};
|
||||
use sc_service::{
|
||||
config::{
|
||||
DatabaseConfig, KeystoreConfig, MultiaddrWithPeerId, NetworkConfiguration,
|
||||
WasmExecutionMethod,
|
||||
},
|
||||
BasePath, Configuration, Error as ServiceError, Role, TaskExecutor,
|
||||
};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use substrate_test_client::BlockchainEventsExt;
|
||||
use substrate_test_runtime_client::AccountKeyring::*;
|
||||
use tokio::{spawn, time::delay_for as sleep};
|
||||
|
||||
static INTEGRATION_TEST_ALLOWED_TIME: Option<&str> = option_env!("INTEGRATION_TEST_ALLOWED_TIME");
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn integration_test() {
|
||||
let task_executor: TaskExecutor = (|fut, _| {
|
||||
spawn(fut);
|
||||
})
|
||||
.into();
|
||||
|
||||
// start alice
|
||||
let mut alice =
|
||||
polkadot_test_service::run_test_node(task_executor.clone(), Alice, || {}, vec![]);
|
||||
|
||||
// start bob
|
||||
let mut bob = polkadot_test_service::run_test_node(
|
||||
task_executor.clone(),
|
||||
Bob,
|
||||
|| {},
|
||||
vec![alice.addr.clone()],
|
||||
);
|
||||
|
||||
let t1 = sleep(Duration::from_secs(
|
||||
INTEGRATION_TEST_ALLOWED_TIME
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(600),
|
||||
))
|
||||
.fuse();
|
||||
|
||||
let t2 = async {
|
||||
let para_id = ParaId::from(100);
|
||||
|
||||
future::join(alice.wait_for_blocks(2), bob.wait_for_blocks(2)).await;
|
||||
|
||||
// export genesis state
|
||||
let genesis_state = crate::command::generate_genesis_state(para_id)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
// create and sign transaction
|
||||
let function = polkadot_test_runtime::Call::Sudo(pallet_sudo::Call::sudo(Box::new(
|
||||
polkadot_test_runtime::Call::Registrar(registrar::Call::register_para(
|
||||
para_id,
|
||||
Info {
|
||||
scheduling: Scheduling::Always,
|
||||
},
|
||||
parachain_runtime::WASM_BINARY.to_vec().into(),
|
||||
genesis_state.into(),
|
||||
)),
|
||||
)));
|
||||
|
||||
// register parachain
|
||||
let _ = alice.call_function(function, Alice).await.unwrap();
|
||||
|
||||
// run cumulus charlie
|
||||
let key = Arc::new(sp_core::Pair::from_seed(&[10; 32]));
|
||||
let mut polkadot_config = polkadot_test_service::node_config(
|
||||
|| {},
|
||||
task_executor.clone(),
|
||||
Charlie,
|
||||
vec![alice.addr.clone(), bob.addr.clone()],
|
||||
);
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
polkadot_config.rpc_http = Some(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 27016));
|
||||
polkadot_config.rpc_methods = sc_service::config::RpcMethods::Unsafe;
|
||||
let parachain_config =
|
||||
parachain_config(task_executor.clone(), Charlie, vec![], para_id).unwrap();
|
||||
let service =
|
||||
crate::service::run_collator(parachain_config, key, polkadot_config, para_id).unwrap();
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
service.client.wait_for_blocks(4).await;
|
||||
|
||||
alice.task_manager.terminate();
|
||||
bob.task_manager.terminate();
|
||||
}
|
||||
.fuse();
|
||||
|
||||
pin_mut!(t1, t2);
|
||||
|
||||
select! {
|
||||
_ = t1 => {
|
||||
panic!("the test took too long, maybe no parachain blocks have been produced");
|
||||
},
|
||||
_ = t2 => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parachain_config(
|
||||
task_executor: TaskExecutor,
|
||||
key: Sr25519Keyring,
|
||||
boot_nodes: Vec<MultiaddrWithPeerId>,
|
||||
para_id: ParaId,
|
||||
) -> Result<Configuration, ServiceError> {
|
||||
let base_path = BasePath::new_temp_dir()?;
|
||||
let root = base_path.path().to_path_buf();
|
||||
let role = Role::Authority {
|
||||
sentry_nodes: Vec::new(),
|
||||
};
|
||||
let key_seed = key.to_seed();
|
||||
let spec = crate::chain_spec::get_chain_spec(para_id);
|
||||
|
||||
let mut network_config = NetworkConfiguration::new(
|
||||
format!("Cumulus Test Node for: {}", key_seed),
|
||||
"network/test/0.1",
|
||||
Default::default(),
|
||||
None,
|
||||
);
|
||||
let informant_output_format = OutputFormat {
|
||||
enable_color: false,
|
||||
prefix: format!("[{}] ", key_seed),
|
||||
};
|
||||
|
||||
network_config.boot_nodes = boot_nodes;
|
||||
|
||||
network_config.allow_non_globals_in_dht = true;
|
||||
|
||||
network_config
|
||||
.listen_addresses
|
||||
.push(multiaddr::Protocol::Memory(rand::random()).into());
|
||||
|
||||
network_config.transport = TransportConfig::MemoryOnly;
|
||||
|
||||
Ok(Configuration {
|
||||
impl_name: "cumulus-test-node".to_string(),
|
||||
impl_version: "0.1".to_string(),
|
||||
role,
|
||||
task_executor,
|
||||
transaction_pool: Default::default(),
|
||||
network: network_config,
|
||||
keystore: KeystoreConfig::Path {
|
||||
path: root.join("key"),
|
||||
password: None,
|
||||
},
|
||||
database: DatabaseConfig::RocksDb {
|
||||
path: root.join("db"),
|
||||
cache_size: 128,
|
||||
},
|
||||
state_cache_size: 16777216,
|
||||
state_cache_child_ratio: None,
|
||||
pruning: Default::default(),
|
||||
chain_spec: Box::new(spec),
|
||||
wasm_method: WasmExecutionMethod::Interpreted,
|
||||
// NOTE: we enforce the use of the native runtime to make the errors more debuggable
|
||||
execution_strategies: ExecutionStrategies {
|
||||
syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
importing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
other: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
},
|
||||
rpc_http: None,
|
||||
rpc_ws: None,
|
||||
rpc_ipc: None,
|
||||
rpc_ws_max_connections: None,
|
||||
rpc_cors: None,
|
||||
rpc_methods: Default::default(),
|
||||
prometheus_config: None,
|
||||
telemetry_endpoints: None,
|
||||
telemetry_external_transport: None,
|
||||
default_heap_pages: None,
|
||||
offchain_worker: Default::default(),
|
||||
force_authoring: false,
|
||||
disable_grandpa: false,
|
||||
dev_key_seed: Some(key_seed),
|
||||
tracing_targets: None,
|
||||
tracing_receiver: Default::default(),
|
||||
max_runtime_instances: 8,
|
||||
announce_block: true,
|
||||
base_path: Some(base_path),
|
||||
informant_output_format,
|
||||
})
|
||||
}
|
||||
@@ -24,6 +24,8 @@ mod chain_spec;
|
||||
mod service;
|
||||
mod cli;
|
||||
mod command;
|
||||
#[cfg(test)]
|
||||
mod integration_test;
|
||||
|
||||
fn main() -> sc_cli::Result<()> {
|
||||
command::run()
|
||||
|
||||
@@ -25,7 +25,7 @@ use sc_finality_grandpa::{
|
||||
FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider,
|
||||
};
|
||||
use sc_informant::OutputFormat;
|
||||
use sc_service::{Configuration, TaskManager};
|
||||
use sc_service::{Configuration, ServiceComponents, TFullBackend, TFullClient};
|
||||
use std::sync::Arc;
|
||||
|
||||
// Our native executor instance.
|
||||
@@ -55,10 +55,12 @@ macro_rules! new_full_start {
|
||||
client.clone(),
|
||||
builder.prometheus_registry(),
|
||||
));
|
||||
let pool = sc_transaction_pool::BasicPool::new(
|
||||
let pool = sc_transaction_pool::BasicPool::new_full(
|
||||
builder.config().transaction_pool.clone(),
|
||||
pool_api,
|
||||
builder.prometheus_registry(),
|
||||
builder.spawn_handle(),
|
||||
client.clone(),
|
||||
);
|
||||
Ok(pool)
|
||||
})?
|
||||
@@ -86,7 +88,19 @@ pub fn run_collator(
|
||||
key: Arc<CollatorPair>,
|
||||
mut polkadot_config: polkadot_collator::Configuration,
|
||||
id: polkadot_primitives::parachain::Id,
|
||||
) -> sc_service::error::Result<TaskManager> {
|
||||
) -> sc_service::error::Result<ServiceComponents<
|
||||
parachain_runtime::opaque::Block,
|
||||
TFullBackend<parachain_runtime::opaque::Block>,
|
||||
sc_consensus::LongestChain<TFullBackend<parachain_runtime::opaque::Block>, parachain_runtime::opaque::Block>,
|
||||
sc_transaction_pool::BasicPool<
|
||||
sc_transaction_pool::FullChainApi<
|
||||
TFullClient<parachain_runtime::opaque::Block, parachain_runtime::RuntimeApi, crate::service::Executor>,
|
||||
parachain_runtime::opaque::Block,
|
||||
>,
|
||||
parachain_runtime::opaque::Block,
|
||||
>,
|
||||
TFullClient<parachain_runtime::opaque::Block, parachain_runtime::RuntimeApi, crate::service::Executor>,
|
||||
>> {
|
||||
let mut parachain_config = prepare_collator_config(parachain_config);
|
||||
|
||||
parachain_config.informant_output_format = OutputFormat {
|
||||
@@ -152,5 +166,5 @@ pub fn run_collator(
|
||||
.spawn_essential_handle()
|
||||
.spawn("polkadot", polkadot_future);
|
||||
|
||||
Ok(service.task_manager)
|
||||
Ok(service)
|
||||
}
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// TODO: this is necessary for the jsonrpsee macro used
|
||||
#![allow(unused_variables, dead_code)]
|
||||
|
||||
use assert_cmd::cargo::cargo_bin;
|
||||
use async_std::{net, task::sleep};
|
||||
use codec::Encode;
|
||||
use futures::{future::FutureExt, join, pin_mut, select};
|
||||
use jsonrpsee::{raw::RawClient, transport::http::HttpTransportClient};
|
||||
use polkadot_primitives::parachain::{Info, Scheduling};
|
||||
use polkadot_primitives::Hash as PHash;
|
||||
use polkadot_runtime::{Header, Runtime, SignedExtra, SignedPayload};
|
||||
use polkadot_runtime_common::{parachains, registrar, BlockHashCount, claims};
|
||||
use serde_json::Value;
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_runtime::generic;
|
||||
use sp_version::RuntimeVersion;
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
env, fs,
|
||||
io::Read,
|
||||
path::PathBuf,
|
||||
process::{Child, Command, Stdio},
|
||||
time::Duration,
|
||||
};
|
||||
use substrate_test_runtime_client::AccountKeyring::Alice;
|
||||
use tempfile::tempdir;
|
||||
|
||||
static POLKADOT_ARGS: &[&str] = &["polkadot", "--chain=res/polkadot_chainspec.json"];
|
||||
static INTEGRATION_TEST_ALLOWED_TIME: Option<&str> = option_env!("INTEGRATION_TEST_ALLOWED_TIME");
|
||||
|
||||
jsonrpsee::rpc_api! {
|
||||
Author {
|
||||
#[rpc(method = "author_submitExtrinsic", positional_params)]
|
||||
fn submit_extrinsic(extrinsic: String) -> PHash;
|
||||
}
|
||||
|
||||
Chain {
|
||||
#[rpc(method = "chain_getFinalizedHead")]
|
||||
fn current_block_hash() -> PHash;
|
||||
|
||||
#[rpc(method = "chain_getHeader", positional_params)]
|
||||
fn header(hash: PHash) -> Option<Header>;
|
||||
|
||||
#[rpc(method = "chain_getBlockHash", positional_params)]
|
||||
fn block_hash(hash: Option<u64>) -> Option<PHash>;
|
||||
}
|
||||
|
||||
State {
|
||||
#[rpc(method = "state_getRuntimeVersion")]
|
||||
fn runtime_version() -> RuntimeVersion;
|
||||
}
|
||||
|
||||
System {
|
||||
#[rpc(method = "system_networkState")]
|
||||
fn network_state() -> Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from
|
||||
// https://github.com/rust-lang/cargo/blob/485670b3983b52289a2f353d589c57fae2f60f82/tests/testsuite/support/mod.rs#L507
|
||||
fn target_dir() -> PathBuf {
|
||||
env::current_exe()
|
||||
.ok()
|
||||
.map(|mut path| {
|
||||
path.pop();
|
||||
if path.ends_with("deps") {
|
||||
path.pop();
|
||||
}
|
||||
path
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
struct ChildHelper<'a> {
|
||||
name: String,
|
||||
child: &'a mut Child,
|
||||
}
|
||||
|
||||
impl<'a> Drop for ChildHelper<'a> {
|
||||
fn drop(&mut self) {
|
||||
let name = self.name.clone();
|
||||
|
||||
self.terminate();
|
||||
|
||||
let mut stdout = String::new();
|
||||
if let Some(reader) = self.child.stdout.as_mut() {
|
||||
let _ = reader.read_to_string(&mut stdout);
|
||||
}
|
||||
eprintln!("process '{}' stdout:\n{}\n", name, stdout,);
|
||||
|
||||
let mut stderr = String::new();
|
||||
if let Some(reader) = self.child.stderr.as_mut() {
|
||||
let _ = reader.read_to_string(&mut stderr);
|
||||
}
|
||||
eprintln!("process '{}' stderr:\n{}\n", name, stderr,);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ChildHelper<'a> {
|
||||
fn new(name: &str, child: &'a mut Child) -> ChildHelper<'a> {
|
||||
ChildHelper {
|
||||
name: name.to_string(),
|
||||
child,
|
||||
}
|
||||
}
|
||||
|
||||
fn terminate(&mut self) {
|
||||
match self.child.try_wait() {
|
||||
Ok(Some(_)) => return,
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
eprintln!("could not wait for child process to finish: {}", err);
|
||||
let _ = self.child.kill();
|
||||
let _ = self.child.wait();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.child.kill();
|
||||
|
||||
let _ = self.child.wait();
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_tcp<A: net::ToSocketAddrs + std::fmt::Display>(address: A) {
|
||||
while let Err(err) = net::TcpStream::connect(&address).await {
|
||||
eprintln!("Waiting for {} to be up ({})...", address, err);
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// wait for parachain blocks to be produced
|
||||
async fn wait_for_blocks(number_of_blocks: usize, mut client: &mut RawClient<HttpTransportClient>) {
|
||||
let mut previous_blocks = HashSet::with_capacity(number_of_blocks);
|
||||
|
||||
loop {
|
||||
let current_block_hash = Chain::block_hash(&mut client, None).await.unwrap().unwrap();
|
||||
|
||||
if previous_blocks.insert(current_block_hash) {
|
||||
eprintln!("new parachain block: {}", current_block_hash);
|
||||
|
||||
if previous_blocks.len() == number_of_blocks {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
#[ignore]
|
||||
#[cfg(feature = "disabled")]
|
||||
async fn integration_test() {
|
||||
assert!(
|
||||
!net::TcpStream::connect("127.0.0.1:27015").await.is_ok(),
|
||||
"tcp port is already open 127.0.0.1:27015, this test cannot be run",
|
||||
);
|
||||
assert!(
|
||||
!net::TcpStream::connect("127.0.0.1:27016").await.is_ok(),
|
||||
"tcp port is already open 127.0.0.1:27016, this test cannot be run",
|
||||
);
|
||||
|
||||
let t1 = sleep(Duration::from_secs(
|
||||
INTEGRATION_TEST_ALLOWED_TIME
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(600),
|
||||
))
|
||||
.fuse();
|
||||
let t2 = async {
|
||||
// start alice
|
||||
let polkadot_alice_dir = tempdir().unwrap();
|
||||
let mut polkadot_alice = Command::new(cargo_bin("cumulus-test-parachain-collator"))
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.args(POLKADOT_ARGS)
|
||||
.arg("--base-path")
|
||||
.arg(polkadot_alice_dir.path())
|
||||
.arg("--alice")
|
||||
.arg("--rpc-methods=unsafe")
|
||||
.arg("--rpc-port=27015")
|
||||
.arg("--port=27115")
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let polkadot_alice_helper = ChildHelper::new("alice", &mut polkadot_alice);
|
||||
|
||||
// start bob
|
||||
let polkadot_bob_dir = tempdir().unwrap();
|
||||
let mut polkadot_bob = Command::new(cargo_bin("cumulus-test-parachain-collator"))
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.args(POLKADOT_ARGS)
|
||||
.arg("--base-path")
|
||||
.arg(polkadot_bob_dir.path())
|
||||
.arg("--bob")
|
||||
.arg("--rpc-methods=unsafe")
|
||||
.arg("--rpc-port=27016")
|
||||
.arg("--port=27116")
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let polkadot_bob_helper = ChildHelper::new("bob", &mut polkadot_bob);
|
||||
|
||||
// wait for both nodes to be up and running
|
||||
join!(
|
||||
wait_for_tcp("127.0.0.1:27015"),
|
||||
wait_for_tcp("127.0.0.1:27016")
|
||||
);
|
||||
|
||||
// export genesis state
|
||||
let cmd = Command::new(cargo_bin("cumulus-test-parachain-collator"))
|
||||
.arg("export-genesis-state")
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(cmd.status.success());
|
||||
let output = &cmd.stdout;
|
||||
let genesis_state = hex::decode(&output[2..output.len() - 1]).unwrap();
|
||||
|
||||
// connect RPC clients
|
||||
let transport_client_alice =
|
||||
jsonrpsee::transport::http::HttpTransportClient::new("http://127.0.0.1:27015");
|
||||
let mut client_alice = jsonrpsee::raw::RawClient::new(transport_client_alice);
|
||||
let transport_client_bob =
|
||||
jsonrpsee::transport::http::HttpTransportClient::new("http://127.0.0.1:27016");
|
||||
let mut client_bob = jsonrpsee::raw::RawClient::new(transport_client_bob);
|
||||
|
||||
// retrieve nodes network id
|
||||
let polkadot_alice_id = System::network_state(&mut client_alice).await.unwrap()["peerId"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let polkadot_bob_id = System::network_state(&mut client_bob).await.unwrap()["peerId"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
// retrieve runtime version
|
||||
let runtime_version = State::runtime_version(&mut client_alice).await.unwrap();
|
||||
|
||||
// get the current block
|
||||
let current_block_hash = Chain::block_hash(&mut client_alice, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let current_block = Chain::header(&mut client_alice, current_block_hash)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.number
|
||||
.saturated_into::<u64>();
|
||||
|
||||
let genesis_block = Chain::block_hash(&mut client_alice, 0)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// create and sign transaction
|
||||
let wasm = fs::read(target_dir().join(
|
||||
"wbuild/cumulus-test-parachain-runtime/cumulus_test_parachain_runtime.compact.wasm",
|
||||
))
|
||||
.unwrap();
|
||||
let call = pallet_sudo::Call::sudo(Box::new(
|
||||
registrar::Call::<Runtime>::register_para(
|
||||
100.into(),
|
||||
Info {
|
||||
scheduling: Scheduling::Always,
|
||||
},
|
||||
wasm.into(),
|
||||
genesis_state.into(),
|
||||
)
|
||||
.into(),
|
||||
));
|
||||
let nonce = 0;
|
||||
let period = BlockHashCount::get()
|
||||
.checked_next_power_of_two()
|
||||
.map(|c| c / 2)
|
||||
.unwrap_or(2) as u64;
|
||||
let tip = 0;
|
||||
let extra: SignedExtra = (
|
||||
frame_system::CheckSpecVersion::<Runtime>::new(),
|
||||
frame_system::CheckTxVersion::<Runtime>::new(),
|
||||
frame_system::CheckGenesis::<Runtime>::new(),
|
||||
frame_system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
|
||||
frame_system::CheckNonce::<Runtime>::from(nonce),
|
||||
frame_system::CheckWeight::<Runtime>::new(),
|
||||
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
|
||||
registrar::LimitParathreadCommits::<Runtime>::new(),
|
||||
parachains::ValidateDoubleVoteReports::<Runtime>::new(),
|
||||
pallet_grandpa::ValidateEquivocationReport::<Runtime>::new(),
|
||||
claims::PrevalidateAttests::<Runtime>::new(),
|
||||
);
|
||||
let raw_payload = SignedPayload::from_raw(
|
||||
call.clone().into(),
|
||||
extra.clone(),
|
||||
(
|
||||
(),
|
||||
runtime_version.spec_version,
|
||||
runtime_version.transaction_version,
|
||||
genesis_block,
|
||||
current_block_hash,
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
),
|
||||
);
|
||||
let signature = raw_payload.using_encoded(|e| Alice.sign(e));
|
||||
|
||||
// register parachain
|
||||
let ex = polkadot_runtime::UncheckedExtrinsic::new_signed(
|
||||
call.into(),
|
||||
Alice.into(),
|
||||
sp_runtime::MultiSignature::Sr25519(signature),
|
||||
extra,
|
||||
);
|
||||
let _register_block_hash =
|
||||
Author::submit_extrinsic(&mut client_alice, format!("0x{}", hex::encode(ex.encode())))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// run cumulus charlie
|
||||
let cumulus_charlie_dir = tempdir().unwrap();
|
||||
let mut cumulus_charlie = Command::new(cargo_bin("cumulus-test-parachain-collator"))
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.arg("--base-path")
|
||||
.arg(cumulus_charlie_dir.path())
|
||||
.arg("--rpc-methods=unsafe")
|
||||
.arg("--rpc-port=27017")
|
||||
.arg("--port=27117")
|
||||
.arg("--")
|
||||
.arg(format!(
|
||||
"--bootnodes=/ip4/127.0.0.1/tcp/27115/p2p/{}",
|
||||
polkadot_alice_id
|
||||
))
|
||||
.arg(format!(
|
||||
"--bootnodes=/ip4/127.0.0.1/tcp/27116/p2p/{}",
|
||||
polkadot_bob_id
|
||||
))
|
||||
.arg("--charlie")
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let cumulus_charlie_helper = ChildHelper::new("cumulus-charlie", &mut cumulus_charlie);
|
||||
wait_for_tcp("127.0.0.1:27017").await;
|
||||
|
||||
// connect rpc client to cumulus
|
||||
let transport_client_cumulus_charlie =
|
||||
jsonrpsee::transport::http::HttpTransportClient::new("http://127.0.0.1:27017");
|
||||
let mut client_cumulus_charlie =
|
||||
jsonrpsee::raw::RawClient::new(transport_client_cumulus_charlie);
|
||||
|
||||
wait_for_blocks(4, &mut client_cumulus_charlie).await;
|
||||
}
|
||||
.fuse();
|
||||
|
||||
pin_mut!(t1, t2);
|
||||
|
||||
select! {
|
||||
_ = t1 => {
|
||||
panic!("the test took too long, maybe no parachain blocks have been produced");
|
||||
},
|
||||
_ = t2 => {},
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
runtime = { package = "cumulus-runtime", path = "../../runtime", default-features = false }
|
||||
substrate-test-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
|
||||
substrate-test-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch", version = "2.0.0-rc4" }
|
||||
|
||||
[build-dependencies]
|
||||
wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = " 1.0.6" }
|
||||
|
||||
Reference in New Issue
Block a user