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

fix: hrmp #278

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
12 changes: 7 additions & 5 deletions Cargo.lock

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

33 changes: 32 additions & 1 deletion crates/pop-cli/src/commands/up/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use console::{Emoji, Style, Term};
use duct::cmd;
use pop_common::Status;
use pop_parachains::{Error, IndexSet, NetworkNode, Zombienet};
use pop_parachains::{clear_dmpq, Error, IndexSet, NetworkNode, RelayChain, Zombienet};
use std::{path::Path, time::Duration};
use tokio::time::sleep;

Expand Down Expand Up @@ -147,6 +147,37 @@
}

spinner.stop(result);

// Check for any specified channels
if zombienet.hrmp_channels() {
let relay_chain = zombienet.relay_chain();
match RelayChain::from(relay_chain) {
None => {
log::error(format!("🚫 Using `{relay_chain}` with HRMP channels is currently unsupported. Please use `paseo-local` or `rococo-local`."))?;
},
Some(_) => {
use tokio::time::sleep;
let spinner = cliclack::spinner();
spinner.start("Connecting to relay chain to prepare channels...");
// Allow relay node time to start
sleep(Duration::from_secs(10)).await;
spinner.start("Preparing channels...");
let relay_endpoint = network.relaychain().nodes()[0].client().await?;
let para_ids: Vec<_> =
network.parachains().iter().map(|p| p.para_id()).collect();
tokio::spawn(async move {
if let Err(e) = clear_dmpq(relay_endpoint, &para_ids).await {
spinner.stop("");
log::error(format!("🚫 Could not prepare channels: {e}"))?;
return Ok::<(), Error>(());
}
spinner.stop("Channels successfully prepared for initialization.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

First time I tried with an old chain-spec-generator the message was Channels successfully prepared for initialization.. but no channels were actually opened. This is likely nothing to worry about, as it should not occur to any user once we start using the releases from https://github.com/r0gue-io/paseo-network-runtimes.

Ok::<(), Error>(())
});
},
}
}

tokio::signal::ctrl_c().await?;
outro("Done")?;
},
Expand Down Expand Up @@ -255,7 +286,7 @@
let binaries: Vec<_> = binaries
.into_iter()
.filter(|b| !b.exists() || (latest && b.stale()))
.map(|b| {

Check warning on line 289 in crates/pop-cli/src/commands/up/parachain.rs

View workflow job for this annotation

GitHub Actions / clippy

using `map` over `inspect`

warning: using `map` over `inspect` --> crates/pop-cli/src/commands/up/parachain.rs:289:5 | 289 | .map(|b| { | ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_inspect = note: `#[warn(clippy::manual_inspect)]` on by default help: try | 289 ~ .inspect(|b| { 290 | if latest && b.stale() { 291 | b.use_latest() 292 ~ } |
if latest && b.stale() {
b.use_latest()
}
Expand Down
2 changes: 2 additions & 0 deletions crates/pop-parachains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ glob.workspace = true
serde_json.workspace = true
strum.workspace = true
strum_macros.workspace = true
subxt-signer.workspace = true
subxt.workspace = true
tar.workspace = true
tempfile.workspace = true
thiserror.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions crates/pop-parachains/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,46 @@
use zombienet_sdk::OrchestratorError;

#[derive(Error, Debug)]
pub enum Error {

Check warning on line 7 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for an enum

warning: missing documentation for an enum --> crates/pop-parachains/src/errors.rs:7:1 | 7 | pub enum Error { | ^^^^^^^^^^^^^^ | = note: requested on the command line with `-W missing-docs`
#[error("User aborted due to existing target directory.")]
Aborted,

Check warning on line 9 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:9:2 | 9 | Aborted, | ^^^^^^^
#[error("Anyhow error: {0}")]
AnyhowError(#[from] anyhow::Error),

Check warning on line 11 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:11:2 | 11 | AnyhowError(#[from] anyhow::Error), | ^^^^^^^^^^^
#[error("{0}")]
CommonError(#[from] pop_common::Error),

Check warning on line 13 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:13:2 | 13 | CommonError(#[from] pop_common::Error), | ^^^^^^^^^^^
#[error("Configuration error: {0}")]
Config(String),

Check warning on line 15 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:15:2 | 15 | Config(String), | ^^^^^^
#[error("Failed to access the current directory")]
CurrentDirAccess,

Check warning on line 17 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:17:2 | 17 | CurrentDirAccess, | ^^^^^^^^^^^^^^^^
#[error("Failed to parse the endowment value")]
EndowmentError,

Check warning on line 19 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:19:2 | 19 | EndowmentError, | ^^^^^^^^^^^^^^
#[error("IO error: {0}")]
IO(#[from] std::io::Error),

Check warning on line 21 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:21:2 | 21 | IO(#[from] std::io::Error), | ^^
#[error("JSON error: {0}")]
JsonError(#[from] serde_json::Error),

Check warning on line 23 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:23:2 | 23 | JsonError(#[from] serde_json::Error), | ^^^^^^^^^
#[error("Missing binary: {0}")]
MissingBinary(String),

Check warning on line 25 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:25:2 | 25 | MissingBinary(String), | ^^^^^^^^^^^^^
#[error("Missing chain spec file at: {0}")]
MissingChainSpec(String),

Check warning on line 27 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:27:2 | 27 | MissingChainSpec(String), | ^^^^^^^^^^^^^^^^
#[error("Command {command} doesn't exist in binary {binary}")]
MissingCommand { command: String, binary: String },

Check warning on line 29 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a struct field

warning: missing documentation for a struct field --> crates/pop-parachains/src/errors.rs:29:36 | 29 | MissingCommand { command: String, binary: String }, | ^^^^^^^^^^^^^^

Check warning on line 29 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a struct field

warning: missing documentation for a struct field --> crates/pop-parachains/src/errors.rs:29:19 | 29 | MissingCommand { command: String, binary: String }, | ^^^^^^^^^^^^^^^

Check warning on line 29 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:29:2 | 29 | MissingCommand { command: String, binary: String }, | ^^^^^^^^^^^^^^
#[error("Orchestrator error: {0}")]
OrchestratorError(#[from] OrchestratorError),

Check warning on line 31 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:31:2 | 31 | OrchestratorError(#[from] OrchestratorError), | ^^^^^^^^^^^^^^^^^
#[error("Failed to create pallet directory")]
PalletDirCreation,

Check warning on line 33 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:33:2 | 33 | PalletDirCreation, | ^^^^^^^^^^^^^^^^^
#[error("Invalid path")]
PathError,

Check warning on line 35 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:35:2 | 35 | PathError, | ^^^^^^^^^
#[error("Failed to execute rustfmt")]
RustfmtError(std::io::Error),

Check warning on line 37 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:37:2 | 37 | RustfmtError(std::io::Error), | ^^^^^^^^^^^^
#[error("Template error: {0}")]
SourcingError(#[from] pop_common::sourcing::Error),

Check warning on line 39 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:39:2 | 39 | SourcingError(#[from] pop_common::sourcing::Error), | ^^^^^^^^^^^^^
/// An error occurred whilst interacting with a chain using `subxt`.
#[error("Subxt error: {0}")]
SubXtError(#[from] subxt::Error),
#[error("Toml error: {0}")]
TomlError(#[from] toml_edit::de::Error),

Check warning on line 44 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:44:2 | 44 | TomlError(#[from] toml_edit::de::Error), | ^^^^^^^^^
#[error("Unsupported command: {0}")]
UnsupportedCommand(String),

Check warning on line 46 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:46:2 | 46 | UnsupportedCommand(String), | ^^^^^^^^^^^^^^^^^^
#[error("Failed to locate the workspace")]
WorkspaceLocate,

Check warning on line 48 in crates/pop-parachains/src/errors.rs

View workflow job for this annotation

GitHub Actions / clippy

missing documentation for a variant

warning: missing documentation for a variant --> crates/pop-parachains/src/errors.rs:48:2 | 48 | WorkspaceLocate, | ^^^^^^^^^^^^^^^
}
2 changes: 2 additions & 0 deletions crates/pop-parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod errors;
mod generator;
mod new_pallet;
mod new_parachain;
mod relay;
mod templates;
mod up;
mod utils;
Expand All @@ -18,6 +19,7 @@ pub use errors::Error;
pub use indexmap::IndexSet;
pub use new_pallet::{create_pallet_template, new_pallet_options::*, TemplatePalletConfig};
pub use new_parachain::instantiate_template_dir;
pub use relay::{clear_dmpq, RelayChain};
pub use templates::{Config, Parachain, Provider};
pub use up::Zombienet;
pub use utils::helpers::is_initial_endowment_valid;
Expand Down
80 changes: 80 additions & 0 deletions crates/pop-parachains/src/relay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-3.0

use crate::Error;
use sp_core::twox_128;
use subxt::{
config::BlockHash,
dynamic::{self, Value},
ext::sp_core,
OnlineClient, PolkadotConfig,
};

/// Clears the DMPQ state for the given parachain IDs.
///
/// # Arguments
/// * `relay_chain` - The relay chain.
/// * `client` - Client for the network which state is to be modified.
/// * `para_ids` - List of ids to build the keys that will be mutated.
pub async fn clear_dmpq(
client: OnlineClient<PolkadotConfig>,
para_ids: &[u32],
) -> Result<impl BlockHash, Error> {
// Wait for blocks to be produced.
let mut sub = client.blocks().subscribe_finalized().await?;
for _ in 0..2 {
sub.next().await;
}

// Generate storage keys to be removed
let dmp = twox_128("Dmp".as_bytes());
let dmp_queues = twox_128("DownwardMessageQueues".as_bytes());
let dmp_queue_heads = twox_128("DownwardMessageQueueHeads".as_bytes());
let mut clear_dmq_keys = Vec::<Vec<u8>>::new();
for id in para_ids {
let id = id.to_le_bytes();
// DMP Queue Head
let mut key = dmp.to_vec();
key.extend(&dmp_queue_heads);
key.extend(sp_core::twox_64(&id));
key.extend(id);
clear_dmq_keys.push(key);
// DMP Queue
let mut key = dmp.to_vec();
key.extend(&dmp_queues);
key.extend(sp_core::twox_64(&id));
key.extend(id);
clear_dmq_keys.push(key);
}

// Submit calls to remove specified keys
let sudo = subxt_signer::sr25519::dev::alice();
let kill_storage = dynamic::tx(
"System",
"kill_storage",
vec![Value::unnamed_composite(clear_dmq_keys.into_iter().map(Value::from_bytes))],
);
let sudo_call = dynamic::tx("Sudo", "sudo", vec![kill_storage.into_value()]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this is merged before pop call parachain, I will refactor it to make use of the logic there: https://github.com/r0gue-io/pop-cli/blob/feat-call-extrinsic-sudo-wrap/crates/pop-parachains/src/call/mod.rs#L43

Ok(client.tx().sign_and_submit_default(&sudo_call, &sudo).await?)
}

/// A supported relay chain.
pub enum RelayChain {
/// Paseo.
PaseoLocal,
/// Rococo.
RococoLocal,
}

impl RelayChain {
/// Attempts to convert a chain identifier into a supported `RelayChain` variant.
///
/// # Arguments
/// * `id` - The relay chain identifier.
pub fn from(id: &str) -> Option<RelayChain> {
match id {
"paseo-local" => Some(RelayChain::PaseoLocal),
"rococo-local" => Some(RelayChain::RococoLocal),
_ => None,
}
}
}
19 changes: 16 additions & 3 deletions crates/pop-parachains/src/up/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub struct Zombienet {
relay_chain: RelayChain,
/// The configuration required to launch parachains.
parachains: IndexMap<u32, Parachain>,
/// Whether any HRMP channels are to be pre-opened.
hrmp_channels: bool,
}

impl Zombienet {
Expand Down Expand Up @@ -59,7 +61,7 @@ impl Zombienet {
// Parse network config
let network_config = NetworkConfiguration::from(network_config)?;
// Determine relay and parachain requirements based on arguments and config
let relay_chain = Self::relay_chain(
let relay_chain = Self::_relay_chain(
relay_chain_version,
relay_chain_runtime_version,
&network_config,
Expand All @@ -84,7 +86,7 @@ impl Zombienet {
cache,
)
.await?;
Ok(Self { network_config, relay_chain, parachains })
Ok(Self { network_config, relay_chain, parachains, hrmp_channels: false })
}

/// The binaries required to launch the network.
Expand Down Expand Up @@ -216,7 +218,7 @@ impl Zombienet {
/// will use the latest available version).
/// * `network_config` - The network configuration to be used to launch a network.
/// * `cache` - The location used for caching binaries.
async fn relay_chain(
async fn _relay_chain(
version: Option<&str>,
runtime_version: Option<&str>,
network_config: &NetworkConfiguration,
Expand Down Expand Up @@ -276,6 +278,16 @@ impl Zombienet {
Ok(relay::default(version, runtime_version, chain, cache).await?)
}

/// The name of the relay chain.
pub fn relay_chain(&self) -> &str {
&self.relay_chain.chain
}

/// Whether any HRMP channels are to be pre-opened.
pub fn hrmp_channels(&self) -> bool {
self.hrmp_channels
}

/// Launches the local network.
pub async fn spawn(&mut self) -> Result<Network<LocalFileSystem>, Error> {
// Symlink polkadot workers
Expand Down Expand Up @@ -304,6 +316,7 @@ impl Zombienet {
let config = self.network_config.configure(&self.relay_chain, &self.parachains)?;
let path = config.path().to_str().expect("temp config file should have a path");
let network_config = NetworkConfig::load_from_toml(path)?;
self.hrmp_channels = !network_config.hrmp_channels().is_empty();
Ok(network_config.spawn_native().await?)
}
}
Expand Down
4 changes: 3 additions & 1 deletion crates/pop-parachains/src/utils/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ pub fn is_initial_endowment_valid(initial_endowment: &str) -> bool {
initial_endowment.parse::<u128>().is_ok() ||
is_valid_bitwise_left_shift(initial_endowment).is_ok()
}
// Auxiliar method to check if the endowment input with a shift left (1u64 << 60) format is valid.

// Auxiliary method to check if the endowment input with a shift left (1u64 << 60) format is valid.
// Parse the self << rhs format and check the shift left operation is valid.
fn is_valid_bitwise_left_shift(initial_endowment: &str) -> Result<u128, Error> {
let v: Vec<&str> = initial_endowment.split(" << ").collect();
Expand Down Expand Up @@ -87,6 +88,7 @@ mod tests {
use super::*;
use crate::generator::parachain::ChainSpec;
use askama::Template;
use std::env::var;
use tempfile::tempdir;

#[test]
Expand Down
19 changes: 19 additions & 0 deletions tests/networks/kusama+asset-hub.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# pop up parachain -f ./tests/networks/kusama+asset-hub.toml

[relaychain]
chain = "kusama-local"

[[relaychain.nodes]]
name = "alice"
validator = true

[[relaychain.nodes]]
name = "bob"
validator = true

[[parachains]]
id = 1000
chain = "asset-hub-kusama-local"

[[parachains.collators]]
name = "asset-hub"
19 changes: 19 additions & 0 deletions tests/networks/paseo+asset-hub.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# pop up parachain -f ./tests/networks/paseo+asset-hub.toml

[relaychain]
chain = "paseo-local"

[[relaychain.nodes]]
name = "alice"
validator = true

[[relaychain.nodes]]
name = "bob"
validator = true

[[parachains]]
id = 1000
chain = "asset-hub-paseo-local"

[[parachains.collators]]
name = "asset-hub"
19 changes: 19 additions & 0 deletions tests/networks/polkadot+asset-hub.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# pop up parachain -f ./tests/networks/polkadot+asset-hub.toml

[relaychain]
chain = "polkadot-local"

[[relaychain.nodes]]
name = "alice"
validator = true

[[relaychain.nodes]]
name = "bob"
validator = true

[[parachains]]
id = 1000
chain = "asset-hub-polkadot-local"

[[parachains.collators]]
name = "asset-hub"
14 changes: 13 additions & 1 deletion tests/networks/pop.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,16 @@ default_command = "pop-node"

[[parachains.collators]]
name = "pop"
args = ["-lruntime::contracts=debug"]
args = ["-lruntime::contracts=debug"]

[[hrmp_channels]]
sender = 1000
recipient = 4385
max_capacity = 1000
max_message_size = 5000

[[hrmp_channels]]
sender = 4385
recipient = 1000
max_capacity = 1000
max_message_size = 8000
19 changes: 19 additions & 0 deletions tests/networks/rococo+asset-hub.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# pop up parachain -f ./tests/networks/rococo+asset-hub.toml

[relaychain]
chain = "rococo-local"

[[relaychain.nodes]]
name = "alice"
validator = true

[[relaychain.nodes]]
name = "bob"
validator = true

[[parachains]]
id = 1000
chain = "asset-hub-rococo-local"

[[parachains.collators]]
name = "asset-hub"
Loading