Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ git2 = { version = "0.18", default-features = true, features = ["vendored-openss
glob = { version = "0.3.1", default-features = false }
log = { version = "0.4.20", default-features = false }
mockito = { version = "1.4.0", default-features = false }
rustilities = "3.0.0"
tar = { version = "0.4.40", default-features = false }
tempfile = { version = "3.10", default-features = false }
thiserror = { version = "1.0.58", default-features = false }
Expand Down
Binary file added artifacts/mock_runtime.compact.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions crates/pop-chains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ url.workspace = true

askama.workspace = true
indexmap.workspace = true
rustilities = { workspace = true, features = ["manifest"] }
scale.workspace = true
scale-info.workspace = true
scale-value.workspace = true
Expand Down
8 changes: 6 additions & 2 deletions crates/pop-chains/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ use std::path::Path;

let path = Path::new("./"); // Location of the parachain project.
let builder = ChainSpecBuilder::Node { node_path: path.join("node"), default_bootnode: false, profile: Profile::Release };
let spec_name = "MySpec";
let spec_id = "my_spec";
// Build the node binary first
builder.build(&[]).unwrap();
// Generate a plain chain specification file of a parachain
let plain_chain_spec_path = path.join("plain-parachain-chainspec.json");
builder.generate_plain_chain_spec("dev", &plain_chain_spec_path).unwrap();
builder.generate_plain_chain_spec("dev", &plain_chain_spec_path, Some(spec_name), Some(spec_id)).unwrap();
// Customize your chain specification
let mut chain_spec = ChainSpec::from(&plain_chain_spec_path).unwrap();
chain_spec.replace_para_id(2002);
Expand All @@ -72,11 +74,13 @@ use std::path::Path;

let path = Path::new("./"); // Location of the parachain project.
let builder = ChainSpecBuilder::Node { node_path: path.join("node"), default_bootnode: false, profile: Profile::Release };
let spec_name = "MySpec";
let spec_id = "my_spec";
// Build the node binary first
let binary_path = builder.build(&[]).unwrap();
// Generate a plain chain specification file of a parachain
let plain_chain_spec_path = path.join("plain-parachain-chainspec.json");
builder.generate_plain_chain_spec("dev", &plain_chain_spec_path).unwrap();
builder.generate_plain_chain_spec("dev", &plain_chain_spec_path, Some(spec_name), Some(spec_id)).unwrap();
// Generate a raw chain specification file of a parachain
let chain_spec = builder.generate_raw_chain_spec(&plain_chain_spec_path, "raw-parachain-chainspec.json").unwrap();
// Export the WebAssembly runtime for the parachain.
Expand Down
133 changes: 124 additions & 9 deletions crates/pop-chains/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
use crate::errors::{Error, handle_command_error};
use anyhow::{Result, anyhow};
use duct::cmd;
use pop_common::{
Profile, account_id::convert_to_evm_accounts, find_workspace_toml, manifest::from_path,
};
use pop_common::{Profile, account_id::convert_to_evm_accounts, manifest::from_path};
use sc_chain_spec::{GenericChainSpec, NoExtension};
use serde_json::{Value, json};
use sp_core::bytes::to_hex;
Expand Down Expand Up @@ -87,7 +85,7 @@ impl ChainSpecBuilder {
pub fn artifact_path(&self) -> Result<PathBuf> {
let manifest = from_path(&self.path())?;
let package = manifest.package().name();
let root_folder = find_workspace_toml(&self.path())
let root_folder = rustilities::manifest::find_workspace_manifest(self.path())
.ok_or(anyhow::anyhow!("Not inside a workspace"))?
.parent()
.expect("Path to Cargo.toml workspace root folder must exist")
Expand Down Expand Up @@ -117,10 +115,14 @@ impl ChainSpecBuilder {
/// # Arguments
/// * `chain_or_preset` - The chain (when using a node) or preset (when using a runtime) name.
/// * `output_file` - The path where the chain spec should be written.
/// * `name` - The name to be used on the chain spec if specified.
/// * `id` - The ID to be used on the chain spec if specified.
pub fn generate_plain_chain_spec(
&self,
chain_or_preset: &str,
output_file: &Path,
name: Option<&str>,
id: Option<&str>,
) -> Result<(), Error> {
match self {
ChainSpecBuilder::Node { default_bootnode, .. } => generate_plain_chain_spec_with_node(
Expand All @@ -133,6 +135,8 @@ impl ChainSpecBuilder {
fs::read(self.artifact_path()?)?,
output_file,
chain_or_preset,
name,
id,
),
}
}
Expand Down Expand Up @@ -329,16 +333,27 @@ pub fn generate_raw_chain_spec_with_runtime(
/// * `wasm` - The WebAssembly runtime bytes.
/// * `plain_chain_spec` - The path where the plain chain specification should be written.
/// * `preset` - Preset name for genesis configuration.
/// * `name` - The name to be used on the chain spec if specified.
/// * `id` - The ID to be used on the chain spec if specified.
pub fn generate_plain_chain_spec_with_runtime(
wasm: Vec<u8>,
plain_chain_spec: &Path,
preset: &str,
name: Option<&str>,
id: Option<&str>,
) -> Result<(), Error> {
let chain_spec = GenericChainSpec::<NoExtension>::builder(&wasm[..], None)
.with_genesis_config_preset_name(preset.trim())
.build()
.as_json(false)
.map_err(|e| anyhow::anyhow!(e))?;
let mut chain_spec = GenericChainSpec::<NoExtension>::builder(&wasm[..], None)
.with_genesis_config_preset_name(preset.trim());

if let Some(name) = name {
chain_spec = chain_spec.with_name(name);
}

if let Some(id) = id {
chain_spec = chain_spec.with_id(id);
}

let chain_spec = chain_spec.build().as_json(false).map_err(|e| anyhow::anyhow!(e))?;
fs::write(plain_chain_spec, chain_spec)?;

Ok(())
Expand Down Expand Up @@ -781,6 +796,8 @@ mod tests {
use strum::VariantArray;
use tempfile::{Builder, TempDir, tempdir};

static MOCK_WASM: &[u8] = include_bytes!("../../../../artifacts/mock_runtime.compact.wasm");

fn setup_template_and_instantiate() -> Result<TempDir> {
let temp_dir = tempdir().expect("Failed to create temp dir");
let config = Config {
Expand Down Expand Up @@ -1055,6 +1072,104 @@ mod tests {
Ok(())
}

#[tokio::test]
async fn generate_plain_chain_spec_with_runtime_works_with_name_and_id_override() -> Result<()>
{
let temp_dir =
setup_template_and_instantiate().expect("Failed to setup template and instantiate");
// Test generate chain spec
let plain_chain_spec = &temp_dir.path().join("plain-parachain-chainspec.json");
generate_plain_chain_spec_with_runtime(
Vec::from(MOCK_WASM),
plain_chain_spec,
"local_testnet",
Some("POP Chain Spec"),
Some("pop-chain-spec"),
)?;
assert!(plain_chain_spec.exists());
let raw_chain_spec =
generate_raw_chain_spec_with_runtime(plain_chain_spec, "raw-parachain-chainspec.json")?;
assert!(raw_chain_spec.exists());
let content = fs::read_to_string(raw_chain_spec.clone()).expect("Could not read file");
assert!(content.contains("\"name\": \"POP Chain Spec\""));
assert!(content.contains("\"id\": \"pop-chain-spec\""));
assert!(content.contains("\"bootNodes\": []"));
Ok(())
}

#[tokio::test]
async fn generate_plain_chain_spec_with_runtime_works_with_name_override() -> Result<()> {
let temp_dir =
setup_template_and_instantiate().expect("Failed to setup template and instantiate");
// Test generate chain spec
let plain_chain_spec = &temp_dir.path().join("plain-parachain-chainspec.json");
generate_plain_chain_spec_with_runtime(
Vec::from(MOCK_WASM),
plain_chain_spec,
"local_testnet",
Some("POP Chain Spec"),
None,
)?;
assert!(plain_chain_spec.exists());
let raw_chain_spec =
generate_raw_chain_spec_with_runtime(plain_chain_spec, "raw-parachain-chainspec.json")?;
assert!(raw_chain_spec.exists());
let content = fs::read_to_string(raw_chain_spec.clone()).expect("Could not read file");
assert!(content.contains("\"name\": \"POP Chain Spec\""));
assert!(content.contains("\"id\": \"dev\""));
assert!(content.contains("\"bootNodes\": []"));
Ok(())
}

#[tokio::test]
async fn generate_plain_chain_spec_with_runtime_works_with_id_override() -> Result<()> {
let temp_dir =
setup_template_and_instantiate().expect("Failed to setup template and instantiate");
// Test generate chain spec
let plain_chain_spec = &temp_dir.path().join("plain-parachain-chainspec.json");
generate_plain_chain_spec_with_runtime(
Vec::from(MOCK_WASM),
plain_chain_spec,
"local_testnet",
None,
Some("pop-chain-spec"),
)?;
assert!(plain_chain_spec.exists());
let raw_chain_spec =
generate_raw_chain_spec_with_runtime(plain_chain_spec, "raw-parachain-chainspec.json")?;
assert!(raw_chain_spec.exists());
let content = fs::read_to_string(raw_chain_spec.clone()).expect("Could not read file");
assert!(content.contains("\"name\": \"Development\""));
assert!(content.contains("\"id\": \"pop-chain-spec\""));
assert!(content.contains("\"bootNodes\": []"));
Ok(())
}

#[tokio::test]
async fn generate_plain_chain_spec_with_runtime_works_without_name_and_id_override()
-> Result<()> {
let temp_dir =
setup_template_and_instantiate().expect("Failed to setup template and instantiate");
// Test generate chain spec
let plain_chain_spec = &temp_dir.path().join("plain-parachain-chainspec.json");
generate_plain_chain_spec_with_runtime(
Vec::from(MOCK_WASM),
plain_chain_spec,
"local_testnet",
None,
None,
)?;
assert!(plain_chain_spec.exists());
let raw_chain_spec =
generate_raw_chain_spec_with_runtime(plain_chain_spec, "raw-parachain-chainspec.json")?;
assert!(raw_chain_spec.exists());
let content = fs::read_to_string(raw_chain_spec.clone()).expect("Could not read file");
assert!(content.contains("\"name\": \"Development\""));
assert!(content.contains("\"id\": \"dev\""));
assert!(content.contains("\"bootNodes\": []"));
Ok(())
}

#[tokio::test]
async fn fails_to_generate_plain_chain_spec_when_file_missing() -> Result<()> {
let temp_dir =
Expand Down
1 change: 1 addition & 0 deletions crates/pop-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ duct.workspace = true
env_logger.workspace = true
os_info.workspace = true
reqwest.workspace = true
rustilities = { workspace = true, features = ["manifest"]}
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
strum.workspace = true
Expand Down
5 changes: 3 additions & 2 deletions crates/pop-cli/src/commands/build/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{PACKAGE, PARACHAIN};
use crate::{
cli,
common::{
builds::create_chain_spec_builder,
builds::{ChainPath, create_chain_spec_builder},
runtime::Feature::{Benchmark, TryRuntime},
},
style::style,
Expand Down Expand Up @@ -65,7 +65,8 @@ impl BuildChain {

// Build parachain.
cli.warning("NOTE: this may take some time...")?;
let builder = create_chain_spec_builder(&self.path, &self.profile, false, cli)?;
let builder =
create_chain_spec_builder(ChainPath::Base(&self.path), &self.profile, false, cli)?;
let features_arr: Vec<_> = features.into_iter().map(|s| s.to_string()).collect();
let binary = builder.build(features_arr.as_slice())?;
cli.info(format!("The {project} was built in {} mode.", self.profile))?;
Expand Down
4 changes: 2 additions & 2 deletions crates/pop-cli/src/commands/build/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
runtime::{build_runtime, ensure_runtime_binary_exists},
},
};
use pop_common::{Profile, find_workspace_toml};
use pop_common::Profile;
use std::{
collections::HashSet,
path::{Path, PathBuf},
Expand Down Expand Up @@ -89,7 +89,7 @@ impl BuildRuntime {
if self.profile == Profile::Debug {
cli.warning("NOTE: this command now defaults to DEBUG builds. Please use `--release` (or simply `-r`) for a release build...")?;
}
let workspace_root = find_workspace_toml(&self.path);
let workspace_root = rustilities::manifest::find_workspace_manifest(&self.path);
let target_path = self
.profile
.target_directory(&workspace_root.unwrap_or(self.path.to_path_buf()))
Expand Down
Loading
Loading