Skip to content

Commit

Permalink
feat: add paseo support (#182)
Browse files Browse the repository at this point in the history
* feat: support chain spec generators

* feat: enable specification of runtime versions (chain spec generation)

* chore: add additional network config examples, used for manual testing

* build(deps): bump zombienet

* test: update integration test

* test(up): add more integration tests

* test(up): add tests
  • Loading branch information
evilrobot-01 authored Jun 25, 2024
1 parent 7de050e commit a14186d
Show file tree
Hide file tree
Showing 12 changed files with 1,080 additions and 112 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ toml_edit = { version = "0.22", features = ["serde"] }
symlink = "0.1"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
zombienet-sdk = "0.2.2"
zombienet-support = "0.2.2"
zombienet-sdk = "0.2.5"
zombienet-support = "0.2.5"
git2_credentials = "0.13.0"

# pop-cli
Expand Down
25 changes: 18 additions & 7 deletions crates/pop-cli/src/commands/up/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,23 @@ pub(crate) struct ZombienetCommand {
/// The Zombienet network configuration file to be used.
#[arg(short, long)]
file: String,
/// The version of Polkadot to be used for the relay chain, as per the release tag (e.g.
/// "v1.11.0").
/// The version of the binary to be used for the relay chain, as per the release tag (e.g. "v1.13.0").
/// See https://github.com/paritytech/polkadot-sdk/releases for more details.
#[arg(short, long)]
relay_chain: Option<String>,
/// The version of Polkadot to be used for a system parachain, as per the release tag (e.g.
/// "v1.11.0"). Defaults to the relay chain version if not specified.
/// The version of the runtime to be used for the relay chain, as per the release tag (e.g. "v1.2.7").
/// See https://github.com/polkadot-fellows/runtimes/releases for more details.
#[arg(short = 'R', long)]
relay_chain_runtime: Option<String>,
/// The version of the binary to be used for system parachains, as per the release tag (e.g. "v1.13.0").
/// Defaults to the relay chain version if not specified.
/// See https://github.com/paritytech/polkadot-sdk/releases for more details.
#[arg(short, long)]
system_parachain: Option<String>,
/// The version of the runtime to be used for system parachains, as per the release tag (e.g. "v1.2.7").
/// See https://github.com/polkadot-fellows/runtimes/releases for more details.
#[arg(short = 'S', long)]
system_parachain_runtime: Option<String>,
/// The url of the git repository of a parachain to be used, with branch/release tag/commit specified as #fragment (e.g. 'https://github.com/org/repository#ref').
/// A specific binary name can also be optionally specified via query string parameter (e.g. 'https://github.com/org/repository?binaryname#ref'), defaulting to the name of the repository when not specified.
#[arg(short, long)]
Expand All @@ -49,8 +58,10 @@ impl ZombienetCommand {
let mut zombienet = match Zombienet::new(
&cache,
&self.file,
self.relay_chain.as_ref().map(|v| v.as_str()),
self.system_parachain.as_ref().map(|v| v.as_str()),
self.relay_chain.as_deref(),
self.relay_chain_runtime.as_deref(),
self.system_parachain.as_deref(),
self.system_parachain_runtime.as_deref(),
self.parachain.as_ref(),
)
.await
Expand Down Expand Up @@ -167,7 +178,7 @@ impl ZombienetCommand {
))
.dim()
.to_string();
log::warning(format!("⚠️ The following binaries specified in the network configuration file cannot be found locally:\n {list}"))?;
log::warning(format!("⚠️ The following binaries required to launch the network cannot be found locally:\n {list}"))?;

// Prompt for automatic sourcing of binaries
let list = style(format!(
Expand Down
196 changes: 196 additions & 0 deletions crates/pop-parachains/src/up/chain_specs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// SPDX-License-Identifier: GPL-3.0

use crate::{
up::{
sourcing::{
self,
traits::{Source as _, *},
GitHub::*,
Source,
},
target,
},
Binary, Error,
};
use std::path::Path;
use strum::{EnumProperty as _, VariantArray as _};
use strum_macros::{AsRefStr, EnumProperty, VariantArray};

/// A supported runtime.
#[derive(AsRefStr, Debug, EnumProperty, PartialEq, VariantArray)]
pub(super) enum Runtime {
/// Kusama.
#[strum(props(
Repository = "https://github.com/r0gue-io/polkadot-runtimes",
Binary = "chain-spec-generator",
Chain = "kusama-local",
Fallback = "v1.2.7"
))]
Kusama,
/// Paseo.
#[strum(props(
Repository = "https://github.com/r0gue-io/paseo-runtimes",
Binary = "chain-spec-generator",
Chain = "paseo-local",
Fallback = "v1.2.4"
))]
Paseo,
/// Polkadot.
#[strum(props(
Repository = "https://github.com/r0gue-io/polkadot-runtimes",
Binary = "chain-spec-generator",
Chain = "polkadot-local",
Fallback = "v1.2.7"
))]
Polkadot,
}

impl TryInto for &Runtime {
/// Attempt the conversion.
///
/// # Arguments
/// * `tag` - If applicable, a tag used to determine a specific release.
/// * `latest` - If applicable, some specifier used to determine the latest source.
fn try_into(&self, tag: Option<String>, latest: Option<String>) -> Result<Source, Error> {
Ok(match self {
_ => {
// Source from GitHub release asset
let repo = crate::GitHub::parse(self.repository())?;
let name = self.name().to_lowercase();
let binary = self.binary();
Source::GitHub(ReleaseArchive {
owner: repo.org,
repository: repo.name,
tag,
tag_format: self.tag_format().map(|t| t.into()),
archive: format!("{binary}-{}.tar.gz", target()?),
contents: vec![(binary, Some(format!("{name}-{binary}")))],
latest,
})
},
})
}
}

impl Runtime {
/// The chain spec identifier.
fn chain(&self) -> &'static str {
self.get_str("Chain").expect("expected specification of `Chain`")
}

/// The name of the runtime.
fn name(&self) -> &str {
self.as_ref()
}
}

impl sourcing::traits::Source for Runtime {}

pub(super) async fn chain_spec_generator(
chain: &str,
version: Option<&str>,
cache: &Path,
) -> Result<Option<Binary>, Error> {
for runtime in Runtime::VARIANTS.iter().filter(|r| chain.to_lowercase().ends_with(r.chain())) {
let name = format!("{}-{}", runtime.name().to_lowercase(), runtime.binary());
let releases = runtime.releases().await?;
let tag = Binary::resolve_version(&name, version, &releases, cache);
// Only set latest when caller has not explicitly specified a version to use
let latest = version
.is_none()
.then(|| releases.iter().nth(0).map(|v| v.to_string()))
.flatten();
let binary = Binary::Source {
name: name.to_string(),
source: TryInto::try_into(&runtime, tag, latest)?,
cache: cache.to_path_buf(),
};
return Ok(Some(binary));
}
Ok(None)
}

#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;

#[tokio::test]
async fn kusama_works() -> anyhow::Result<()> {
let expected = Runtime::Kusama;
let version = "v1.2.7";
let temp_dir = tempdir()?;
let binary = chain_spec_generator("kusama-local", Some(version), temp_dir.path())
.await?
.unwrap();
assert!(matches!(binary, Binary::Source { name, source, cache }
if name == format!("{}-{}", expected.name().to_lowercase(), expected.binary()) &&
source == Source::GitHub(ReleaseArchive {
owner: "r0gue-io".to_string(),
repository: "polkadot-runtimes".to_string(),
tag: Some(version.to_string()),
tag_format: None,
archive: format!("chain-spec-generator-{}.tar.gz", target()?),
contents: ["chain-spec-generator"].map(|b| (b, Some(format!("kusama-{b}").to_string()))).to_vec(),
latest: binary.latest().map(|l| l.to_string()),
}) &&
cache == temp_dir.path()
));
Ok(())
}

#[tokio::test]
async fn paseo_works() -> anyhow::Result<()> {
let expected = Runtime::Paseo;
let version = "v1.2.4";
let temp_dir = tempdir()?;
let binary = chain_spec_generator("paseo-local", Some(version), temp_dir.path())
.await?
.unwrap();
assert!(matches!(binary, Binary::Source { name, source, cache }
if name == format!("{}-{}", expected.name().to_lowercase(), expected.binary()) &&
source == Source::GitHub(ReleaseArchive {
owner: "r0gue-io".to_string(),
repository: "paseo-runtimes".to_string(),
tag: Some(version.to_string()),
tag_format: None,
archive: format!("chain-spec-generator-{}.tar.gz", target()?),
contents: ["chain-spec-generator"].map(|b| (b, Some(format!("paseo-{b}").to_string()))).to_vec(),
latest: binary.latest().map(|l| l.to_string()),
}) &&
cache == temp_dir.path()
));
Ok(())
}

#[tokio::test]
async fn polkadot_works() -> anyhow::Result<()> {
let expected = Runtime::Polkadot;
let version = "v1.2.7";
let temp_dir = tempdir()?;
let binary = chain_spec_generator("polkadot-local", Some(version), temp_dir.path())
.await?
.unwrap();
assert!(matches!(binary, Binary::Source { name, source, cache }
if name == format!("{}-{}", expected.name().to_lowercase(), expected.binary()) &&
source == Source::GitHub(ReleaseArchive {
owner: "r0gue-io".to_string(),
repository: "polkadot-runtimes".to_string(),
tag: Some(version.to_string()),
tag_format: None,
archive: format!("chain-spec-generator-{}.tar.gz", target()?),
contents: ["chain-spec-generator"].map(|b| (b, Some(format!("polkadot-{b}").to_string()))).to_vec(),
latest: binary.latest().map(|l| l.to_string()),
}) &&
cache == temp_dir.path()
));
Ok(())
}

#[tokio::test]
async fn chain_spec_generator_returns_none_when_no_match() -> anyhow::Result<()> {
let temp_dir = tempdir()?;
assert_eq!(chain_spec_generator("rococo-local", None, temp_dir.path()).await?, None);
Ok(())
}
}
Loading

0 comments on commit a14186d

Please sign in to comment.