From 8f06454782e489efad75a13aabf9fbce04ce2dc6 Mon Sep 17 00:00:00 2001 From: My Name Date: Thu, 29 Feb 2024 02:03:39 +0000 Subject: [PATCH] feat: init xtask support --- .cargo/config.toml | 2 + .gitignore | 3 - Cargo.lock | 51 +++++++++---- Cargo.toml | 2 +- xtask/Cargo.toml | 11 +++ xtask/src/flags.rs | 66 +++++++++++++++++ xtask/src/main.rs | 173 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 290 insertions(+), 18 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/flags.rs create mode 100644 xtask/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..35049cbcb --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" diff --git a/.gitignore b/.gitignore index fd122b369..ebba65f35 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,6 @@ .DS_Store -# The cache for docker container dependency -.cargo - # The cache for chain data in container .local diff --git a/Cargo.lock b/Cargo.lock index 7429bc023..790a763c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -278,7 +278,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 0.38.28", + "rustix 0.38.31", "slab", "tracing", "windows-sys 0.52.0", @@ -3077,7 +3077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.3", - "rustix 0.38.28", + "rustix 0.38.31", "windows-sys 0.48.0", ] @@ -3327,9 +3327,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -4033,7 +4033,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.28", + "rustix 0.38.31", ] [[package]] @@ -5298,7 +5298,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite 0.2.13", - "rustix 0.38.28", + "rustix 0.38.31", "tracing", "windows-sys 0.52.0", ] @@ -6067,9 +6067,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.4.1", "errno", @@ -8503,15 +8503,14 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", - "rustix 0.38.28", - "windows-sys 0.48.0", + "rustix 0.38.31", + "windows-sys 0.52.0", ] [[package]] @@ -9605,7 +9604,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.28", + "rustix 0.38.31", ] [[package]] @@ -9929,6 +9928,30 @@ dependencies = [ "time", ] +[[package]] +name = "xflags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944" +dependencies = [ + "xflags-macros", +] + +[[package]] +name = "xflags-macros" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155" + +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "serde_json", + "tempfile", + "xflags", +] + [[package]] name = "yamux" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index e17d4c1e0..5e50e173a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["node", "pallets/subspace", "runtime"] +members = ["node", "pallets/subspace", "runtime", "xtask"] resolver = "2" [profile.release] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 000000000..e35588ef7 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "xtask" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde_json = { workspace = true, features = ["std"] } +tempfile = "3.10.1" +xflags = "0.3.2" diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs new file mode 100644 index 000000000..0a7afbf68 --- /dev/null +++ b/xtask/src/flags.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +xflags::xflags! { + src "src/flags.rs" + + cmd localnet { + + cmd run { + optional --path path: PathBuf + optional --chain-name chain_name: String + optional --chain-path chain: PathBuf + optional --secrets-path secrets_path: PathBuf + optional --base-path base_path: PathBuf + optional --port tcp_port: u16 + optional --rpc-port rpc_port: u16 + repeated --bootnodes bootnodes: String + optional --validator + optional --purge + } + } +} + +// generated start +// The following code is generated by `xflags` macro. +// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate. +#[derive(Debug)] +pub struct Localnet { + pub subcommand: LocalnetCmd, +} + +#[derive(Debug)] +pub enum LocalnetCmd { + Run(Run), +} + +#[derive(Debug)] +pub struct Run { + pub path: Option, + pub chain_name: Option, + pub chain_path: Option, + pub secrets_path: Option, + pub base_path: Option, + pub port: Option, + pub rpc_port: Option, + pub bootnodes: Vec, + pub validator: bool, + pub purge: bool, +} + +impl Localnet { + #[allow(dead_code)] + pub fn from_env_or_exit() -> Self { + Self::from_env_or_exit_() + } + + #[allow(dead_code)] + pub fn from_env() -> xflags::Result { + Self::from_env_() + } + + #[allow(dead_code)] + pub fn from_vec(args: Vec) -> xflags::Result { + Self::from_vec_(args) + } +} +// generated end diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 000000000..ee6a06fb3 --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,173 @@ +use std::fs::File; + +mod flags; + +fn main() { + let flags = flags::Localnet::from_env_or_exit(); + match flags.subcommand { + flags::LocalnetCmd::Run(r) => { + let path = r.path.unwrap_or_else(|| { + tempfile::Builder::new() + .prefix("commune-node-data") + .tempdir() + .expect("failed to create tempdir") + .into_path() + }); + match (path.exists(), path.is_dir()) { + (true, false) => panic!("provided path must be a directory"), + (false, false) => std::fs::create_dir(&path).unwrap(), + _ => {}, + } + + let base_path = r + .base_path + .or_else(|| { + let path = path.join("data"); + path.is_dir().then_some(path) + }) + .unwrap_or_else(|| path.join("data")); + + let chain_path = r + .chain_path + .or_else(|| { + let path = path.join("spec.json"); + path.is_file().then_some(path) + }) + .unwrap_or_else(|| { + let chain = path.join("spec.json"); + let chain_name = r.chain_name.expect( + "chain name must be specified if no chain path is provided or found", + ); + let output = foo::build_chain_spec(&chain_name).output().unwrap(); + std::fs::write(&chain, &output.stdout).unwrap(); + chain + }); + + let secrets_path = r.secrets_path.unwrap_or_else(|| path.clone()); + + let key_aura = secrets_path.join("aura.sr25519.key.json"); + if !key_aura.exists() { + let output = foo::key_generate().output().unwrap(); + std::fs::write(&key_aura, &output.stdout).unwrap(); + } + + let mnemonic = { + let val: serde_json::Value = + serde_json::from_reader(File::open(key_aura).unwrap()).unwrap(); + val.get("secretPhrase").unwrap().as_str().unwrap().to_string() + }; + + let key_gran = secrets_path.join("gran.ed25519.key.json"); + if !key_gran.exists() { + let output = foo::key_inspect_cmd(&mnemonic).output().unwrap(); + std::fs::write(&key_gran, &output.stdout).unwrap(); + } + + let _key_insert_aura = foo::key_insert_cmd(&base_path, &chain_path, &mnemonic, "aura") + .spawn() + .unwrap() + .wait(); + let _key_insert_gran = foo::key_insert_cmd(&base_path, &chain_path, &mnemonic, "gran") + .spawn() + .unwrap() + .wait(); + + let bootnodes = (!r.bootnodes.is_empty()).then_some(r.bootnodes); + let run = foo::run_node( + &base_path, + &chain_path, + r.port.unwrap_or(30333), + r.rpc_port.unwrap_or(9944), + r.validator, + bootnodes, + ) + .spawn() + .unwrap() + .wait(); + }, + } +} + +mod foo { + use std::{ffi::OsStr, process::Command}; + + pub fn base_node_run_cmd() -> Command { + let mut cmd = Command::new("cargo"); + cmd.args(&["run", "--release", "--package", "node-subspace", "--"]); + cmd + } + + pub fn build_chain_spec(chain_spec: &str) -> Command { + let mut cmd = base_node_run_cmd(); + cmd.args(&["build-spec", "--raw"]) + .args(&["--chain", chain_spec]) + .arg("--disable-default-bootnode"); + cmd + } + + pub fn key_generate() -> Command { + let mut cmd = base_node_run_cmd(); + cmd.args(&["key", "generate"]) + .args(&["--scheme", "sr25519"]) + .args(&["--output-type", "json"]); + cmd + } + + pub fn key_insert_cmd( + base_path: &dyn AsRef, + chain_spec: &dyn AsRef, + mnemonic: &str, + key_type: &str, + ) -> Command { + let mut cmd = base_node_run_cmd(); + cmd.args(&["key", "insert"]) + .args(&[&"--base-path" as &(dyn AsRef<_>), base_path]) + .args(&[&"--chain" as &(dyn AsRef<_>), chain_spec]) + .args(&[ + "--scheme", + match key_type { + "aura" => "sr25519", + "gran" => "sr25519", + _ => panic!(), + }, + ]) + .args(&["--suri", &mnemonic]) + .args(&["--key-type", key_type]); + cmd + } + + pub fn key_inspect_cmd(mnemonic: &str) -> Command { + let mut cmd = base_node_run_cmd(); + cmd.args(&["key", "inspect"]) + .args(&["--scheme", "sr25519"]) + .args(&["--output-type", "json"]) + .arg(mnemonic); + cmd + } + + pub fn run_node( + base_path: &dyn AsRef, + chain_spec: &dyn AsRef, + port: u16, + rpc_port: u16, + is_validator: bool, + bootnodes: Option>, + ) -> Command { + let mut cmd = base_node_run_cmd(); + + cmd.args(&[&"--base-path" as &(dyn AsRef<_>), base_path]) + .args(&[&"--chain" as &(dyn AsRef<_>), chain_spec]) + .args(&["--unsafe-rpc-external", "--rpc-cors", "all"]) + .args(&["--port", &port.to_string(), "--rpc-port", &rpc_port.to_string()]); + + if is_validator { + cmd.arg("--validator"); + } + + if let Some(bootnodes) = bootnodes { + cmd.arg("--bootnodes").args(&bootnodes); + } + + cmd + } +}