diff --git a/Cargo.lock b/Cargo.lock index 5943f556..639542d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4776,7 +4776,6 @@ dependencies = [ "url", "walkdir", "zombienet-sdk", - "zombienet-support", ] [[package]] @@ -8515,9 +8514,9 @@ dependencies = [ [[package]] name = "zombienet-configuration" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ee069fa52f2057eaae7f27f0c638d4a5f630e42159f66665398681cdd82d4f" +checksum = "23322e411b8d19b41b5c20ab8e88c10822189a4fcfd069c7fcd1542b8d3035aa" dependencies = [ "anyhow", "lazy_static", @@ -8533,9 +8532,9 @@ dependencies = [ [[package]] name = "zombienet-orchestrator" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbffc9d2fd1c8f727718a197f7fc65ad7b7a2397855f87a6deb738a26d499f8" +checksum = "381f701565b3918a909132743b3674569ce3da25b5c3a6493883abaf1046577a" dependencies = [ "anyhow", "async-trait", @@ -8543,6 +8542,7 @@ dependencies = [ "glob-match", "hex", "libp2p", + "libsecp256k1", "multiaddr", "rand", "regex", @@ -8565,9 +8565,9 @@ dependencies = [ [[package]] name = "zombienet-prom-metrics-parser" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af494234607b9bbfee8b6ab93a0b85c5f9238c6ffdb9c46f1db3e811b1940e0e" +checksum = "dab79fa58bcfecbcd41485c6f13052853ccde8b09f173b601f78747d7abc2b7f" dependencies = [ "pest", "pest_derive", @@ -8576,9 +8576,9 @@ dependencies = [ [[package]] name = "zombienet-provider" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c900c3a42098db63bbf4ac1b3ce37157d66a1e6627ac4c806bf7a346253a9093" +checksum = "6af0264938da61b25da89f17ee0630393a4ba793582a4a8a1650eb15b47fc1ef" dependencies = [ "anyhow", "async-trait", @@ -8607,9 +8607,9 @@ dependencies = [ [[package]] name = "zombienet-sdk" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27224e17fd674c21c1ac16280bc85d2333ee71520fa02a1c6de6aa6f642aa1b5" +checksum = "5bc5b7ebfba4ab62486c8cb5bcd7345c4376487487cfe3481476cb4d4accc75e" dependencies = [ "async-trait", "futures", @@ -8624,9 +8624,9 @@ dependencies = [ [[package]] name = "zombienet-support" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f4ec8f69b9c4b6407ae721911da25df0c99a1d70da1e4b9d7ee11bcbea0594a" +checksum = "6f5b80d34a0eecca69dd84c2e13f84f1fae0cc378baf4f15f769027af068418b" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 8ca9fa23..3a2e1904 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,8 +60,7 @@ toml_edit = { version = "0.22", features = ["serde"] } symlink = "0.1" serde_json = { version = "1.0", features = ["preserve_order"] } serde = { version = "1.0", features = ["derive"] } -zombienet-sdk = "0.2.7" -zombienet-support = "0.2.7" +zombienet-sdk = "0.2.10" git2_credentials = "0.13.0" # pop-cli diff --git a/crates/pop-cli/src/commands/new/parachain.rs b/crates/pop-cli/src/commands/new/parachain.rs index 830ee7ad..b565e3e8 100644 --- a/crates/pop-cli/src/commands/new/parachain.rs +++ b/crates/pop-cli/src/commands/new/parachain.rs @@ -15,7 +15,7 @@ use cliclack::{ outro, outro_cancel, }; use pop_common::{ - enum_variants, + enum_variants, enum_variants_for_help, templates::{Template, Type}, Git, GitHub, Release, }; @@ -40,8 +40,9 @@ pub struct NewParachainCommand { #[arg( short = 't', long, - help = "Template to use.", - value_parser = enum_variants!(Parachain) + help = format!("Template to use. [possible values: {}]", enum_variants_for_help!(Parachain)), + value_parser = enum_variants!(Parachain), + hide_possible_values = true // Hide the deprecated templates )] pub(crate) template: Option, #[arg( @@ -126,10 +127,9 @@ async fn guide_user_to_generate_parachain(verify: bool) -> Result Result<() provider, template ))); }; + if template.is_deprecated() { + warning(format!("NOTE: this template is deprecated.{}", template.deprecated_message()))?; + } Ok(()) } @@ -253,7 +256,7 @@ fn display_select_options(provider: &Provider) -> Result<&Parachain> { if i == 0 { prompt = prompt.initial_value(template); } - prompt = prompt.item(template, template.name(), template.description()); + prompt = prompt.item(template, template.name(), template.description().trim()); } Ok(prompt.interact()?) } @@ -467,11 +470,11 @@ mod tests { fn test_is_template_supported() -> Result<()> { is_template_supported(&Provider::Pop, &Parachain::Standard)?; assert!(is_template_supported(&Provider::Pop, &Parachain::ParityContracts).is_err()); - assert!(is_template_supported(&Provider::Pop, &Parachain::ParityFPT).is_err()); + assert!(is_template_supported(&Provider::Pop, &Parachain::ParityGeneric).is_err()); assert!(is_template_supported(&Provider::Parity, &Parachain::Standard).is_err()); is_template_supported(&Provider::Parity, &Parachain::ParityContracts)?; - is_template_supported(&Provider::Parity, &Parachain::ParityFPT) + is_template_supported(&Provider::Parity, &Parachain::ParityGeneric) } #[test] diff --git a/crates/pop-common/src/templates/mod.rs b/crates/pop-common/src/templates/mod.rs index e4f7604a..0ccbf45d 100644 --- a/crates/pop-common/src/templates/mod.rs +++ b/crates/pop-common/src/templates/mod.rs @@ -45,6 +45,16 @@ pub trait Template: fn template_type(&self) -> Result<&str, Error> { self.get_str(Self::PROPERTY).ok_or(Error::TypeMissing) } + + /// Get whether the template is deprecated. + fn is_deprecated(&self) -> bool { + self.get_str("IsDeprecated").map_or(false, |s| s == "true") + } + + /// Get the deprecation message for the template + fn deprecated_message(&self) -> &str { + self.get_str("DeprecatedMessage").unwrap_or_default() + } } /// A trait for defining overarching types of specific template variants. @@ -76,7 +86,7 @@ pub trait Type: Clone + Default + EnumMessage + Eq + PartialEq + Va fn templates(&self) -> Vec<&T> { T::VARIANTS .iter() - .filter(|t| t.get_str(T::PROPERTY) == Some(self.name())) + .filter(|t| t.get_str(T::PROPERTY) == Some(self.name()) && !t.is_deprecated()) .collect() } @@ -99,3 +109,15 @@ macro_rules! enum_variants { .try_map(|s| <$e>::from_str(&s).map_err(|e| format!("could not convert from {s} to type"))) }}; } + +#[macro_export] +macro_rules! enum_variants_for_help { + ($e:ty) => {{ + <$e>::VARIANTS + .iter() + .filter(|variant| !variant.is_deprecated()) // Exclude deprecated variants for --help + .map(|v| v.as_ref()) + .collect::>() + .join(", ") + }}; +} diff --git a/crates/pop-parachains/Cargo.toml b/crates/pop-parachains/Cargo.toml index 1ac8166b..4b135c8f 100644 --- a/crates/pop-parachains/Cargo.toml +++ b/crates/pop-parachains/Cargo.toml @@ -31,7 +31,6 @@ toml_edit.workspace = true walkdir.workspace = true # Zombienet zombienet-sdk.workspace = true -zombienet-support.workspace = true # Pop pop-common = { path = "../pop-common", version = "0.3.0" } diff --git a/crates/pop-parachains/src/templates.rs b/crates/pop-parachains/src/templates.rs index c90234c8..be258366 100644 --- a/crates/pop-parachains/src/templates.rs +++ b/crates/pop-parachains/src/templates.rs @@ -38,7 +38,7 @@ impl Type for Provider { match &self { Provider::Pop => Some(Parachain::Standard), Provider::OpenZeppelin => Some(Parachain::OpenZeppelinGeneric), - Provider::Parity => Some(Parachain::ParityContracts), + Provider::Parity => Some(Parachain::ParityGeneric), } } } @@ -136,11 +136,24 @@ pub enum Parachain { ) )] OpenZeppelinGeneric, + /// The Parachain-Ready Template From Polkadot SDK. + #[strum( + serialize = "paritytech/polkadot-sdk-parachain-template", + message = "Polkadot SDK's Parachain Template", + detailed_message = "The Parachain-Ready Template From Polkadot SDK.", + props( + Provider = "Parity", + Repository = "https://github.com/paritytech/polkadot-sdk-parachain-template", + Network = "./zombienet.toml", + License = "Unlicense" + ) + )] + ParityGeneric, /// Minimal Substrate node configured for smart contracts via pallet-contracts. #[strum( - serialize = "cpt", + serialize = "paritytech/substrate-contracts-node", message = "Contracts", - detailed_message = "Minimal Substrate node configured for smart contracts via pallet-contracts.", + detailed_message = "Minimal Substrate node configured for smart contracts via pallet-contracts. [deprecated]. Suggested to use Pop > Contracts template instead.", props( Provider = "Parity", Repository = "https://github.com/paritytech/substrate-contracts-node", @@ -149,20 +162,22 @@ pub enum Parachain { ) )] ParityContracts, - /// Template node for a Frontier (EVM) based parachain. + /// [Deprecated] This command is deprecated, please use 'paritytech/substrate-contracts-node' + /// instead. #[strum( - serialize = "fpt", - message = "EVM", - detailed_message = "Template node for a Frontier (EVM) based parachain.", + serialize = "cpt", + message = "Contracts", + detailed_message = "Minimal Substrate node configured for smart contracts via pallet-contracts.", props( Provider = "Parity", - Repository = "https://github.com/paritytech/frontier-parachain-template", - Network = "./zombienet-config.toml", - License = "Unlicense" + Repository = "https://github.com/paritytech/substrate-contracts-node", + Network = "./zombienet.toml", + License = "Unlicense", + IsDeprecated = "true", + DeprecatedMessage = "This template is deprecated. Please use paritytech/substrate-contracts-node in the future.", ) )] - ParityFPT, - + DeprecatedParityContracts, // templates for unit tests below #[cfg(test)] #[strum( @@ -175,7 +190,9 @@ pub enum Parachain { Network = "", SupportedVersions = "v1.0.0,v2.0.0", IsAudited = "true", - License = "Unlicense" + IsDeprecated = "true", + DeprecatedMessage = "This template is deprecated. Please use test_02 in the future.", + License = "Unlicense", ) )] TestTemplate01, @@ -233,8 +250,9 @@ mod tests { ("evm".to_string(), EVM), // openzeppelin ("polkadot-generic-runtime-template".to_string(), OpenZeppelinGeneric), - ("cpt".to_string(), ParityContracts), - ("fpt".to_string(), ParityFPT), + ("paritytech/polkadot-sdk-parachain-template".to_string(), ParityGeneric), + ("paritytech/substrate-contracts-node".to_string(), ParityContracts), + ("cpt".to_string(), DeprecatedParityContracts), ("test_01".to_string(), TestTemplate01), ("test_02".to_string(), TestTemplate02), ]) @@ -251,8 +269,15 @@ mod tests { "polkadot-generic-runtime-template".to_string(), "https://github.com/OpenZeppelin/polkadot-runtime-templates", ), + ( + "paritytech/polkadot-sdk-parachain-template".to_string(), + "https://github.com/paritytech/polkadot-sdk-parachain-template", + ), + ( + "paritytech/substrate-contracts-node".to_string(), + "https://github.com/paritytech/substrate-contracts-node", + ), ("cpt".to_string(), "https://github.com/paritytech/substrate-contracts-node"), - ("fpt".to_string(), "https://github.com/paritytech/frontier-parachain-template"), ("test_01".to_string(), ""), ("test_02".to_string(), ""), ]) @@ -265,8 +290,9 @@ mod tests { (Contracts, Some("./network.toml")), (EVM, Some("./network.toml")), (OpenZeppelinGeneric, Some("./zombienet-config/devnet.toml")), + (ParityGeneric, Some("./zombienet.toml")), (ParityContracts, Some("./zombienet.toml")), - (ParityFPT, Some("./zombienet-config.toml")), + (DeprecatedParityContracts, Some("./zombienet.toml")), (TestTemplate01, Some("")), (TestTemplate02, Some("")), ] @@ -280,8 +306,9 @@ mod tests { (Contracts, Some("Unlicense")), (EVM, Some("Unlicense")), (OpenZeppelinGeneric, Some("GPL-3.0")), + (ParityGeneric, Some("Unlicense")), (ParityContracts, Some("Unlicense")), - (ParityFPT, Some("Unlicense")), + (DeprecatedParityContracts, Some("Unlicense")), (TestTemplate01, Some("Unlicense")), (TestTemplate02, Some("GPL-3.0")), ] @@ -295,7 +322,7 @@ mod tests { assert_eq!(Provider::Pop.provides(&template), true); assert_eq!(Provider::Parity.provides(&template), false); } - if matches!(template, ParityContracts | ParityFPT) { + if matches!(template, ParityContracts | ParityGeneric) { assert_eq!(Provider::Pop.provides(&template), false); assert_eq!(Provider::Parity.provides(&template), true) } @@ -348,7 +375,7 @@ mod tests { let mut provider = Provider::Pop; assert_eq!(provider.default_template(), Some(Standard)); provider = Provider::Parity; - assert_eq!(provider.default_template(), Some(ParityContracts)); + assert_eq!(provider.default_template(), Some(ParityGeneric)); } #[test] @@ -356,7 +383,7 @@ mod tests { let mut provider = Provider::Pop; assert_eq!(provider.templates(), [&Standard, &Assets, &Contracts, &EVM]); provider = Provider::Parity; - assert_eq!(provider.templates(), [&ParityContracts, &ParityFPT]); + assert_eq!(provider.templates(), [&ParityGeneric, &ParityContracts]); } #[test] @@ -399,4 +426,25 @@ mod tests { let template = TestTemplate02; assert_eq!(template.is_audited(), false); } + + #[test] + fn test_is_deprecated() { + let template = TestTemplate01; + assert_eq!(template.is_deprecated(), true); + + let template = TestTemplate02; + assert_eq!(template.is_deprecated(), false); + } + + #[test] + fn test_deprecated_message() { + let template = TestTemplate01; + assert_eq!( + template.deprecated_message(), + "This template is deprecated. Please use test_02 in the future." + ); + + let template = TestTemplate02; + assert_eq!(template.deprecated_message(), ""); + } } diff --git a/crates/pop-parachains/src/up/mod.rs b/crates/pop-parachains/src/up/mod.rs index 80716606..1406280c 100644 --- a/crates/pop-parachains/src/up/mod.rs +++ b/crates/pop-parachains/src/up/mod.rs @@ -16,8 +16,7 @@ use std::{ use symlink::{remove_symlink_file, symlink_file}; use tempfile::{Builder, NamedTempFile}; use toml_edit::{value, ArrayOfTables, DocumentMut, Formatted, Item, Table, Value}; -use zombienet_sdk::{Network, NetworkConfig, NetworkConfigExt}; -use zombienet_support::fs::local::LocalFileSystem; +use zombienet_sdk::{LocalFileSystem, Network, NetworkConfig, NetworkConfigExt}; mod chain_specs; mod parachains; @@ -150,6 +149,14 @@ impl Zombienet { } } } + // Check if collator has defined command + if let Some(collator) = table.get("collator").and_then(|i| i.as_table()) { + if let Some(command) = + NetworkConfiguration::command(collator).and_then(|i| i.as_str()) + { + return Some(Item::Value(Value::String(Formatted::new(command.into())))); + } + } // Otherwise default to polkadot-parachain Some(Item::Value(Value::String(Formatted::new("polkadot-parachain".into())))) @@ -203,6 +210,16 @@ impl Zombienet { continue; } + // Check if command references a parachain template binary without a specified path + // (e.g. Polkadot SDK parachain template) + if command == "parachain-template-node" || command == "substrate-contracts-node" { + let binary_path = PathBuf::from("./target/release").join(&command); + if !binary_path.exists() { + return Err(Error::MissingBinary(command)); + } + paras.insert(id, Parachain::from_local(id, binary_path, chain)?); + continue; + } return Err(Error::MissingBinary(command)); } Ok(paras) @@ -456,6 +473,12 @@ impl NetworkConfiguration { } } } + // Resolve individual collator command to binary + if let Some(collator) = table.get_mut("collator").and_then(|p| p.as_table_mut()) { + if let Some(command) = NetworkConfiguration::command_mut(collator) { + *command = value(&path) + } + } } } @@ -653,7 +676,11 @@ fn resolve_manifest(package: &str, path: &Path) -> Result, Error mod tests { use super::*; use anyhow::Result; - use std::{env::current_dir, fs::File, io::Write}; + use std::{ + env::current_dir, + fs::{create_dir_all, remove_dir, remove_file, File}, + io::Write, + }; use tempfile::tempdir; mod zombienet { @@ -1100,6 +1127,77 @@ default_command = "./target/release/parachain-template-node" Ok(()) } + #[tokio::test] + async fn new_with_local_parachain_without_path_works() -> Result<()> { + let temp_dir = tempdir()?; + let cache = PathBuf::from(temp_dir.path()); + let config = Builder::new().suffix(".toml").tempfile()?; + writeln!( + config.as_file(), + r#" +[relaychain] +chain = "rococo-local" + +[[parachains]] +id = 1000 + +[parachains.collator] +name = "collator" +command = "parachain-template-node" + +[[parachains]] +id = 2000 + +[parachains.collator] +name = "collator" +command = "substrate-contracts-node" +"# + )?; + assert!(matches!( + Zombienet::new(&cache, config.path().to_str().unwrap(), None, None, None, None, None).await, + Err(Error::MissingBinary(command)) + if command == "parachain-template-node" + )); + // Create the binaries in the hardcoded path + let parachain_template = PathBuf::from("target/release/parachain-template-node"); + create_dir_all(parachain_template.parent().unwrap())?; + File::create(¶chain_template)?; + let parachain_contracts_template = + PathBuf::from("target/release/substrate-contracts-node"); + File::create(¶chain_contracts_template)?; + + let zombienet = Zombienet::new( + &cache, + config.path().to_str().unwrap(), + None, + None, + None, + None, + None, + ) + .await?; + // Remove the binary hardcoded path + remove_file(¶chain_template)?; + remove_file(¶chain_contracts_template)?; + remove_dir(parachain_template.parent().unwrap())?; + + assert_eq!(zombienet.parachains.len(), 2); + let parachain = &zombienet.parachains.get(&1000).unwrap().binary; + assert_eq!(parachain.name(), "parachain-template-node"); + assert_eq!(parachain.path(), Path::new("./target/release/parachain-template-node")); + assert_eq!(parachain.version(), None); + assert!(matches!(parachain, Binary::Local { .. })); + let contract_parachain = &zombienet.parachains.get(&2000).unwrap().binary; + assert_eq!(contract_parachain.name(), "substrate-contracts-node"); + assert_eq!( + contract_parachain.path(), + Path::new("./target/release/substrate-contracts-node") + ); + assert_eq!(contract_parachain.version(), None); + assert!(matches!(contract_parachain, Binary::Local { .. })); + Ok(()) + } + #[tokio::test] async fn new_with_collator_command_works() -> Result<()> { let temp_dir = tempdir()?; @@ -1555,6 +1653,14 @@ default_command = "./target/release/parachain-template-node" [[parachains.collators]] name = "collator" command = "./target/release/parachain-template-node" + +[[parachains]] +id = 2002 +default_command = "./target/release/parachain-template-node" + +[parachains.collator] +name = "collator" +command = "./target/release/parachain-template-node" "# )?; let mut network_config = NetworkConfiguration::from(config.path())?; @@ -1624,6 +1730,19 @@ command = "./target/release/parachain-template-node" chain_spec_generator: None, }, ), + ( + 2002, + Parachain { + id: 2002, + binary: Binary::Local { + name: "parachain-template-node".to_string(), + path: parachain_template.to_path_buf(), + manifest: None, + }, + chain: None, + chain_spec_generator: None, + }, + ), ] .into(), )?; @@ -1669,6 +1788,14 @@ default_command = "{3}" name = "collator" command = "{3}" +[[parachains]] +id = 2002 +default_command = "{3}" + +[parachains.collator] +name = "collator" +command = "{3}" + [settings] timeout = 1000 node_spawn_timeout = 300