diff --git a/crates/pop-cli/src/commands/new/parachain.rs b/crates/pop-cli/src/commands/new/parachain.rs index e65035cf..22d335a5 100644 --- a/crates/pop-cli/src/commands/new/parachain.rs +++ b/crates/pop-cli/src/commands/new/parachain.rs @@ -127,10 +127,9 @@ async fn guide_user_to_generate_parachain(verify: bool) -> Result 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()?) } @@ -471,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-parachains/src/templates.rs b/crates/pop-parachains/src/templates.rs index 324f6f23..5ea91513 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), } } } @@ -130,7 +130,7 @@ pub enum Parachain { Provider = "OpenZeppelin", Repository = "https://github.com/OpenZeppelin/polkadot-runtime-templates", Network = "./zombienet-config/devnet.toml", - SupportedVersions = "v1.0.0,v2.0.1,v2.0.3", + SupportedVersions = "v1.0.0,v2.0.1,v2.0.3,v3.0.0", IsAudited = "true", License = "GPL-3.0" ) @@ -145,38 +145,38 @@ pub enum Parachain { Provider = "OpenZeppelin", Repository = "https://github.com/OpenZeppelin/polkadot-runtime-templates", Network = "./zombienet-config/devnet.toml", - SupportedVersions = "v2.0.3", + SupportedVersions = "v2.0.3,v3.0.0", IsAudited = "true", License = "GPL-3.0" ) )] OpenZeppelinEVM, - /// Minimal Substrate node configured for smart contracts via pallet-contracts. + /// The Parachain-Ready Template From Polkadot SDK. #[strum( - serialize = "cpt", - message = "Contracts", - detailed_message = "Minimal Substrate node configured for smart contracts via pallet-contracts.", + 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/substrate-contracts-node", + Repository = "https://github.com/paritytech/polkadot-sdk-parachain-template", Network = "./zombienet.toml", License = "Unlicense" ) )] - ParityContracts, - /// Template node for a Frontier (EVM) based parachain. + ParityGeneric, + /// Minimal Substrate node configured for smart contracts via pallet-contracts. #[strum( - serialize = "fpt", - message = "EVM", - detailed_message = "Template node for a Frontier (EVM) based parachain.", + serialize = "paritytech/substrate-contracts-node", + 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", + Repository = "https://github.com/paritytech/substrate-contracts-node", + Network = "./zombienet.toml", License = "Unlicense" ) )] - ParityFPT, + ParityContracts, // templates for unit tests below #[cfg(test)] #[strum( @@ -256,8 +256,9 @@ mod tests { // openzeppelin ("openzeppelin/generic-template".to_string(), OpenZeppelinGeneric), ("openzeppelin/evm-template".to_string(), OpenZeppelinEVM), - ("cpt".to_string(), ParityContracts), - ("fpt".to_string(), ParityFPT), + // pàrity + ("paritytech/polkadot-sdk-parachain-template".to_string(), ParityGeneric), + ("paritytech/substrate-contracts-node".to_string(), ParityContracts), ("test_01".to_string(), TestTemplate01), ("test_02".to_string(), TestTemplate02), ]) @@ -271,8 +272,8 @@ mod tests { (EVM, "evm".to_string()), (OpenZeppelinGeneric, "generic-template".to_string()), (OpenZeppelinEVM, "evm-template".to_string()), - (ParityContracts, "cpt".to_string()), - (ParityFPT, "fpt".to_string()), + (ParityGeneric, "polkadot-sdk-parachain-template".to_string()), + (ParityContracts, "substrate-contracts-node".to_string()), (TestTemplate01, "test_01".to_string()), (TestTemplate02, "test_02".to_string()), ]) @@ -297,8 +298,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(), ""), ]) @@ -312,8 +320,8 @@ mod tests { (EVM, Some("./network.toml")), (OpenZeppelinGeneric, Some("./zombienet-config/devnet.toml")), (OpenZeppelinEVM, Some("./zombienet-config/devnet.toml")), + (ParityGeneric, Some("./zombienet.toml")), (ParityContracts, Some("./zombienet.toml")), - (ParityFPT, Some("./zombienet-config.toml")), (TestTemplate01, Some("")), (TestTemplate02, Some("")), ] @@ -328,8 +336,8 @@ mod tests { (EVM, Some("Unlicense")), (OpenZeppelinGeneric, Some("GPL-3.0")), (OpenZeppelinEVM, Some("GPL-3.0")), + (ParityGeneric, Some("Unlicense")), (ParityContracts, Some("Unlicense")), - (ParityFPT, Some("Unlicense")), (TestTemplate01, Some("Unlicense")), (TestTemplate02, Some("GPL-3.0")), ] @@ -343,7 +351,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) } @@ -397,7 +405,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] @@ -405,7 +413,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] diff --git a/crates/pop-parachains/src/up/mod.rs b/crates/pop-parachains/src/up/mod.rs index abefa805..a603ca30 100644 --- a/crates/pop-parachains/src/up/mod.rs +++ b/crates/pop-parachains/src/up/mod.rs @@ -153,6 +153,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())))) @@ -206,6 +214,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) @@ -479,6 +497,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) + } + } } } @@ -676,7 +700,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; pub(crate) const VERSION: &str = "stable2409"; @@ -1123,6 +1151,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()?; @@ -1619,6 +1718,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())?; @@ -1688,6 +1795,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(), )?; @@ -1733,6 +1853,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