Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: logic for parachain registration #410

Open
wants to merge 22 commits into
base: feat/deploy-parachain
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
77309e2
feat: deploy a parachain commands
AlexD10S Feb 10, 2025
f9dffc6
feat: build specs in pop up
AlexD10S Feb 10, 2025
8016272
feat: logic to interact with a chain
AlexD10S Feb 11, 2025
11869aa
feat: register parachain
AlexD10S Feb 11, 2025
d30c135
refactor: clean code and improve docs
AlexD10S Feb 11, 2025
9bd7229
test: unit tests for pop up methods
AlexD10S Feb 11, 2025
5952580
refactor: small fixes with visibility and removing logs
AlexD10S Feb 12, 2025
d5bd298
feat: return events in submit_signed_extrinsic
AlexD10S Feb 13, 2025
6abeba8
feat: get para_id from event
AlexD10S Feb 14, 2025
d360dba
test: fix detects_parachain_correctly
AlexD10S Feb 17, 2025
7f9b926
refactor: improve docs and code
AlexD10S Feb 17, 2025
ece5507
test: fix change_working_directory_works
AlexD10S Feb 17, 2025
e413871
fix: clippy warnings
AlexD10S Feb 18, 2025
7d87f17
refactor: move submit_extrinsic_with_wallet in a common file
AlexD10S Feb 20, 2025
ae3d9a4
refactor: remove unnecesary code
AlexD10S Feb 20, 2025
54a676e
refactor: UpChainCommand structure
AlexD10S Feb 20, 2025
db6e30d
test: adjust tests to refactored struct
AlexD10S Feb 20, 2025
50983c1
refactor: renaming prepare_register_parachain_call_data and prepare_r…
AlexD10S Feb 20, 2025
cfc566e
refactor: move events module
AlexD10S Feb 20, 2025
93053df
fix: submit_extrinsic_with_wallet under parachain feature
AlexD10S Feb 20, 2025
849dff0
refactor: remove unnecesary code
AlexD10S Feb 20, 2025
74cf390
test: increase coverage with reserve_parachain_id_fails_wrong_chain a…
AlexD10S Feb 20, 2025
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
1 change: 1 addition & 0 deletions 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 @@ -49,6 +49,7 @@ subxt = "0.38.0"
ink_env = "5.0.0"
sp-core = "32.0.0"
sp-weights = "31.0.0"
scale = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] }
scale-info = { version = "2.11.4", default-features = false, features = ["derive"] }
scale-value = { version = "0.17.0", default-features = false, features = ["from-string", "parser-ss58"] }
contract-build = "5.0.2"
Expand Down
89 changes: 62 additions & 27 deletions crates/pop-cli/src/commands/build/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
style::style,
};
use clap::{Args, ValueEnum};
use cliclack::spinner;
use cliclack::{spinner, ProgressBar};
use pop_common::Profile;
use pop_parachains::{
binary_path, build_parachain, export_wasm_file, generate_genesis_state_file,
Expand Down Expand Up @@ -193,7 +193,7 @@
///
/// # Arguments
/// * `cli` - The cli.
async fn configure_build_spec(
pub(crate) async fn configure_build_spec(
self,
cli: &mut impl cli::traits::Cli,
) -> anyhow::Result<BuildSpec> {
Expand Down Expand Up @@ -439,7 +439,7 @@

// Represents the configuration for building a chain specification.
#[derive(Debug)]
struct BuildSpec {
pub(crate) struct BuildSpec {
output_file: PathBuf,
profile: Profile,
id: u32,
Expand All @@ -461,39 +461,18 @@
fn build(self, cli: &mut impl cli::traits::Cli) -> anyhow::Result<&'static str> {
cli.intro("Building your chain spec")?;
let mut generated_files = vec![];
let BuildSpec {
ref output_file,
ref profile,
id,
default_bootnode,
ref chain,
genesis_state,
genesis_code,
..
} = self;
let BuildSpec { ref output_file, ref profile, id, genesis_code, genesis_state, .. } = self;
// Ensure binary is built.
let binary_path = ensure_binary_exists(cli, profile)?;
let spinner = spinner();
spinner.start("Generating chain specification...");

// Generate chain spec.
generate_plain_chain_spec(&binary_path, output_file, default_bootnode, chain)?;
Copy link
Collaborator Author

@AlexD10S AlexD10S Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored the logic for generating the chain spec and raw chain spec into the generate_chain_spec function.

// Customize spec based on input.
self.customize()?;
let raw_chain_spec = self.generate_chain_spec(&binary_path, &spinner)?;

generated_files.push(format!(
"Plain text chain specification file generated at: {}",
&output_file.display()
));

// Generate raw spec.
spinner.set_message("Generating raw chain specification...");
let spec_name = &output_file
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(DEFAULT_SPEC_NAME)
.trim_end_matches(".json");
let raw_spec_name = format!("{spec_name}-raw.json");
let raw_chain_spec = generate_raw_chain_spec(&binary_path, output_file, &raw_spec_name)?;
generated_files.push(format!(
"Raw chain specification file generated at: {}",
raw_chain_spec.display()
Expand Down Expand Up @@ -529,6 +508,62 @@
Ok("spec")
}

/// Generates plain and raw chain specification files.
fn generate_chain_spec(
&self,
binary_path: &PathBuf,
spinner: &ProgressBar,
) -> anyhow::Result<PathBuf> {
let BuildSpec { output_file, chain, .. } = self;
spinner.start("Generating chain specification...");

// Generate plain chain spec.
generate_plain_chain_spec(&binary_path, output_file, self.default_bootnode, chain)?;

Check warning on line 521 in crates/pop-cli/src/commands/build/spec.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler

warning: this expression creates a reference which is immediately dereferenced by the compiler --> crates/pop-cli/src/commands/build/spec.rs:521:29 | 521 | generate_plain_chain_spec(&binary_path, output_file, self.default_bootnode, chain)?; | ^^^^^^^^^^^^ help: change this to: `binary_path` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow = note: `#[warn(clippy::needless_borrow)]` on by default
// Customize spec based on input.
self.customize()?;

// Generate raw spec.
spinner.set_message("Generating raw chain specification...");
let spec_name = &output_file
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(DEFAULT_SPEC_NAME)
.trim_end_matches(".json");
let raw_spec_name = format!("{spec_name}-raw.json");
let raw_chain_spec = generate_raw_chain_spec(&binary_path, output_file, &raw_spec_name)?;

Check warning on line 533 in crates/pop-cli/src/commands/build/spec.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler

warning: this expression creates a reference which is immediately dereferenced by the compiler --> crates/pop-cli/src/commands/build/spec.rs:533:48 | 533 | let raw_chain_spec = generate_raw_chain_spec(&binary_path, output_file, &raw_spec_name)?; | ^^^^^^^^^^^^ help: change this to: `binary_path` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

Ok(raw_chain_spec)
}

/// Generates chain specification files and returns the file paths for the generated genesis
/// code and genesis state files.
///
/// # Arguments
/// * `cli` - The cli.
pub(crate) fn generate_genesis_artifacts(
self,
cli: &mut impl cli::traits::Cli,
) -> anyhow::Result<(PathBuf, PathBuf)> {
// Ensure binary is built once.
let binary_path = ensure_binary_exists(cli, &self.profile)?;
let spinner = spinner();
spinner.start("Generating files...");

let raw_chain_spec = self.generate_chain_spec(&binary_path, &spinner)?;

spinner.set_message("Generating genesis code...");
let wasm_file_name = format!("para-{}.wasm", self.id);
let genesis_code = export_wasm_file(&binary_path, &raw_chain_spec, &wasm_file_name)?;

spinner.set_message("Generating genesis state...");
let genesis_file_name = format!("para-{}-genesis-state", self.id);
let genesis_state =
generate_genesis_state_file(&binary_path, &raw_chain_spec, &genesis_file_name)?;

spinner.stop("Genesis artifacts generated successfully.");
Ok((genesis_state, genesis_code))
}

// Customize a chain specification.
fn customize(&self) -> anyhow::Result<()> {
let mut chain_spec = ChainSpec::from(&self.output_file)?;
Expand Down
39 changes: 27 additions & 12 deletions crates/pop-cli/src/commands/call/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
construct_extrinsic, construct_sudo_extrinsic, decode_call_data, encode_call_data,
find_dispatchable_by_name, find_pallet_by_name, parse_chain_metadata, set_up_client,
sign_and_submit_extrinsic, submit_signed_extrinsic, supported_actions, Action, CallData,
DynamicPayload, Function, OnlineClient, Pallet, Param, Payload, SubstrateConfig,
DynamicPayload, ExtrinsicEvents, Function, OnlineClient, Pallet, Param, Payload,
SubstrateConfig,
};
use url::Url;

Expand Down Expand Up @@ -109,7 +110,15 @@
// Sign and submit the extrinsic.
let result = if self.use_wallet {
let call_data = xt.encode_call_data(&chain.client.metadata())?;
submit_extrinsic_with_wallet(&chain.client, &chain.url, call_data, &mut cli).await
match submit_extrinsic_with_wallet(&chain.client, &chain.url, call_data, &mut cli)
.await
{
Ok(_) => Ok(()),
Err(e) => {
display_message(&e.to_string(), false, &mut cli)?;
break;
},
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? And is the error not duplicate with line 127

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, improved in ae3d9a4

} else {
call.submit_extrinsic(&chain.client, &chain.url, xt, &mut cli).await
};
Expand Down Expand Up @@ -358,13 +367,13 @@
}

// Represents a chain, including its URL, client connection, and available pallets.
struct Chain {
pub(crate) struct Chain {
// Websocket endpoint of the node.
url: Url,
pub(crate) url: Url,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trivial but line 363 already set this struct to pub(crate), we can simply set this field to pub.

// The client used to interact with the chain.
client: OnlineClient<SubstrateConfig>,
pub(crate) client: OnlineClient<SubstrateConfig>,
// A list of pallets available on the chain.
pallets: Vec<Pallet>,
pub(crate) pallets: Vec<Pallet>,
}

/// Represents a configured dispatchable function call, including the pallet, function, arguments,
Expand Down Expand Up @@ -473,13 +482,19 @@
}
}

// Sign and submit an extrinsic using wallet integration.
async fn submit_extrinsic_with_wallet(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context: Moved into common/wallet

/// Sign and submit an extrinsic using wallet integration, then returns the resulting events.
///
/// # Arguments
/// * `client` - The client used to interact with the chain.
/// * `url` - Endpoint of the node.
/// * `call_data` - The call data to be signed.
/// * `cli` - The CLI implementation to be used.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only required for public docs, as well as ///

Copy link
Collaborator Author

@AlexD10S AlexD10S Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored 7d87f17

pub(crate) async fn submit_extrinsic_with_wallet(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is now reused in pop up, so it might make sense to move it to a common file. But I wasn’t sure about making additional changes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this should be moved there.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! Moved in 7d87f17

client: &OnlineClient<SubstrateConfig>,
url: &Url,
call_data: Vec<u8>,
cli: &mut impl Cli,
) -> Result<()> {
) -> Result<ExtrinsicEvents<SubstrateConfig>> {
let maybe_payload = request_signature(call_data, url.to_string()).await?;
if let Some(payload) = maybe_payload {
cli.success("Signed payload received.")?;
Expand All @@ -492,11 +507,11 @@
.await
.map_err(|err| anyhow!("{}", format!("{err:?}")))?;

spinner.stop(format!("Extrinsic submitted with hash: {:?}", result));
spinner.stop(format!("Extrinsic submitted with hash: {:?}", result.extrinsic_hash()));
Ok(result)
} else {
display_message("No signed payload received.", false, cli)?;
return Err(anyhow!("No signed payload received."));

Check warning on line 513 in crates/pop-cli/src/commands/call/chain.rs

View workflow job for this annotation

GitHub Actions / clippy

unneeded `return` statement

warning: unneeded `return` statement --> crates/pop-cli/src/commands/call/chain.rs:513:3 | 513 | return Err(anyhow!("No signed payload received.")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return = note: `#[warn(clippy::needless_return)]` on by default help: remove `return` | 513 - return Err(anyhow!("No signed payload received.")); 513 + Err(anyhow!("No signed payload received.")) |
}
Ok(())
}

// Displays a message to the user, with formatting based on the success status.
Expand Down
25 changes: 19 additions & 6 deletions crates/pop-cli/src/commands/up/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use std::path::PathBuf;
mod contract;
#[cfg(feature = "parachain")]
mod network;
#[cfg(feature = "parachain")]
mod parachain;

/// Arguments for launching or deploying a project.
#[derive(Args, Clone)]
Expand All @@ -25,6 +27,10 @@ pub(crate) struct UpArgs {
#[arg(value_name = "PATH", index = 1, global = true, conflicts_with = "path")]
pub path_pos: Option<PathBuf>,

#[command(flatten)]
#[cfg(feature = "parachain")]
pub(crate) parachain: parachain::UpParachainCommand,

#[command(flatten)]
#[cfg(feature = "contract")]
pub(crate) contract: contract::UpContractCommand,
Expand Down Expand Up @@ -73,7 +79,9 @@ impl Command {
}
#[cfg(feature = "parachain")]
if pop_parachains::is_supported(project_path.as_deref())? {
cli.warning("Parachain deployment is currently not implemented.")?;
let mut cmd = args.parachain;
cmd.path = project_path;
cmd.execute(cli).await?;
return Ok("parachain");
}
cli.warning(
Expand All @@ -85,7 +93,7 @@ impl Command {

#[cfg(test)]
mod tests {
use super::{contract::UpContractCommand, *};
use super::{contract::UpContractCommand, parachain::UpParachainCommand, *};

use cli::MockCli;
use duct::cmd;
Expand Down Expand Up @@ -114,6 +122,7 @@ mod tests {
skip_confirm: false,
valid: false,
},
parachain: UpParachainCommand::default(),
command: None,
})
}
Expand All @@ -138,17 +147,21 @@ mod tests {
async fn detects_parachain_correctly() -> anyhow::Result<()> {
let temp_dir = tempfile::tempdir()?;
let name = "parachain";
let project_path = temp_dir.path().join(name);
let path = temp_dir.path();
let project_path = path.join(name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems unnecessary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored ae3d9a4

let config = Config {
symbol: "DOT".to_string(),
decimals: 18,
initial_endowment: "1000000".to_string(),
};
instantiate_template_dir(&Parachain::Standard, &project_path, None, config)?;

let args = create_up_args(project_path)?;
let mut cli =
MockCli::new().expect_warning("Parachain deployment is currently not implemented.");
let mut args = create_up_args(project_path)?;
args.parachain.relay_url = Some(Url::parse("wss://polkadot-rpc.publicnode.com")?);
args.parachain.id = Some(2000);
args.parachain.genesis_code = Some(PathBuf::from("path/to/genesis"));
args.parachain.genesis_state = Some(PathBuf::from("path/to/state"));
let mut cli = MockCli::new();
assert_eq!(Command::execute_project_deployment(args, &mut cli).await?, "parachain");
cli.verify()
}
Expand Down
Loading
Loading