diff --git a/crates/configuration/src/global_settings.rs b/crates/configuration/src/global_settings.rs index f6e73028979536592c44c68851f1bdef68c6cd1f..36a7600854bf55237a084da83a0257535fb0d2dd 100644 --- a/crates/configuration/src/global_settings.rs +++ b/crates/configuration/src/global_settings.rs @@ -235,7 +235,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "global_settings.bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); } @@ -250,7 +250,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "global_settings.bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); assert_eq!( @@ -268,7 +268,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "global_settings.local_ip: invalid IP address syntax" ); } @@ -284,7 +284,7 @@ mod tests { assert_eq!(errors.len(), 3); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "global_settings.bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); assert_eq!( diff --git a/crates/configuration/src/network.rs b/crates/configuration/src/network.rs index ee67b191e8ae6f59b1f005322479b629d06ccb56..cba24ca68b2c041bcb1caba99a3c7fdb5fd6e54c 100644 --- a/crates/configuration/src/network.rs +++ b/crates/configuration/src/network.rs @@ -582,7 +582,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.default_image: 'invalid.image' doesn't match regex '^([ip]|[hostname]/)?[tag_name]:[tag_version]?$'" ); assert_eq!( @@ -622,7 +622,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[1000].collators['collator1'].command: 'invalid command' shouldn't contains whitespace" ); assert_eq!( @@ -679,7 +679,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[1000].collators['collator1'].command: 'invalid command' shouldn't contains whitespace" ); assert_eq!( @@ -724,7 +724,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "global_settings.local_ip: invalid IP address syntax" ); assert_eq!( @@ -766,7 +766,7 @@ mod tests { assert_eq!(errors.len(), 3); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.nodes['node'].command: 'invalid command' shouldn't contains whitespace" ); assert_eq!( diff --git a/crates/configuration/src/parachain.rs b/crates/configuration/src/parachain.rs index 58cd23c863f48f40d630bd98efdf3a2bf732941a..5f3aa083790ff2dc6977e26f4d839dabe5313a9d 100644 --- a/crates/configuration/src/parachain.rs +++ b/crates/configuration/src/parachain.rs @@ -831,7 +831,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[1000].chain: 'invalid chain' shouldn't contains whitespace" ); } @@ -853,7 +853,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[1000].default_command: 'invalid command' shouldn't contains whitespace" ); } @@ -875,7 +875,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"parachain[1000].default_image: 'invalid image' doesn't match regex '^([ip]|[hostname]/)?[tag_name]:[tag_version]?$'" ); } @@ -902,7 +902,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"parachain[1000].default_resources.request_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -925,7 +925,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[2000].genesis_wasm_generator: 'invalid command' shouldn't contains whitespace" ); } @@ -948,7 +948,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[1000].genesis_state_generator: 'invalid command' shouldn't contains whitespace" ); } @@ -971,7 +971,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[2000].bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); assert_eq!( @@ -995,7 +995,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[1000].collators['collator'].command: 'invalid command' shouldn't contains whitespace" ); } @@ -1024,7 +1024,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[2000].collators['collator2'].command: 'invalid command' shouldn't contains whitespace" ); } @@ -1060,7 +1060,7 @@ mod tests { assert_eq!(errors.len(), 5); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "parachain[2000].bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); assert_eq!( diff --git a/crates/configuration/src/relaychain.rs b/crates/configuration/src/relaychain.rs index a3782cda2798152a2fab1c687fbe3bf6d2582973..9d33d5fac40c7cb658b9891b255cf21cf344583f 100644 --- a/crates/configuration/src/relaychain.rs +++ b/crates/configuration/src/relaychain.rs @@ -511,7 +511,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.chain: 'invalid chain' shouldn't contains whitespace" ); } @@ -531,7 +531,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.default_command: 'invalid command' shouldn't contains whitespace" ); } @@ -551,7 +551,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"relaychain.default_image: 'invalid image' doesn't match regex '^([ip]|[hostname]/)?[tag_name]:[tag_version]?$'" ); } @@ -576,7 +576,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"relaychain.default_resources.request_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -595,7 +595,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.nodes['node'].command: 'invalid command' shouldn't contains whitespace" ); } @@ -620,7 +620,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.nodes['node2'].command: 'invalid command' shouldn't contains whitespace" ); } @@ -646,7 +646,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "relaychain.default_resources.limit_cpu: 'invalid' doesn't match regex '^\\d+(.\\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); assert_eq!( diff --git a/crates/configuration/src/shared/node.rs b/crates/configuration/src/shared/node.rs index 16b3905e9b0ea4cbfe039ce200f167988d8e19de..85ff15fece82dca13dad35743b4e0c7fd290b89e 100644 --- a/crates/configuration/src/shared/node.rs +++ b/crates/configuration/src/shared/node.rs @@ -717,7 +717,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "command: 'invalid command' shouldn't contains whitespace" ); } @@ -734,7 +734,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "image: 'myinvalid.image' doesn't match regex '^([ip]|[hostname]/)?[tag_name]:[tag_version]?$'" ); } @@ -752,7 +752,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); } @@ -770,7 +770,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "bootnodes_addresses[0]: '/ip4//tcp/45421' failed to parse: invalid IPv4 address syntax" ); assert_eq!( @@ -792,7 +792,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"resources.limit_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -814,7 +814,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"resources.limit_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); assert_eq!( @@ -842,7 +842,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 4); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "command: 'invalid command' shouldn't contains whitespace" ); assert_eq!( @@ -875,7 +875,7 @@ mod tests { assert_eq!(node_name, "mynode"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "name: 'mynode' is already used across config" ); } @@ -897,7 +897,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "ws_port: '30333' is already used across config" ); } @@ -919,7 +919,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "rpc_port: '4444' is already used across config" ); } @@ -941,7 +941,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "prometheus_port: '9089' is already used across config" ); } @@ -963,7 +963,7 @@ mod tests { assert_eq!(node_name, "node"); assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), "p2p_port: '45093' is already used across config" ); } diff --git a/crates/configuration/src/shared/resources.rs b/crates/configuration/src/shared/resources.rs index 8537b188db7795999fb315335679a8e62bd7fa86..425831dca2f7ef20713c272fe49e7106e8d7a33f 100644 --- a/crates/configuration/src/shared/resources.rs +++ b/crates/configuration/src/shared/resources.rs @@ -423,7 +423,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"request_memory: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -436,7 +436,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"request_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -449,7 +449,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"limit_memory: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -462,7 +462,7 @@ mod tests { assert_eq!(errors.len(), 1); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"limit_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); } @@ -478,7 +478,7 @@ mod tests { assert_eq!(errors.len(), 2); assert_eq!( - errors.get(0).unwrap().to_string(), + errors.first().unwrap().to_string(), r"limit_cpu: 'invalid' doesn't match regex '^\d+(.\d+)?(m|K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'" ); assert_eq!( diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml index dce89cfbc4d4ea8978661a4101bc599a6942612e..a39fd0e23c7a9fa00f7bc41cca2fce6557d4ebda 100644 --- a/crates/examples/Cargo.toml +++ b/crates/examples/Cargo.toml @@ -13,3 +13,5 @@ provider = { path = "../provider" } # to review the exports for neeeded types support = { path = "../support" } tokio = { workspace = true } +futures = { workspace = true } +subxt = { workspace = true } diff --git a/crates/examples/examples/simple_network_example.rs b/crates/examples/examples/simple_network_example.rs index fb42ef2317747156a69940412f49a474e4f2405f..a8731cc2d3666ee310213d62becffff19dd9f624 100644 --- a/crates/examples/examples/simple_network_example.rs +++ b/crates/examples/examples/simple_network_example.rs @@ -1,6 +1,7 @@ // use std::time::Duration; use configuration::NetworkConfig; +use futures::stream::StreamExt; use orchestrator::Orchestrator; use provider::NativeProvider; use support::{fs::local::LocalFileSystem, process::os::OsProcessManager}; @@ -14,11 +15,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let pm = OsProcessManager; let provider = NativeProvider::new(fs.clone(), pm); let orchestrator = Orchestrator::new(fs, provider); - orchestrator.spawn(config).await?; + let network = orchestrator.spawn(config).await?; println!("🚀🚀🚀🚀 network deployed"); - // For now let just loop.... - #[allow(clippy::empty_loop)] - loop {} - // Ok(()) + let client = network + .get_node("alice")? + .client::<subxt::PolkadotConfig>() + .await?; + let mut blocks = client.blocks().subscribe_finalized().await?.take(3); + + while let Some(block) = blocks.next().await { + println!("Block #{}", block?.header().number); + } + + Ok(()) } diff --git a/crates/orchestrator/src/network/node.rs b/crates/orchestrator/src/network/node.rs index 0be0b8848a2d1a911136e2fe52ba35e512921f7c..904f96f1ecc9c1e99a79437c6f8e37598994a2e2 100644 --- a/crates/orchestrator/src/network/node.rs +++ b/crates/orchestrator/src/network/node.rs @@ -3,6 +3,7 @@ use std::{sync::Arc, time::Duration}; use anyhow::anyhow; use prom_metrics_parser::MetricMap; use provider::DynNode; +use subxt::{backend::rpc::RpcClient, OnlineClient}; use tokio::sync::RwLock; use crate::network_spec::node::NodeSpec; @@ -45,6 +46,18 @@ impl NetworkNode { Ok(()) } + /// Get the rpc client for the node + pub async fn rpc(&self) -> Result<RpcClient, subxt::Error> { + RpcClient::from_url(&self.ws_uri).await + } + + /// Get the online client for the node + pub async fn client<Config: subxt::Config>( + &self, + ) -> Result<OnlineClient<Config>, subxt::Error> { + OnlineClient::from_url(&self.ws_uri).await + } + /// Resume the node, this is implemented by resuming the /// actual process (e.g polkadot) with sendig `SIGCONT` signal pub async fn resume(&self) -> Result<(), anyhow::Error> { diff --git a/crates/orchestrator/src/network_spec.rs b/crates/orchestrator/src/network_spec.rs index 13f49b870bba2ff73311abebc612b3bc17b08c08..a38a4f26f7bc5e2a6d0d9bbe7920a75b63ede64b 100644 --- a/crates/orchestrator/src/network_spec.rs +++ b/crates/orchestrator/src/network_spec.rs @@ -81,7 +81,7 @@ mod tests { .unwrap(); let network_spec = NetworkSpec::from_config(&config).await.unwrap(); - let alice = network_spec.relaychain.nodes.get(0).unwrap(); + let alice = network_spec.relaychain.nodes.first().unwrap(); let bob = network_spec.relaychain.nodes.get(1).unwrap(); assert_eq!(alice.command.as_str(), "polkadot"); assert_eq!(bob.command.as_str(), "polkadot1"); @@ -90,7 +90,7 @@ mod tests { // paras assert_eq!(network_spec.parachains.len(), 1); - let para_100 = network_spec.parachains.get(0).unwrap(); + let para_100 = network_spec.parachains.first().unwrap(); assert_eq!(para_100.id, 100); } } diff --git a/crates/orchestrator/src/spawner.rs b/crates/orchestrator/src/spawner.rs index 0ff0e7148ab8eb7567381aa337485afa9f0eae83..18db51f2d41353f96f2b44f04f6e421c83cde5a6 100644 --- a/crates/orchestrator/src/spawner.rs +++ b/crates/orchestrator/src/spawner.rs @@ -108,20 +108,20 @@ where let (program, args) = match ctx.role { // Collator should be `non-cumulus` one (e.g adder/undying) ZombieRole::Node | ZombieRole::Collator => { - let maybe_para_id = ctx.parachain.map(|para| para.id); generators::generate_node_command(node, gen_opts, maybe_para_id) }, ZombieRole::CumulusCollator => { - let para = ctx.parachain.expect("parachain must be part of the context, this is a bug"); + let para = ctx + .parachain + .expect("parachain must be part of the context, this is a bug"); let full_p2p = generators::generate_node_port(None)?; generators::generate_node_command_cumulus(node, gen_opts, para.id, full_p2p.0) - } - _ => unreachable!() - // TODO: do we need those? - // ZombieRole::Bootnode => todo!(), - // ZombieRole::Companion => todo!(), + }, + _ => unreachable!(), /* TODO: do we need those? + * ZombieRole::Bootnode => todo!(), + * ZombieRole::Companion => todo!(), */ }; println!("\n");