From 5f60e9a75194737bb7a5331bd6b7cf4c3ad4e4c2 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 4 Mar 2024 11:41:38 +0530 Subject: [PATCH 01/57] init: Pallet-engine --- Cargo.lock | 49 + Cargo.toml | 8 +- src/commands/add/mod.rs | 58 ++ src/commands/mod.rs | 1 + src/engines/pallet_engine/mod.rs | 341 +++++++ src/engines/pallet_engine/pallet_entry.rs | 42 + src/engines/pallet_engine/parser.rs | 959 ++++++++++++++++++ .../template.rs} | 19 +- src/main.rs | 25 +- 9 files changed, 1486 insertions(+), 16 deletions(-) create mode 100644 src/commands/add/mod.rs create mode 100644 src/engines/pallet_engine/mod.rs create mode 100644 src/engines/pallet_engine/pallet_entry.rs create mode 100644 src/engines/pallet_engine/parser.rs rename src/engines/{pallet_engine.rs => pallet_engine/template.rs} (81%) diff --git a/Cargo.lock b/Cargo.lock index 12214068..f608434d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -845,6 +845,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cfg-expr" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -2097,6 +2106,30 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-support-procedural-tools" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ac1266522a8c9a2d2d26d205ec3028b88582d5f3cd5cbc75d0ec8271d197b7" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c078db2242ea7265faa486004e7fd8daaf1a577cfcac0070ce55d926922883" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "from_variant" version = "0.1.6" @@ -4233,20 +4266,26 @@ version = "0.1.0" dependencies = [ "anyhow", "askama", + "cfg-expr", "clap", "cliclack", "console", "dirs", "duct", + "frame-support-procedural-tools", "git2", "indexmap 2.2.4", "log", + "prettyplease", + "proc-macro2", + "quote", "reqwest", "serde", "serde_json", "strum 0.26.1", "strum_macros 0.26.1", "symlink", + "syn 2.0.52", "tempdir", "tempfile", "tokio", @@ -4270,6 +4309,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn 2.0.52", +] + [[package]] name = "primeorder" version = "0.13.6" diff --git a/Cargo.toml b/Cargo.toml index 509ec347..3755b052 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,12 @@ strum_macros = "0.26" tempfile = "3.8" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } walkdir = "2.4" +frame-support-procedural-tools = "9.0.0" +proc-macro2 = { version = "1.0.70", features = ["span-locations"] } +quote = "1.0.33" +syn = { version = "2.0.39", features = ["full"] } +cfg-expr = "0.15.5" +prettyplease = "0.2.15" # contracts @@ -56,4 +62,4 @@ parachain = [ "dep:url", "dep:zombienet-sdk", "dep:zombienet-support" -] \ No newline at end of file +] diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs new file mode 100644 index 00000000..e463ed52 --- /dev/null +++ b/src/commands/add/mod.rs @@ -0,0 +1,58 @@ +use std::path::PathBuf; + +use clap::{Args, Subcommand}; + +use crate::engines::pallet_engine::TemplatePalletConfig; + +#[derive(Args)] +#[command(args_conflicts_with_subcommands = true)] +pub(crate) struct AddArgs { + #[command(subcommand)] + /// Pallet to add to the runtime + pub(crate) pallet: AddPallet, + #[arg(global = true, short)] + /// Runtime path; + /// Cargo Manifest path will be inferred as `../Cargo.toml` + pub(crate) runtime: Option, +} + +#[derive(Subcommand)] +#[command(subcommand_required = true)] +pub(crate) enum AddPallet { + /// Insert `pallet-template` into the runtime. Useful for quick start pallet-template dev + Template(TemplatePalletConfig), + /// Insert a frame-pallet into the runtime. + Frame(FrameArgs), +} + +#[derive(Args)] +pub(crate) struct FrameArgs { + #[arg(short, long)] + pub(crate) name: String, +} + +impl AddArgs { + pub(crate) fn execute(&self) -> anyhow::Result<()> { + let runtime_path = match self.runtime { + Some(ref s) => PathBuf::from(s), + None => { + // TODO: Fetch runtime either from cache + // Fix: This is a placeholder path, should not be used + PathBuf::from("my-app/runtime/src/lib.rs") + } + }; + let pallet = match self.pallet { + AddPallet::Template(TemplatePalletConfig { + ref name, + ref authors, + ref description, + }) => format!( + "Template with name: {name}, authors: {authors:?}, description: {description:?}" + ), + AddPallet::Frame(FrameArgs { ref name }) => format!("p-frame-{name}"), + }; + crate::engines::pallet_engine::execute(self.pallet.clone(), runtime_path)?; + println!("Added {}\n-> to {}", pallet, runtime_path.display()); + Ok(()) + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a301bb8e..4592d7d8 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,2 +1,3 @@ pub(crate) mod new; pub(crate) mod up; +pub(crate) mod add; diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs new file mode 100644 index 00000000..8f1a0f4e --- /dev/null +++ b/src/engines/pallet_engine/mod.rs @@ -0,0 +1,341 @@ +#![allow(unused)] +//! Pallet Engine - A set of tools to add pallets to your runtime +//! To add a pallet one usually needs to consider a few pieces of information together: +//! +//! 1. How is the pallet going to be configured? (impl pallet::Config for Runtime) +//! 2. How is the runtime instantiated in the current input source? (i.e. what kind of runtime declaration are we working with?) +//! 3. Are there benchmarks for the current pallet that would need to be included in the runtime and subsequently the runtime manifest? (including entries for list_benchmarks!) +//! +//! These are some necessary questions, but not an exhaustive list. One might further have to answer the following: +//! 1. Does adding this pallet exceed the total number of pallets > 255? +//! 2. Does the computed pallet index overflow the u8 bound? (gaps in explicit pallet index declarations) +//! 3. Is the pallet already in the runtime? If yes, do we add a second instance or abort? +//! 4. Does this pallet require a genesis configuration? +//! +//! It is the goal of this module, to answer all of these questions. + +mod pallet_entry; +mod parser; +mod template; + +use anyhow::{anyhow, bail, Context}; +use pallet_entry::Numbers; +use parser::RuntimeDeclaration; +use proc_macro2::TokenStream; +use std::{ + collections::HashMap, + fs::{self, File, OpenOptions}, + io::{BufRead, BufReader, Write}, + path::{Path, PathBuf}, +}; +use syn::{spanned::Spanned, ItemMacro}; +pub use template::{create_pallet_template, TemplatePalletConfig}; + +use pallet_entry::{AddPalletEntry, ReadPalletEntry}; + + +/// The main entry point into the engine. +pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { + Ok(()) +} + + +/// The Pallet Engine has two Paths `input` and `output`. +/// During processing, we want to keep the input source and the output source separate as +/// to have assurance that our references into the `input` file are still valid during construction of `output`. +/// Once fully processed, `output` can simply overwrite `input` +pub struct PalletEngine { + /// Input source to PalletEngine - This will be the path to the runtime/src/lib.rs + /// In code, this is never touched directly until the final step where it's overwritten + /// Interim, it's treated as immutable data + input: PathBuf, + /// Stores the details of the runtime pallets built from input + details: PalletDetails, + /// This stores the path to the runtime file being processed + /// User must have read/write permissions for potentially destructive editing + /// All insertions are ultimately written here + output: PathBuf, + // /// This stores the path to the runtime manifest file runtime/Cargo.toml + // manifest: PathBuf, +} + +/// PalletDetails is data generated after parsing of a given `input` runtime file +/// This will make observations as to which pallets are there, if there are instances of the pallets +/// among details such as the span of the construct_runtime! macro, the type of runtime declaration etc. +struct PalletDetails { + /// Number of pallets in the runtime, changes based on pallets added to output + pallets: Vec, + /// construct_runtime! macro span start location. Any pallet that's being added + /// should search, uptil this point to make sure existing pallets do not conflict + crt_start: usize, + /// construct_runtime! macro span end location. + /// construct_runtime! macro span end location. + /// For changes that happen after construct_runtime! is edited + crt_end: usize, + /// Total number of lines in input. Useful for inserting lines. + file_end: usize, + /// Type of runtime declaration being processed + declaration: RuntimeDeclaration, +} +// Public API +impl PalletEngine { + /// Query the output path + pub fn output(&self) -> &Path { + &self.output + } + /// Create a new PalletEngine + pub fn new(input: PathBuf) -> anyhow::Result { + let tmp_dir = tempfile::TempDir::new()?; + let output : PathBuf = tmp_dir.path().join("lib.rs"); + // Open the file specified in `output`. If non-empty, delete its contents. + if output.exists() && output.is_file() { + std::fs::remove_file(output.as_path())?; + } + File::create(output.as_path()).context(format!( + "Failed to create PalletEngine with output: {}", + output.display() + ))?; + // Build Pallet Details + let __buf = BufReader::new(File::open(&input)?); + let file_end = __buf.lines().count(); + let rt = fs::read_to_string(&input)?; + let ast: syn::File = syn::parse_file(rt.as_ref())?; + let mut details = Option::::None; + for item in ast.items.iter() { + match item { + syn::Item::Macro(ItemMacro { mac, .. }) => { + if let Some(mac_id) = mac.path.get_ident() { + if mac_id == "construct_runtime" { + let (crt_start, crt_end) = + (item.span().start().line, item.span().end().line); + let declaration = + mac.parse_body::().map_err(|e| { + anyhow!("Cannot parse construct_runtime from input").context(e) + })?; + let pallets = Self::build_pallet_details(&declaration)?; + details = Some(PalletDetails { + pallets, + crt_start, + crt_end, + file_end, + declaration, + }); + } + } + } + _ => {} + }; + } + let Some(details) = details else { + bail!("No pallets/construct_runtime! found in input"); + }; + Ok(Self { + input, + output, + details, + }) + } + /// Helper for PalletEngine::new, Builds pallet details from the construct_runtime! macro + fn build_pallet_details( + declaration: &RuntimeDeclaration, + ) -> anyhow::Result> { + // Instance map to track the number of current instances for a pallet entry + let mut imap: HashMap = HashMap::new(); + let mut pe: HashMap = HashMap::new(); + let pallet_entries = match declaration { + RuntimeDeclaration::Implicit(i) => { + for pallet in i.pallets.iter() { + let entry: String = pallet.span.source_text().unwrap(); + let entry = entry.split(':').next().unwrap().to_string(); + let index = pallet.index; + if pallet.instance.is_some() { + // If using instance syntax i.e. pallet:: set instance to 1 + imap.entry(entry.clone()) + .and_modify(|e| *e += 1) + .or_insert(1); + }; + pe.entry(entry.clone()) + .and_modify(|e| { + let v = imap.get(&entry).unwrap_or(&0); + e.numbers.instance = *v; + }) + .or_insert(ReadPalletEntry { + entry: entry.to_string(), + numbers: Numbers { index, instance: 0 }, + }); + } + pe.into_iter().map(|e| e.1).collect() + } + RuntimeDeclaration::Explicit(e) | RuntimeDeclaration::ExplicitExpanded(e) => { + for pallet in e.pallets.iter() { + let entry: String = pallet.span.source_text().unwrap(); + let entry = entry.split(':').next().unwrap().to_string(); + let index = Some(pallet.index); + if pallet.instance.is_some() { + // If using instance syntax i.e. pallet:: set instance to 1 + imap.entry(entry.clone()) + .and_modify(|e| *e += 1) + .or_insert(1); + }; + pe.entry(entry.clone()) + .and_modify(|e| { + let v = imap.get(&entry).unwrap_or(&0); + e.numbers.instance = *v; + }) + .or_insert(ReadPalletEntry { + entry: entry.to_string(), + numbers: Numbers { index, instance: 0 }, + }); + } + pe.into_iter().map(|e| e.1).collect() + } + }; + Ok(pallet_entries) + } +} + +// Private methods for internal use. +impl PalletEngine { + /// Add `n` line-breaks to output + fn add_new_line(&self, n: usize) -> anyhow::Result<()> { + let mut file = OpenOptions::new().append(true).open(&self.output)?; + let newlines: String = std::iter::repeat('\n').take(n).collect(); + Ok(file.write_all(format!("{newlines}").as_bytes())?) + } + /// Append raw tokens to `output` file + fn append_tokens(&self, tokens: TokenStream) -> anyhow::Result<()> { + let content = prettyplease::unparse(&syn::parse_file(&tokens.to_string())?); + let mut file = OpenOptions::new().append(true).open(&self.output)?; + file.write_all(content.as_bytes())?; + Ok(()) + } + /// Append string as is to `output` file + fn append_str(&self, content: String) -> anyhow::Result<()> { + let mut file = OpenOptions::new().append(true).open(&self.output)?; + file.write_all(content.as_bytes())?; + Ok(()) + } + /// Append lines [start..end] from `input` source to `output`. + /// Typically used to scaffold the `output` before and after making changes + fn append_lines_from(&self, start: usize, end: usize) -> anyhow::Result<()> { + let file = File::open(self.input.as_path())?; + let reader = BufReader::new(file); + // Assuming a worst case of 150 chars per line which is almost never the case in a typical substrate runtime file + // In the kitchensink node the maximum line length is 138 chars wide + let mut snip = String::with_capacity(150 * (end - start)); + let mut current_line = 0; + + for line in reader.lines() { + current_line += 1; + + if current_line < start { + // Skip lines until start + continue; + } else if current_line > end { + // Stop reading after end + break; + } + + snip.push_str(&line?); + snip.push('\n'); + } + let mut file = OpenOptions::new().append(true).open(&self.output)?; + file.write_all(snip.as_bytes())?; + Ok(()) + } + /// Insert string at line. Errors if line number doesn't exist in `output` + fn insert_at(&self, line: usize, str: &str) -> anyhow::Result<()> { + let reader = BufReader::new(File::open(&self.output)?); + let mut temp_file = tempfile::NamedTempFile::new()?; + let temp_path = &temp_file.path().to_path_buf(); + let mut written = false; + for (idx, l) in reader.lines().enumerate() { + if idx == line { + writeln!(temp_file, "{str}")?; + written = true; + } + writeln!(temp_file, "{}", l?)?; + } + fs::rename(temp_path, &self.output)?; + if !written { + bail!("PalletEngine output doesn't have line {line} to insert at"); + } + Ok(()) + } + /// Insert raw string at construct_runtime! Fails if there's no construct_runtime! in `output` + /// By default inserts at the end of the macro + fn insert_str_runtime(&self, str: &str) -> anyhow::Result<()> { + let runtime_contents = fs::read_to_string(&self.output)?; + let ast: syn::File = syn::parse_file(runtime_contents.as_ref())?; + let mut runtime_found = false; + for item in ast.items.iter() { + match item { + syn::Item::Macro(syn::ItemMacro { mac, .. }) => { + if let Some(mac_id) = mac.path.get_ident() { + if mac_id == "construct_runtime" { + runtime_found = true; + let r: RuntimeDeclaration = mac.parse_body().map_err(|err| { + anyhow!("PalletEngine output is in not parseable").context(err) + })?; + match r { + RuntimeDeclaration::Implicit(i) => { + let ultimate = i + .pallets + .last() + // This may be handled in the case that there's no pallets in CRT to begin with + // And subsequent pallets will be added + .expect("Fatal: No pallets defined in construct_runtime!") + .clone(); + let end = ultimate.span.end().line; + self.insert_at(end, str)?; + } + RuntimeDeclaration::Explicit(e) + | RuntimeDeclaration::ExplicitExpanded(e) => { + let end = e + .pallets + .last() + .expect("Fatal: No pallets defined in construct_runtime!") + .span + .end() + .line; + self.insert_at(end, str)?; + } + } + } + } + } + _ => {} + } + } + if !runtime_found { + // Should never happen + panic!("Construct Runtime not found in PalletEngine output. Cannot add pallet"); + } + Ok(()) + } + /// Add a new pallet to RuntimeDeclaration and return it. + /// Used to pass a typed AddPallet struct to modify the RuntimeDeclaration + fn add_pallet_runtime(&mut self, new_pallet: AddPalletEntry) -> anyhow::Result<()> { + match &mut self.details.declaration { + RuntimeDeclaration::Implicit(i) => { + let mut ultimate = i + .pallets + .last() + .expect("Fatal: No pallets defined in construct_runtime!") + .clone(); + ultimate.index = new_pallet.index; + ultimate.path.inner.segments[0].ident = new_pallet.path; + ultimate.name = new_pallet.name; + // println!("Ultimate pallet: {:?}", ultimate); + i.pallets.push(ultimate); + Ok(()) + } + RuntimeDeclaration::Explicit(e) => { + todo!() + } + RuntimeDeclaration::ExplicitExpanded(e) => { + todo!() + } + } + } +} diff --git a/src/engines/pallet_engine/pallet_entry.rs b/src/engines/pallet_engine/pallet_entry.rs new file mode 100644 index 00000000..f3af4589 --- /dev/null +++ b/src/engines/pallet_engine/pallet_entry.rs @@ -0,0 +1,42 @@ +#![allow(unused)] +use syn::Ident; + +/// Format containing necessary information for appending pallets +pub(super) struct AddPalletEntry { + pub(super) index: Option, + pub(super) path: Ident, + pub(super) name: Ident, +} +impl AddPalletEntry { + fn new(index: Option, path: &str, name: &str) -> Self { + let path = Ident::new(path, proc_macro2::Span::call_site()); + let name = Ident::new(name, proc_macro2::Span::call_site()); + Self { index, path, name } + } +} + +impl From for AddPalletEntry { + fn from(value: ReadPalletEntry) -> Self { + todo!("") + } +} + + +/// All information that's needed to represent a pallet in a construct_runtime! invocation +/// The processing must be based on the context i.e. the type of RuntimeDeclaration in the runtime +pub(super) struct ReadPalletEntry { + /// Pallet identifier. "System" in `System: frame_system = 1` + pub(super) entry: String, + /// Stores a tuple of information (index, instance). For single instances, instance = 0 + pub(super) numbers: Numbers, +} +#[derive(Default, Debug)] +pub(super) struct Numbers { + /// Stores the first index as parsed from input file + pub(super) index: Option, + /// Counts the number of instances in runtime file + /// 0 means only 1 unique instance was found + /// 1 means the pallet is using instance syntax pallet:: + /// >1 means multiple pallet instances were found + pub(super) instance: u8, +} \ No newline at end of file diff --git a/src/engines/pallet_engine/parser.rs b/src/engines/pallet_engine/parser.rs new file mode 100644 index 00000000..7c57ada4 --- /dev/null +++ b/src/engines/pallet_engine/parser.rs @@ -0,0 +1,959 @@ +#![allow(unused)] +// This file is part of Substrate modified to fit pallet manipulation needs for pop-cli + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use frame_support_procedural_tools::syn_ext as ext; +use proc_macro2::{Delimiter, Group, Punct, Spacing, Span, TokenStream}; +use quote::{quote, ToTokens, TokenStreamExt}; +use std::{ + collections::{HashMap, HashSet}, + str::FromStr, +}; +use syn::{ + ext::IdentExt, + parse::{Parse, ParseStream}, + parse_quote, + punctuated::Punctuated, + spanned::Spanned, + token, Attribute, Error, Ident, Path, Result, Token, +}; +/// Span for delimiting tokens. +macro_rules! bs_delim_span { + ($d:ident) => { + proc_macro2::Group::new(proc_macro2::Delimiter::$d, proc_macro2::TokenStream::new()) + .delim_span() + }; + ($d:ident, $group:tt) => { + proc_macro2::Group::new(proc_macro2::Delimiter::$d, $group).delim_span() + }; +} +/// Tokens that delimit a group +macro_rules! delim_token { + (Parenthesis, $group:tt) => { + syn::token::Paren { + span: bs_delim_span!(Parenthesis, $group), + } + }; + ($d:ident) => { + syn::token::$d { + span: bs_delim_span!($d), + } + }; + ($d:ident, $group:tt) => { + syn::token::$d { + span: bs_delim_span!($d, $group), + } + }; +} +mod keyword { + syn::custom_keyword!(Block); + syn::custom_keyword!(NodeBlock); + syn::custom_keyword!(UncheckedExtrinsic); + syn::custom_keyword!(Pallet); + syn::custom_keyword!(Call); + syn::custom_keyword!(Storage); + syn::custom_keyword!(Event); + syn::custom_keyword!(Error); + syn::custom_keyword!(Config); + syn::custom_keyword!(Origin); + syn::custom_keyword!(Inherent); + syn::custom_keyword!(ValidateUnsigned); + syn::custom_keyword!(FreezeReason); + syn::custom_keyword!(HoldReason); + syn::custom_keyword!(LockId); + syn::custom_keyword!(SlashReason); + syn::custom_keyword!(exclude_parts); + syn::custom_keyword!(use_parts); + syn::custom_keyword!(expanded); +} + +/// Declaration of a runtime. +/// +/// Pallet declare their part either explicitly or implicitly (using no part declaration) +/// If all pallet have explicit parts then the runtime declaration is explicit, otherwise it is +/// implicit. +#[derive(Debug)] +pub enum RuntimeDeclaration { + Implicit(ImplicitRuntimeDeclaration), + Explicit(ExplicitRuntimeDeclaration), + ExplicitExpanded(ExplicitRuntimeDeclaration), +} + +impl ToTokens for RuntimeDeclaration { + fn to_tokens(&self, tokens: &mut TokenStream) { + let group = match self { + RuntimeDeclaration::Implicit(i) => i.to_token_stream(), + RuntimeDeclaration::Explicit(_) | RuntimeDeclaration::ExplicitExpanded(_) => { + unimplemented!() + } + }; + let crt = syn::Macro { + path: parse_quote!(construct_runtime), + bang_token: Token![!](Span::call_site()), + tokens: group.clone(), + delimiter: syn::MacroDelimiter::Paren(delim_token!(Parenthesis, group)), + }; + tokens.extend(crt.into_token_stream()); + } +} + +/// Declaration of a runtime with some pallet with implicit declaration of parts. +#[derive(Debug)] +pub struct ImplicitRuntimeDeclaration { + pub name: Ident, + pub where_section: Option, + pub pallets: Vec, +} +impl ToTokens for ImplicitRuntimeDeclaration { + fn to_tokens(&self, tokens: &mut TokenStream) { + let (name, where_section) = (&self.name, &self.where_section); + tokens.extend(quote!( + pub struct #name #where_section)); + let mut pallets = TokenStream::new(); + for p in &self.pallets { + pallets.extend(p.to_token_stream()); + } + tokens.append(Group::new(Delimiter::Brace, pallets)); + } +} + +/// Declaration of a runtime with all pallet having explicit declaration of parts. +#[derive(Debug)] +pub struct ExplicitRuntimeDeclaration { + pub name: Ident, + pub where_section: Option, + pub pallets: Vec, + pub pallets_token: token::Brace, +} + +impl Parse for RuntimeDeclaration { + fn parse(input: ParseStream) -> Result { + input.parse::()?; + + // Support either `enum` or `struct`. + if input.peek(Token![struct]) { + input.parse::()?; + } else { + input.parse::()?; + } + + let name = input.parse::()?; + let where_section = if input.peek(token::Where) { + Some(input.parse()?) + } else { + None + }; + let pallets = + input.parse::>>()?; + let pallets_token = pallets.token; + + match convert_pallets(pallets.content.inner.into_iter().collect())? { + PalletsConversion::Implicit(pallets) => { + Ok(RuntimeDeclaration::Implicit(ImplicitRuntimeDeclaration { + name, + where_section, + pallets, + })) + } + PalletsConversion::Explicit(pallets) => { + Ok(RuntimeDeclaration::Explicit(ExplicitRuntimeDeclaration { + name, + where_section, + pallets, + pallets_token, + })) + } + PalletsConversion::ExplicitExpanded(pallets) => Ok( + RuntimeDeclaration::ExplicitExpanded(ExplicitRuntimeDeclaration { + name, + where_section, + pallets, + pallets_token, + }), + ), + } + } +} + +#[derive(Debug)] +pub struct WhereSection { + pub span: Span, + pub block: syn::TypePath, + pub node_block: syn::TypePath, + pub unchecked_extrinsic: syn::TypePath, +} + +impl ToTokens for WhereSection { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(quote!()); + } +} + +impl Parse for WhereSection { + fn parse(input: ParseStream) -> Result { + input.parse::()?; + + let mut definitions = Vec::new(); + while !input.peek(token::Brace) { + let definition: WhereDefinition = input.parse()?; + definitions.push(definition); + if !input.peek(Token![,]) { + if !input.peek(token::Brace) { + return Err(input.error("Expected `,` or `{`")); + } + break; + } + input.parse::()?; + } + let block = remove_kind(input, WhereKind::Block, &mut definitions)?.value; + let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value; + let unchecked_extrinsic = + remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value; + if let Some(WhereDefinition { + ref kind_span, + ref kind, + .. + }) = definitions.first() + { + let msg = format!( + "`{:?}` was declared above. Please use exactly one declaration for `{:?}`.", + kind, kind + ); + return Err(Error::new(*kind_span, msg)); + } + Ok(Self { + span: input.span(), + block, + node_block, + unchecked_extrinsic, + }) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum WhereKind { + Block, + NodeBlock, + UncheckedExtrinsic, +} + +#[derive(Debug)] +pub struct WhereDefinition { + pub kind_span: Span, + pub kind: WhereKind, + pub value: syn::TypePath, +} + +impl Parse for WhereDefinition { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + let (kind_span, kind) = if lookahead.peek(keyword::Block) { + (input.parse::()?.span(), WhereKind::Block) + } else if lookahead.peek(keyword::NodeBlock) { + ( + input.parse::()?.span(), + WhereKind::NodeBlock, + ) + } else if lookahead.peek(keyword::UncheckedExtrinsic) { + ( + input.parse::()?.span(), + WhereKind::UncheckedExtrinsic, + ) + } else { + return Err(lookahead.error()); + }; + + Ok(Self { + kind_span, + kind, + value: { + let _: Token![=] = input.parse()?; + input.parse()? + }, + }) + } +} + +/// The declaration of a pallet. +#[derive(Debug, Clone)] +pub struct PalletDeclaration { + /// Span for current pallet + pub span: Span, + /// Is this pallet fully expanded? + pub is_expanded: bool, + /// The name of the pallet, e.g.`System` in `System: frame_system`. + pub name: Ident, + /// Optional attributes tagged right above a pallet declaration. + pub attrs: Vec, + /// Optional fixed index, e.g. `MyPallet ... = 3,`. + pub index: Option, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. + pub path: PalletPath, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. + pub instance: Option, + /// The declared pallet parts, + /// e.g. `Some([Pallet, Call])` for `System: system::{Pallet, Call}` + /// or `None` for `System: system`. + pub pallet_parts: Option>, + /// The specified parts, either use_parts or exclude_parts. + pub specified_parts: SpecifiedParts, +} + +impl ToTokens for PalletDeclaration { + fn to_tokens(&self, tokens: &mut TokenStream) { + let PalletDeclaration { name, path, .. } = self; + tokens.extend(quote!(#name )); + if let Some(instance) = &self.instance { + tokens.extend(quote!(: #path::<#instance>)); + } else { + tokens.extend(quote!(: #path)) + } + if let Some(idx) = self.index { + let idx = format!(" = {},", idx); + // This means no help from rustfmt + tokens.extend(TokenStream::from_str(&idx)); + // If we want rustfmt we would have to handroll our own solution or forgo indices + // (which is bad and probably not what the developer wants which is to delete code) + // tokens.extend(quote!(,)); + } else { + tokens.append(Punct::new(',', Spacing::Alone)); + } + } +} + +/// The possible declaration of pallet parts to use. +#[derive(Debug, Clone)] +pub enum SpecifiedParts { + /// Use all the pallet parts except those specified. + Exclude(Vec), + /// Use only the specified pallet parts. + Use(Vec), + /// Use the all the pallet parts. + All, +} + +impl Parse for PalletDeclaration { + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let span = input.span(); + let name = input.parse()?; + let _: Token![:] = input.parse()?; + let path = input.parse()?; + + // Parse for instance. + let instance = if input.peek(Token![::]) && input.peek3(Token![<]) { + let _: Token![::] = input.parse()?; + let _: Token![<] = input.parse()?; + let res = Some(input.parse()?); + let _: Token![>] = input.parse()?; + res + } else if !(input.peek(Token![::]) && input.peek3(token::Brace)) + && !input.peek(keyword::expanded) + && !input.peek(keyword::exclude_parts) + && !input.peek(keyword::use_parts) + && !input.peek(Token![=]) + && !input.peek(Token![,]) + && !input.is_empty() + { + return Err(input.error( + "Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,`", + )); + } else { + None + }; + + // Check if the pallet is fully expanded. + let (is_expanded, extra_parts) = if input.peek(keyword::expanded) { + let _: keyword::expanded = input.parse()?; + let _: Token![::] = input.parse()?; + (true, parse_pallet_parts(input)?) + } else { + (false, vec![]) + }; + + // Parse for explicit parts + let pallet_parts = if input.peek(Token![::]) && input.peek3(token::Brace) { + let _: Token![::] = input.parse()?; + let mut parts = parse_pallet_parts(input)?; + parts.extend(extra_parts.into_iter()); + Some(parts) + } else if !input.peek(keyword::exclude_parts) + && !input.peek(keyword::use_parts) + && !input.peek(Token![=]) + && !input.peek(Token![,]) + && !input.is_empty() + { + return Err(input.error( + "Unexpected tokens, expected one of `::{`, `exclude_parts`, `use_parts`, `=`, `,`", + )); + } else { + is_expanded.then_some(extra_parts) + }; + + // Parse for specified parts + let specified_parts = if input.peek(keyword::exclude_parts) { + let _: keyword::exclude_parts = input.parse()?; + SpecifiedParts::Exclude(parse_pallet_parts_no_generic(input)?) + } else if input.peek(keyword::use_parts) { + let _: keyword::use_parts = input.parse()?; + SpecifiedParts::Use(parse_pallet_parts_no_generic(input)?) + } else if !input.peek(Token![=]) && !input.peek(Token![,]) && !input.is_empty() { + return Err(input.error("Unexpected tokens, expected one of `exclude_parts`, `=`, `,`")); + } else { + SpecifiedParts::All + }; + + // Parse for pallet index + let index = if input.peek(Token![=]) { + input.parse::()?; + let index = input.parse::()?; + let index = index.base10_parse::()?; + Some(index) + } else if !input.peek(Token![,]) && !input.is_empty() { + return Err(input.error("Unexpected tokens, expected one of `=`, `,`")); + } else { + None + }; + + Ok(Self { + span, + is_expanded, + attrs, + name, + path, + instance, + pallet_parts, + specified_parts, + index, + }) + } +} + +/// A struct representing a path to a pallet. `PalletPath` is almost identical to the standard +/// Rust path with a few restrictions: +/// - No leading colons allowed +/// - Path segments can only consist of identifers separated by colons +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PalletPath { + pub inner: Path, +} + +impl PalletPath { + pub fn module_name(&self) -> String { + self.inner + .segments + .iter() + .fold(String::new(), |mut acc, segment| { + if !acc.is_empty() { + acc.push_str("::"); + } + acc.push_str(&segment.ident.to_string()); + acc + }) + } +} + +impl Parse for PalletPath { + fn parse(input: ParseStream) -> Result { + let mut res = PalletPath { + inner: Path { + leading_colon: None, + segments: Punctuated::new(), + }, + }; + + let lookahead = input.lookahead1(); + if lookahead.peek(Token![crate]) + || lookahead.peek(Token![self]) + || lookahead.peek(Token![super]) + || lookahead.peek(Ident) + { + let ident = input.call(Ident::parse_any)?; + res.inner.segments.push(ident.into()); + } else { + return Err(lookahead.error()); + } + + while input.peek(Token![::]) && input.peek3(Ident) { + input.parse::()?; + let ident = input.parse::()?; + res.inner.segments.push(ident.into()); + } + Ok(res) + } +} + +impl quote::ToTokens for PalletPath { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.inner.to_tokens(tokens); + } +} + +/// Parse [`PalletPart`]'s from a braces enclosed list that is split by commas, e.g. +/// +/// `{ Call, Event }` +fn parse_pallet_parts(input: ParseStream) -> Result> { + let pallet_parts: ext::Braces> = input.parse()?; + + let mut resolved = HashSet::new(); + for part in pallet_parts.content.inner.iter() { + if !resolved.insert(part.name()) { + let msg = format!( + "`{}` was already declared before. Please remove the duplicate declaration", + part.name(), + ); + return Err(Error::new(part.keyword.span(), msg)); + } + } + + Ok(pallet_parts.content.inner.into_iter().collect()) +} + +#[derive(Debug, Clone)] +pub enum PalletPartKeyword { + Pallet(keyword::Pallet), + Call(keyword::Call), + Storage(keyword::Storage), + Event(keyword::Event), + Error(keyword::Error), + Config(keyword::Config), + Origin(keyword::Origin), + Inherent(keyword::Inherent), + ValidateUnsigned(keyword::ValidateUnsigned), + FreezeReason(keyword::FreezeReason), + HoldReason(keyword::HoldReason), + LockId(keyword::LockId), + SlashReason(keyword::SlashReason), +} + +impl Parse for PalletPartKeyword { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + + if lookahead.peek(keyword::Pallet) { + Ok(Self::Pallet(input.parse()?)) + } else if lookahead.peek(keyword::Call) { + Ok(Self::Call(input.parse()?)) + } else if lookahead.peek(keyword::Storage) { + Ok(Self::Storage(input.parse()?)) + } else if lookahead.peek(keyword::Event) { + Ok(Self::Event(input.parse()?)) + } else if lookahead.peek(keyword::Error) { + Ok(Self::Error(input.parse()?)) + } else if lookahead.peek(keyword::Config) { + Ok(Self::Config(input.parse()?)) + } else if lookahead.peek(keyword::Origin) { + Ok(Self::Origin(input.parse()?)) + } else if lookahead.peek(keyword::Inherent) { + Ok(Self::Inherent(input.parse()?)) + } else if lookahead.peek(keyword::ValidateUnsigned) { + Ok(Self::ValidateUnsigned(input.parse()?)) + } else if lookahead.peek(keyword::FreezeReason) { + Ok(Self::FreezeReason(input.parse()?)) + } else if lookahead.peek(keyword::HoldReason) { + Ok(Self::HoldReason(input.parse()?)) + } else if lookahead.peek(keyword::LockId) { + Ok(Self::LockId(input.parse()?)) + } else if lookahead.peek(keyword::SlashReason) { + Ok(Self::SlashReason(input.parse()?)) + } else { + Err(lookahead.error()) + } + } +} + +impl PalletPartKeyword { + /// Returns the name of `Self`. + fn name(&self) -> &'static str { + match self { + Self::Pallet(_) => "Pallet", + Self::Call(_) => "Call", + Self::Storage(_) => "Storage", + Self::Event(_) => "Event", + Self::Error(_) => "Error", + Self::Config(_) => "Config", + Self::Origin(_) => "Origin", + Self::Inherent(_) => "Inherent", + Self::ValidateUnsigned(_) => "ValidateUnsigned", + Self::FreezeReason(_) => "FreezeReason", + Self::HoldReason(_) => "HoldReason", + Self::LockId(_) => "LockId", + Self::SlashReason(_) => "SlashReason", + } + } + + /// Returns `true` if this pallet part is allowed to have generic arguments. + fn allows_generic(&self) -> bool { + Self::all_generic_arg().iter().any(|n| *n == self.name()) + } + + /// Returns the names of all pallet parts that allow to have a generic argument. + fn all_generic_arg() -> &'static [&'static str] { + &["Event", "Error", "Origin", "Config"] + } +} + +impl ToTokens for PalletPartKeyword { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Self::Pallet(inner) => inner.to_tokens(tokens), + Self::Call(inner) => inner.to_tokens(tokens), + Self::Storage(inner) => inner.to_tokens(tokens), + Self::Event(inner) => inner.to_tokens(tokens), + Self::Error(inner) => inner.to_tokens(tokens), + Self::Config(inner) => inner.to_tokens(tokens), + Self::Origin(inner) => inner.to_tokens(tokens), + Self::Inherent(inner) => inner.to_tokens(tokens), + Self::ValidateUnsigned(inner) => inner.to_tokens(tokens), + Self::FreezeReason(inner) => inner.to_tokens(tokens), + Self::HoldReason(inner) => inner.to_tokens(tokens), + Self::LockId(inner) => inner.to_tokens(tokens), + Self::SlashReason(inner) => inner.to_tokens(tokens), + } + } +} + +#[derive(Debug, Clone)] +pub struct PalletPart { + pub keyword: PalletPartKeyword, + pub generics: syn::Generics, +} + +impl Parse for PalletPart { + fn parse(input: ParseStream) -> Result { + let keyword: PalletPartKeyword = input.parse()?; + + let generics: syn::Generics = input.parse()?; + if !generics.params.is_empty() && !keyword.allows_generic() { + let valid_generics = PalletPart::format_names(PalletPartKeyword::all_generic_arg()); + let msg = format!( + "`{}` is not allowed to have generics. \ + Only the following pallets are allowed to have generics: {}.", + keyword.name(), + valid_generics, + ); + return Err(syn::Error::new(keyword.span(), msg)); + } + + Ok(Self { keyword, generics }) + } +} + +impl PalletPart { + pub fn format_names(names: &[&'static str]) -> String { + let res: Vec<_> = names.iter().map(|s| format!("`{}`", s)).collect(); + res.join(", ") + } + + /// The name of this pallet part. + pub fn name(&self) -> &'static str { + self.keyword.name() + } +} + +fn remove_kind( + input: ParseStream, + kind: WhereKind, + definitions: &mut Vec, +) -> Result { + if let Some(pos) = definitions.iter().position(|d| d.kind == kind) { + Ok(definitions.remove(pos)) + } else { + let msg = format!( + "Missing associated type for `{:?}`. Add `{:?}` = ... to where section.", + kind, kind + ); + Err(input.error(msg)) + } +} + +/// The declaration of a part without its generics +#[derive(Debug, Clone)] +pub struct PalletPartNoGeneric { + keyword: PalletPartKeyword, +} + +impl Parse for PalletPartNoGeneric { + fn parse(input: ParseStream) -> Result { + Ok(Self { + keyword: input.parse()?, + }) + } +} + +/// Parse [`PalletPartNoGeneric`]'s from a braces enclosed list that is split by commas, e.g. +/// +/// `{ Call, Event }` +fn parse_pallet_parts_no_generic(input: ParseStream) -> Result> { + let pallet_parts: ext::Braces> = + input.parse()?; + + let mut resolved = HashSet::new(); + for part in pallet_parts.content.inner.iter() { + if !resolved.insert(part.keyword.name()) { + let msg = format!( + "`{}` was already declared before. Please remove the duplicate declaration", + part.keyword.name(), + ); + return Err(Error::new(part.keyword.span(), msg)); + } + } + + Ok(pallet_parts.content.inner.into_iter().collect()) +} + +/// The final definition of a pallet with the resulting fixed index and explicit parts. +#[derive(Debug, Clone)] +pub struct Pallet { + /// Span for current pallet + pub span: Span, + /// Is this pallet fully expanded? + pub is_expanded: bool, + /// The name of the pallet, e.g.`System` in `System: frame_system`. + pub name: Ident, + /// Either automatically infered, or defined (e.g. `MyPallet ... = 3,`). + pub index: u8, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. + pub path: PalletPath, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. + pub instance: Option, + /// The pallet parts to use for the pallet. + pub pallet_parts: Vec, + /// Expressions specified inside of a #[cfg] attribute. + pub cfg_pattern: Vec, +} + +impl Pallet { + /// Get resolved pallet parts + pub fn pallet_parts(&self) -> &[PalletPart] { + &self.pallet_parts + } + + /// Find matching parts + pub fn find_part(&self, name: &str) -> Option<&PalletPart> { + self.pallet_parts.iter().find(|part| part.name() == name) + } + + /// Return whether pallet contains part + pub fn exists_part(&self, name: &str) -> bool { + self.find_part(name).is_some() + } +} + +/// Result of a conversion of a declaration of pallets. +/// +/// # State Transitions +/// +/// ```ignore +/// +----------+ +----------+ +------------------+ +/// | Implicit | -> | Explicit | -> | ExplicitExpanded | +/// +----------+ +----------+ +------------------+ +/// ``` +enum PalletsConversion { + /// Pallets implicitely declare parts. + /// + /// `System: frame_system`. + Implicit(Vec), + /// Pallets explicitly declare parts. + /// + /// `System: frame_system::{Pallet, Call}` + /// + /// However, for backwards compatibility with Polkadot/Kusama + /// we must propagate some other parts to the pallet by default. + Explicit(Vec), + /// Pallets explicitly declare parts that are fully expanded. + /// + /// This is the end state that contains extra parts included by + /// default by Subtrate. + /// + /// `System: frame_system expanded::{Error} ::{Pallet, Call}` + /// + /// For this example, the `Pallet`, `Call` and `Error` parts are collected. + ExplicitExpanded(Vec), +} + +/// Convert from the parsed pallet declaration to their final information. +/// +/// Check if all pallet have explicit declaration of their parts, if so then assign index to each +/// pallet using same rules as rust for fieldless enum. I.e. implicit are assigned number +/// incrementedly from last explicit or 0. +fn convert_pallets(pallets: Vec) -> syn::Result { + if pallets.iter().any(|pallet| pallet.pallet_parts.is_none()) { + return Ok(PalletsConversion::Implicit(pallets)); + } + + let mut indices = HashMap::new(); + let mut last_index: Option = None; + let mut names = HashMap::new(); + let mut is_expanded = true; + + let pallets = pallets + .into_iter() + .map(|pallet| { + let final_index = match pallet.index { + Some(i) => i, + None => last_index + .map_or(Some(0), |i| i.checked_add(1)) + .ok_or_else(|| { + let msg = "Pallet index doesn't fit into u8, index is 256"; + syn::Error::new(pallet.name.span(), msg) + })?, + }; + + last_index = Some(final_index); + + if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) { + let msg = format!( + "Pallet indices are conflicting: Both pallets {} and {} are at index {}", + used_pallet, pallet.name, final_index, + ); + let mut err = syn::Error::new(used_pallet.span(), &msg); + err.combine(syn::Error::new(pallet.name.span(), msg)); + return Err(err); + } + + if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) { + let msg = "Two pallets with the same name!"; + + let mut err = syn::Error::new(used_pallet, &msg); + err.combine(syn::Error::new(pallet.name.span(), &msg)); + return Err(err); + } + + let mut pallet_parts = pallet.pallet_parts.expect("Checked above"); + + let available_parts = pallet_parts + .iter() + .map(|part| part.keyword.name()) + .collect::>(); + + // Check parts are correctly specified + match &pallet.specified_parts { + SpecifiedParts::Exclude(parts) | SpecifiedParts::Use(parts) => { + for part in parts { + if !available_parts.contains(part.keyword.name()) { + let msg = format!( + "Invalid pallet part specified, the pallet `{}` doesn't have the \ + `{}` part. Available parts are: {}.", + pallet.name, + part.keyword.name(), + pallet_parts.iter().fold(String::new(), |fold, part| { + if fold.is_empty() { + format!("`{}`", part.keyword.name()) + } else { + format!("{}, `{}`", fold, part.keyword.name()) + } + }) + ); + return Err(syn::Error::new(part.keyword.span(), msg)); + } + } + } + SpecifiedParts::All => (), + } + + // Set only specified parts. + match pallet.specified_parts { + SpecifiedParts::Exclude(excluded_parts) => pallet_parts.retain(|part| { + !excluded_parts + .iter() + .any(|excluded_part| excluded_part.keyword.name() == part.keyword.name()) + }), + SpecifiedParts::Use(used_parts) => pallet_parts.retain(|part| { + used_parts + .iter() + .any(|use_part| use_part.keyword.name() == part.keyword.name()) + }), + SpecifiedParts::All => (), + } + + let cfg_pattern = pallet + .attrs + .iter() + .map(|attr| { + if attr + .path() + .segments + .first() + .map_or(false, |s| s.ident != "cfg") + { + let msg = "Unsupported attribute, only #[cfg] is supported on pallet \ + declarations in `construct_runtime`"; + return Err(syn::Error::new(attr.span(), msg)); + } + + attr.parse_args_with(|input: syn::parse::ParseStream| { + // Required, otherwise the parse stream doesn't advance and will result in + // an error. + let input = input.parse::()?; + cfg_expr::Expression::parse(&input.to_string()) + .map_err(|e| syn::Error::new(attr.span(), e.to_string())) + }) + }) + .collect::>>()?; + + is_expanded &= pallet.is_expanded; + + Ok(Pallet { + span: pallet.span, + is_expanded: pallet.is_expanded, + name: pallet.name, + index: final_index, + path: pallet.path, + instance: pallet.instance, + cfg_pattern, + pallet_parts, + }) + }) + .collect::>>()?; + + if is_expanded { + Ok(PalletsConversion::ExplicitExpanded(pallets)) + } else { + Ok(PalletsConversion::Explicit(pallets)) + } +} +pub fn check_pallet_number(input: proc_macro2::TokenStream, pallet_num: usize) -> Result<()> { + let max_pallet_num = { + if cfg!(feature = "tuples-96") { + 96 + } else if cfg!(feature = "tuples-128") { + 128 + } else { + 64 + } + }; + + if pallet_num > max_pallet_num { + let no_feature = max_pallet_num == 128; + return Err(syn::Error::new( + input.span(), + format!( + "{} To increase this limit, enable the tuples-{} feature of [frame_support]. {}", + "The number of pallets exceeds the maximum number of tuple elements.", + max_pallet_num + 32, + if no_feature { + "If the feature does not exist - it needs to be implemented." + } else { + "" + }, + ), + )); + } + + Ok(()) +} diff --git a/src/engines/pallet_engine.rs b/src/engines/pallet_engine/template.rs similarity index 81% rename from src/engines/pallet_engine.rs rename to src/engines/pallet_engine/template.rs index e1ceead0..74c75b16 100644 --- a/src/engines/pallet_engine.rs +++ b/src/engines/pallet_engine/template.rs @@ -4,7 +4,12 @@ use crate::{ }; use std::{fs, path::PathBuf}; -pub fn create_pallet_template(path: Option, config: TemplatePalletConfig) -> anyhow::Result<()> { +use super::{pallet_entry::AddPalletEntry, PalletEngine}; + +pub fn create_pallet_template( + path: Option, + config: TemplatePalletConfig, +) -> anyhow::Result<()> { let target = resolve_pallet_path(path); // TODO : config.name might use `-` or use snake_case. We want to use pallet_template for the pallet dirs // and PalletTemplate for the runtime macro @@ -17,12 +22,16 @@ pub fn create_pallet_template(path: Option, config: TemplatePalletConfig render_pallet(pallet_name, config, &pallet_path)?; Ok(()) } +#[derive(clap::Args)] pub struct TemplatePalletConfig { - pub(crate) name: String, - pub(crate) authors: String, - pub(crate) description: String, + #[arg(short, long, default_value_t = String::from("template"))] + pub name: String, + #[arg(short, long, default_value_t = String::from("author"))] + pub authors: String, + #[arg(short, long, default_value_t = String::from("description"))] + pub description: String, } -/// Generate a pallet folder and file structure +/// Generate a pallet folder and file structure fn generate_pallet_structure(target: &PathBuf, pallet_name: &str) -> anyhow::Result<()> { use fs::{create_dir, File}; let (pallet, src) = ( diff --git a/src/main.rs b/src/main.rs index 9358f64f..8563742d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,37 +11,42 @@ mod style; use anyhow::{anyhow, Result}; use clap::{Parser, Subcommand}; +use commands::{new, add, up}; use std::{fs::create_dir_all, path::PathBuf}; #[derive(Parser)] #[command(author, version, about, styles=style::get_styles())] pub struct Cli { #[command(subcommand)] - command: Commands, + branch: Branch, } #[derive(Subcommand)] #[command(subcommand_required = true)] -enum Commands { - New(commands::new::NewArgs), +enum Branch { + /// Create a new parachain or smart contract. + New(new::NewArgs), /// Deploy a parachain or smart contract. - Up(commands::up::UpArgs), + Up(up::UpArgs), + /// Add a pallet into a runtime + Add(add::AddArgs), } #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); - match &cli.command { - Commands::New(args) => match &args.command { + match &cli.branch { + Branch::New(args) => match &args.command { #[cfg(feature = "parachain")] - commands::new::NewCommands::Parachain(cmd) => cmd.execute(), + new::NewCommands::Parachain(cmd) => cmd.execute(), #[cfg(feature = "parachain")] - commands::new::NewCommands::Pallet(cmd) => cmd.execute(), + new::NewCommands::Pallet(cmd) => cmd.execute(), }, - Commands::Up(args) => Ok(match &args.command { + Branch::Up(args) => Ok(match &args.command { #[cfg(feature = "parachain")] - commands::up::UpCommands::Parachain(cmd) => cmd.execute().await?, + up::UpCommands::Parachain(cmd) => cmd.execute().await?, }), + Branch::Add(args) => args.execute(), } } From ee058b3fa116e193e07224cd4208642cd452cf2b Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 6 Mar 2024 14:52:54 +0530 Subject: [PATCH 02/57] tidy --- src/commands/add/mod.rs | 25 ++++++++-------- src/engines/pallet_engine/mod.rs | 12 ++++---- src/engines/pallet_engine/template.rs | 2 +- src/main.rs | 43 +++++++++++++-------------- 4 files changed, 39 insertions(+), 43 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index e463ed52..92a30b01 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -16,18 +16,19 @@ pub(crate) struct AddArgs { pub(crate) runtime: Option, } -#[derive(Subcommand)] +#[derive(Subcommand, Clone)] #[command(subcommand_required = true)] pub(crate) enum AddPallet { - /// Insert `pallet-template` into the runtime. Useful for quick start pallet-template dev - Template(TemplatePalletConfig), + /// Insert `pallet-template` into the runtime. + Template, /// Insert a frame-pallet into the runtime. Frame(FrameArgs), } -#[derive(Args)] +#[derive(Args, Clone)] pub(crate) struct FrameArgs { #[arg(short, long)] + // TODO: Not ready for use pub(crate) name: String, } @@ -42,16 +43,14 @@ impl AddArgs { } }; let pallet = match self.pallet { - AddPallet::Template(TemplatePalletConfig { - ref name, - ref authors, - ref description, - }) => format!( - "Template with name: {name}, authors: {authors:?}, description: {description:?}" - ), - AddPallet::Frame(FrameArgs { ref name }) => format!("p-frame-{name}"), + AddPallet::Template => format!("pallet-template"), + AddPallet::Frame(FrameArgs { ref name }) => { + eprintln!("Sorry, frame pallets cannot be added right now"); + std::process::exit(1); + // format!("FRAME-pallet-{name}") + }, }; - crate::engines::pallet_engine::execute(self.pallet.clone(), runtime_path)?; + crate::engines::pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; println!("Added {}\n-> to {}", pallet, runtime_path.display()); Ok(()) } diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 8f1a0f4e..a582bc6a 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -1,4 +1,3 @@ -#![allow(unused)] //! Pallet Engine - A set of tools to add pallets to your runtime //! To add a pallet one usually needs to consider a few pieces of information together: //! @@ -10,7 +9,7 @@ //! 1. Does adding this pallet exceed the total number of pallets > 255? //! 2. Does the computed pallet index overflow the u8 bound? (gaps in explicit pallet index declarations) //! 3. Is the pallet already in the runtime? If yes, do we add a second instance or abort? -//! 4. Does this pallet require a genesis configuration? +//! 4. Does this pallet require a genesis configuration? //! //! It is the goal of this module, to answer all of these questions. @@ -33,13 +32,14 @@ pub use template::{create_pallet_template, TemplatePalletConfig}; use pallet_entry::{AddPalletEntry, ReadPalletEntry}; - /// The main entry point into the engine. -pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { +pub fn execute( + pallet: crate::commands::add::AddPallet, + runtime_path: PathBuf, +) -> anyhow::Result<()> { Ok(()) } - /// The Pallet Engine has two Paths `input` and `output`. /// During processing, we want to keep the input source and the output source separate as /// to have assurance that our references into the `input` file are still valid during construction of `output`. @@ -86,7 +86,7 @@ impl PalletEngine { /// Create a new PalletEngine pub fn new(input: PathBuf) -> anyhow::Result { let tmp_dir = tempfile::TempDir::new()?; - let output : PathBuf = tmp_dir.path().join("lib.rs"); + let output: PathBuf = tmp_dir.path().join("lib.rs"); // Open the file specified in `output`. If non-empty, delete its contents. if output.exists() && output.is_file() { std::fs::remove_file(output.as_path())?; diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index 74c75b16..b1817d12 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -22,7 +22,7 @@ pub fn create_pallet_template( render_pallet(pallet_name, config, &pallet_path)?; Ok(()) } -#[derive(clap::Args)] +#[derive(clap::Args, Clone)] pub struct TemplatePalletConfig { #[arg(short, long, default_value_t = String::from("template"))] pub name: String, diff --git a/src/main.rs b/src/main.rs index b4f175fd..71664637 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,60 +12,57 @@ mod helpers; #[cfg(feature = "parachain")] mod parachains; - use anyhow::{anyhow, Result}; use clap::{Parser, Subcommand}; -use commands::{build, new, add, up, test}; use std::{fs::create_dir_all, path::PathBuf}; #[derive(Parser)] #[command(author, version, about, styles=style::get_styles())] pub struct Cli { #[command(subcommand)] - branch: Branch, + command: Commands, } #[derive(Subcommand)] #[command(subcommand_required = true)] -enum Branch { +enum Commands { /// Build a parachain, a pallet or smart contract. - /// Create a new parachain or smart contract. - New(new::NewArgs), + New(commands::new::NewArgs), /// Compile a parachain or smart contract. - Build(build::BuildArgs), + Build(commands::build::BuildArgs), /// Deploy a parachain or smart contract. - Up(up::UpArgs), - /// Add a pallet into a runtime - Add(add::AddArgs), + Up(commands::up::UpArgs), /// Test a smart contract. - Test(test::TestArgs), + Test(commands::test::TestArgs), + /// Add a pallet to the runtime + Add(commands::add::AddArgs), } #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); - match &cli.branch { - Branch::New(args) => match &args.command { + match &cli.command { + Commands::New(args) => match &args.command { #[cfg(feature = "parachain")] - new::NewCommands::Parachain(cmd) => cmd.execute(), + commands::new::NewCommands::Parachain(cmd) => cmd.execute(), #[cfg(feature = "parachain")] - new::NewCommands::Pallet(cmd) => cmd.execute(), + commands::new::NewCommands::Pallet(cmd) => cmd.execute(), #[cfg(feature = "contract")] - new::NewCommands::Contract(cmd) => cmd.execute(), + commands::new::NewCommands::Contract(cmd) => cmd.execute(), }, - Branch::Build(args) => match &args.command { + Commands::Build(args) => match &args.command { #[cfg(feature = "contract")] - build::BuildCommands::Contract(cmd) => cmd.execute(), + commands::build::BuildCommands::Contract(cmd) => cmd.execute(), }, - Branch::Up(args) => Ok(match &args.command { + Commands::Up(args) => Ok(match &args.command { #[cfg(feature = "parachain")] - up::UpCommands::Parachain(cmd) => cmd.execute().await?, + commands::up::UpCommands::Parachain(cmd) => cmd.execute().await?, }), - Branch::Test(args) => match &args.command { + Commands::Test(args) => match &args.command { #[cfg(feature = "contract")] - test::TestCommands::Contract(cmd) => cmd.execute(), + commands::test::TestCommands::Contract(cmd) => cmd.execute(), }, - Branch::Add(args) => args.execute(), + Commands::Add(args) => args.execute(), } } From e7b791ad0f3d4ad374c28da48d7353bbcd56471b Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 6 Mar 2024 16:04:25 +0530 Subject: [PATCH 03/57] step_builder for pallet-engine --- src/commands/add/mod.rs | 4 +- src/engines/pallet_engine/mod.rs | 22 +++-- src/engines/pallet_engine/pallet_entry.rs | 2 +- src/engines/pallet_engine/steps.rs | 107 ++++++++++++++++++++++ 4 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 src/engines/pallet_engine/steps.rs diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 92a30b01..ca98478f 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use clap::{Args, Subcommand}; -use crate::engines::pallet_engine::TemplatePalletConfig; +use crate::engines::pallet_engine::{self, TemplatePalletConfig}; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] @@ -50,7 +50,7 @@ impl AddArgs { // format!("FRAME-pallet-{name}") }, }; - crate::engines::pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; + pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; println!("Added {}\n-> to {}", pallet, runtime_path.display()); Ok(()) } diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index a582bc6a..6dcba594 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -15,10 +15,13 @@ mod pallet_entry; mod parser; +mod steps; mod template; +use crate::commands::add::AddPallet; use anyhow::{anyhow, bail, Context}; use pallet_entry::Numbers; +use pallet_entry::{AddPalletEntry, ReadPalletEntry}; use parser::RuntimeDeclaration; use proc_macro2::TokenStream; use std::{ @@ -27,17 +30,15 @@ use std::{ io::{BufRead, BufReader, Write}, path::{Path, PathBuf}, }; +use steps::{run_steps, step_builder, Steps}; use syn::{spanned::Spanned, ItemMacro}; pub use template::{create_pallet_template, TemplatePalletConfig}; -use pallet_entry::{AddPalletEntry, ReadPalletEntry}; - /// The main entry point into the engine. -pub fn execute( - pallet: crate::commands::add::AddPallet, - runtime_path: PathBuf, -) -> anyhow::Result<()> { - Ok(()) +pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { + let mut pe = PalletEngine::new(input)?; + let steps = step_builder(pallet)?; + run_steps(pe, steps) } /// The Pallet Engine has two Paths `input` and `output`. @@ -84,9 +85,9 @@ impl PalletEngine { &self.output } /// Create a new PalletEngine - pub fn new(input: PathBuf) -> anyhow::Result { + pub fn new(input: &PathBuf) -> anyhow::Result { let tmp_dir = tempfile::TempDir::new()?; - let output: PathBuf = tmp_dir.path().join("lib.rs"); + let output: PathBuf = tmp_dir.path().join("temp_lib.rs"); // Open the file specified in `output`. If non-empty, delete its contents. if output.exists() && output.is_file() { std::fs::remove_file(output.as_path())?; @@ -130,7 +131,7 @@ impl PalletEngine { bail!("No pallets/construct_runtime! found in input"); }; Ok(Self { - input, + input: input.to_owned(), output, details, }) @@ -195,6 +196,7 @@ impl PalletEngine { } // Private methods for internal use. +#[allow(unused)] impl PalletEngine { /// Add `n` line-breaks to output fn add_new_line(&self, n: usize) -> anyhow::Result<()> { diff --git a/src/engines/pallet_engine/pallet_entry.rs b/src/engines/pallet_engine/pallet_entry.rs index f3af4589..94b755e8 100644 --- a/src/engines/pallet_engine/pallet_entry.rs +++ b/src/engines/pallet_engine/pallet_entry.rs @@ -8,7 +8,7 @@ pub(super) struct AddPalletEntry { pub(super) name: Ident, } impl AddPalletEntry { - fn new(index: Option, path: &str, name: &str) -> Self { + pub(super) fn new(index: Option, path: &str, name: &str) -> Self { let path = Ident::new(path, proc_macro2::Span::call_site()); let name = Ident::new(name, proc_macro2::Span::call_site()); Self { index, path, name } diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs new file mode 100644 index 00000000..39ad7c75 --- /dev/null +++ b/src/engines/pallet_engine/steps.rs @@ -0,0 +1,107 @@ +use super::{pallet_entry::AddPalletEntry, PalletEngine}; +use crate::commands::add::AddPallet; +use anyhow::{bail, Result}; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use dependency::Dependency; +/// Define the steps needed for a particular pallet insertion +pub(super) enum Steps { + /// Import statements for pallet + RuntimePalletImport(TokenStream2), + /// Every pallet must impl pallet::Config for Runtime + RuntimePalletConfiguration(TokenStream2), + /// The runtime/Cargo.toml needs an import for the pallet being inserted + /// This includes features [try-runtime, runtime-benchmarks, std], path information for `git` or local path + RuntimePalletDependency(Dependency), + /// ConstructRuntime! entry + ConstructRuntimeEntry(AddPalletEntry), + /// Include a `list_benchmarks!` entry + ListBenchmarks(String), + /// Does pallet require a genesis configuration? + ChainspecGenesisConfig(String), + /// ChainSpec imports if necessary + ChainspecGenesisImport(TokenStream2), + /// Node specific imports if the above two are required + NodePalletDependency(Dependency), +} + +pub(super) fn step_builder(pallet: AddPallet) -> Result> { + use Steps::*; + let mut steps: Vec = vec![]; + match pallet { + // Adding a pallet-parachain-template requires 5 distinct steps + AddPallet::Template => { + // TODO: Add cargo dependency + // steps.push(RuntimePalletDependency(Dependency::runtime_template())); + steps.push(RuntimePalletImport(quote!( + pub use pallet_parachain_template; + ))); + steps.push(RuntimePalletConfiguration(quote!( + /// Configure the pallet template in pallets/template. + impl pallet_parachain_template::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + } + ))); + steps.push(ConstructRuntimeEntry(AddPalletEntry::new( + // Index + None, + // Path + "pallet_parachain_template", + // Pallet name + // TODO (high priority): implement name conflict resolution strategy + "Template", + ))); + // TODO + // steps.push(NodePalletDependency(Dependency::node_template())) + } + AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), + }; + Ok(steps) +} + +pub(super) fn run_steps(pe: PalletEngine, steps: Vec) -> Result<()> { + Ok(()) +} + +mod dependency { + use strum_macros::{Display, EnumString}; + + #[derive(EnumString, Display)] + pub(super) enum Features { + #[strum(serialize = "std")] + Std, + #[strum(serialize = "runtime-benchmarks")] + RuntimeBenchmarks, + #[strum(serialize = "try-runtime")] + TryRuntime, + Custom(String), + } + pub(super) struct Dependency { + features: Vec, + path: String, + no_default_features: bool, + } + + impl Dependency { + /// Dependencies required for adding a pallet-parachain-template to runtime + pub(super) fn runtime_template() -> Self { + Self { + features: vec![ + Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std, + ], + // TODO hardcode for now + path: format!(r#"path = "../pallets/template""#), + no_default_features: true, + } + } + /// Dependencies required for adding a pallet-parachain-template to node + pub(super) fn node_template() -> Self { + Self { + features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], + // TODO hardcode for now + path: format!(r#"path = "../pallets/template""#), + no_default_features: false, + } + } + } +} From c3dcfa05a291af7ea98835391b8ed643e4baac23 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 7 Mar 2024 15:01:19 +0530 Subject: [PATCH 04/57] insert_import_stmts --- src/commands/add/mod.rs | 2 +- src/engines/pallet_engine/mod.rs | 107 ++++++++++++++++++++++++++--- src/engines/pallet_engine/steps.rs | 52 +++++++++++--- 3 files changed, 141 insertions(+), 20 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index ca98478f..633557af 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -19,7 +19,7 @@ pub(crate) struct AddArgs { #[derive(Subcommand, Clone)] #[command(subcommand_required = true)] pub(crate) enum AddPallet { - /// Insert `pallet-template` into the runtime. + /// Insert `pallet-parachain-template` into the runtime. Template, /// Insert a frame-pallet into the runtime. Frame(FrameArgs), diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 6dcba594..7576da90 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -31,7 +31,7 @@ use std::{ path::{Path, PathBuf}, }; use steps::{run_steps, step_builder, Steps}; -use syn::{spanned::Spanned, ItemMacro}; +use syn::{spanned::Spanned, Item, ItemMacro}; pub use template::{create_pallet_template, TemplatePalletConfig}; /// The main entry point into the engine. @@ -41,10 +41,21 @@ pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { run_steps(pe, steps) } +/// State of PalletEngine at any given moment in time +#[derive(Debug, Default, PartialEq)] +enum State { + #[default] + Init, + Import, + Config, + ConstructRuntime, + Benchmarks, + ImplRuntimeApi, +} /// The Pallet Engine has two Paths `input` and `output`. -/// During processing, we want to keep the input source and the output source separate as -/// to have assurance that our references into the `input` file are still valid during construction of `output`. -/// Once fully processed, `output` can simply overwrite `input` +/// During processing, we keep the input source as read only and perform all processing into the `output` sink +/// This allows for manual checking using a diff tool that the edits performed are indeed satisfactory before calling merge +/// which will overwrite `input` with the processed `output` pub struct PalletEngine { /// Input source to PalletEngine - This will be the path to the runtime/src/lib.rs /// In code, this is never touched directly until the final step where it's overwritten @@ -52,12 +63,18 @@ pub struct PalletEngine { input: PathBuf, /// Stores the details of the runtime pallets built from input details: PalletDetails, + /// Stores imports necessary to make new items available + imports: ImportDetails, /// This stores the path to the runtime file being processed /// User must have read/write permissions for potentially destructive editing /// All insertions are ultimately written here output: PathBuf, // /// This stores the path to the runtime manifest file runtime/Cargo.toml // manifest: PathBuf, + /// State + state: State, + /// Cursor for tracking where we are in the output + cursor: usize, } /// PalletDetails is data generated after parsing of a given `input` runtime file @@ -68,22 +85,52 @@ struct PalletDetails { pallets: Vec, /// construct_runtime! macro span start location. Any pallet that's being added /// should search, uptil this point to make sure existing pallets do not conflict + /// Note: Read-only from self.input crt_start: usize, /// construct_runtime! macro span end location. - /// construct_runtime! macro span end location. /// For changes that happen after construct_runtime! is edited + /// Note: Read-only from self.input crt_end: usize, /// Total number of lines in input. Useful for inserting lines. file_end: usize, /// Type of runtime declaration being processed declaration: RuntimeDeclaration, } +struct ImportDetails { + /// On reading the source file, we obtain `last_import` which is the ending line of final import + /// statement, and also from where additional pallet imports must be added + last_import: usize, + /// Tracker for the number of imports added by PalletEngine. Initial value is 0. + counter: usize, +} // Public API impl PalletEngine { /// Query the output path pub fn output(&self) -> &Path { &self.output } + /// Consume self merging `output` and `input` + /// Call this to finalize edits + pub fn merge(self) -> Result<()> { + fs::copy(&self.output, &self.input)?; + fs::remove_file(self.output); + Ok(()) + } + /// Prepare `output` by first, adding pre-CRT items such as imports and modules + /// Then adding the construct_runtime! macro + /// And finally adding the post-CRT items such as benchmarks, impl_runtime_apis! and so forth + pub fn prepare_output(&mut self) -> anyhow::Result<()> { + if self.state != State::Init { + bail!("PalletEngine is not in Init stage, cursor: {}", self.cursor); + } + else { + // First pre-CRT items - imports + pe.append_lines(0, self.imports.last_import)?; + pe.cursor = self.imports.last_import; + pe.state = State::Import; + Ok(()) + } + } /// Create a new PalletEngine pub fn new(input: &PathBuf) -> anyhow::Result { let tmp_dir = tempfile::TempDir::new()?; @@ -102,11 +149,22 @@ impl PalletEngine { let rt = fs::read_to_string(&input)?; let ast: syn::File = syn::parse_file(rt.as_ref())?; let mut details = Option::::None; - for item in ast.items.iter() { + let mut last_import = None; + let mut _macro_cross = false; + for (idx, item) in ast.items.iter().enumerate() { match item { - syn::Item::Macro(ItemMacro { mac, .. }) => { + Item::Use(_) => { + // Fetch last import + // Note, other use statements are present inside modules in a standard runtime + // Additional safety mechanism to make sure pallet-imports are always before construct_runtime! + if !_macro_cross { + last_import = Some(item.span().end().line); + } + } + Item::Macro(ItemMacro { mac, .. }) => { if let Some(mac_id) = mac.path.get_ident() { if mac_id == "construct_runtime" { + _macro_cross = true; let (crt_start, crt_end) = (item.span().start().line, item.span().end().line); let declaration = @@ -127,13 +185,20 @@ impl PalletEngine { _ => {} }; } + let imports = ImportDetails { + last_import: last_import.expect("Imports are always present"), + counter: 0, + }; let Some(details) = details else { bail!("No pallets/construct_runtime! found in input"); }; Ok(Self { input: input.to_owned(), + imports, output, details, + state: State::Init, + cursor: 0 }) } /// Helper for PalletEngine::new, Builds pallet details from the construct_runtime! macro @@ -196,27 +261,44 @@ impl PalletEngine { } // Private methods for internal use. +// Note: Some methods update `self.cursor` and they take exclusive refs (&mut self) +// For functions which don't do that (i.e. take ref by &self), the caller must decide how to increment cursor +// This is relevant when calling methods like `append_tokens` or `append_str` which append single and multi-line strs +// without analyzing it for newlines. #[allow(unused)] impl PalletEngine { /// Add `n` line-breaks to output fn add_new_line(&self, n: usize) -> anyhow::Result<()> { let mut file = OpenOptions::new().append(true).open(&self.output)?; let newlines: String = std::iter::repeat('\n').take(n).collect(); - Ok(file.write_all(format!("{newlines}").as_bytes())?) + let rs = file.write_all(format!("{newlines}").as_bytes())?; + self.cursor += 1; + Ok(rs) } - /// Append raw tokens to `output` file + /// Append raw tokens to `output` file, cursor should be handled by caller fn append_tokens(&self, tokens: TokenStream) -> anyhow::Result<()> { let content = prettyplease::unparse(&syn::parse_file(&tokens.to_string())?); let mut file = OpenOptions::new().append(true).open(&self.output)?; file.write_all(content.as_bytes())?; Ok(()) } - /// Append string as is to `output` file + /// Append string as is to `output` file, cursor should be handled by caller fn append_str(&self, content: String) -> anyhow::Result<()> { let mut file = OpenOptions::new().append(true).open(&self.output)?; file.write_all(content.as_bytes())?; Ok(()) } + /// Insert import statement + /// As of now, it's imperative to call this function for pre-CRT item insertions + /// The correctness of calling this function depends on the `state` of PalletEngine + /// and the step_runner makes sure that it will only call this function when State is either + /// `State::Init` or `State::Import` + fn insert_import(&mut self, import_stmt: TokenStream) -> anyhow::Result<()> { + self.append_tokens(import_stmt); + self.imports.counter += 1; + self.imports.last_import += 1; + Ok(()) + } /// Append lines [start..end] from `input` source to `output`. /// Typically used to scaffold the `output` before and after making changes fn append_lines_from(&self, start: usize, end: usize) -> anyhow::Result<()> { @@ -246,6 +328,7 @@ impl PalletEngine { Ok(()) } /// Insert string at line. Errors if line number doesn't exist in `output` + /// cursor should be handled by caller fn insert_at(&self, line: usize, str: &str) -> anyhow::Result<()> { let reader = BufReader::new(File::open(&self.output)?); let mut temp_file = tempfile::NamedTempFile::new()?; @@ -266,7 +349,7 @@ impl PalletEngine { } /// Insert raw string at construct_runtime! Fails if there's no construct_runtime! in `output` /// By default inserts at the end of the macro - fn insert_str_runtime(&self, str: &str) -> anyhow::Result<()> { + fn insert_str_runtime(&mut self, str: &str) -> anyhow::Result<()> { let runtime_contents = fs::read_to_string(&self.output)?; let ast: syn::File = syn::parse_file(runtime_contents.as_ref())?; let mut runtime_found = false; @@ -313,6 +396,8 @@ impl PalletEngine { // Should never happen panic!("Construct Runtime not found in PalletEngine output. Cannot add pallet"); } + // Typically insert_str_runtime would be used to insert a single pallet entry so this is okay + self.cursor += 1; Ok(()) } /// Add a new pallet to RuntimeDeclaration and return it. diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 39ad7c75..d830956b 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,9 +1,11 @@ use super::{pallet_entry::AddPalletEntry, PalletEngine}; use crate::commands::add::AddPallet; use anyhow::{bail, Result}; +use dependency::Dependency; +use log::error; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use dependency::Dependency; +use Steps::*; /// Define the steps needed for a particular pallet insertion pub(super) enum Steps { /// Import statements for pallet @@ -26,13 +28,11 @@ pub(super) enum Steps { } pub(super) fn step_builder(pallet: AddPallet) -> Result> { - use Steps::*; let mut steps: Vec = vec![]; match pallet { // Adding a pallet-parachain-template requires 5 distinct steps AddPallet::Template => { - // TODO: Add cargo dependency - // steps.push(RuntimePalletDependency(Dependency::runtime_template())); + steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(quote!( pub use pallet_parachain_template; ))); @@ -51,15 +51,49 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - // TODO - // steps.push(NodePalletDependency(Dependency::node_template())) + steps.push(NodePalletDependency(Dependency::node_template())) } AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; Ok(steps) } -pub(super) fn run_steps(pe: PalletEngine, steps: Vec) -> Result<()> { +pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { + use super::State::*; + pe.prepare_output()?; + for step in steps.into_iter() { + match step { + RuntimePalletImport(stmt) => { + match pe.state { + Init => { + warn!("Non fatal: `prepare_output` was not called"); + pe.state = Import; + pe.insert_import(stmt); + } + Import => pe.insert_import(stmt), + _ => { + // We don't support writing import statements in any other engine state + // Log non-fatal error and continue + error!("Cannot write import stmts. Check step builder"); + continue; + } + } + pe.insert_import(quote!( + pub use pallet_parachain_template; + )); + } + // RuntimePalletConfiguration(step) => pe.insert(step), + // RuntimePalletDependency(step) => pe.insert(step), + // ConstructRuntimeEntry(step) => pe.insert(step), + // ListBenchmarks(step) => pe.insert(step), + // ChainspecGenesisConfig(step) => pe.insert(step), + // ChainspecGenesisImport(step) => pe.insert(step), + // NodePalletDependency(step) => pe.insert(step), + _ => { + unimplemented!() + } + } + } Ok(()) } @@ -87,7 +121,9 @@ mod dependency { pub(super) fn runtime_template() -> Self { Self { features: vec![ - Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std, + Features::RuntimeBenchmarks, + Features::TryRuntime, + Features::Std, ], // TODO hardcode for now path: format!(r#"path = "../pallets/template""#), From 0cfec787c14c05e4dcf33aa28402cb2a769a2a58 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 7 Mar 2024 15:36:22 +0530 Subject: [PATCH 05/57] fix build errors --- src/commands/add/mod.rs | 4 ++-- src/engines/pallet_engine/mod.rs | 17 +++++++++-------- src/engines/pallet_engine/steps.rs | 21 +++++++++++---------- src/engines/pallet_engine/template.rs | 2 +- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 633557af..a6b76bed 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use clap::{Args, Subcommand}; -use crate::engines::pallet_engine::{self, TemplatePalletConfig}; +use crate::engines::pallet_engine; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] @@ -44,7 +44,7 @@ impl AddArgs { }; let pallet = match self.pallet { AddPallet::Template => format!("pallet-template"), - AddPallet::Frame(FrameArgs { ref name }) => { + AddPallet::Frame(FrameArgs { .. }) => { eprintln!("Sorry, frame pallets cannot be added right now"); std::process::exit(1); // format!("FRAME-pallet-{name}") diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 7576da90..85e3d1a8 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -1,3 +1,4 @@ +#![allow(unused)] //! Pallet Engine - A set of tools to add pallets to your runtime //! To add a pallet one usually needs to consider a few pieces of information together: //! @@ -30,13 +31,13 @@ use std::{ io::{BufRead, BufReader, Write}, path::{Path, PathBuf}, }; -use steps::{run_steps, step_builder, Steps}; +use steps::{run_steps, step_builder}; use syn::{spanned::Spanned, Item, ItemMacro}; pub use template::{create_pallet_template, TemplatePalletConfig}; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { - let mut pe = PalletEngine::new(input)?; + let mut pe = PalletEngine::new(&runtime_path)?; let steps = step_builder(pallet)?; run_steps(pe, steps) } @@ -111,7 +112,7 @@ impl PalletEngine { } /// Consume self merging `output` and `input` /// Call this to finalize edits - pub fn merge(self) -> Result<()> { + pub fn merge(self) -> anyhow::Result<()> { fs::copy(&self.output, &self.input)?; fs::remove_file(self.output); Ok(()) @@ -125,9 +126,9 @@ impl PalletEngine { } else { // First pre-CRT items - imports - pe.append_lines(0, self.imports.last_import)?; - pe.cursor = self.imports.last_import; - pe.state = State::Import; + self.append_lines_from(0, self.imports.last_import)?; + self.cursor = self.imports.last_import; + self.state = State::Import; Ok(()) } } @@ -151,7 +152,7 @@ impl PalletEngine { let mut details = Option::::None; let mut last_import = None; let mut _macro_cross = false; - for (idx, item) in ast.items.iter().enumerate() { + for item in ast.items.iter() { match item { Item::Use(_) => { // Fetch last import @@ -268,7 +269,7 @@ impl PalletEngine { #[allow(unused)] impl PalletEngine { /// Add `n` line-breaks to output - fn add_new_line(&self, n: usize) -> anyhow::Result<()> { + fn add_new_line(&mut self, n: usize) -> anyhow::Result<()> { let mut file = OpenOptions::new().append(true).open(&self.output)?; let newlines: String = std::iter::repeat('\n').take(n).collect(); let rs = file.write_all(format!("{newlines}").as_bytes())?; diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index d830956b..91965e48 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,8 +1,9 @@ +#![allow(unused)] use super::{pallet_entry::AddPalletEntry, PalletEngine}; use crate::commands::add::AddPallet; -use anyhow::{bail, Result}; +use anyhow::Result; use dependency::Dependency; -use log::error; +use log::{error, warn}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use Steps::*; @@ -70,9 +71,9 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { pe.state = Import; pe.insert_import(stmt); } - Import => pe.insert_import(stmt), + Import => pe.insert_import(stmt)?, _ => { - // We don't support writing import statements in any other engine state + // We don't support writing import statements in any other engine state // Log non-fatal error and continue error!("Cannot write import stmts. Check step builder"); continue; @@ -92,8 +93,8 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { _ => { unimplemented!() } - } - } + }; // -- match -- + } // -- for -- Ok(()) } @@ -101,7 +102,7 @@ mod dependency { use strum_macros::{Display, EnumString}; #[derive(EnumString, Display)] - pub(super) enum Features { + pub(in crate::engines::pallet_engine) enum Features { #[strum(serialize = "std")] Std, #[strum(serialize = "runtime-benchmarks")] @@ -110,7 +111,7 @@ mod dependency { TryRuntime, Custom(String), } - pub(super) struct Dependency { + pub(in crate::engines::pallet_engine) struct Dependency { features: Vec, path: String, no_default_features: bool, @@ -118,7 +119,7 @@ mod dependency { impl Dependency { /// Dependencies required for adding a pallet-parachain-template to runtime - pub(super) fn runtime_template() -> Self { + pub(in crate::engines::pallet_engine) fn runtime_template() -> Self { Self { features: vec![ Features::RuntimeBenchmarks, @@ -131,7 +132,7 @@ mod dependency { } } /// Dependencies required for adding a pallet-parachain-template to node - pub(super) fn node_template() -> Self { + pub(in crate::engines::pallet_engine) fn node_template() -> Self { Self { features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], // TODO hardcode for now diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index b1817d12..3dd08694 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -4,7 +4,7 @@ use crate::{ }; use std::{fs, path::PathBuf}; -use super::{pallet_entry::AddPalletEntry, PalletEngine}; +// use super::{pallet_entry::AddPalletEntry, PalletEngine}; pub fn create_pallet_template( path: Option, From 685f3c73970c5012cd09ba277c63bded34d65f74 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 8 Mar 2024 13:44:52 +0530 Subject: [PATCH 06/57] prepare_config --- src/engines/pallet_engine/mod.rs | 79 +++++++++++++++++++++++------- src/engines/pallet_engine/steps.rs | 49 +++++++++++++----- 2 files changed, 98 insertions(+), 30 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 85e3d1a8..edd3ef8c 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -21,6 +21,7 @@ mod template; use crate::commands::add::AddPallet; use anyhow::{anyhow, bail, Context}; +use log::warn; use pallet_entry::Numbers; use pallet_entry::{AddPalletEntry, ReadPalletEntry}; use parser::RuntimeDeclaration; @@ -44,6 +45,7 @@ pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { /// State of PalletEngine at any given moment in time #[derive(Debug, Default, PartialEq)] +// TODO: Impl sequence checking through discriminants enum State { #[default] Init, @@ -117,21 +119,6 @@ impl PalletEngine { fs::remove_file(self.output); Ok(()) } - /// Prepare `output` by first, adding pre-CRT items such as imports and modules - /// Then adding the construct_runtime! macro - /// And finally adding the post-CRT items such as benchmarks, impl_runtime_apis! and so forth - pub fn prepare_output(&mut self) -> anyhow::Result<()> { - if self.state != State::Init { - bail!("PalletEngine is not in Init stage, cursor: {}", self.cursor); - } - else { - // First pre-CRT items - imports - self.append_lines_from(0, self.imports.last_import)?; - self.cursor = self.imports.last_import; - self.state = State::Import; - Ok(()) - } - } /// Create a new PalletEngine pub fn new(input: &PathBuf) -> anyhow::Result { let tmp_dir = tempfile::TempDir::new()?; @@ -199,7 +186,7 @@ impl PalletEngine { output, details, state: State::Init, - cursor: 0 + cursor: 0, }) } /// Helper for PalletEngine::new, Builds pallet details from the construct_runtime! macro @@ -268,6 +255,52 @@ impl PalletEngine { // without analyzing it for newlines. #[allow(unused)] impl PalletEngine { + /// Prepare `output` by first, adding pre-CRT items such as imports and modules + /// Then adding the construct_runtime! macro + /// And finally adding the post-CRT items such as benchmarks, impl_runtime_apis! and so forth + fn prepare_output(&mut self) -> anyhow::Result<()> { + if self.state != State::Init { + bail!("PalletEngine is not in Init stage, cursor: {}", self.cursor); + } else { + // First pre-CRT items - imports + self.append_lines_from(0, self.imports.last_import)?; + self.cursor = self.imports.last_import; + self.state = State::Import; + Ok(()) + } + } + /// Prepare `output` for taking new pallet configurations + fn prepare_config(&mut self) -> anyhow::Result<()> { + if self.state != State::Import { + bail!( + "PalletEngine is not in Import stage, cursor: {}", + self.cursor + ); + } else { + self.append_lines_from(self.imports.last_import + 1, self.details.crt_start - 1); + self.state = State::Config; + Ok(()) + } + } + /// Prepare `output` for CRT items + fn prepare_crt(&mut self) -> anyhow::Result<()> { + if self.state != State::Config { + bail!( + "PalletEngine is not in Config stage, cursor: {}", + self.cursor + ); + } else if self.state == State::ConstructRuntime { + warn!( + "PalletEngine is already in ConstructRuntime stage, cursor: {}", + self.cursor + ); + return Ok(()); + } + self.add_new_line(1)?; + self.append_lines_from(self.details.crt_start, self.details.crt_end); + self.state = State::ConstructRuntime; + Ok(()) + } /// Add `n` line-breaks to output fn add_new_line(&mut self, n: usize) -> anyhow::Result<()> { let mut file = OpenOptions::new().append(true).open(&self.output)?; @@ -300,6 +333,12 @@ impl PalletEngine { self.imports.last_import += 1; Ok(()) } + /// Insert configuartion for a pallet - only for pallet-template atm + fn insert_config(&mut self, config: TokenStream) -> anyhow::Result<()> { + self.append_tokens(config); + self.cursor += 3; // TODO : change to count_newlines() + Ok(()) + } /// Append lines [start..end] from `input` source to `output`. /// Typically used to scaffold the `output` before and after making changes fn append_lines_from(&self, start: usize, end: usize) -> anyhow::Result<()> { @@ -414,7 +453,6 @@ impl PalletEngine { ultimate.index = new_pallet.index; ultimate.path.inner.segments[0].ident = new_pallet.path; ultimate.name = new_pallet.name; - // println!("Ultimate pallet: {:?}", ultimate); i.pallets.push(ultimate); Ok(()) } @@ -424,6 +462,11 @@ impl PalletEngine { RuntimeDeclaration::ExplicitExpanded(e) => { todo!() } - } + }; + Ok(()) } } +// TODO +// fn count_newlines(tokens: TokenStream) -> usize { +// unimplemented!() +// } diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 91965e48..6bb307b6 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,4 +1,3 @@ -#![allow(unused)] use super::{pallet_entry::AddPalletEntry, PalletEngine}; use crate::commands::add::AddPallet; use anyhow::Result; @@ -26,8 +25,22 @@ pub(super) enum Steps { ChainspecGenesisImport(TokenStream2), /// Node specific imports if the above two are required NodePalletDependency(Dependency), + /// PalletEngine Specific Commands + Commands, } - +enum Commands { + SwitchToConfig, + SwitchToCRT, +} +macro_rules! steps { + ($cmd:expr) => { + steps.push($cmd); + }; +} +/// Some rules to follow when constructing steps: +/// The pallet engine state expects to go as edits would, i.e. top to bottom lexically +/// So it makes sense for any given file, to first include an import, then items that refer to it +/// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` sin that order. pub(super) fn step_builder(pallet: AddPallet) -> Result> { let mut steps: Vec = vec![]; match pallet { @@ -37,12 +50,14 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { steps.push(RuntimePalletImport(quote!( pub use pallet_parachain_template; ))); + steps.push(SwitchToConfig); steps.push(RuntimePalletConfiguration(quote!( /// Configure the pallet template in pallets/template. impl pallet_parachain_template::Config for Runtime { type RuntimeEvent = RuntimeEvent; } ))); + steps.push(SwitchToCrt); steps.push(ConstructRuntimeEntry(AddPalletEntry::new( // Index None, @@ -58,16 +73,19 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { }; Ok(steps) } - +/// Execute steps on PalletEngine. +/// Each execution edits a file. +/// Sequence of steps matters so take care when ordering them pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { use super::State::*; pe.prepare_output()?; for step in steps.into_iter() { match step { + // RuntimePalletDependency(step) => pe.insert(step), RuntimePalletImport(stmt) => { match pe.state { Init => { - warn!("Non fatal: `prepare_output` was not called"); + warn!("`prepare_output` was not called"); pe.state = Import; pe.insert_import(stmt); } @@ -75,17 +93,24 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { _ => { // We don't support writing import statements in any other engine state // Log non-fatal error and continue - error!("Cannot write import stmts. Check step builder"); + error!( + "Cannot write import stmts in state {0:?}. Check step builder", + pe.state + ); continue; } - } - pe.insert_import(quote!( - pub use pallet_parachain_template; - )); + }; } - // RuntimePalletConfiguration(step) => pe.insert(step), - // RuntimePalletDependency(step) => pe.insert(step), - // ConstructRuntimeEntry(step) => pe.insert(step), + SwitchToConfig => pe.prepare_config()?, + RuntimePalletConfiguration(config) => { + if pe.state != Config { + // Not really a fatal error, but may cause unexpected behaviour + warn!("Engine not in Config state, executing config insertion anyways"); + } + pe.insert_config(config)? + }, + SwitchToCRT => pe.prepare_crt()?, + ConstructRuntimeEntry(p) => pe.add_pallet_runtime(p)?, // ListBenchmarks(step) => pe.insert(step), // ChainspecGenesisConfig(step) => pe.insert(step), // ChainspecGenesisImport(step) => pe.insert(step), From 6dd21d16c5f5afa8828406d6a2b4e13eb8537739 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 8 Mar 2024 15:13:30 +0530 Subject: [PATCH 07/57] fix more runtime errors --- Cargo.lock | 1 + Cargo.toml | 1 + src/commands/add/mod.rs | 17 ++++++--- src/engines/pallet_engine/mod.rs | 25 +++++++++---- src/engines/pallet_engine/pallet_entry.rs | 1 + src/engines/pallet_engine/steps.rs | 43 ++++++++++++++--------- 6 files changed, 60 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 982d60d9..ed4ddbd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4452,6 +4452,7 @@ dependencies = [ "toml_edit 0.22.6", "tracing-subscriber 0.3.18", "url", + "uuid", "walkdir", "zombienet-sdk", "zombienet-support", diff --git a/Cargo.toml b/Cargo.toml index 1c9fb56b..004b7b98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ tracing-subscriber = { version = "0.3", optional = true } url = { version = "2.5", optional = true } zombienet-sdk = { git = "https://github.com/paritytech/zombienet-sdk", optional = true } zombienet-support = { git = "https://github.com/paritytech/zombienet-sdk", optional = true } +uuid = { version = "1.7.0", features = ["v4"] } [features] diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index a6b76bed..c8de71c5 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -10,7 +10,7 @@ pub(crate) struct AddArgs { #[command(subcommand)] /// Pallet to add to the runtime pub(crate) pallet: AddPallet, - #[arg(global = true, short)] + #[arg(global = true, short, long)] /// Runtime path; /// Cargo Manifest path will be inferred as `../Cargo.toml` pub(crate) runtime: Option, @@ -35,11 +35,20 @@ pub(crate) struct FrameArgs { impl AddArgs { pub(crate) fn execute(&self) -> anyhow::Result<()> { let runtime_path = match self.runtime { - Some(ref s) => PathBuf::from(s), + Some(ref s) => { + let path = PathBuf::from(s); + // println!("Using runtime path: {}", &path.display()); + if !path.exists() { + anyhow::bail!("Runtime path does not exist: {}", path.display()); + } + path + } None => { // TODO: Fetch runtime either from cache // Fix: This is a placeholder path, should not be used - PathBuf::from("my-app/runtime/src/lib.rs") + unimplemented!( + "provide a runtime path until cache is implemented: --runtime " + ); } }; let pallet = match self.pallet { @@ -48,7 +57,7 @@ impl AddArgs { eprintln!("Sorry, frame pallets cannot be added right now"); std::process::exit(1); // format!("FRAME-pallet-{name}") - }, + } }; pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; println!("Added {}\n-> to {}", pallet, runtime_path.display()); diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index edd3ef8c..b026869a 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -79,6 +79,12 @@ pub struct PalletEngine { /// Cursor for tracking where we are in the output cursor: usize, } +impl Drop for PalletEngine { + fn drop(&mut self) { + let output_dir = self.output.parent().unwrap(); + let _ = fs::remove_dir_all(output_dir); + } +} /// PalletDetails is data generated after parsing of a given `input` runtime file /// This will make observations as to which pallets are there, if there are instances of the pallets @@ -115,19 +121,22 @@ impl PalletEngine { /// Consume self merging `output` and `input` /// Call this to finalize edits pub fn merge(self) -> anyhow::Result<()> { + // TODO: since we are not interacting with any post-CRT items, this is ok + self.append_lines_from(self.details.crt_end + 1, self.details.file_end)?; fs::copy(&self.output, &self.input)?; - fs::remove_file(self.output); + fs::remove_file(&self.output); Ok(()) } /// Create a new PalletEngine pub fn new(input: &PathBuf) -> anyhow::Result { - let tmp_dir = tempfile::TempDir::new()?; - let output: PathBuf = tmp_dir.path().join("temp_lib.rs"); + let tmp_dir = PathBuf::from(format!("/tmp/pallet_engine_{}", uuid::Uuid::new_v4())); + fs::create_dir(&tmp_dir).context("Failed to create temporary directory for PalletEngine")?; + let output: PathBuf = tmp_dir.join("out_lib.rs"); // Open the file specified in `output`. If non-empty, delete its contents. if output.exists() && output.is_file() { std::fs::remove_file(output.as_path())?; } - File::create(output.as_path()).context(format!( + File::create(&output).context(format!( "Failed to create PalletEngine with output: {}", output.display() ))?; @@ -363,7 +372,10 @@ impl PalletEngine { snip.push_str(&line?); snip.push('\n'); } - let mut file = OpenOptions::new().append(true).open(&self.output)?; + let mut file = OpenOptions::new() + .append(true) + .open(&self.output) + .context("fn append_lines_from - cannot open output")?; file.write_all(snip.as_bytes())?; Ok(()) } @@ -448,13 +460,12 @@ impl PalletEngine { let mut ultimate = i .pallets .last() - .expect("Fatal: No pallets defined in construct_runtime!") + .ok_or(anyhow!("Fatal: No pallets defined in construct_runtime!"))? .clone(); ultimate.index = new_pallet.index; ultimate.path.inner.segments[0].ident = new_pallet.path; ultimate.name = new_pallet.name; i.pallets.push(ultimate); - Ok(()) } RuntimeDeclaration::Explicit(e) => { todo!() diff --git a/src/engines/pallet_engine/pallet_entry.rs b/src/engines/pallet_engine/pallet_entry.rs index 94b755e8..a3fa7331 100644 --- a/src/engines/pallet_engine/pallet_entry.rs +++ b/src/engines/pallet_engine/pallet_entry.rs @@ -2,6 +2,7 @@ use syn::Ident; /// Format containing necessary information for appending pallets +#[derive(Debug)] pub(super) struct AddPalletEntry { pub(super) index: Option, pub(super) path: Ident, diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 6bb307b6..4bf4a2d3 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -6,7 +6,9 @@ use log::{error, warn}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use Steps::*; +use super::State; /// Define the steps needed for a particular pallet insertion +#[derive(Debug)] pub(super) enum Steps { /// Import statements for pallet RuntimePalletImport(TokenStream2), @@ -25,13 +27,10 @@ pub(super) enum Steps { ChainspecGenesisImport(TokenStream2), /// Node specific imports if the above two are required NodePalletDependency(Dependency), - /// PalletEngine Specific Commands - Commands, -} -enum Commands { - SwitchToConfig, - SwitchToCRT, + /// PalletEngine State transitions + SwitchTo(State), } + macro_rules! steps { ($cmd:expr) => { steps.push($cmd); @@ -46,18 +45,18 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { match pallet { // Adding a pallet-parachain-template requires 5 distinct steps AddPallet::Template => { - steps.push(RuntimePalletDependency(Dependency::runtime_template())); + // steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(quote!( pub use pallet_parachain_template; ))); - steps.push(SwitchToConfig); + steps.push(SwitchTo(State::Config)); steps.push(RuntimePalletConfiguration(quote!( /// Configure the pallet template in pallets/template. impl pallet_parachain_template::Config for Runtime { type RuntimeEvent = RuntimeEvent; } ))); - steps.push(SwitchToCrt); + steps.push(SwitchTo(State::ConstructRuntime)); steps.push(ConstructRuntimeEntry(AddPalletEntry::new( // Index None, @@ -67,7 +66,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - steps.push(NodePalletDependency(Dependency::node_template())) + // steps.push(NodePalletDependency(Dependency::node_template())) } AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; @@ -76,6 +75,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { /// Execute steps on PalletEngine. /// Each execution edits a file. /// Sequence of steps matters so take care when ordering them +/// Works only for Template pallets at the moment.. See config and CRT inserts pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { use super::State::*; pe.prepare_output()?; @@ -101,32 +101,40 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { } }; } - SwitchToConfig => pe.prepare_config()?, + SwitchTo(State::Config) => pe.prepare_config()?, RuntimePalletConfiguration(config) => { if pe.state != Config { // Not really a fatal error, but may cause unexpected behaviour warn!("Engine not in Config state, executing config insertion anyways"); } pe.insert_config(config)? - }, - SwitchToCRT => pe.prepare_crt()?, - ConstructRuntimeEntry(p) => pe.add_pallet_runtime(p)?, + } + SwitchTo(State::ConstructRuntime) => pe.prepare_crt()?, + ConstructRuntimeEntry(_entry) => { + // TODO : Switch to add_pallet_runtime + // pe.add_pallet_runtime(entry)? + pe.insert_str_runtime("\t\tTemplate: pallet_parachain_template = 100,")?; + } + // ListBenchmarks(step) => pe.insert(step), // ListBenchmarks(step) => pe.insert(step), // ChainspecGenesisConfig(step) => pe.insert(step), // ChainspecGenesisImport(step) => pe.insert(step), // NodePalletDependency(step) => pe.insert(step), - _ => { - unimplemented!() + step => { + unimplemented!("{step:?} unimplemented") } }; // -- match -- } // -- for -- + // Finalize runtime edits + pe.merge()?; + // TODO: Finalize toml and chainspec edits Ok(()) } mod dependency { use strum_macros::{Display, EnumString}; - #[derive(EnumString, Display)] + #[derive(EnumString, Display, Debug)] pub(in crate::engines::pallet_engine) enum Features { #[strum(serialize = "std")] Std, @@ -136,6 +144,7 @@ mod dependency { TryRuntime, Custom(String), } + #[derive(Debug)] pub(in crate::engines::pallet_engine) struct Dependency { features: Vec, path: String, From 7e81cc26d14d6d3cb46c023c23a666618d110d8f Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 8 Mar 2024 18:12:54 +0530 Subject: [PATCH 08/57] update lockfile --- Cargo.lock | 235 +++++++++++++++++++++++++++++------------------------ 1 file changed, 129 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bd898bf..fc5999d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,9 +93,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom 0.2.12", @@ -1043,9 +1043,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "byte-slice-cast" @@ -1136,10 +1136,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.88" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ + "jobserver", "libc", ] @@ -1177,9 +1178,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1200,9 +1201,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" dependencies = [ "clap_builder", "clap_derive", @@ -1210,9 +1211,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -1458,7 +1459,7 @@ dependencies = [ "contract-metadata", "escape8259", "hex", - "indexmap 2.2.4", + "indexmap 2.2.5", "ink_env", "ink_metadata", "itertools 0.12.1", @@ -1695,9 +1696,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.118" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673ca5ae28334544ec2a6b18ebe666c42a2650abfb48abbd532ed409a44be2b" +checksum = "635179be18797d7e10edb9cd06c859580237750c7351f39ed9b298bfc17544ad" dependencies = [ "cc", "cxxbridge-flags", @@ -1707,9 +1708,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.118" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df46fe0eb43066a332586114174c449a62c25689f85a08f28fdcc8e12c380b9" +checksum = "9324397d262f63ef77eb795d900c0d682a34a43ac0932bec049ed73055d52f63" dependencies = [ "cc", "codespan-reporting", @@ -1722,15 +1723,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.118" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "886acf875df67811c11cd015506b3392b9e1820b1627af1a6f4e93ccdfc74d11" +checksum = "a87ff7342ffaa54b7c61618e0ce2bbcf827eba6d55b923b83d82551acbbecfe5" [[package]] name = "cxxbridge-macro" -version = "1.0.118" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d151cc139c3080e07f448f93a1284577ab2283d2a44acd902c6fba9ec20b6de" +checksum = "70b5b86cf65fa0626d85720619d80b288013477a91a0389fa8bc716bf4903ad1" dependencies = [ "proc-macro2", "quote", @@ -2963,11 +2964,11 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "polyval", ] @@ -3026,7 +3027,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.4", + "indexmap 2.2.5", "slab", "tokio", "tokio-util", @@ -3063,7 +3064,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.10", + "ahash 0.8.11", ] [[package]] @@ -3072,7 +3073,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.10", + "ahash 0.8.11", "allocator-api2", "serde", ] @@ -3179,9 +3180,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -3408,9 +3409,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.4" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "967d6dd42f16dbf0eb8040cb9e477933562684d3918f7d253f2ff9087fb3e7a3" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -3647,6 +3648,15 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jobserver" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +dependencies = [ + "libc", +] + [[package]] name = "joinery" version = "2.1.0" @@ -3655,9 +3665,9 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -3961,7 +3971,7 @@ version = "0.87.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d8893eb18fbf6bb6c80ef6ee7dd11ec32b1dc3c034c988ac1b3a84d46a230ae" dependencies = [ - "ahash 0.8.10", + "ahash 0.8.11", "async-trait", "backoff", "derivative", @@ -4242,18 +4252,18 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linkme" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca16377a6dae364fb00769699ba440899f1a720d4f5abf2667d0a8a95f933dd" +checksum = "bb2cfee0de9bd869589fb9a015e155946d1be5ff415cb844c2caccc6cc4b5db9" dependencies = [ "linkme-impl", ] [[package]] name = "linkme-impl" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e5ac81de04bf8215501c50a436632c3789b22ef1625fe0bf8927dd4ba3696c5" +checksum = "adf157a4dc5a29b7b464aa8fe7edeff30076e07e13646a1c3874f58477dc99f8" dependencies = [ "proc-macro2", "quote", @@ -4432,9 +4442,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -4721,9 +4731,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" @@ -4982,9 +4992,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.7" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" dependencies = [ "memchr", "thiserror", @@ -4993,9 +5003,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.7" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1288dbd7786462961e69bfd4df7848c1e37e8b74303dbdab82c3a9cdd2809" +checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" dependencies = [ "pest", "pest_generator", @@ -5003,9 +5013,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.7" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1381c29a877c6d34b8c176e734f35d7f7f5b3adaefe940cb4d1bb7af94678e2e" +checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" dependencies = [ "pest", "pest_meta", @@ -5016,9 +5026,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.7" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0934d6907f148c22a3acbda520c7eed243ad7487a30f51f6ce52b58b7077a8a" +checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" dependencies = [ "once_cell", "pest", @@ -5069,18 +5079,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", @@ -5267,19 +5277,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "universal-hash", ] [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", "universal-hash", ] @@ -5299,7 +5309,7 @@ dependencies = [ "duct", "frame-support-procedural-tools", "git2", - "indexmap 2.2.4", + "indexmap 2.2.5", "ink_env", "log", "prettyplease", @@ -5346,6 +5356,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettier-please" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" +dependencies = [ + "proc-macro2", + "syn 2.0.52", +] + [[package]] name = "prettyplease" version = "0.2.16" @@ -5394,7 +5414,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_edit 0.20.2", + "toml_edit 0.20.7", ] [[package]] @@ -5677,7 +5697,7 @@ checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.5", + "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -5692,9 +5712,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -6106,9 +6126,9 @@ checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "ryu-js" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4950d85bc52415f8432144c97c4791bd0c4f7954de32a7270ee9cccd3c22b12b" +checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" [[package]] name = "same-file" @@ -6285,7 +6305,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" dependencies = [ - "ahash 0.8.10", + "ahash 0.8.11", "cfg-if", "hashbrown 0.13.2", ] @@ -6524,7 +6544,7 @@ version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ - "indexmap 2.2.4", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -6587,7 +6607,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.4", + "indexmap 2.2.5", "serde", "serde_derive", "serde_json", @@ -6600,7 +6620,7 @@ version = "0.9.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ - "indexmap 2.2.4", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -6617,7 +6637,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -6664,7 +6684,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug 0.3.1", ] [[package]] @@ -7528,7 +7548,7 @@ version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e4d24d84a0beb44a71dcac1b41980e1edf7fb722c7f3046710136a283cd479b" dependencies = [ - "ahash 0.8.10", + "ahash 0.8.11", "hash-db", "lazy_static", "memory-db", @@ -7743,13 +7763,13 @@ dependencies = [ [[package]] name = "substrate-bip39" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e620c7098893ba667438b47169c00aacdd9e7c10e042250ce2b60b087ec97328" +checksum = "6a7590dc041b9bc2825e52ce5af8416c73dbe9d0654402bfd4b4941938b94d8f" dependencies = [ "hmac 0.11.0", "pbkdf2 0.8.0", - "schnorrkel 0.9.1", + "schnorrkel 0.11.4", "sha2 0.9.9", "zeroize", ] @@ -8748,7 +8768,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.4", + "indexmap 2.2.5", "serde", "serde_spanned", "toml_datetime", @@ -8757,11 +8777,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.2.4", + "indexmap 2.2.5", "toml_datetime", "winnow 0.5.40", ] @@ -8772,7 +8792,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.4", + "indexmap 2.2.5", "toml_datetime", "winnow 0.5.40", ] @@ -8783,11 +8803,11 @@ version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" dependencies = [ - "indexmap 2.2.4", + "indexmap 2.2.5", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.4", + "winnow 0.6.5", ] [[package]] @@ -9340,9 +9360,9 @@ checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -9371,9 +9391,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -9381,9 +9401,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -9396,9 +9416,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -9408,9 +9428,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9418,9 +9438,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -9431,9 +9451,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-opt" @@ -9672,9 +9692,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -9966,9 +9986,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4776665517ff33198f045bcddb9f0fc13db5d1e944a5c3debddedd9c78753c" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] @@ -10081,7 +10101,7 @@ dependencies = [ [[package]] name = "zombienet-configuration" version = "0.1.0-alpha.1" -source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800020f7d1574081fc600" +source = "git+https://github.com/paritytech/zombienet-sdk#c4b328f40082dddb921f5365ca15c6e0995172e7" dependencies = [ "anyhow", "lazy_static", @@ -10097,7 +10117,7 @@ dependencies = [ [[package]] name = "zombienet-orchestrator" version = "0.1.0-alpha.1" -source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800020f7d1574081fc600" +source = "git+https://github.com/paritytech/zombienet-sdk#c4b328f40082dddb921f5365ca15c6e0995172e7" dependencies = [ "anyhow", "futures", @@ -10125,7 +10145,7 @@ dependencies = [ [[package]] name = "zombienet-prom-metrics-parser" version = "0.1.0-alpha.1" -source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800020f7d1574081fc600" +source = "git+https://github.com/paritytech/zombienet-sdk#c4b328f40082dddb921f5365ca15c6e0995172e7" dependencies = [ "pest", "pest_derive", @@ -10135,10 +10155,11 @@ dependencies = [ [[package]] name = "zombienet-provider" version = "0.1.0-alpha.1" -source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800020f7d1574081fc600" +source = "git+https://github.com/paritytech/zombienet-sdk#c4b328f40082dddb921f5365ca15c6e0995172e7" dependencies = [ "anyhow", "async-trait", + "flate2", "futures", "hex", "k8s-openapi", @@ -10155,6 +10176,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", + "url", "uuid", "zombienet-configuration", "zombienet-support", @@ -10163,10 +10185,11 @@ dependencies = [ [[package]] name = "zombienet-sdk" version = "0.1.0-alpha.1" -source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800020f7d1574081fc600" +source = "git+https://github.com/paritytech/zombienet-sdk#c4b328f40082dddb921f5365ca15c6e0995172e7" dependencies = [ "async-trait", "futures", + "lazy_static", "subxt 0.33.0", "tokio", "zombienet-configuration", @@ -10178,7 +10201,7 @@ dependencies = [ [[package]] name = "zombienet-support" version = "0.1.0-alpha.1" -source = "git+https://github.com/paritytech/zombienet-sdk#f78a5e95327f2fde514800020f7d1574081fc600" +source = "git+https://github.com/paritytech/zombienet-sdk#c4b328f40082dddb921f5365ca15c6e0995172e7" dependencies = [ "anyhow", "async-trait", From 69d94911f54993fc057fc9f736115f925d1265de Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 8 Mar 2024 18:39:40 +0530 Subject: [PATCH 09/57] minor adjustments --- src/commands/add/mod.rs | 7 +++---- src/engines/pallet_engine/steps.rs | 7 +------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index c8de71c5..4c70f8c6 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -11,7 +11,7 @@ pub(crate) struct AddArgs { /// Pallet to add to the runtime pub(crate) pallet: AddPallet, #[arg(global = true, short, long)] - /// Runtime path; + /// Runtime path; for example: `sub0/runtime/src/lib.rs` /// Cargo Manifest path will be inferred as `../Cargo.toml` pub(crate) runtime: Option, } @@ -37,9 +37,8 @@ impl AddArgs { let runtime_path = match self.runtime { Some(ref s) => { let path = PathBuf::from(s); - // println!("Using runtime path: {}", &path.display()); if !path.exists() { - anyhow::bail!("Runtime path does not exist: {}", path.display()); + anyhow::bail!("Invalid runtime path: {}", path.display()); } path } @@ -52,7 +51,7 @@ impl AddArgs { } }; let pallet = match self.pallet { - AddPallet::Template => format!("pallet-template"), + AddPallet::Template => format!("pallet-parachain-template"), AddPallet::Frame(FrameArgs { .. }) => { eprintln!("Sorry, frame pallets cannot be added right now"); std::process::exit(1); diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 4bf4a2d3..56930f59 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -30,12 +30,6 @@ pub(super) enum Steps { /// PalletEngine State transitions SwitchTo(State), } - -macro_rules! steps { - ($cmd:expr) => { - steps.push($cmd); - }; -} /// Some rules to follow when constructing steps: /// The pallet engine state expects to go as edits would, i.e. top to bottom lexically /// So it makes sense for any given file, to first include an import, then items that refer to it @@ -47,6 +41,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { AddPallet::Template => { // steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(quote!( + // Imports by pop-cli pub use pallet_parachain_template; ))); steps.push(SwitchTo(State::Config)); From 2e6aef6d6341cbfd6ee21a97ab91fc115a5d452f Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 8 Mar 2024 19:01:05 +0530 Subject: [PATCH 10/57] prepare test harness for add-pallet --- src/engines/pallet_engine/mod.rs | 798 ++++++++++++++--------------- src/engines/pallet_engine/steps.rs | 2 +- tests/add/add.rs | 0 tests/add/lib.rs | 779 ++++++++++++++++++++++++++++ tests/add/out_lib.rs | 0 5 files changed, 1173 insertions(+), 406 deletions(-) create mode 100644 tests/add/add.rs create mode 100644 tests/add/lib.rs create mode 100644 tests/add/out_lib.rs diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index b026869a..f485a0b3 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -27,10 +27,10 @@ use pallet_entry::{AddPalletEntry, ReadPalletEntry}; use parser::RuntimeDeclaration; use proc_macro2::TokenStream; use std::{ - collections::HashMap, - fs::{self, File, OpenOptions}, - io::{BufRead, BufReader, Write}, - path::{Path, PathBuf}, + collections::HashMap, + fs::{self, File, OpenOptions}, + io::{BufRead, BufReader, Write}, + path::{Path, PathBuf}, }; use steps::{run_steps, step_builder}; use syn::{spanned::Spanned, Item, ItemMacro}; @@ -38,223 +38,218 @@ pub use template::{create_pallet_template, TemplatePalletConfig}; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { - let mut pe = PalletEngine::new(&runtime_path)?; - let steps = step_builder(pallet)?; - run_steps(pe, steps) + let mut pe = PalletEngine::new(&runtime_path)?; + let steps = step_builder(pallet)?; + run_steps(pe, steps) } /// State of PalletEngine at any given moment in time #[derive(Debug, Default, PartialEq)] // TODO: Impl sequence checking through discriminants enum State { - #[default] - Init, - Import, - Config, - ConstructRuntime, - Benchmarks, - ImplRuntimeApi, + #[default] + Init, + Import, + Config, + ConstructRuntime, + Benchmarks, + ImplRuntimeApi, } /// The Pallet Engine has two Paths `input` and `output`. /// During processing, we keep the input source as read only and perform all processing into the `output` sink /// This allows for manual checking using a diff tool that the edits performed are indeed satisfactory before calling merge /// which will overwrite `input` with the processed `output` pub struct PalletEngine { - /// Input source to PalletEngine - This will be the path to the runtime/src/lib.rs - /// In code, this is never touched directly until the final step where it's overwritten - /// Interim, it's treated as immutable data - input: PathBuf, - /// Stores the details of the runtime pallets built from input - details: PalletDetails, - /// Stores imports necessary to make new items available - imports: ImportDetails, - /// This stores the path to the runtime file being processed - /// User must have read/write permissions for potentially destructive editing - /// All insertions are ultimately written here - output: PathBuf, - // /// This stores the path to the runtime manifest file runtime/Cargo.toml - // manifest: PathBuf, - /// State - state: State, - /// Cursor for tracking where we are in the output - cursor: usize, + /// Input source to PalletEngine - This will be the path to the runtime/src/lib.rs + /// In code, this is never touched directly until the final step where it's overwritten + /// Interim, it's treated as immutable data + input: PathBuf, + /// Stores the details of the runtime pallets built from input + details: PalletDetails, + /// Stores imports necessary to make new items available + imports: ImportDetails, + /// This stores the path to the runtime file being processed + /// User must have read/write permissions for potentially destructive editing + /// All insertions are ultimately written here + output: PathBuf, + // /// This stores the path to the runtime manifest file runtime/Cargo.toml + // manifest: PathBuf, + /// State + state: State, + /// Cursor for tracking where we are in the output + cursor: usize, } impl Drop for PalletEngine { - fn drop(&mut self) { - let output_dir = self.output.parent().unwrap(); - let _ = fs::remove_dir_all(output_dir); - } + fn drop(&mut self) { + let output_dir = self.output.parent().unwrap(); + let _ = fs::remove_dir_all(output_dir); + } } /// PalletDetails is data generated after parsing of a given `input` runtime file /// This will make observations as to which pallets are there, if there are instances of the pallets /// among details such as the span of the construct_runtime! macro, the type of runtime declaration etc. struct PalletDetails { - /// Number of pallets in the runtime, changes based on pallets added to output - pallets: Vec, - /// construct_runtime! macro span start location. Any pallet that's being added - /// should search, uptil this point to make sure existing pallets do not conflict - /// Note: Read-only from self.input - crt_start: usize, - /// construct_runtime! macro span end location. - /// For changes that happen after construct_runtime! is edited - /// Note: Read-only from self.input - crt_end: usize, - /// Total number of lines in input. Useful for inserting lines. - file_end: usize, - /// Type of runtime declaration being processed - declaration: RuntimeDeclaration, + /// Number of pallets in the runtime, changes based on pallets added to output + pallets: Vec, + /// construct_runtime! macro span start location. Any pallet that's being added + /// should search, uptil this point to make sure existing pallets do not conflict + /// Note: Read-only from self.input + crt_start: usize, + /// construct_runtime! macro span end location. + /// For changes that happen after construct_runtime! is edited + /// Note: Read-only from self.input + crt_end: usize, + /// Total number of lines in input. Useful for inserting lines. + file_end: usize, + /// Type of runtime declaration being processed + declaration: RuntimeDeclaration, } struct ImportDetails { - /// On reading the source file, we obtain `last_import` which is the ending line of final import - /// statement, and also from where additional pallet imports must be added - last_import: usize, - /// Tracker for the number of imports added by PalletEngine. Initial value is 0. - counter: usize, + /// On reading the source file, we obtain `last_import` which is the ending line of final import + /// statement, and also from where additional pallet imports must be added + last_import: usize, + /// Tracker for the number of imports added by PalletEngine. Initial value is 0. + counter: usize, } // Public API impl PalletEngine { - /// Query the output path - pub fn output(&self) -> &Path { - &self.output - } - /// Consume self merging `output` and `input` - /// Call this to finalize edits - pub fn merge(self) -> anyhow::Result<()> { - // TODO: since we are not interacting with any post-CRT items, this is ok - self.append_lines_from(self.details.crt_end + 1, self.details.file_end)?; - fs::copy(&self.output, &self.input)?; - fs::remove_file(&self.output); - Ok(()) - } - /// Create a new PalletEngine - pub fn new(input: &PathBuf) -> anyhow::Result { - let tmp_dir = PathBuf::from(format!("/tmp/pallet_engine_{}", uuid::Uuid::new_v4())); - fs::create_dir(&tmp_dir).context("Failed to create temporary directory for PalletEngine")?; - let output: PathBuf = tmp_dir.join("out_lib.rs"); - // Open the file specified in `output`. If non-empty, delete its contents. - if output.exists() && output.is_file() { - std::fs::remove_file(output.as_path())?; - } - File::create(&output).context(format!( - "Failed to create PalletEngine with output: {}", - output.display() - ))?; - // Build Pallet Details - let __buf = BufReader::new(File::open(&input)?); - let file_end = __buf.lines().count(); - let rt = fs::read_to_string(&input)?; - let ast: syn::File = syn::parse_file(rt.as_ref())?; - let mut details = Option::::None; - let mut last_import = None; - let mut _macro_cross = false; - for item in ast.items.iter() { - match item { - Item::Use(_) => { - // Fetch last import - // Note, other use statements are present inside modules in a standard runtime - // Additional safety mechanism to make sure pallet-imports are always before construct_runtime! - if !_macro_cross { - last_import = Some(item.span().end().line); - } - } - Item::Macro(ItemMacro { mac, .. }) => { - if let Some(mac_id) = mac.path.get_ident() { - if mac_id == "construct_runtime" { - _macro_cross = true; - let (crt_start, crt_end) = - (item.span().start().line, item.span().end().line); - let declaration = - mac.parse_body::().map_err(|e| { - anyhow!("Cannot parse construct_runtime from input").context(e) - })?; - let pallets = Self::build_pallet_details(&declaration)?; - details = Some(PalletDetails { - pallets, - crt_start, - crt_end, - file_end, - declaration, - }); - } - } - } - _ => {} - }; - } - let imports = ImportDetails { - last_import: last_import.expect("Imports are always present"), - counter: 0, - }; - let Some(details) = details else { - bail!("No pallets/construct_runtime! found in input"); - }; - Ok(Self { - input: input.to_owned(), - imports, - output, - details, - state: State::Init, - cursor: 0, - }) - } - /// Helper for PalletEngine::new, Builds pallet details from the construct_runtime! macro - fn build_pallet_details( - declaration: &RuntimeDeclaration, - ) -> anyhow::Result> { - // Instance map to track the number of current instances for a pallet entry - let mut imap: HashMap = HashMap::new(); - let mut pe: HashMap = HashMap::new(); - let pallet_entries = match declaration { - RuntimeDeclaration::Implicit(i) => { - for pallet in i.pallets.iter() { - let entry: String = pallet.span.source_text().unwrap(); - let entry = entry.split(':').next().unwrap().to_string(); - let index = pallet.index; - if pallet.instance.is_some() { - // If using instance syntax i.e. pallet:: set instance to 1 - imap.entry(entry.clone()) - .and_modify(|e| *e += 1) - .or_insert(1); - }; - pe.entry(entry.clone()) - .and_modify(|e| { - let v = imap.get(&entry).unwrap_or(&0); - e.numbers.instance = *v; - }) - .or_insert(ReadPalletEntry { - entry: entry.to_string(), - numbers: Numbers { index, instance: 0 }, - }); - } - pe.into_iter().map(|e| e.1).collect() - } - RuntimeDeclaration::Explicit(e) | RuntimeDeclaration::ExplicitExpanded(e) => { - for pallet in e.pallets.iter() { - let entry: String = pallet.span.source_text().unwrap(); - let entry = entry.split(':').next().unwrap().to_string(); - let index = Some(pallet.index); - if pallet.instance.is_some() { - // If using instance syntax i.e. pallet:: set instance to 1 - imap.entry(entry.clone()) - .and_modify(|e| *e += 1) - .or_insert(1); - }; - pe.entry(entry.clone()) - .and_modify(|e| { - let v = imap.get(&entry).unwrap_or(&0); - e.numbers.instance = *v; - }) - .or_insert(ReadPalletEntry { - entry: entry.to_string(), - numbers: Numbers { index, instance: 0 }, - }); - } - pe.into_iter().map(|e| e.1).collect() - } - }; - Ok(pallet_entries) - } + /// Query the output path + pub fn output(&self) -> &Path { + &self.output + } + /// Consume self merging `output` and `input` + /// Call this to finalize edits + pub fn merge(self) -> anyhow::Result<()> { + // TODO: since we are not interacting with any post-CRT items, this is ok + self.append_lines_from(self.details.crt_end + 1, self.details.file_end)?; + fs::copy(&self.output, &self.input)?; + fs::remove_file(&self.output); + Ok(()) + } + /// Create a new PalletEngine + pub fn new(input: &PathBuf) -> anyhow::Result { + let tmp_dir = PathBuf::from(format!("/tmp/pallet_engine_{}", uuid::Uuid::new_v4())); + fs::create_dir(&tmp_dir) + .context("Failed to create temporary directory for PalletEngine")?; + let output: PathBuf = tmp_dir.join("out_lib.rs"); + // Open the file specified in `output`. If non-empty, delete its contents. + if output.exists() && output.is_file() { + std::fs::remove_file(output.as_path())?; + } + File::create(&output) + .context(format!("Failed to create PalletEngine with output: {}", output.display()))?; + // Build Pallet Details + let __buf = BufReader::new(File::open(&input)?); + let file_end = __buf.lines().count(); + let rt = fs::read_to_string(&input)?; + let ast: syn::File = syn::parse_file(rt.as_ref())?; + let mut details = Option::::None; + let mut last_import = None; + let mut _macro_cross = false; + for item in ast.items.iter() { + match item { + Item::Use(_) => { + // Fetch last import + // Note, other use statements are present inside modules in a standard runtime + // Additional safety mechanism to make sure pallet-imports are always before construct_runtime! + if !_macro_cross { + last_import = Some(item.span().end().line); + } + }, + Item::Macro(ItemMacro { mac, .. }) => { + if let Some(mac_id) = mac.path.get_ident() { + if mac_id == "construct_runtime" { + _macro_cross = true; + let (crt_start, crt_end) = + (item.span().start().line, item.span().end().line); + let declaration = + mac.parse_body::().map_err(|e| { + anyhow!("Cannot parse construct_runtime from input").context(e) + })?; + let pallets = Self::build_pallet_details(&declaration)?; + details = Some(PalletDetails { + pallets, + crt_start, + crt_end, + file_end, + declaration, + }); + } + } + }, + _ => {}, + }; + } + let imports = ImportDetails { + last_import: last_import.expect("Imports are always present"), + counter: 0, + }; + let Some(details) = details else { + bail!("No pallets/construct_runtime! found in input"); + }; + Ok(Self { + input: input.to_owned(), + imports, + output, + details, + state: State::Init, + cursor: 0, + }) + } + /// Helper for PalletEngine::new, Builds pallet details from the construct_runtime! macro + fn build_pallet_details( + declaration: &RuntimeDeclaration, + ) -> anyhow::Result> { + // Instance map to track the number of current instances for a pallet entry + let mut imap: HashMap = HashMap::new(); + let mut pe: HashMap = HashMap::new(); + let pallet_entries = match declaration { + RuntimeDeclaration::Implicit(i) => { + for pallet in i.pallets.iter() { + let entry: String = pallet.span.source_text().unwrap(); + let entry = entry.split(':').next().unwrap().to_string(); + let index = pallet.index; + if pallet.instance.is_some() { + // If using instance syntax i.e. pallet:: set instance to 1 + imap.entry(entry.clone()).and_modify(|e| *e += 1).or_insert(1); + }; + pe.entry(entry.clone()) + .and_modify(|e| { + let v = imap.get(&entry).unwrap_or(&0); + e.numbers.instance = *v; + }) + .or_insert(ReadPalletEntry { + entry: entry.to_string(), + numbers: Numbers { index, instance: 0 }, + }); + } + pe.into_iter().map(|e| e.1).collect() + }, + RuntimeDeclaration::Explicit(e) | RuntimeDeclaration::ExplicitExpanded(e) => { + for pallet in e.pallets.iter() { + let entry: String = pallet.span.source_text().unwrap(); + let entry = entry.split(':').next().unwrap().to_string(); + let index = Some(pallet.index); + if pallet.instance.is_some() { + // If using instance syntax i.e. pallet:: set instance to 1 + imap.entry(entry.clone()).and_modify(|e| *e += 1).or_insert(1); + }; + pe.entry(entry.clone()) + .and_modify(|e| { + let v = imap.get(&entry).unwrap_or(&0); + e.numbers.instance = *v; + }) + .or_insert(ReadPalletEntry { + entry: entry.to_string(), + numbers: Numbers { index, instance: 0 }, + }); + } + pe.into_iter().map(|e| e.1).collect() + }, + }; + Ok(pallet_entries) + } } // Private methods for internal use. @@ -264,218 +259,211 @@ impl PalletEngine { // without analyzing it for newlines. #[allow(unused)] impl PalletEngine { - /// Prepare `output` by first, adding pre-CRT items such as imports and modules - /// Then adding the construct_runtime! macro - /// And finally adding the post-CRT items such as benchmarks, impl_runtime_apis! and so forth - fn prepare_output(&mut self) -> anyhow::Result<()> { - if self.state != State::Init { - bail!("PalletEngine is not in Init stage, cursor: {}", self.cursor); - } else { - // First pre-CRT items - imports - self.append_lines_from(0, self.imports.last_import)?; - self.cursor = self.imports.last_import; - self.state = State::Import; - Ok(()) - } - } - /// Prepare `output` for taking new pallet configurations - fn prepare_config(&mut self) -> anyhow::Result<()> { - if self.state != State::Import { - bail!( - "PalletEngine is not in Import stage, cursor: {}", - self.cursor - ); - } else { - self.append_lines_from(self.imports.last_import + 1, self.details.crt_start - 1); - self.state = State::Config; - Ok(()) - } - } - /// Prepare `output` for CRT items - fn prepare_crt(&mut self) -> anyhow::Result<()> { - if self.state != State::Config { - bail!( - "PalletEngine is not in Config stage, cursor: {}", - self.cursor - ); - } else if self.state == State::ConstructRuntime { - warn!( - "PalletEngine is already in ConstructRuntime stage, cursor: {}", - self.cursor - ); - return Ok(()); - } - self.add_new_line(1)?; - self.append_lines_from(self.details.crt_start, self.details.crt_end); - self.state = State::ConstructRuntime; - Ok(()) - } - /// Add `n` line-breaks to output - fn add_new_line(&mut self, n: usize) -> anyhow::Result<()> { - let mut file = OpenOptions::new().append(true).open(&self.output)?; - let newlines: String = std::iter::repeat('\n').take(n).collect(); - let rs = file.write_all(format!("{newlines}").as_bytes())?; - self.cursor += 1; - Ok(rs) - } - /// Append raw tokens to `output` file, cursor should be handled by caller - fn append_tokens(&self, tokens: TokenStream) -> anyhow::Result<()> { - let content = prettyplease::unparse(&syn::parse_file(&tokens.to_string())?); - let mut file = OpenOptions::new().append(true).open(&self.output)?; - file.write_all(content.as_bytes())?; - Ok(()) - } - /// Append string as is to `output` file, cursor should be handled by caller - fn append_str(&self, content: String) -> anyhow::Result<()> { - let mut file = OpenOptions::new().append(true).open(&self.output)?; - file.write_all(content.as_bytes())?; - Ok(()) - } - /// Insert import statement - /// As of now, it's imperative to call this function for pre-CRT item insertions - /// The correctness of calling this function depends on the `state` of PalletEngine - /// and the step_runner makes sure that it will only call this function when State is either - /// `State::Init` or `State::Import` - fn insert_import(&mut self, import_stmt: TokenStream) -> anyhow::Result<()> { - self.append_tokens(import_stmt); - self.imports.counter += 1; - self.imports.last_import += 1; - Ok(()) - } - /// Insert configuartion for a pallet - only for pallet-template atm - fn insert_config(&mut self, config: TokenStream) -> anyhow::Result<()> { - self.append_tokens(config); - self.cursor += 3; // TODO : change to count_newlines() - Ok(()) - } - /// Append lines [start..end] from `input` source to `output`. - /// Typically used to scaffold the `output` before and after making changes - fn append_lines_from(&self, start: usize, end: usize) -> anyhow::Result<()> { - let file = File::open(self.input.as_path())?; - let reader = BufReader::new(file); - // Assuming a worst case of 150 chars per line which is almost never the case in a typical substrate runtime file - // In the kitchensink node the maximum line length is 138 chars wide - let mut snip = String::with_capacity(150 * (end - start)); - let mut current_line = 0; + /// Prepare `output` by first, adding pre-CRT items such as imports and modules + /// Then adding the construct_runtime! macro + /// And finally adding the post-CRT items such as benchmarks, impl_runtime_apis! and so forth + fn prepare_output(&mut self) -> anyhow::Result<()> { + if self.state != State::Init { + bail!("PalletEngine is not in Init stage, cursor: {}", self.cursor); + } else { + // First pre-CRT items - imports + self.append_lines_from(0, self.imports.last_import)?; + self.cursor = self.imports.last_import; + self.state = State::Import; + Ok(()) + } + } + /// Prepare `output` for taking new pallet configurations + fn prepare_config(&mut self) -> anyhow::Result<()> { + if self.state != State::Import { + bail!("PalletEngine is not in Import stage, cursor: {}", self.cursor); + } else { + self.append_lines_from(self.imports.last_import + 1, self.details.crt_start - 1); + self.state = State::Config; + Ok(()) + } + } + /// Prepare `output` for CRT items + fn prepare_crt(&mut self) -> anyhow::Result<()> { + if self.state != State::Config { + bail!("PalletEngine is not in Config stage, cursor: {}", self.cursor); + } else if self.state == State::ConstructRuntime { + warn!("PalletEngine is already in ConstructRuntime stage, cursor: {}", self.cursor); + return Ok(()); + } + self.add_new_line(1)?; + self.cursor += 1; + self.append_lines_from(self.details.crt_start, self.details.crt_end); + self.state = State::ConstructRuntime; + Ok(()) + } + /// Add `n` line-breaks to output + fn add_new_line(&mut self, n: usize) -> anyhow::Result<()> { + let mut file = OpenOptions::new().append(true).open(&self.output)?; + let newlines: String = std::iter::repeat('\n').take(n).collect(); + let rs = file.write_all(format!("{newlines}").as_bytes())?; + self.cursor += 1; + Ok(rs) + } + /// Append raw tokens to `output` file, cursor should be handled by caller + fn append_tokens(&self, tokens: TokenStream) -> anyhow::Result<()> { + let content = prettyplease::unparse(&syn::parse_file(&tokens.to_string())?); + let mut file = OpenOptions::new().append(true).open(&self.output)?; + file.write_all(content.as_bytes())?; + Ok(()) + } + /// Append string as is to `output` file, cursor should be handled by caller + fn append_str(&self, content: String) -> anyhow::Result<()> { + let mut file = OpenOptions::new().append(true).open(&self.output)?; + file.write_all(content.as_bytes())?; + Ok(()) + } + /// Insert import statement + /// As of now, it's imperative to call this function for pre-CRT item insertions + /// The correctness of calling this function depends on the `state` of PalletEngine + /// and the step_runner makes sure that it will only call this function when State is either + /// `State::Init` or `State::Import` + fn insert_import(&mut self, import_stmt: TokenStream) -> anyhow::Result<()> { + self.append_tokens(import_stmt); + self.imports.counter += 1; + self.imports.last_import += 1; + Ok(()) + } + /// Insert configuartion for a pallet - only for pallet-template atm + fn insert_config(&mut self, config: TokenStream) -> anyhow::Result<()> { + self.append_tokens(config); + self.cursor += 3; // TODO : change to count_newlines() + Ok(()) + } + /// Append lines [start..end] from `input` source to `output`. + /// Typically used to scaffold the `output` before and after making changes + fn append_lines_from(&self, start: usize, end: usize) -> anyhow::Result<()> { + let file = File::open(self.input.as_path())?; + let reader = BufReader::new(file); + // Assuming a worst case of 150 chars per line which is almost never the case in a typical substrate runtime file + // In the kitchensink node the maximum line length is 138 chars wide + let mut snip = String::with_capacity(150 * (end - start)); + let mut current_line = 0; - for line in reader.lines() { - current_line += 1; + for line in reader.lines() { + current_line += 1; - if current_line < start { - // Skip lines until start - continue; - } else if current_line > end { - // Stop reading after end - break; - } + if current_line < start { + // Skip lines until start + continue; + } else if current_line > end { + // Stop reading after end + break; + } - snip.push_str(&line?); - snip.push('\n'); - } - let mut file = OpenOptions::new() - .append(true) - .open(&self.output) - .context("fn append_lines_from - cannot open output")?; - file.write_all(snip.as_bytes())?; - Ok(()) - } - /// Insert string at line. Errors if line number doesn't exist in `output` - /// cursor should be handled by caller - fn insert_at(&self, line: usize, str: &str) -> anyhow::Result<()> { - let reader = BufReader::new(File::open(&self.output)?); - let mut temp_file = tempfile::NamedTempFile::new()?; - let temp_path = &temp_file.path().to_path_buf(); - let mut written = false; - for (idx, l) in reader.lines().enumerate() { - if idx == line { - writeln!(temp_file, "{str}")?; - written = true; - } - writeln!(temp_file, "{}", l?)?; - } - fs::rename(temp_path, &self.output)?; - if !written { - bail!("PalletEngine output doesn't have line {line} to insert at"); - } - Ok(()) - } - /// Insert raw string at construct_runtime! Fails if there's no construct_runtime! in `output` - /// By default inserts at the end of the macro - fn insert_str_runtime(&mut self, str: &str) -> anyhow::Result<()> { - let runtime_contents = fs::read_to_string(&self.output)?; - let ast: syn::File = syn::parse_file(runtime_contents.as_ref())?; - let mut runtime_found = false; - for item in ast.items.iter() { - match item { - syn::Item::Macro(syn::ItemMacro { mac, .. }) => { - if let Some(mac_id) = mac.path.get_ident() { - if mac_id == "construct_runtime" { - runtime_found = true; - let r: RuntimeDeclaration = mac.parse_body().map_err(|err| { - anyhow!("PalletEngine output is in not parseable").context(err) - })?; - match r { - RuntimeDeclaration::Implicit(i) => { - let ultimate = i - .pallets - .last() - // This may be handled in the case that there's no pallets in CRT to begin with - // And subsequent pallets will be added - .expect("Fatal: No pallets defined in construct_runtime!") - .clone(); - let end = ultimate.span.end().line; - self.insert_at(end, str)?; - } - RuntimeDeclaration::Explicit(e) - | RuntimeDeclaration::ExplicitExpanded(e) => { - let end = e - .pallets - .last() - .expect("Fatal: No pallets defined in construct_runtime!") - .span - .end() - .line; - self.insert_at(end, str)?; - } - } - } - } - } - _ => {} - } - } - if !runtime_found { - // Should never happen - panic!("Construct Runtime not found in PalletEngine output. Cannot add pallet"); - } - // Typically insert_str_runtime would be used to insert a single pallet entry so this is okay - self.cursor += 1; - Ok(()) - } - /// Add a new pallet to RuntimeDeclaration and return it. - /// Used to pass a typed AddPallet struct to modify the RuntimeDeclaration - fn add_pallet_runtime(&mut self, new_pallet: AddPalletEntry) -> anyhow::Result<()> { - match &mut self.details.declaration { - RuntimeDeclaration::Implicit(i) => { - let mut ultimate = i - .pallets - .last() - .ok_or(anyhow!("Fatal: No pallets defined in construct_runtime!"))? - .clone(); - ultimate.index = new_pallet.index; - ultimate.path.inner.segments[0].ident = new_pallet.path; - ultimate.name = new_pallet.name; - i.pallets.push(ultimate); - } - RuntimeDeclaration::Explicit(e) => { - todo!() - } - RuntimeDeclaration::ExplicitExpanded(e) => { - todo!() - } - }; - Ok(()) - } + snip.push_str(&line?); + snip.push('\n'); + } + let mut file = OpenOptions::new() + .append(true) + .open(&self.output) + .context("fn append_lines_from - cannot open output")?; + file.write_all(snip.as_bytes())?; + Ok(()) + } + /// Insert string at line. Errors if line number doesn't exist in `output` + /// cursor should be handled by caller + fn insert_at(&self, line: usize, str: &str) -> anyhow::Result<()> { + let reader = BufReader::new(File::open(&self.output)?); + let mut temp_file = tempfile::NamedTempFile::new()?; + let temp_path = &temp_file.path().to_path_buf(); + let mut written = false; + for (idx, l) in reader.lines().enumerate() { + if idx == line { + writeln!(temp_file, "{str}")?; + written = true; + } + writeln!(temp_file, "{}", l?)?; + } + fs::rename(temp_path, &self.output)?; + if !written { + bail!("PalletEngine output doesn't have line {line} to insert at"); + } + Ok(()) + } + /// Insert raw string at construct_runtime! Fails if there's no construct_runtime! in `output` + /// By default inserts at the end of the macro. + /// Note: cursor is only incremented by one, so `str` is expected to be a single line + fn insert_str_runtime(&mut self, str: &str) -> anyhow::Result<()> { + let runtime_contents = fs::read_to_string(&self.output)?; + let ast: syn::File = syn::parse_file(runtime_contents.as_ref())?; + let mut runtime_found = false; + for item in ast.items.iter() { + match item { + syn::Item::Macro(syn::ItemMacro { mac, .. }) => { + if let Some(mac_id) = mac.path.get_ident() { + if mac_id == "construct_runtime" { + runtime_found = true; + let r: RuntimeDeclaration = mac.parse_body().map_err(|err| { + anyhow!("PalletEngine output is in not parseable").context(err) + })?; + match r { + RuntimeDeclaration::Implicit(i) => { + let ultimate = i + .pallets + .last() + // This may be handled in the case that there's no pallets in CRT to begin with + // And subsequent pallets will be added + .expect("Fatal: No pallets defined in construct_runtime!") + .clone(); + let end = ultimate.span.end().line; + self.insert_at(end, str)?; + }, + RuntimeDeclaration::Explicit(e) + | RuntimeDeclaration::ExplicitExpanded(e) => { + let end = e + .pallets + .last() + .expect("Fatal: No pallets defined in construct_runtime!") + .span + .end() + .line; + self.insert_at(end, str)?; + }, + } + } + } + }, + _ => {}, + } + } + if !runtime_found { + // Should never happen + panic!("Construct Runtime not found in PalletEngine output. Cannot add pallet"); + } + // Typically insert_str_runtime would be used to insert a single pallet entry so this is okay + self.cursor += 1; + Ok(()) + } + /// Add a new pallet to RuntimeDeclaration and return it. + /// Used to pass a typed AddPallet struct to modify the RuntimeDeclaration + fn add_pallet_runtime(&mut self, new_pallet: AddPalletEntry) -> anyhow::Result<()> { + match &mut self.details.declaration { + RuntimeDeclaration::Implicit(i) => { + let mut ultimate = i + .pallets + .last() + .ok_or(anyhow!("Fatal: No pallets defined in construct_runtime!"))? + .clone(); + ultimate.index = new_pallet.index; + ultimate.path.inner.segments[0].ident = new_pallet.path; + ultimate.name = new_pallet.name; + i.pallets.push(ultimate); + }, + RuntimeDeclaration::Explicit(e) => { + todo!() + }, + RuntimeDeclaration::ExplicitExpanded(e) => { + todo!() + }, + }; + Ok(()) + } } // TODO // fn count_newlines(tokens: TokenStream) -> usize { diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 56930f59..ee0630ae 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -105,7 +105,7 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { pe.insert_config(config)? } SwitchTo(State::ConstructRuntime) => pe.prepare_crt()?, - ConstructRuntimeEntry(_entry) => { + ConstructRuntimeEntry(entry) => { // TODO : Switch to add_pallet_runtime // pe.add_pallet_runtime(entry)? pe.insert_str_runtime("\t\tTemplate: pallet_parachain_template = 100,")?; diff --git a/tests/add/add.rs b/tests/add/add.rs new file mode 100644 index 00000000..e69de29b diff --git a/tests/add/lib.rs b/tests/add/lib.rs new file mode 100644 index 00000000..44936443 --- /dev/null +++ b/tests/add/lib.rs @@ -0,0 +1,779 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +mod weights; +pub mod xcm_config; + +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; +use smallvec::smallvec; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, +}; + +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; +use frame_support::{ + construct_runtime, + dispatch::DispatchClass, + genesis_builder_helper::{build_config, create_default_config}, + parameter_types, + traits::{ + ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, TransformOrigin, + }, + weights::{ + constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, + PalletId, +}; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, +}; +use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; +pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; +pub use sp_runtime::{MultiAddress, Perbill, Permill}; +use xcm_config::{RelayLocation, XcmOriginToTransactDispatchOrigin}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; + +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; + +// XCM Imports +use xcm::latest::prelude::BodyId; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Nonce = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// An index to a block. +pub type BlockNumber = u32; + +/// The address format for describing accounts. +pub type Address = MultiAddress; + +/// Block header type as expected by this runtime. +pub type Header = generic::Header; + +/// Block type as expected by this runtime. +pub type Block = generic::Block; + +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; + +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); + +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; + +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; + +/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the +/// node's balance type. +/// +/// This should typically create a mapping between the following ranges: +/// - `[0, MAXIMUM_BLOCK_WEIGHT]` +/// - `[Balance::min, Balance::max]` +/// +/// Yet, it can be used for any other sort of change to weight-fee. Some examples being: +/// - Setting it to `0` will essentially disable the weight fee. +/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: + // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT + let p = MILLIUNIT / 10; + let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + use sp_runtime::{ + generic, + traits::{BlakeTwo256, Hash as HashT}, + }; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; + /// Opaque block hash type. + pub type Hash = ::Output; +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + } +} + +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("template-parachain"), + impl_name: create_runtime_str!("template-parachain"), + authoring_version: 1, + spec_version: 1, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +/// This determines the average expected block time that we are targeting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 12000; + +// NOTE: Currently it is not possible to change the slot duration after the chain has started. +// Attempting to do so will brick block production. +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +// Unit = the base number of indivisible units for balances +pub const UNIT: Balance = 1_000_000_000_000; +pub const MILLIUNIT: Balance = 1_000_000_000; +pub const MICROUNIT: Balance = 1_000_000; + +/// The existential deposit. Set to 1/10 of the Connected Relay Chain. +pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; + +/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is +/// used to limit the maximal weight of a single extrinsic. +const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); + +/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by +/// `Operational` extrinsics. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +/// We allow for 0.5 of a second of compute with a 12 second average block time. +const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( + WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), + cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64, +); + +/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included +/// into the relay chain. +const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; +/// How many parachain blocks are processed by the relay chain per parent. Limits the +/// number of blocks authored per slot. +const BLOCK_PROCESSING_VELOCITY: u32 = 1; +/// Relay chain slot duration, in milliseconds. +const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + + // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. + // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the + // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize + // the lazy contract deletion. + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const SS58Prefix: u16 = 42; +} + +// Configure FRAME pallets to include in runtime. + +impl frame_system::Config for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Nonce; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The block type. + type Block = Block; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Runtime version. + type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type WeightInfo = (); +} + +impl pallet_authorship::Config for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (CollatorSelection,); +} + +parameter_types! { + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = 10 * MICROUNIT; +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = ConstU8<5>; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = (); +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); + type SelfParaId = parachain_info::Pallet; + type OutboundXcmpMessageSource = XcmpQueue; + type DmpQueue = frame_support::traits::EnqueueWithOrigin; + type ReservedDmpWeight = ReservedDmpWeight; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< + Runtime, + RELAY_CHAIN_SLOT_DURATION_MILLIS, + BLOCK_PROCESSING_VELOCITY, + UNINCLUDED_SEGMENT_CAPACITY, + >; +} + +impl parachain_info::Config for Runtime {} + +parameter_types! { + pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< + cumulus_primitives_core::AggregateMessageOrigin, + >; + #[cfg(not(feature = "runtime-benchmarks"))] + type MessageProcessor = xcm_builder::ProcessXcmMessage< + AggregateMessageOrigin, + xcm_executor::XcmExecutor, + RuntimeCall, + >; + type Size = u32; + // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: + type QueueChangeHandler = NarrowOriginToSibling; + type QueuePausedQuery = NarrowOriginToSibling; + type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type MaxStale = sp_core::ConstU32<8>; + type ServiceWeight = MessageQueueServiceWeight; +} + +impl cumulus_pallet_aura_ext::Config for Runtime {} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ChannelInfo = ParachainSystem; + type VersionWrapper = (); + // Enqueue XCMP messages from siblings for later processing. + type XcmpQueue = TransformOrigin; + type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = (); + type PriceForSiblingDelivery = NoPriceForMessageDelivery; +} + +parameter_types! { + pub const Period: u32 = 6 * HOURS; + pub const Offset: u32 = 0; +} + +impl pallet_session::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ValidatorId = ::AccountId; + // we don't have stash and controller, thus we don't need the convert as well. + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionManager = CollatorSelection; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; + type WeightInfo = (); +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<100_000>; + type AllowMultipleBlocksPerSlot = ConstBool; + #[cfg(feature = "experimental")] + type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; +} + +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const SessionLength: BlockNumber = 6 * HOURS; + // StakingAdmin pluralistic body. + pub const StakingAdminBodyId: BodyId = BodyId::Defense; +} + +/// We allow root and the StakingAdmin to execute privileged collator selection operations. +pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< + EnsureRoot, + EnsureXcm>, +>; + +impl pallet_collator_selection::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type PotId = PotId; + type MaxCandidates = ConstU32<100>; + type MinEligibleCollators = ConstU32<4>; + type MaxInvulnerables = ConstU32<20>; + // should be a multiple of session or things will get inconsistent + type KickThreshold = Period; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = (); +} + +construct_runtime!( + pub enum Runtime + { + // System support stuff. + System: frame_system = 0, + ParachainSystem: cumulus_pallet_parachain_system = 1, + Timestamp: pallet_timestamp = 2, + ParachainInfo: parachain_info = 3, + + // Monetary stuff. + Balances: pallet_balances = 10, + TransactionPayment: pallet_transaction_payment = 11, + + // Governance + Sudo: pallet_sudo = 15, + + // Collator support. The order of these 4 are important and shall not change. + Authorship: pallet_authorship = 20, + CollatorSelection: pallet_collator_selection = 21, + Session: pallet_session = 22, + Aura: pallet_aura = 23, + AuraExt: cumulus_pallet_aura_ext = 24, + + // XCM helpers. + XcmpQueue: cumulus_pallet_xcmp_queue = 30, + PolkadotXcm: pallet_xcm = 31, + CumulusXcm: cumulus_pallet_xcm = 32, + MessageQueue: pallet_message_queue = 33, + } +); + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_session, SessionBench::] + [pallet_timestamp, Timestamp] + [pallet_message_queue, MessageQueue] + [pallet_sudo, Sudo] + [pallet_collator_selection, CollatorSelection] + [cumulus_pallet_parachain_system, ParachainSystem] + [cumulus_pallet_xcmp_queue, XcmpQueue] + ); +} + +impl_runtime_apis! { + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities().into_inner() + } + } + + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi + for Runtime + { + fn query_call_info( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::RuntimeDispatchInfo { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_call_fee_details(call, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl cumulus_primitives_core::CollectCollationInfo for Runtime { + fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info(header) + } + } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + let weight = Executive::try_runtime_upgrade(checks).unwrap(); + (weight, RuntimeBlockWeights::get().max_block) + } + + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; + + use frame_system_benchmarking::Pallet as SystemBench; + impl frame_system_benchmarking::Config for Runtime { + fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { + ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); + Ok(()) + } + + fn verify_set_code() { + System::assert_last_event(cumulus_pallet_parachain_system::Event::::ValidationFunctionStored.into()); + } + } + + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + impl cumulus_pallet_session_benchmarking::Config for Runtime {} + + use frame_support::traits::WhitelistedStorageKeys; + let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + add_benchmarks!(params, batches); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } + + impl sp_genesis_builder::GenesisBuilder for Runtime { + fn create_default_config() -> Vec { + create_default_config::() + } + + fn build_config(config: Vec) -> sp_genesis_builder::Result { + build_config::(config) + } + } +} + +cumulus_pallet_parachain_system::register_validate_block! { + Runtime = Runtime, + BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, +} diff --git a/tests/add/out_lib.rs b/tests/add/out_lib.rs new file mode 100644 index 00000000..e69de29b From 83d2d2c5fc1db89f60714ae97936f25fc5eac91e Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 8 Mar 2024 22:41:59 +0530 Subject: [PATCH 11/57] test : add_parachain_pallet_template --- Cargo.lock | 81 ++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/engines/pallet_engine/mod.rs | 2 +- tests/add.rs | 20 ++++++++ tests/add/add.rs | 0 tests/add/out_lib.rs | 0 6 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/add.rs delete mode 100644 tests/add/add.rs delete mode 100644 tests/add/out_lib.rs diff --git a/Cargo.lock b/Cargo.lock index fc5999d4..b4c9cdcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,6 +418,21 @@ dependencies = [ "nom", ] +[[package]] +name = "assert_cmd" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "ast_node" version = "0.9.5" @@ -1041,6 +1056,17 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "regex-automata 0.4.6", + "serde", +] + [[package]] name = "bumpalo" version = "3.15.4" @@ -2183,6 +2209,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.8.1" @@ -2257,6 +2289,12 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "docify" version = "0.2.7" @@ -5299,6 +5337,7 @@ version = "0.1.0" dependencies = [ "anyhow", "askama", + "assert_cmd", "cfg-expr", "clap", "cliclack", @@ -5356,6 +5395,33 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "predicates" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "prettier-please" version = "0.2.0" @@ -8492,6 +8558,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "text_lines" version = "0.6.0" @@ -9352,6 +9424,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.1" diff --git a/Cargo.toml b/Cargo.toml index db6b1c17..40f1b8c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ name = "pop" path = "src/main.rs" [dev-dependencies] +assert_cmd = "2.0.14" tempdir = "0.3.7" [dependencies] diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index f485a0b3..ec3c6458 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -468,4 +468,4 @@ impl PalletEngine { // TODO // fn count_newlines(tokens: TokenStream) -> usize { // unimplemented!() -// } +// } \ No newline at end of file diff --git a/tests/add.rs b/tests/add.rs new file mode 100644 index 00000000..d2177c2e --- /dev/null +++ b/tests/add.rs @@ -0,0 +1,20 @@ +use assert_cmd::Command; +use std::fs; +use std::path::PathBuf; +use tempdir::TempDir; +#[test] +fn add_parachain_pallet_template() { + let temp_dir = TempDir::new("add-pallet-test").unwrap(); + let output = temp_dir.path().join("test_lib.rs"); + fs::copy(PathBuf::from("tests/add/lib.rs"), &output).unwrap(); + Command::cargo_bin("pop") + .unwrap() + .args(&["add", "template", "-r", "test_lib.rs"]) + .current_dir(&temp_dir) + .assert() + .success(); + let contents : String = fs::read_to_string(&output).unwrap(); + assert!(contents.contains("pub use pallet_parachain_template;")); + assert!(contents.contains("impl pallet_parachain_template::Config for Runtime {")); + assert!(contents.contains("Template: pallet_parachain_template")); +} diff --git a/tests/add/add.rs b/tests/add/add.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/add/out_lib.rs b/tests/add/out_lib.rs deleted file mode 100644 index e69de29b..00000000 From cc3ca54511d315be0aebe2d0d853ac563df1abe3 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sat, 9 Mar 2024 11:45:34 +0530 Subject: [PATCH 12/57] improve test --- tests/add.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/add.rs b/tests/add.rs index d2177c2e..c0c58968 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -6,15 +6,18 @@ use tempdir::TempDir; fn add_parachain_pallet_template() { let temp_dir = TempDir::new("add-pallet-test").unwrap(); let output = temp_dir.path().join("test_lib.rs"); - fs::copy(PathBuf::from("tests/add/lib.rs"), &output).unwrap(); + let source_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/add/lib.rs"); + println!("source file : {:?}", source_file); + fs::copy(&source_file, &output).unwrap(); Command::cargo_bin("pop") .unwrap() .args(&["add", "template", "-r", "test_lib.rs"]) .current_dir(&temp_dir) .assert() .success(); - let contents : String = fs::read_to_string(&output).unwrap(); - assert!(contents.contains("pub use pallet_parachain_template;")); - assert!(contents.contains("impl pallet_parachain_template::Config for Runtime {")); - assert!(contents.contains("Template: pallet_parachain_template")); + let contents = fs::read_to_string(&output).unwrap(); + + assert_eq!(contents.matches("pub use pallet_parachain_template;").count(), 1); + assert_eq!(contents.matches("impl pallet_parachain_template::Config for Runtime {").count(), 1); + assert_eq!(contents.matches("Template: pallet_parachain_template").count(), 1); } From 0d4063490f2e2a709af4bf7722c37fe563ee9d90 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sat, 9 Mar 2024 12:07:53 +0530 Subject: [PATCH 13/57] style command --- src/commands/add/mod.rs | 96 ++++++++++++++++++++++------------------- tests/add.rs | 1 + 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 4c70f8c6..8daefd88 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -1,65 +1,71 @@ use std::path::PathBuf; -use clap::{Args, Subcommand}; - use crate::engines::pallet_engine; +use clap::{Args, Subcommand}; +use cliclack::{intro, outro}; +use console::style; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub(crate) struct AddArgs { - #[command(subcommand)] - /// Pallet to add to the runtime - pub(crate) pallet: AddPallet, - #[arg(global = true, short, long)] - /// Runtime path; for example: `sub0/runtime/src/lib.rs` - /// Cargo Manifest path will be inferred as `../Cargo.toml` - pub(crate) runtime: Option, + #[command(subcommand)] + /// Pallet to add to the runtime + pub(crate) pallet: AddPallet, + #[arg(global = true, short, long)] + /// Runtime path; for example: `sub0/runtime/src/lib.rs` + /// Cargo Manifest path will be inferred as `../Cargo.toml` + pub(crate) runtime: Option, } #[derive(Subcommand, Clone)] #[command(subcommand_required = true)] pub(crate) enum AddPallet { - /// Insert `pallet-parachain-template` into the runtime. - Template, - /// Insert a frame-pallet into the runtime. - Frame(FrameArgs), + /// Insert `pallet-parachain-template` into the runtime. + Template, + /// Insert a frame-pallet into the runtime. + Frame(FrameArgs), } #[derive(Args, Clone)] pub(crate) struct FrameArgs { - #[arg(short, long)] - // TODO: Not ready for use - pub(crate) name: String, + #[arg(short, long)] + // TODO: Not ready for use + pub(crate) name: String, } impl AddArgs { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - let runtime_path = match self.runtime { - Some(ref s) => { - let path = PathBuf::from(s); - if !path.exists() { - anyhow::bail!("Invalid runtime path: {}", path.display()); - } - path - } - None => { - // TODO: Fetch runtime either from cache - // Fix: This is a placeholder path, should not be used - unimplemented!( - "provide a runtime path until cache is implemented: --runtime " - ); - } - }; - let pallet = match self.pallet { - AddPallet::Template => format!("pallet-parachain-template"), - AddPallet::Frame(FrameArgs { .. }) => { - eprintln!("Sorry, frame pallets cannot be added right now"); - std::process::exit(1); - // format!("FRAME-pallet-{name}") - } - }; - pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; - println!("Added {}\n-> to {}", pallet, runtime_path.display()); - Ok(()) - } + pub(crate) fn execute(&self) -> anyhow::Result<()> { + let runtime_path = match self.runtime { + Some(ref s) => { + let path = PathBuf::from(s); + if !path.exists() { + anyhow::bail!("Invalid runtime path: {}", path.display()); + } + path + }, + None => { + // TODO: Fetch runtime either from cache + // Fix: This is a placeholder path, should not be used + unimplemented!( + "provide a runtime path until cache is implemented: --runtime " + ); + }, + }; + let pallet = match self.pallet { + AddPallet::Template => format!("pallet-parachain-template"), + AddPallet::Frame(FrameArgs { .. }) => { + eprintln!("Sorry, frame pallets cannot be added right now"); + std::process::exit(1); + // format!("FRAME-pallet-{name}") + }, + }; + intro(format!( + "{}: Adding pallet \"{}\"!", + style(" Pop CLI ").black().on_magenta(), + &pallet, + ))?; + pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; + outro(format!("Added {}\n-> to {}", pallet, runtime_path.display()))?; + Ok(()) + } } diff --git a/tests/add.rs b/tests/add.rs index c0c58968..c3db72d2 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -2,6 +2,7 @@ use assert_cmd::Command; use std::fs; use std::path::PathBuf; use tempdir::TempDir; + #[test] fn add_parachain_pallet_template() { let temp_dir = TempDir::new("add-pallet-test").unwrap(); From 736deb49cfa9c5f5b628c65c30bf406534c496ac Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sat, 9 Mar 2024 13:58:10 +0530 Subject: [PATCH 14/57] tweaks for correct cursor tracking --- src/engines/pallet_engine/mod.rs | 49 +++-- src/engines/pallet_engine/steps.rs | 292 +++++++++++++++-------------- 2 files changed, 177 insertions(+), 164 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index ec3c6458..d7d5ad69 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -78,6 +78,7 @@ pub struct PalletEngine { state: State, /// Cursor for tracking where we are in the output cursor: usize, + } impl Drop for PalletEngine { fn drop(&mut self) { @@ -109,8 +110,6 @@ struct ImportDetails { /// On reading the source file, we obtain `last_import` which is the ending line of final import /// statement, and also from where additional pallet imports must be added last_import: usize, - /// Tracker for the number of imports added by PalletEngine. Initial value is 0. - counter: usize, } // Public API impl PalletEngine { @@ -120,9 +119,9 @@ impl PalletEngine { } /// Consume self merging `output` and `input` /// Call this to finalize edits - pub fn merge(self) -> anyhow::Result<()> { + pub fn merge(mut self) -> anyhow::Result<()> { // TODO: since we are not interacting with any post-CRT items, this is ok - self.append_lines_from(self.details.crt_end + 1, self.details.file_end)?; + &mut self.append_lines_from(self.details.crt_end + 1, self.details.file_end)?; fs::copy(&self.output, &self.input)?; fs::remove_file(&self.output); Ok(()) @@ -183,7 +182,6 @@ impl PalletEngine { } let imports = ImportDetails { last_import: last_import.expect("Imports are always present"), - counter: 0, }; let Some(details) = details else { bail!("No pallets/construct_runtime! found in input"); @@ -268,7 +266,7 @@ impl PalletEngine { } else { // First pre-CRT items - imports self.append_lines_from(0, self.imports.last_import)?; - self.cursor = self.imports.last_import; + self.state = State::Import; Ok(()) } @@ -292,7 +290,6 @@ impl PalletEngine { return Ok(()); } self.add_new_line(1)?; - self.cursor += 1; self.append_lines_from(self.details.crt_start, self.details.crt_end); self.state = State::ConstructRuntime; Ok(()) @@ -323,21 +320,21 @@ impl PalletEngine { /// The correctness of calling this function depends on the `state` of PalletEngine /// and the step_runner makes sure that it will only call this function when State is either /// `State::Init` or `State::Import` - fn insert_import(&mut self, import_stmt: TokenStream) -> anyhow::Result<()> { - self.append_tokens(import_stmt); - self.imports.counter += 1; - self.imports.last_import += 1; + fn insert_import(&mut self, import_stmt: (TokenStream, usize)) -> anyhow::Result<()> { + self.append_tokens(import_stmt.0); + self.imports.last_import += import_stmt.1; Ok(()) } /// Insert configuartion for a pallet - only for pallet-template atm - fn insert_config(&mut self, config: TokenStream) -> anyhow::Result<()> { - self.append_tokens(config); - self.cursor += 3; // TODO : change to count_newlines() + fn insert_config(&mut self, config: (TokenStream, usize)) -> anyhow::Result<()> { + self.append_tokens(config.0); + self.cursor += config.1; Ok(()) } /// Append lines [start..end] from `input` source to `output`. /// Typically used to scaffold the `output` before and after making changes - fn append_lines_from(&self, start: usize, end: usize) -> anyhow::Result<()> { + /// Increment cursor by exactly the number of lines inserted + fn append_lines_from(&mut self, start: usize, end: usize) -> anyhow::Result<()> { let file = File::open(self.input.as_path())?; let reader = BufReader::new(file); // Assuming a worst case of 150 chars per line which is almost never the case in a typical substrate runtime file @@ -364,6 +361,13 @@ impl PalletEngine { .open(&self.output) .context("fn append_lines_from - cannot open output")?; file.write_all(snip.as_bytes())?; + self.cursor += end - start; + Ok(()) + } + /// Same as `append_lines_from` but doesn't update cursor + fn append_lines_from_no_update(&mut self, start: usize, end: usize) -> anyhow::Result<()> { + self.append_lines_from(start, end)?; + self.cursor -= (end - start); Ok(()) } /// Insert string at line. Errors if line number doesn't exist in `output` @@ -441,8 +445,14 @@ impl PalletEngine { Ok(()) } /// Add a new pallet to RuntimeDeclaration and return it. - /// Used to pass a typed AddPallet struct to modify the RuntimeDeclaration + /// Used to pass a typed AddPallet to modify the RuntimeDeclaration + /// Overwrites existing CRT in output, this means that `self.cursor` has to backtracked to crt_start + /// and updated after the pallet entry has been inserted fn add_pallet_runtime(&mut self, new_pallet: AddPalletEntry) -> anyhow::Result<()> { + use std::io::{Seek, SeekFrom}; + // re-render output CRT: + self.insert_at(self.cursor, "//---- ReRender from add_pallet_runtime ----\n")?; + println!("cursor -> {}", self.cursor); match &mut self.details.declaration { RuntimeDeclaration::Implicit(i) => { let mut ultimate = i @@ -462,10 +472,9 @@ impl PalletEngine { todo!() }, }; + // new_lines will tell cursor to update accounting for the new pallet + // self.render_pallets(new_lines)?; Ok(()) } } -// TODO -// fn count_newlines(tokens: TokenStream) -> usize { -// unimplemented!() -// } \ No newline at end of file +// TODO \ No newline at end of file diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index ee0630ae..8525e3ee 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,3 +1,4 @@ +use super::State; use super::{pallet_entry::AddPalletEntry, PalletEngine}; use crate::commands::add::AddPallet; use anyhow::Result; @@ -6,168 +7,171 @@ use log::{error, warn}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use Steps::*; -use super::State; /// Define the steps needed for a particular pallet insertion +/// As of now, there's no clean solution to find out the newlines (\n) in a TokenStream +/// so variants expecting Tokenstreams accompany a line count datum for PalletEngine cursor. #[derive(Debug)] pub(super) enum Steps { - /// Import statements for pallet - RuntimePalletImport(TokenStream2), - /// Every pallet must impl pallet::Config for Runtime - RuntimePalletConfiguration(TokenStream2), - /// The runtime/Cargo.toml needs an import for the pallet being inserted - /// This includes features [try-runtime, runtime-benchmarks, std], path information for `git` or local path - RuntimePalletDependency(Dependency), - /// ConstructRuntime! entry - ConstructRuntimeEntry(AddPalletEntry), - /// Include a `list_benchmarks!` entry - ListBenchmarks(String), - /// Does pallet require a genesis configuration? - ChainspecGenesisConfig(String), - /// ChainSpec imports if necessary - ChainspecGenesisImport(TokenStream2), - /// Node specific imports if the above two are required - NodePalletDependency(Dependency), - /// PalletEngine State transitions - SwitchTo(State), + /// Import statements for pallet + RuntimePalletImport((TokenStream2, usize)), + /// Every pallet must impl pallet::Config for Runtime + RuntimePalletConfiguration((TokenStream2, usize)), + /// The runtime/Cargo.toml needs an import for the pallet being inserted + /// This includes features [try-runtime, runtime-benchmarks, std], path information for `git` or local path + RuntimePalletDependency(Dependency), + /// ConstructRuntime! entry + ConstructRuntimeEntry(AddPalletEntry), + /// Include a `list_benchmarks!` entry + ListBenchmarks(String), + /// Does pallet require a genesis configuration? + ChainspecGenesisConfig(String), + /// ChainSpec imports if necessary + ChainspecGenesisImport((TokenStream2, usize)), + /// Node specific imports if the above two are required + NodePalletDependency(Dependency), + /// PalletEngine State transitions + SwitchTo(State), } /// Some rules to follow when constructing steps: /// The pallet engine state expects to go as edits would, i.e. top to bottom lexically /// So it makes sense for any given file, to first include an import, then items that refer to it /// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` sin that order. pub(super) fn step_builder(pallet: AddPallet) -> Result> { - let mut steps: Vec = vec![]; - match pallet { - // Adding a pallet-parachain-template requires 5 distinct steps - AddPallet::Template => { - // steps.push(RuntimePalletDependency(Dependency::runtime_template())); - steps.push(RuntimePalletImport(quote!( - // Imports by pop-cli - pub use pallet_parachain_template; - ))); - steps.push(SwitchTo(State::Config)); - steps.push(RuntimePalletConfiguration(quote!( - /// Configure the pallet template in pallets/template. - impl pallet_parachain_template::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - } - ))); - steps.push(SwitchTo(State::ConstructRuntime)); - steps.push(ConstructRuntimeEntry(AddPalletEntry::new( - // Index - None, - // Path - "pallet_parachain_template", - // Pallet name - // TODO (high priority): implement name conflict resolution strategy - "Template", - ))); - // steps.push(NodePalletDependency(Dependency::node_template())) - } - AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), - }; - Ok(steps) + let mut steps: Vec = vec![]; + match pallet { + // Adding a pallet-parachain-template requires 5 distinct steps + AddPallet::Template => { + // steps.push(RuntimePalletDependency(Dependency::runtime_template())); + steps.push(RuntimePalletImport(( + quote!( + // Imports by pop-cli + pub use pallet_parachain_template; + ), + 3, + ))); + steps.push(SwitchTo(State::Config)); + steps.push(RuntimePalletConfiguration(( + quote!( + /// Configure the pallet template in pallets/template. + impl pallet_parachain_template::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + } + ), + 5, + ))); + steps.push(SwitchTo(State::ConstructRuntime)); + steps.push(ConstructRuntimeEntry(AddPalletEntry::new( + // Index + None, + // Path + "pallet_parachain_template", + // Pallet name + // TODO (high priority): implement name conflict resolution strategy + "Template", + ))); + // steps.push(NodePalletDependency(Dependency::node_template())) + }, + AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), + }; + Ok(steps) } /// Execute steps on PalletEngine. /// Each execution edits a file. /// Sequence of steps matters so take care when ordering them /// Works only for Template pallets at the moment.. See config and CRT inserts pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { - use super::State::*; - pe.prepare_output()?; - for step in steps.into_iter() { - match step { - // RuntimePalletDependency(step) => pe.insert(step), - RuntimePalletImport(stmt) => { - match pe.state { - Init => { - warn!("`prepare_output` was not called"); - pe.state = Import; - pe.insert_import(stmt); - } - Import => pe.insert_import(stmt)?, - _ => { - // We don't support writing import statements in any other engine state - // Log non-fatal error and continue - error!( - "Cannot write import stmts in state {0:?}. Check step builder", - pe.state - ); - continue; - } - }; - } - SwitchTo(State::Config) => pe.prepare_config()?, - RuntimePalletConfiguration(config) => { - if pe.state != Config { - // Not really a fatal error, but may cause unexpected behaviour - warn!("Engine not in Config state, executing config insertion anyways"); - } - pe.insert_config(config)? - } - SwitchTo(State::ConstructRuntime) => pe.prepare_crt()?, - ConstructRuntimeEntry(entry) => { - // TODO : Switch to add_pallet_runtime - // pe.add_pallet_runtime(entry)? - pe.insert_str_runtime("\t\tTemplate: pallet_parachain_template = 100,")?; - } - // ListBenchmarks(step) => pe.insert(step), - // ListBenchmarks(step) => pe.insert(step), - // ChainspecGenesisConfig(step) => pe.insert(step), - // ChainspecGenesisImport(step) => pe.insert(step), - // NodePalletDependency(step) => pe.insert(step), - step => { - unimplemented!("{step:?} unimplemented") - } - }; // -- match -- - } // -- for -- - // Finalize runtime edits - pe.merge()?; - // TODO: Finalize toml and chainspec edits - Ok(()) + use super::State::*; + pe.prepare_output()?; + for step in steps.into_iter() { + match step { + // RuntimePalletDependency(step) => pe.insert(step), + RuntimePalletImport(stmt) => { + match pe.state { + Init => { + warn!("`prepare_output` was not called"); + pe.state = Import; + pe.insert_import(stmt); + }, + Import => pe.insert_import(stmt)?, + _ => { + // We don't support writing import statements in any other engine state + // Log non-fatal error and continue + error!( + "Cannot write import stmts in state {0:?}. Check step builder", + pe.state + ); + continue; + }, + }; + }, + SwitchTo(State::Config) => pe.prepare_config()?, + RuntimePalletConfiguration(config) => { + if pe.state != Config { + // Not really a fatal error, but may cause unexpected behaviour + warn!("Engine not in Config state, executing config insertion anyways"); + } + pe.insert_config(config)? + }, + SwitchTo(State::ConstructRuntime) => pe.prepare_crt()?, + ConstructRuntimeEntry(entry) => { + // TODO : Switch to add_pallet_runtime + pe.add_pallet_runtime(entry)? + // pe.insert_str_runtime("\t\tTemplate: pallet_parachain_template = 100,")?; + }, + // ListBenchmarks(step) => pe.insert(step), + // ListBenchmarks(step) => pe.insert(step), + // ChainspecGenesisConfig(step) => pe.insert(step), + // ChainspecGenesisImport(step) => pe.insert(step), + // NodePalletDependency(step) => pe.insert(step), + step => { + unimplemented!("{step:?} unimplemented") + }, + }; // -- match -- + } // -- for -- + // Finalize runtime edits + pe.merge()?; + // TODO: Finalize toml and chainspec edits + Ok(()) } mod dependency { - use strum_macros::{Display, EnumString}; + use strum_macros::{Display, EnumString}; - #[derive(EnumString, Display, Debug)] - pub(in crate::engines::pallet_engine) enum Features { - #[strum(serialize = "std")] - Std, - #[strum(serialize = "runtime-benchmarks")] - RuntimeBenchmarks, - #[strum(serialize = "try-runtime")] - TryRuntime, - Custom(String), - } - #[derive(Debug)] - pub(in crate::engines::pallet_engine) struct Dependency { - features: Vec, - path: String, - no_default_features: bool, - } + #[derive(EnumString, Display, Debug)] + pub(in crate::engines::pallet_engine) enum Features { + #[strum(serialize = "std")] + Std, + #[strum(serialize = "runtime-benchmarks")] + RuntimeBenchmarks, + #[strum(serialize = "try-runtime")] + TryRuntime, + Custom(String), + } + #[derive(Debug)] + pub(in crate::engines::pallet_engine) struct Dependency { + features: Vec, + path: String, + no_default_features: bool, + } - impl Dependency { - /// Dependencies required for adding a pallet-parachain-template to runtime - pub(in crate::engines::pallet_engine) fn runtime_template() -> Self { - Self { - features: vec![ - Features::RuntimeBenchmarks, - Features::TryRuntime, - Features::Std, - ], - // TODO hardcode for now - path: format!(r#"path = "../pallets/template""#), - no_default_features: true, - } - } - /// Dependencies required for adding a pallet-parachain-template to node - pub(in crate::engines::pallet_engine) fn node_template() -> Self { - Self { - features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], - // TODO hardcode for now - path: format!(r#"path = "../pallets/template""#), - no_default_features: false, - } - } - } + impl Dependency { + /// Dependencies required for adding a pallet-parachain-template to runtime + pub(in crate::engines::pallet_engine) fn runtime_template() -> Self { + Self { + features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], + // TODO hardcode for now + path: format!(r#"path = "../pallets/template""#), + no_default_features: true, + } + } + /// Dependencies required for adding a pallet-parachain-template to node + pub(in crate::engines::pallet_engine) fn node_template() -> Self { + Self { + features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], + // TODO hardcode for now + path: format!(r#"path = "../pallets/template""#), + no_default_features: false, + } + } + } } From 85a7e47aaa9e8d24f47d95472ebdc8f25836d1d6 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sat, 9 Mar 2024 14:11:55 +0530 Subject: [PATCH 15/57] default to use insert_str_runtime for implicit runtime decl entries. --- src/engines/pallet_engine/mod.rs | 63 +++++++++++++++--------------- src/engines/pallet_engine/steps.rs | 4 +- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index d7d5ad69..42136731 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -26,6 +26,7 @@ use pallet_entry::Numbers; use pallet_entry::{AddPalletEntry, ReadPalletEntry}; use parser::RuntimeDeclaration; use proc_macro2::TokenStream; +use quote::quote; use std::{ collections::HashMap, fs::{self, File, OpenOptions}, @@ -78,7 +79,6 @@ pub struct PalletEngine { state: State, /// Cursor for tracking where we are in the output cursor: usize, - } impl Drop for PalletEngine { fn drop(&mut self) { @@ -180,9 +180,8 @@ impl PalletEngine { _ => {}, }; } - let imports = ImportDetails { - last_import: last_import.expect("Imports are always present"), - }; + let imports = + ImportDetails { last_import: last_import.expect("Imports are always present") }; let Some(details) = details else { bail!("No pallets/construct_runtime! found in input"); }; @@ -328,7 +327,7 @@ impl PalletEngine { /// Insert configuartion for a pallet - only for pallet-template atm fn insert_config(&mut self, config: (TokenStream, usize)) -> anyhow::Result<()> { self.append_tokens(config.0); - self.cursor += config.1; + self.cursor += config.1; Ok(()) } /// Append lines [start..end] from `input` source to `output`. @@ -449,32 +448,34 @@ impl PalletEngine { /// Overwrites existing CRT in output, this means that `self.cursor` has to backtracked to crt_start /// and updated after the pallet entry has been inserted fn add_pallet_runtime(&mut self, new_pallet: AddPalletEntry) -> anyhow::Result<()> { - use std::io::{Seek, SeekFrom}; - // re-render output CRT: - self.insert_at(self.cursor, "//---- ReRender from add_pallet_runtime ----\n")?; - println!("cursor -> {}", self.cursor); - match &mut self.details.declaration { - RuntimeDeclaration::Implicit(i) => { - let mut ultimate = i - .pallets - .last() - .ok_or(anyhow!("Fatal: No pallets defined in construct_runtime!"))? - .clone(); - ultimate.index = new_pallet.index; - ultimate.path.inner.segments[0].ident = new_pallet.path; - ultimate.name = new_pallet.name; - i.pallets.push(ultimate); - }, - RuntimeDeclaration::Explicit(e) => { - todo!() - }, - RuntimeDeclaration::ExplicitExpanded(e) => { - todo!() - }, - }; - // new_lines will tell cursor to update accounting for the new pallet - // self.render_pallets(new_lines)?; + let mut entry = String::new(); + let AddPalletEntry { name, path, index } = new_pallet; + if let Some(idx) = index { + entry = format!("\t\t{}: {} = {},", name, path, idx); + } else { + entry = format!("\t\t{}: {},", name, path); + } + self.insert_str_runtime(&entry)?; + // match &mut self.details.declaration { + // RuntimeDeclaration::Implicit(i) => { + // let mut ultimate = i + // .pallets + // .last() + // .ok_or(anyhow!("Fatal: No pallets defined in construct_runtime!"))? + // .clone(); + // ultimate.index = new_pallet.index; + // ultimate.path.inner.segments[0].ident = new_pallet.path; + // ultimate.name = new_pallet.name; + // i.pallets.push(ultimate); + // }, + // RuntimeDeclaration::Explicit(e) => { + // todo!() + // }, + // RuntimeDeclaration::ExplicitExpanded(e) => { + // todo!() + // }, + // }; Ok(()) } } -// TODO \ No newline at end of file +// TODO diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 8525e3ee..cb4183c5 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -61,7 +61,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { ))); steps.push(SwitchTo(State::ConstructRuntime)); steps.push(ConstructRuntimeEntry(AddPalletEntry::new( - // Index + // Index - None, means Pallet Engine will automatically compute an index None, // Path "pallet_parachain_template", @@ -114,9 +114,7 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { }, SwitchTo(State::ConstructRuntime) => pe.prepare_crt()?, ConstructRuntimeEntry(entry) => { - // TODO : Switch to add_pallet_runtime pe.add_pallet_runtime(entry)? - // pe.insert_str_runtime("\t\tTemplate: pallet_parachain_template = 100,")?; }, // ListBenchmarks(step) => pe.insert(step), // ListBenchmarks(step) => pe.insert(step), From 3e2c1509325834de858adccd5b8236ad4c301b02 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sat, 9 Mar 2024 16:46:45 +0530 Subject: [PATCH 16/57] typo --- Cargo.toml | 2 +- src/engines/pallet_engine/steps.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 93ae4a8a..e16a5c10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ walkdir = "2.4" frame-support-procedural-tools = "9.0.0" proc-macro2 = { version = "1.0.70", features = ["span-locations"] } quote = "1.0.33" -syn = { version = "2.0.39", features = ["full"] } +syn = { version = "2.0.52", features = ["full"] } cfg-expr = "0.15.5" prettyplease = "0.2.15" diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index cb4183c5..ea67935c 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -35,7 +35,7 @@ pub(super) enum Steps { /// Some rules to follow when constructing steps: /// The pallet engine state expects to go as edits would, i.e. top to bottom lexically /// So it makes sense for any given file, to first include an import, then items that refer to it -/// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` sin that order. +/// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` in that order. pub(super) fn step_builder(pallet: AddPallet) -> Result> { let mut steps: Vec = vec![]; match pallet { From 13c84bbf8ea76c784966e8b06168115d103fabd9 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sat, 9 Mar 2024 17:20:33 +0530 Subject: [PATCH 17/57] prepare dependency-injection --- Cargo.lock | 1 + Cargo.toml | 1 + src/engines/pallet_engine/mod.rs | 62 +++++++++++++++++++++++++++++- src/engines/pallet_engine/steps.rs | 60 ++++------------------------- 4 files changed, 70 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f3a5939..bd29627d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5473,6 +5473,7 @@ dependencies = [ "tempdir", "tempfile", "tokio", + "toml 0.8.10", "toml_edit 0.22.6", "tracing-subscriber 0.3.18", "url", diff --git a/Cargo.toml b/Cargo.toml index e16a5c10..c816d857 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ url = { version = "2.5", optional = true } zombienet-sdk = { git = "https://github.com/paritytech/zombienet-sdk", optional = true } zombienet-support = { git = "https://github.com/paritytech/zombienet-sdk", optional = true } uuid = { version = "1.7.0", features = ["v4"] } +toml = "0.8.10" [features] diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 42136731..fe05110e 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -21,6 +21,7 @@ mod template; use crate::commands::add::AddPallet; use anyhow::{anyhow, bail, Context}; +use dependency::{Dependency, Features}; use log::warn; use pallet_entry::Numbers; use pallet_entry::{AddPalletEntry, ReadPalletEntry}; @@ -40,8 +41,26 @@ pub use template::{create_pallet_template, TemplatePalletConfig}; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; + // Todo: move logic to sep. function. Add option to source from cli + let runtime_manifest = &runtime_path.parent().unwrap().join("Cargo.toml"); + let node_manifest = &runtime_path.parent().unwrap().parent().unwrap().join("node/Cargo.toml"); + let dep = TomlEditor { runtime: runtime_manifest.to_owned(), node: node_manifest.to_owned() }; let steps = step_builder(pallet)?; - run_steps(pe, steps) + run_steps(pe, dep, steps) +} + +struct TomlEditor { + // workspace + runtime: PathBuf, + node: PathBuf, +} +impl TomlEditor { + fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { + todo!() + } + fn inject_runtime(&self, dep: Dependency) -> anyhow::Result<()> { + todo!() + } } /// State of PalletEngine at any given moment in time @@ -479,3 +498,44 @@ impl PalletEngine { } } // TODO +mod dependency { + use strum_macros::{Display, EnumString}; + + #[derive(EnumString, Display, Debug)] + pub(in crate::engines::pallet_engine) enum Features { + #[strum(serialize = "std")] + Std, + #[strum(serialize = "runtime-benchmarks")] + RuntimeBenchmarks, + #[strum(serialize = "try-runtime")] + TryRuntime, + Custom(String), + } + #[derive(Debug)] + pub(in crate::engines::pallet_engine) struct Dependency { + features: Vec, + path: String, + no_default_features: bool, + } + + impl Dependency { + /// Dependencies required for adding a pallet-parachain-template to runtime + pub(in crate::engines::pallet_engine) fn runtime_template() -> Self { + Self { + features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], + // TODO hardcode for now + path: format!(r#"path = "../pallets/template""#), + no_default_features: true, + } + } + /// Dependencies required for adding a pallet-parachain-template to node + pub(in crate::engines::pallet_engine) fn node_template() -> Self { + Self { + features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], + // TODO hardcode for now + path: format!(r#"path = "../pallets/template""#), + no_default_features: false, + } + } + } +} diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index ea67935c..eead2a58 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,8 +1,6 @@ -use super::State; -use super::{pallet_entry::AddPalletEntry, PalletEngine}; +use super::{pallet_entry::AddPalletEntry, Dependency, Features, PalletEngine, State, TomlEditor}; use crate::commands::add::AddPallet; use anyhow::Result; -use dependency::Dependency; use log::{error, warn}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; @@ -41,7 +39,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { match pallet { // Adding a pallet-parachain-template requires 5 distinct steps AddPallet::Template => { - // steps.push(RuntimePalletDependency(Dependency::runtime_template())); + steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(( quote!( // Imports by pop-cli @@ -69,7 +67,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - // steps.push(NodePalletDependency(Dependency::node_template())) + steps.push(NodePalletDependency(Dependency::node_template())) }, AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; @@ -79,12 +77,12 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { /// Each execution edits a file. /// Sequence of steps matters so take care when ordering them /// Works only for Template pallets at the moment.. See config and CRT inserts -pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { +pub(super) fn run_steps(mut pe: PalletEngine, mut te: TomlEditor, steps: Vec) -> Result<()> { use super::State::*; pe.prepare_output()?; for step in steps.into_iter() { match step { - // RuntimePalletDependency(step) => pe.insert(step), + RuntimePalletDependency(dep) => te.inject_runtime(dep)?, RuntimePalletImport(stmt) => { match pe.state { Init => { @@ -113,14 +111,12 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { pe.insert_config(config)? }, SwitchTo(State::ConstructRuntime) => pe.prepare_crt()?, - ConstructRuntimeEntry(entry) => { - pe.add_pallet_runtime(entry)? - }, + ConstructRuntimeEntry(entry) => pe.add_pallet_runtime(entry)?, // ListBenchmarks(step) => pe.insert(step), // ListBenchmarks(step) => pe.insert(step), // ChainspecGenesisConfig(step) => pe.insert(step), // ChainspecGenesisImport(step) => pe.insert(step), - // NodePalletDependency(step) => pe.insert(step), + NodePalletDependency(dep) => te.inject_node(dep)?, step => { unimplemented!("{step:?} unimplemented") }, @@ -131,45 +127,3 @@ pub(super) fn run_steps(mut pe: PalletEngine, steps: Vec) -> Result<()> { // TODO: Finalize toml and chainspec edits Ok(()) } - -mod dependency { - use strum_macros::{Display, EnumString}; - - #[derive(EnumString, Display, Debug)] - pub(in crate::engines::pallet_engine) enum Features { - #[strum(serialize = "std")] - Std, - #[strum(serialize = "runtime-benchmarks")] - RuntimeBenchmarks, - #[strum(serialize = "try-runtime")] - TryRuntime, - Custom(String), - } - #[derive(Debug)] - pub(in crate::engines::pallet_engine) struct Dependency { - features: Vec, - path: String, - no_default_features: bool, - } - - impl Dependency { - /// Dependencies required for adding a pallet-parachain-template to runtime - pub(in crate::engines::pallet_engine) fn runtime_template() -> Self { - Self { - features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], - // TODO hardcode for now - path: format!(r#"path = "../pallets/template""#), - no_default_features: true, - } - } - /// Dependencies required for adding a pallet-parachain-template to node - pub(in crate::engines::pallet_engine) fn node_template() -> Self { - Self { - features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], - // TODO hardcode for now - path: format!(r#"path = "../pallets/template""#), - no_default_features: false, - } - } - } -} From d066526fd353a26ba70f61feb6a85e14ff667249 Mon Sep 17 00:00:00 2001 From: AlexD10S Date: Sat, 9 Mar 2024 21:18:33 +0100 Subject: [PATCH 18/57] refactor: add pallet subcommand --- src/commands/add/mod.rs | 71 ++++------------------------- src/commands/add/pallet.rs | 72 ++++++++++++++++++++++++++++++ src/engines/pallet_engine/mod.rs | 4 +- src/engines/pallet_engine/steps.rs | 10 ++--- src/main.rs | 7 ++- 5 files changed, 92 insertions(+), 72 deletions(-) create mode 100644 src/commands/add/pallet.rs diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 8daefd88..5086f3b3 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -1,71 +1,16 @@ -use std::path::PathBuf; - -use crate::engines::pallet_engine; use clap::{Args, Subcommand}; -use cliclack::{intro, outro}; -use console::style; + +pub mod pallet; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub(crate) struct AddArgs { #[command(subcommand)] - /// Pallet to add to the runtime - pub(crate) pallet: AddPallet, - #[arg(global = true, short, long)] - /// Runtime path; for example: `sub0/runtime/src/lib.rs` - /// Cargo Manifest path will be inferred as `../Cargo.toml` - pub(crate) runtime: Option, -} - -#[derive(Subcommand, Clone)] -#[command(subcommand_required = true)] -pub(crate) enum AddPallet { - /// Insert `pallet-parachain-template` into the runtime. - Template, - /// Insert a frame-pallet into the runtime. - Frame(FrameArgs), + pub command: AddCommands, } -#[derive(Args, Clone)] -pub(crate) struct FrameArgs { - #[arg(short, long)] - // TODO: Not ready for use - pub(crate) name: String, -} - -impl AddArgs { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - let runtime_path = match self.runtime { - Some(ref s) => { - let path = PathBuf::from(s); - if !path.exists() { - anyhow::bail!("Invalid runtime path: {}", path.display()); - } - path - }, - None => { - // TODO: Fetch runtime either from cache - // Fix: This is a placeholder path, should not be used - unimplemented!( - "provide a runtime path until cache is implemented: --runtime " - ); - }, - }; - let pallet = match self.pallet { - AddPallet::Template => format!("pallet-parachain-template"), - AddPallet::Frame(FrameArgs { .. }) => { - eprintln!("Sorry, frame pallets cannot be added right now"); - std::process::exit(1); - // format!("FRAME-pallet-{name}") - }, - }; - intro(format!( - "{}: Adding pallet \"{}\"!", - style(" Pop CLI ").black().on_magenta(), - &pallet, - ))?; - pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; - outro(format!("Added {}\n-> to {}", pallet, runtime_path.display()))?; - Ok(()) - } -} +#[derive(Subcommand)] +pub(crate) enum AddCommands { + /// Add a pallet to a runtime + Pallet(pallet::AddPalletCommand), +} \ No newline at end of file diff --git a/src/commands/add/pallet.rs b/src/commands/add/pallet.rs new file mode 100644 index 00000000..e197aa5f --- /dev/null +++ b/src/commands/add/pallet.rs @@ -0,0 +1,72 @@ + +use std::path::PathBuf; +use crate::{engines::pallet_engine, style::Theme}; +use clap::Args; +use cliclack::{intro, outro, set_theme, clear_screen}; +use console::style; + +pub(crate) enum PalletType { + /// `pallet-parachain-template`. + Template, + /// frame-pallet. + Frame, +} +pub(crate) struct PalletInfo { + pub(crate) name: String, + pub(crate) pallet_type: PalletType +} + + +#[derive(Args)] +#[command(args_conflicts_with_subcommands = true)] +pub(crate) struct AddPalletCommand { + /// Name of the frame-pallet to insert into the runtime. + #[clap(name = "frame", short('f'), long)] + pub(crate) frame_pallet: Option, + /// Runtime path; for example: `sub0/runtime/src/lib.rs` + /// Cargo Manifest path will be inferred as `../Cargo.toml` + pub(crate) runtime: Option, +} + +impl AddPalletCommand { + pub(crate) fn execute(&self) -> anyhow::Result<()> { + clear_screen()?; + set_theme(Theme); + let runtime_path = match self.runtime { + Some(ref s) => { + let path = PathBuf::from(s); + if !path.exists() { + anyhow::bail!("Invalid runtime path: {}", path.display()); + } + path + }, + None => { + // TODO: Fetch runtime either from cache + // Fix: This is a placeholder path, should not be used + unimplemented!( + "provide a runtime path until cache is implemented: --runtime " + ); + }, + }; + let pallet = PalletInfo { + name: format!("pallet-parachain-template"), + pallet_type: PalletType::Template, + }; + if self.frame_pallet.is_some() { + eprintln!("Sorry, frame pallets cannot be added right now"); + std::process::exit(1); + // pallet = PalletInfo { + // name: format!("FRAME-pallet-{name}"), + // pallet_type: PalletType::FRAME, + // }; + } + intro(format!( + "{}: Adding pallet \"{}\"!", + style(" Pop CLI ").black().on_magenta(), + &pallet.name, + ))?; + pallet_engine::execute(pallet, runtime_path.clone())?; + outro(format!("Added {}\n-> to {}", &self.frame_pallet.clone().unwrap_or(format!("pallet-parachain-template")), runtime_path.display()))?; + Ok(()) + } +} diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index fe05110e..2860ea94 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -19,7 +19,7 @@ mod parser; mod steps; mod template; -use crate::commands::add::AddPallet; +use crate::commands::add::pallet::PalletInfo; use anyhow::{anyhow, bail, Context}; use dependency::{Dependency, Features}; use log::warn; @@ -39,7 +39,7 @@ use syn::{spanned::Spanned, Item, ItemMacro}; pub use template::{create_pallet_template, TemplatePalletConfig}; /// The main entry point into the engine. -pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { +pub fn execute(pallet: PalletInfo, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; // Todo: move logic to sep. function. Add option to source from cli let runtime_manifest = &runtime_path.parent().unwrap().join("Cargo.toml"); diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index eead2a58..dc4d2438 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,5 +1,5 @@ use super::{pallet_entry::AddPalletEntry, Dependency, Features, PalletEngine, State, TomlEditor}; -use crate::commands::add::AddPallet; +use crate::commands::add::pallet::{PalletInfo, PalletType}; use anyhow::Result; use log::{error, warn}; use proc_macro2::TokenStream as TokenStream2; @@ -34,11 +34,11 @@ pub(super) enum Steps { /// The pallet engine state expects to go as edits would, i.e. top to bottom lexically /// So it makes sense for any given file, to first include an import, then items that refer to it /// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` in that order. -pub(super) fn step_builder(pallet: AddPallet) -> Result> { +pub(super) fn step_builder(pallet: PalletInfo) -> Result> { let mut steps: Vec = vec![]; - match pallet { + match pallet.pallet_type { // Adding a pallet-parachain-template requires 5 distinct steps - AddPallet::Template => { + PalletType::Template => { steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(( quote!( @@ -69,7 +69,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { ))); steps.push(NodePalletDependency(Dependency::node_template())) }, - AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), + PalletType::Frame => unimplemented!("Frame pallets not yet implemented"), }; Ok(steps) } diff --git a/src/main.rs b/src/main.rs index 49c2dbcc..ad0801f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,8 @@ enum Commands { /// Test a smart contract. #[clap(alias = "t")] Test(commands::test::TestArgs), - /// Add a pallet to the runtime + /// Add a pallet into the runtime + #[clap(alias = "a")] Add(commands::add::AddArgs), } @@ -73,7 +74,9 @@ async fn main() -> Result<()> { #[cfg(feature = "contract")] commands::test::TestCommands::Contract(cmd) => cmd.execute(), }, - Commands::Add(args) => args.execute(), + Commands::Add(args) => match &args.command { + commands::add::AddCommands::Pallet(cmd) => cmd.execute(), + }, } } From 8932833f1217c3409d1cdb59be50b6576a648ea9 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 10 Mar 2024 12:01:04 +0530 Subject: [PATCH 19/57] Revert "refactor: add pallet subcommand" This reverts commit d066526fd353a26ba70f61feb6a85e14ff667249. --- src/commands/add/mod.rs | 71 +++++++++++++++++++++++++---- src/commands/add/pallet.rs | 72 ------------------------------ src/engines/pallet_engine/mod.rs | 4 +- src/engines/pallet_engine/steps.rs | 10 ++--- src/main.rs | 7 +-- 5 files changed, 72 insertions(+), 92 deletions(-) delete mode 100644 src/commands/add/pallet.rs diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 5086f3b3..8daefd88 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -1,16 +1,71 @@ -use clap::{Args, Subcommand}; +use std::path::PathBuf; -pub mod pallet; +use crate::engines::pallet_engine; +use clap::{Args, Subcommand}; +use cliclack::{intro, outro}; +use console::style; #[derive(Args)] #[command(args_conflicts_with_subcommands = true)] pub(crate) struct AddArgs { #[command(subcommand)] - pub command: AddCommands, + /// Pallet to add to the runtime + pub(crate) pallet: AddPallet, + #[arg(global = true, short, long)] + /// Runtime path; for example: `sub0/runtime/src/lib.rs` + /// Cargo Manifest path will be inferred as `../Cargo.toml` + pub(crate) runtime: Option, +} + +#[derive(Subcommand, Clone)] +#[command(subcommand_required = true)] +pub(crate) enum AddPallet { + /// Insert `pallet-parachain-template` into the runtime. + Template, + /// Insert a frame-pallet into the runtime. + Frame(FrameArgs), } -#[derive(Subcommand)] -pub(crate) enum AddCommands { - /// Add a pallet to a runtime - Pallet(pallet::AddPalletCommand), -} \ No newline at end of file +#[derive(Args, Clone)] +pub(crate) struct FrameArgs { + #[arg(short, long)] + // TODO: Not ready for use + pub(crate) name: String, +} + +impl AddArgs { + pub(crate) fn execute(&self) -> anyhow::Result<()> { + let runtime_path = match self.runtime { + Some(ref s) => { + let path = PathBuf::from(s); + if !path.exists() { + anyhow::bail!("Invalid runtime path: {}", path.display()); + } + path + }, + None => { + // TODO: Fetch runtime either from cache + // Fix: This is a placeholder path, should not be used + unimplemented!( + "provide a runtime path until cache is implemented: --runtime " + ); + }, + }; + let pallet = match self.pallet { + AddPallet::Template => format!("pallet-parachain-template"), + AddPallet::Frame(FrameArgs { .. }) => { + eprintln!("Sorry, frame pallets cannot be added right now"); + std::process::exit(1); + // format!("FRAME-pallet-{name}") + }, + }; + intro(format!( + "{}: Adding pallet \"{}\"!", + style(" Pop CLI ").black().on_magenta(), + &pallet, + ))?; + pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; + outro(format!("Added {}\n-> to {}", pallet, runtime_path.display()))?; + Ok(()) + } +} diff --git a/src/commands/add/pallet.rs b/src/commands/add/pallet.rs deleted file mode 100644 index e197aa5f..00000000 --- a/src/commands/add/pallet.rs +++ /dev/null @@ -1,72 +0,0 @@ - -use std::path::PathBuf; -use crate::{engines::pallet_engine, style::Theme}; -use clap::Args; -use cliclack::{intro, outro, set_theme, clear_screen}; -use console::style; - -pub(crate) enum PalletType { - /// `pallet-parachain-template`. - Template, - /// frame-pallet. - Frame, -} -pub(crate) struct PalletInfo { - pub(crate) name: String, - pub(crate) pallet_type: PalletType -} - - -#[derive(Args)] -#[command(args_conflicts_with_subcommands = true)] -pub(crate) struct AddPalletCommand { - /// Name of the frame-pallet to insert into the runtime. - #[clap(name = "frame", short('f'), long)] - pub(crate) frame_pallet: Option, - /// Runtime path; for example: `sub0/runtime/src/lib.rs` - /// Cargo Manifest path will be inferred as `../Cargo.toml` - pub(crate) runtime: Option, -} - -impl AddPalletCommand { - pub(crate) fn execute(&self) -> anyhow::Result<()> { - clear_screen()?; - set_theme(Theme); - let runtime_path = match self.runtime { - Some(ref s) => { - let path = PathBuf::from(s); - if !path.exists() { - anyhow::bail!("Invalid runtime path: {}", path.display()); - } - path - }, - None => { - // TODO: Fetch runtime either from cache - // Fix: This is a placeholder path, should not be used - unimplemented!( - "provide a runtime path until cache is implemented: --runtime " - ); - }, - }; - let pallet = PalletInfo { - name: format!("pallet-parachain-template"), - pallet_type: PalletType::Template, - }; - if self.frame_pallet.is_some() { - eprintln!("Sorry, frame pallets cannot be added right now"); - std::process::exit(1); - // pallet = PalletInfo { - // name: format!("FRAME-pallet-{name}"), - // pallet_type: PalletType::FRAME, - // }; - } - intro(format!( - "{}: Adding pallet \"{}\"!", - style(" Pop CLI ").black().on_magenta(), - &pallet.name, - ))?; - pallet_engine::execute(pallet, runtime_path.clone())?; - outro(format!("Added {}\n-> to {}", &self.frame_pallet.clone().unwrap_or(format!("pallet-parachain-template")), runtime_path.display()))?; - Ok(()) - } -} diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 2860ea94..fe05110e 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -19,7 +19,7 @@ mod parser; mod steps; mod template; -use crate::commands::add::pallet::PalletInfo; +use crate::commands::add::AddPallet; use anyhow::{anyhow, bail, Context}; use dependency::{Dependency, Features}; use log::warn; @@ -39,7 +39,7 @@ use syn::{spanned::Spanned, Item, ItemMacro}; pub use template::{create_pallet_template, TemplatePalletConfig}; /// The main entry point into the engine. -pub fn execute(pallet: PalletInfo, runtime_path: PathBuf) -> anyhow::Result<()> { +pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; // Todo: move logic to sep. function. Add option to source from cli let runtime_manifest = &runtime_path.parent().unwrap().join("Cargo.toml"); diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index dc4d2438..eead2a58 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -1,5 +1,5 @@ use super::{pallet_entry::AddPalletEntry, Dependency, Features, PalletEngine, State, TomlEditor}; -use crate::commands::add::pallet::{PalletInfo, PalletType}; +use crate::commands::add::AddPallet; use anyhow::Result; use log::{error, warn}; use proc_macro2::TokenStream as TokenStream2; @@ -34,11 +34,11 @@ pub(super) enum Steps { /// The pallet engine state expects to go as edits would, i.e. top to bottom lexically /// So it makes sense for any given file, to first include an import, then items that refer to it /// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` in that order. -pub(super) fn step_builder(pallet: PalletInfo) -> Result> { +pub(super) fn step_builder(pallet: AddPallet) -> Result> { let mut steps: Vec = vec![]; - match pallet.pallet_type { + match pallet { // Adding a pallet-parachain-template requires 5 distinct steps - PalletType::Template => { + AddPallet::Template => { steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(( quote!( @@ -69,7 +69,7 @@ pub(super) fn step_builder(pallet: PalletInfo) -> Result> { ))); steps.push(NodePalletDependency(Dependency::node_template())) }, - PalletType::Frame => unimplemented!("Frame pallets not yet implemented"), + AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; Ok(steps) } diff --git a/src/main.rs b/src/main.rs index ad0801f8..49c2dbcc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,8 +41,7 @@ enum Commands { /// Test a smart contract. #[clap(alias = "t")] Test(commands::test::TestArgs), - /// Add a pallet into the runtime - #[clap(alias = "a")] + /// Add a pallet to the runtime Add(commands::add::AddArgs), } @@ -74,9 +73,7 @@ async fn main() -> Result<()> { #[cfg(feature = "contract")] commands::test::TestCommands::Contract(cmd) => cmd.execute(), }, - Commands::Add(args) => match &args.command { - commands::add::AddCommands::Pallet(cmd) => cmd.execute(), - }, + Commands::Add(args) => args.execute(), } } From 7c2b7ffd7fcd807a9b4a796514f614601526a719 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 10 Mar 2024 12:42:47 +0530 Subject: [PATCH 20/57] add pop add pallet subsubcommand --- src/commands/add/mod.rs | 22 +++++++++++++++++----- src/engines/pallet_engine/mod.rs | 13 +++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 8daefd88..6a832bfc 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -9,13 +9,18 @@ use console::style; #[command(args_conflicts_with_subcommands = true)] pub(crate) struct AddArgs { #[command(subcommand)] - /// Pallet to add to the runtime - pub(crate) pallet: AddPallet, + commands: AddCommands, #[arg(global = true, short, long)] /// Runtime path; for example: `sub0/runtime/src/lib.rs` /// Cargo Manifest path will be inferred as `../Cargo.toml` pub(crate) runtime: Option, } +#[derive(Subcommand)] +#[command(subcommand_required = true)] +pub(crate) enum AddCommands { + #[command(subcommand)] + Pallet(AddPallet), +} #[derive(Subcommand, Clone)] #[command(subcommand_required = true)] @@ -35,7 +40,14 @@ pub(crate) struct FrameArgs { impl AddArgs { pub(crate) fn execute(&self) -> anyhow::Result<()> { - let runtime_path = match self.runtime { + match self.commands { + AddCommands::Pallet(ref cmd) => cmd.clone().execute(&self.runtime), + } + } +} +impl AddPallet { + pub(crate) fn execute(self, runtime_path: &Option) -> anyhow::Result<()> { + let runtime_path = match runtime_path { Some(ref s) => { let path = PathBuf::from(s); if !path.exists() { @@ -51,7 +63,7 @@ impl AddArgs { ); }, }; - let pallet = match self.pallet { + let pallet = match self { AddPallet::Template => format!("pallet-parachain-template"), AddPallet::Frame(FrameArgs { .. }) => { eprintln!("Sorry, frame pallets cannot be added right now"); @@ -64,7 +76,7 @@ impl AddArgs { style(" Pop CLI ").black().on_magenta(), &pallet, ))?; - pallet_engine::execute(self.pallet.clone(), runtime_path.clone())?; + pallet_engine::execute(self, runtime_path.clone())?; outro(format!("Added {}\n-> to {}", pallet, runtime_path.display()))?; Ok(()) } diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index fe05110e..f7e2a389 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -42,17 +42,18 @@ pub use template::{create_pallet_template, TemplatePalletConfig}; pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; // Todo: move logic to sep. function. Add option to source from cli - let runtime_manifest = &runtime_path.parent().unwrap().join("Cargo.toml"); - let node_manifest = &runtime_path.parent().unwrap().parent().unwrap().join("node/Cargo.toml"); - let dep = TomlEditor { runtime: runtime_manifest.to_owned(), node: node_manifest.to_owned() }; + // let runtime_manifest = &runtime_path.parent().unwrap().join("Cargo.toml"); + // let node_manifest = &runtime_path.parent().unwrap().parent().unwrap().join("node/Cargo.toml"); + // let dep = TomlEditor { runtime: runtime_manifest.to_owned(), node: node_manifest.to_owned() }; + let dep = TomlEditor { ..Default::default() }; let steps = step_builder(pallet)?; run_steps(pe, dep, steps) } - +#[derive(Default)] struct TomlEditor { // workspace - runtime: PathBuf, - node: PathBuf, + runtime: Option, + node: Option, } impl TomlEditor { fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { From 70881b8b93bf3775dedbbef42f17b0a41315e0a7 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 10 Mar 2024 12:47:58 +0530 Subject: [PATCH 21/57] fix tests --- src/commands/add/mod.rs | 1 + src/engines/pallet_engine/steps.rs | 4 ++-- src/main.rs | 1 + tests/add.rs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 6a832bfc..f0faf1a6 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -19,6 +19,7 @@ pub(crate) struct AddArgs { #[command(subcommand_required = true)] pub(crate) enum AddCommands { #[command(subcommand)] + #[clap(alias = "p")] Pallet(AddPallet), } diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index eead2a58..a2bc7c26 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -39,7 +39,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { match pallet { // Adding a pallet-parachain-template requires 5 distinct steps AddPallet::Template => { - steps.push(RuntimePalletDependency(Dependency::runtime_template())); + // steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(( quote!( // Imports by pop-cli @@ -67,7 +67,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - steps.push(NodePalletDependency(Dependency::node_template())) + // steps.push(NodePalletDependency(Dependency::node_template())) }, AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; diff --git a/src/main.rs b/src/main.rs index 49c2dbcc..bc556e49 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,6 +41,7 @@ enum Commands { /// Test a smart contract. #[clap(alias = "t")] Test(commands::test::TestArgs), + #[clap(alias = "a")] /// Add a pallet to the runtime Add(commands::add::AddArgs), } diff --git a/tests/add.rs b/tests/add.rs index c3db72d2..bcf92fa1 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -12,7 +12,7 @@ fn add_parachain_pallet_template() { fs::copy(&source_file, &output).unwrap(); Command::cargo_bin("pop") .unwrap() - .args(&["add", "template", "-r", "test_lib.rs"]) + .args(&["add", "pallet", "template", "-r", "test_lib.rs"]) .current_dir(&temp_dir) .assert() .success(); From 023fdbff6bc368bd1b871fe9eec708a122d40afe Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 16:03:05 +0530 Subject: [PATCH 22/57] sub0 - template runtime dep injection --- Cargo.lock | 9 ++- Cargo.toml | 4 +- src/commands/add/mod.rs | 6 +- src/engines/pallet_engine/mod.rs | 109 +++++++++++++++++++++++------ src/engines/pallet_engine/steps.rs | 7 +- src/parachains/zombienet.rs | 8 +-- 6 files changed, 104 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63c674d9..e8ff5af9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5473,8 +5473,7 @@ dependencies = [ "tempdir", "tempfile", "tokio", - "toml 0.8.10", - "toml_edit 0.22.6", + "toml_edit 0.22.7", "tracing-subscriber 0.3.18", "url", "uuid", @@ -8943,7 +8942,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.6", + "toml_edit 0.22.7", ] [[package]] @@ -8992,9 +8991,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ "indexmap 2.2.5", "serde", diff --git a/Cargo.toml b/Cargo.toml index 799a3913..ddaedcb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ quote = "1.0.33" syn = { version = "2.0.52", features = ["full"] } cfg-expr = "0.15.5" prettyplease = "0.2.15" +toml_edit = { version = "0.22.7" } # contracts contract-build = { version = "4.0.0-rc.3", optional = true } @@ -51,13 +52,11 @@ reqwest = { version = "0.11", optional = true } serde_json = { version = "1.0", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } symlink = { version = "0.1", optional = true } -toml_edit = { version = "0.22", optional = true } tracing-subscriber = { version = "0.3", optional = true } url = { version = "2.5", optional = true } zombienet-sdk = { git = "https://github.com/r0gue-io/zombienet-sdk", branch = "pop", optional = true } zombienet-support = { git = "https://github.com/r0gue-io/zombienet-sdk", branch = "pop", optional = true } uuid = { version = "1.7.0", features = ["v4"] } -toml = "0.8.10" [features] default = ["contract", "parachain"] @@ -76,7 +75,6 @@ parachain = [ "dep:reqwest", "dep:serde_json", "dep:symlink", - "dep:toml_edit", "dep:tracing-subscriber", "dep:url", "dep:zombienet-sdk", diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index f0faf1a6..25967759 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -12,7 +12,7 @@ pub(crate) struct AddArgs { commands: AddCommands, #[arg(global = true, short, long)] /// Runtime path; for example: `sub0/runtime/src/lib.rs` - /// Cargo Manifest path will be inferred as `../Cargo.toml` + /// Runtime cargo manifest path will be inferred as `(parent of lib.rs)/Cargo.toml` pub(crate) runtime: Option, } #[derive(Subcommand)] @@ -60,7 +60,7 @@ impl AddPallet { // TODO: Fetch runtime either from cache // Fix: This is a placeholder path, should not be used unimplemented!( - "provide a runtime path until cache is implemented: --runtime " + "provide a runtime path until feat:cache is implemented: --runtime " ); }, }; @@ -69,7 +69,7 @@ impl AddPallet { AddPallet::Frame(FrameArgs { .. }) => { eprintln!("Sorry, frame pallets cannot be added right now"); std::process::exit(1); - // format!("FRAME-pallet-{name}") + // format!("FRAME pallet-{name}") }, }; intro(format!( diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index f7e2a389..1d2866e2 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -20,6 +20,7 @@ mod steps; mod template; use crate::commands::add::AddPallet; +use crate::helpers::write_to_file; use anyhow::{anyhow, bail, Context}; use dependency::{Dependency, Features}; use log::warn; @@ -28,6 +29,7 @@ use pallet_entry::{AddPalletEntry, ReadPalletEntry}; use parser::RuntimeDeclaration; use proc_macro2::TokenStream; use quote::quote; +use std::io::Read; use std::{ collections::HashMap, fs::{self, File, OpenOptions}, @@ -37,30 +39,93 @@ use std::{ use steps::{run_steps, step_builder}; use syn::{spanned::Spanned, Item, ItemMacro}; pub use template::{create_pallet_template, TemplatePalletConfig}; +use toml_edit::DocumentMut; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; - // Todo: move logic to sep. function. Add option to source from cli - // let runtime_manifest = &runtime_path.parent().unwrap().join("Cargo.toml"); - // let node_manifest = &runtime_path.parent().unwrap().parent().unwrap().join("node/Cargo.toml"); - // let dep = TomlEditor { runtime: runtime_manifest.to_owned(), node: node_manifest.to_owned() }; - let dep = TomlEditor { ..Default::default() }; + // Todo: Add option to source from cli + let dep = TomlEditor::from(&runtime_path); let steps = step_builder(pallet)?; run_steps(pe, dep, steps) } #[derive(Default)] struct TomlEditor { - // workspace - runtime: Option, - node: Option, + // workspace: PathBuf, + runtime: PathBuf, + node: PathBuf, } impl TomlEditor { - fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { - todo!() + /// Use default values for runtime/Cargo.toml and ../node/Cargo.toml + fn from(runtime_path: &Path) -> Self { + let runtime_manifest = runtime_path.parent().unwrap().parent().unwrap().join("Cargo.toml"); + let node_manifest = runtime_path + .parent() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap() + .join("node/Cargo.toml"); + // println!("{} {}", runtime_manifest.display(), node_manifest.display()); + Self { runtime: runtime_manifest, node: node_manifest } } + // fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { + + // self.inject(&self.node, dep) + // } fn inject_runtime(&self, dep: Dependency) -> anyhow::Result<()> { - todo!() + let mut s = String::new(); + let mut f = BufReader::new(File::open(&self.node)?); + f.read_to_string(&mut s) + .context("Dependency Injection: Failed to read runtime:Cargo.toml")?; + let doc = s.parse::().context("Cannot parse toml")?; + let updated_doc = self.inject(doc, dep)?.to_string(); + use std::io::Write; + let mut file = OpenOptions::new() + .write(true) + .truncate(true) + .create(false) + .open(&self.runtime) + .unwrap(); + file.write_all(updated_doc.as_bytes()) + .context("failed to update runtime:Cargo.toml") + } + fn inject(&self, mut doc: DocumentMut, dep: Dependency) -> anyhow::Result { + use toml_edit::{value, Item, Table}; + let Dependency { features, path, default_features } = dep; + let mut t = Table::new(); + t["path"] = value(Into::::into(path)); + t["version"] = value("1.0.0-dev"); + t["default-features"] = value(default_features); + doc["dependencies"]["pallet-parachain-template"] = value(t.into_inline_table()); + // for feat in features { + // match feat { + // Features::Std => { + // // features + // println!("std -> {:#?}", doc["features"]); + // let std = doc["features"]["std"].as_value_mut().expect("feature std not found"); + // let arr = std.as_array_mut().unwrap(); + // arr.push_formatted("pallet-parachain-template/std".into()); + // }, + // Features::RuntimeBenchmarks => { + // let rt_bnch = doc["features"]["runtime-benchmarks"] + // .as_value_mut() + // .expect("feature runtime-benchmarks not found"); + // let arr = rt_bnch.as_array_mut().unwrap(); + // arr.push_formatted("pallet-parachain-template/runtime-benchmarks".into()); + // }, + // Features::TryRuntime => { + // let try_rt = doc["features"]["try-runtime"] + // .as_value_mut() + // .expect("feature try-runtime not found"); + // let arr = try_rt.as_array_mut().unwrap(); + // arr.push_formatted("pallet-parachain-template/try-runtime".into()); + // }, + // Features::Custom(_) => unimplemented!("Custom features not supported yet"), + // } + // } + Ok(doc) } } @@ -514,28 +579,30 @@ mod dependency { } #[derive(Debug)] pub(in crate::engines::pallet_engine) struct Dependency { - features: Vec, - path: String, - no_default_features: bool, + pub(in crate::engines::pallet_engine) features: Vec, + /// Maybe local path, git url, or from crates.io in which case we will use this for version + pub(in crate::engines::pallet_engine) path: String, + pub(in crate::engines::pallet_engine) default_features: bool, } impl Dependency { - /// Dependencies required for adding a pallet-parachain-template to runtime - pub(in crate::engines::pallet_engine) fn runtime_template() -> Self { + /// Create dependencies required for adding a pallet-parachain-template to runtime + pub(in crate::engines::pallet_engine) fn template_runtime() -> Self { + log::warn!("Using default path for pallet-template `pallets/template`"); Self { features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], // TODO hardcode for now - path: format!(r#"path = "../pallets/template""#), - no_default_features: true, + path: format!("../pallets/template"), + default_features: false, } } - /// Dependencies required for adding a pallet-parachain-template to node - pub(in crate::engines::pallet_engine) fn node_template() -> Self { + /// Create dependencies required for adding a pallet-parachain-template to node + pub(in crate::engines::pallet_engine) fn template_node() -> Self { Self { features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], // TODO hardcode for now path: format!(r#"path = "../pallets/template""#), - no_default_features: false, + default_features: true, } } } diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index a2bc7c26..0bc81e7b 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -39,7 +39,6 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { match pallet { // Adding a pallet-parachain-template requires 5 distinct steps AddPallet::Template => { - // steps.push(RuntimePalletDependency(Dependency::runtime_template())); steps.push(RuntimePalletImport(( quote!( // Imports by pop-cli @@ -67,7 +66,8 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - // steps.push(NodePalletDependency(Dependency::node_template())) + steps.push(RuntimePalletDependency(Dependency::template_runtime())); + // steps.push(NodePalletDependency(Dependency::template_node())) }, AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; @@ -112,11 +112,12 @@ pub(super) fn run_steps(mut pe: PalletEngine, mut te: TomlEditor, steps: Vec pe.prepare_crt()?, ConstructRuntimeEntry(entry) => pe.add_pallet_runtime(entry)?, + RuntimePalletDependency(dep) => te.inject_runtime(dep)?, + // NodePalletDependency(dep) => te.inject_node(dep)?, // ListBenchmarks(step) => pe.insert(step), // ListBenchmarks(step) => pe.insert(step), // ChainspecGenesisConfig(step) => pe.insert(step), // ChainspecGenesisImport(step) => pe.insert(step), - NodePalletDependency(dep) => te.inject_node(dep)?, step => { unimplemented!("{step:?} unimplemented") }, diff --git a/src/parachains/zombienet.rs b/src/parachains/zombienet.rs index 95274db1..c6d18675 100644 --- a/src/parachains/zombienet.rs +++ b/src/parachains/zombienet.rs @@ -15,7 +15,7 @@ use std::{ }; use symlink::{remove_symlink_file, symlink_file}; use tempfile::{Builder, NamedTempFile}; -use toml_edit::{value, Document, Formatted, Item, Table, Value}; +use toml_edit::{value, DocumentMut, Formatted, Item, Table, Value}; use url::Url; use zombienet_sdk::{Network, NetworkConfig, NetworkConfigExt}; use zombienet_support::fs::local::LocalFileSystem; @@ -26,7 +26,7 @@ pub struct Zombienet { /// The cache location, used for caching binaries. cache: PathBuf, /// The config to be used to launch a network. - network_config: (PathBuf, Document), + network_config: (PathBuf, DocumentMut), /// The binary required to launch the relay chain. relay_chain: Binary, /// The binaries required to launch parachains. @@ -43,7 +43,7 @@ impl Zombienet { ) -> Result { // Parse network config let network_config_path = PathBuf::from(network_config); - let config = std::fs::read_to_string(&network_config_path)?.parse::()?; + let config = std::fs::read_to_string(&network_config_path)?.parse::()?; // Determine binaries let relay_chain_binary = Self::relay_chain(relay_chain_version, &config, &cache).await?; let mut parachain_binaries = IndexMap::new(); @@ -257,7 +257,7 @@ impl Zombienet { async fn relay_chain( version: Option<&String>, - network_config: &Document, + network_config: &DocumentMut, cache: &PathBuf, ) -> Result { const BINARY: &str = "polkadot"; From c15872103388980e3cfac4ea90e60e72434f5bb2 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 16:41:45 +0530 Subject: [PATCH 23/57] fix template toml path --- src/engines/pallet_engine/mod.rs | 53 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 1d2866e2..1cf59689 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -99,32 +99,31 @@ impl TomlEditor { t["version"] = value("1.0.0-dev"); t["default-features"] = value(default_features); doc["dependencies"]["pallet-parachain-template"] = value(t.into_inline_table()); - // for feat in features { - // match feat { - // Features::Std => { - // // features - // println!("std -> {:#?}", doc["features"]); - // let std = doc["features"]["std"].as_value_mut().expect("feature std not found"); - // let arr = std.as_array_mut().unwrap(); - // arr.push_formatted("pallet-parachain-template/std".into()); - // }, - // Features::RuntimeBenchmarks => { - // let rt_bnch = doc["features"]["runtime-benchmarks"] - // .as_value_mut() - // .expect("feature runtime-benchmarks not found"); - // let arr = rt_bnch.as_array_mut().unwrap(); - // arr.push_formatted("pallet-parachain-template/runtime-benchmarks".into()); - // }, - // Features::TryRuntime => { - // let try_rt = doc["features"]["try-runtime"] - // .as_value_mut() - // .expect("feature try-runtime not found"); - // let arr = try_rt.as_array_mut().unwrap(); - // arr.push_formatted("pallet-parachain-template/try-runtime".into()); - // }, - // Features::Custom(_) => unimplemented!("Custom features not supported yet"), - // } - // } + for feat in features { + match feat { + Features::Std => { + // features + let std = doc["features"]["std"].as_value_mut().expect("feature std not found"); + let arr = std.as_array_mut().unwrap(); + arr.push_formatted("pallet-parachain-template/std".into()); + }, + Features::RuntimeBenchmarks => { + let rt_bnch = doc["features"]["runtime-benchmarks"] + .as_value_mut() + .expect("feature runtime-benchmarks not found"); + let arr = rt_bnch.as_array_mut().unwrap(); + arr.push_formatted("pallet-parachain-template/runtime-benchmarks".into()); + }, + Features::TryRuntime => { + let try_rt = doc["features"]["try-runtime"] + .as_value_mut() + .expect("feature try-runtime not found"); + let arr = try_rt.as_array_mut().unwrap(); + arr.push_formatted("pallet-parachain-template/try-runtime".into()); + }, + Features::Custom(_) => unimplemented!("Custom features not supported yet"), + } + } Ok(doc) } } @@ -601,7 +600,7 @@ mod dependency { Self { features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], // TODO hardcode for now - path: format!(r#"path = "../pallets/template""#), + path: format!("../pallets/template"), default_features: true, } } From a6e713f917f9d8a544e33b0b4895a076fc0a59be Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 21:28:11 +0530 Subject: [PATCH 24/57] fix TomlEditor runtime path --- src/commands/new/pallet.rs | 2 +- src/engines/pallet_engine/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/new/pallet.rs b/src/commands/new/pallet.rs index 1f685ff1..f89a8c26 100644 --- a/src/commands/new/pallet.rs +++ b/src/commands/new/pallet.rs @@ -10,7 +10,7 @@ use std::fs; #[derive(Args)] pub struct NewPalletCommand { - #[arg(help = "Name of the pallet", default_value = "pallet-template")] + #[arg(help = "Name of the pallet", default_value = "pallet-parachain-template")] pub(crate) name: String, #[arg(short, long, help = "Name of authors", default_value = "Anonymous")] pub(crate) authors: Option, diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 1cf59689..a78f8f70 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -76,7 +76,7 @@ impl TomlEditor { // } fn inject_runtime(&self, dep: Dependency) -> anyhow::Result<()> { let mut s = String::new(); - let mut f = BufReader::new(File::open(&self.node)?); + let mut f = BufReader::new(File::open(&self.runtime)?); f.read_to_string(&mut s) .context("Dependency Injection: Failed to read runtime:Cargo.toml")?; let doc = s.parse::().context("Cannot parse toml")?; @@ -96,7 +96,7 @@ impl TomlEditor { let Dependency { features, path, default_features } = dep; let mut t = Table::new(); t["path"] = value(Into::::into(path)); - t["version"] = value("1.0.0-dev"); + t["version"] = value("0.1.0"); t["default-features"] = value(default_features); doc["dependencies"]["pallet-parachain-template"] = value(t.into_inline_table()); for feat in features { From ea01eadd993063f6617e8522f3e4ecfc332ff7ac Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 21:55:37 +0530 Subject: [PATCH 25/57] use consistent naming for template pallet : pallet-parachain-template --- README.md | 2 +- src/engines/pallet_engine/mod.rs | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 20c2d053..c630718c 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ There's also the shorter version: pop new parachain my-app -s DOT -d 6 -i 1_000_000_000 ``` -To create a new pallet, simply `pop new pallet`. And that's it. You will have a new `pallet-template` ready for hacking. +To create a new pallet, simply `pop new pallet`. And that's it. You will have a new `pallet-parachain-template` ready for hacking. To customize the new pallet you can follow these options: ```sh diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index a78f8f70..356c0b26 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -587,22 +587,24 @@ mod dependency { impl Dependency { /// Create dependencies required for adding a pallet-parachain-template to runtime pub(in crate::engines::pallet_engine) fn template_runtime() -> Self { - log::warn!("Using default path for pallet-template `pallets/template`"); + log::warn!("Using default path for pallet-parachain-template `pallets/pallet-parachain-template`"); Self { features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], // TODO hardcode for now - path: format!("../pallets/template"), + path: format!("../pallets/pallet-parachain-template"), default_features: false, } } - /// Create dependencies required for adding a pallet-parachain-template to node - pub(in crate::engines::pallet_engine) fn template_node() -> Self { - Self { - features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], - // TODO hardcode for now - path: format!("../pallets/template"), - default_features: true, - } - } + // TODO: Remove code - Node doesn't require template pallet deps by default + // but this maybe desirable for custom pallets. + // /// Create dependencies required for adding a pallet-parachain-template to node + // pub(in crate::engines::pallet_engine) fn template_node() -> Self { + // Self { + // features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], + // // TODO hardcode for now + // path: format!("../pallets/pallet-parachain-template"), + // default_features: true, + // } + // } } } From 8ab1ba93a10dc5fb6e4e74cd464e292454f86c24 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 22:04:02 +0530 Subject: [PATCH 26/57] remove - -> _ substitution in pallet name --- src/engines/pallet_engine/mod.rs | 2 +- src/engines/pallet_engine/steps.rs | 1 - src/engines/pallet_engine/template.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 356c0b26..7437935e 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -596,7 +596,7 @@ mod dependency { } } // TODO: Remove code - Node doesn't require template pallet deps by default - // but this maybe desirable for custom pallets. + // but this maybe desirable for custom pallets. // /// Create dependencies required for adding a pallet-parachain-template to node // pub(in crate::engines::pallet_engine) fn template_node() -> Self { // Self { diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 0bc81e7b..128bf74e 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -67,7 +67,6 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { "Template", ))); steps.push(RuntimePalletDependency(Dependency::template_runtime())); - // steps.push(NodePalletDependency(Dependency::template_node())) }, AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index 3dd08694..60b455e2 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -54,7 +54,7 @@ fn render_pallet( config: TemplatePalletConfig, pallet_path: &PathBuf, ) -> anyhow::Result<()> { - let pallet_name = pallet_name.replace('-', "_"); + // let pallet_name = pallet_name.replace('-', "_"); use crate::engines::generator::{ PalletBenchmarking, PalletCargoToml, PalletLib, PalletMock, PalletTests, }; From 1e6d69063ad12fd63c560384701617ff3f2bb187 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Tue, 12 Mar 2024 17:51:03 +0100 Subject: [PATCH 27/57] fix: use 9090 as pop node id --- tests/zombienet.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/zombienet.toml b/tests/zombienet.toml index 101841bb..3858af5c 100644 --- a/tests/zombienet.toml +++ b/tests/zombienet.toml @@ -23,7 +23,7 @@ default_command = "./polkadot-parachain" name = "asset-hub" [[parachains]] -id = 909 +id = 9090 default_command = "./pop-node" [[parachains.collators]] From 7304889887e41ef32a74ba0f81b09b729b74a85c Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 23:13:10 +0530 Subject: [PATCH 28/57] fix last_import step -_- --- src/engines/pallet_engine/steps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 128bf74e..2be48bdb 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -44,7 +44,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // Imports by pop-cli pub use pallet_parachain_template; ), - 3, + 2, ))); steps.push(SwitchTo(State::Config)); steps.push(RuntimePalletConfiguration(( From aed5436e5ded74aff6c54c4273b4e1fbd4c7b181 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 12 Mar 2024 23:34:14 +0530 Subject: [PATCH 29/57] set pallet-template version 1.0.0 --- src/engines/pallet_engine/mod.rs | 2 +- templates/pallet/Cargo.templ | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 7437935e..852fefbe 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -96,7 +96,7 @@ impl TomlEditor { let Dependency { features, path, default_features } = dep; let mut t = Table::new(); t["path"] = value(Into::::into(path)); - t["version"] = value("0.1.0"); + t["version"] = value("1.0.0"); t["default-features"] = value(default_features); doc["dependencies"]["pallet-parachain-template"] = value(t.into_inline_table()); for feat in features { diff --git a/templates/pallet/Cargo.templ b/templates/pallet/Cargo.templ index f3e2c907..1768773e 100644 --- a/templates/pallet/Cargo.templ +++ b/templates/pallet/Cargo.templ @@ -2,7 +2,7 @@ name = "^^name^^" authors = ["^^authors^^"] description = "^^description^^" -version = "0.1.0" +version = "1.0.0" license = "Unlicense" edition = "2021" From 1f497187dcec767254b9ad2c25f3317f4bed22f3 Mon Sep 17 00:00:00 2001 From: AlexD10S Date: Tue, 12 Mar 2024 20:17:39 +0100 Subject: [PATCH 30/57] fix: in pallet template Cargo use same dependencies versions as base-parachain --- templates/pallet/Cargo.templ | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/pallet/Cargo.templ b/templates/pallet/Cargo.templ index 1768773e..5474d7dc 100644 --- a/templates/pallet/Cargo.templ +++ b/templates/pallet/Cargo.templ @@ -14,17 +14,17 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Substrate -frame-benchmarking = { version = "26.0.0", default-features = false, optional = true} -frame-support = { version = "26.0.0", default-features = false} -frame-system = { version = "26.0.0", default-features = false} +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1", default-features = false } [dev-dependencies] serde = { version = "1.0.188" } # Substrate -sp-core = { version = "26.0.0", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1", default-features = false } # sp-io = { version = "28.0.0", default-features = false} -sp-runtime = { version = "29.0.0", default-features = false} +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1", default-features = false } [features] default = [ "std" ] From a39b1c201970661092713d887e55a18884557ec3 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:57:21 +0100 Subject: [PATCH 31/57] style: fmt --- src/commands/mod.rs | 2 +- src/engines/pallet_engine/pallet_entry.rs | 47 +- src/engines/pallet_engine/parser.rs | 1462 ++++++++++----------- src/engines/pallet_engine/template.rs | 117 +- src/main.rs | 6 +- 5 files changed, 790 insertions(+), 844 deletions(-) diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 0d09fdc8..ab203b7c 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,6 +1,6 @@ +pub(crate) mod add; pub(crate) mod build; pub(crate) mod call; pub(crate) mod new; -pub(crate) mod add; pub(crate) mod test; pub(crate) mod up; diff --git a/src/engines/pallet_engine/pallet_entry.rs b/src/engines/pallet_engine/pallet_entry.rs index a3fa7331..0fa381e4 100644 --- a/src/engines/pallet_engine/pallet_entry.rs +++ b/src/engines/pallet_engine/pallet_entry.rs @@ -4,40 +4,39 @@ use syn::Ident; /// Format containing necessary information for appending pallets #[derive(Debug)] pub(super) struct AddPalletEntry { - pub(super) index: Option, - pub(super) path: Ident, - pub(super) name: Ident, + pub(super) index: Option, + pub(super) path: Ident, + pub(super) name: Ident, } impl AddPalletEntry { - pub(super) fn new(index: Option, path: &str, name: &str) -> Self { - let path = Ident::new(path, proc_macro2::Span::call_site()); - let name = Ident::new(name, proc_macro2::Span::call_site()); - Self { index, path, name } - } + pub(super) fn new(index: Option, path: &str, name: &str) -> Self { + let path = Ident::new(path, proc_macro2::Span::call_site()); + let name = Ident::new(name, proc_macro2::Span::call_site()); + Self { index, path, name } + } } impl From for AddPalletEntry { - fn from(value: ReadPalletEntry) -> Self { - todo!("") - } + fn from(value: ReadPalletEntry) -> Self { + todo!("") + } } - /// All information that's needed to represent a pallet in a construct_runtime! invocation /// The processing must be based on the context i.e. the type of RuntimeDeclaration in the runtime pub(super) struct ReadPalletEntry { - /// Pallet identifier. "System" in `System: frame_system = 1` - pub(super) entry: String, - /// Stores a tuple of information (index, instance). For single instances, instance = 0 - pub(super) numbers: Numbers, + /// Pallet identifier. "System" in `System: frame_system = 1` + pub(super) entry: String, + /// Stores a tuple of information (index, instance). For single instances, instance = 0 + pub(super) numbers: Numbers, } #[derive(Default, Debug)] pub(super) struct Numbers { - /// Stores the first index as parsed from input file - pub(super) index: Option, - /// Counts the number of instances in runtime file - /// 0 means only 1 unique instance was found - /// 1 means the pallet is using instance syntax pallet:: - /// >1 means multiple pallet instances were found - pub(super) instance: u8, -} \ No newline at end of file + /// Stores the first index as parsed from input file + pub(super) index: Option, + /// Counts the number of instances in runtime file + /// 0 means only 1 unique instance was found + /// 1 means the pallet is using instance syntax pallet:: + /// >1 means multiple pallet instances were found + pub(super) instance: u8, +} diff --git a/src/engines/pallet_engine/parser.rs b/src/engines/pallet_engine/parser.rs index 7c57ada4..3a7f85f0 100644 --- a/src/engines/pallet_engine/parser.rs +++ b/src/engines/pallet_engine/parser.rs @@ -20,65 +20,59 @@ use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::{Delimiter, Group, Punct, Spacing, Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use std::{ - collections::{HashMap, HashSet}, - str::FromStr, + collections::{HashMap, HashSet}, + str::FromStr, }; use syn::{ - ext::IdentExt, - parse::{Parse, ParseStream}, - parse_quote, - punctuated::Punctuated, - spanned::Spanned, - token, Attribute, Error, Ident, Path, Result, Token, + ext::IdentExt, + parse::{Parse, ParseStream}, + parse_quote, + punctuated::Punctuated, + spanned::Spanned, + token, Attribute, Error, Ident, Path, Result, Token, }; /// Span for delimiting tokens. macro_rules! bs_delim_span { - ($d:ident) => { - proc_macro2::Group::new(proc_macro2::Delimiter::$d, proc_macro2::TokenStream::new()) - .delim_span() - }; - ($d:ident, $group:tt) => { - proc_macro2::Group::new(proc_macro2::Delimiter::$d, $group).delim_span() - }; + ($d:ident) => { + proc_macro2::Group::new(proc_macro2::Delimiter::$d, proc_macro2::TokenStream::new()) + .delim_span() + }; + ($d:ident, $group:tt) => { + proc_macro2::Group::new(proc_macro2::Delimiter::$d, $group).delim_span() + }; } /// Tokens that delimit a group macro_rules! delim_token { - (Parenthesis, $group:tt) => { - syn::token::Paren { - span: bs_delim_span!(Parenthesis, $group), - } - }; - ($d:ident) => { - syn::token::$d { - span: bs_delim_span!($d), - } - }; - ($d:ident, $group:tt) => { - syn::token::$d { - span: bs_delim_span!($d, $group), - } - }; + (Parenthesis, $group:tt) => { + syn::token::Paren { span: bs_delim_span!(Parenthesis, $group) } + }; + ($d:ident) => { + syn::token::$d { span: bs_delim_span!($d) } + }; + ($d:ident, $group:tt) => { + syn::token::$d { span: bs_delim_span!($d, $group) } + }; } mod keyword { - syn::custom_keyword!(Block); - syn::custom_keyword!(NodeBlock); - syn::custom_keyword!(UncheckedExtrinsic); - syn::custom_keyword!(Pallet); - syn::custom_keyword!(Call); - syn::custom_keyword!(Storage); - syn::custom_keyword!(Event); - syn::custom_keyword!(Error); - syn::custom_keyword!(Config); - syn::custom_keyword!(Origin); - syn::custom_keyword!(Inherent); - syn::custom_keyword!(ValidateUnsigned); - syn::custom_keyword!(FreezeReason); - syn::custom_keyword!(HoldReason); - syn::custom_keyword!(LockId); - syn::custom_keyword!(SlashReason); - syn::custom_keyword!(exclude_parts); - syn::custom_keyword!(use_parts); - syn::custom_keyword!(expanded); + syn::custom_keyword!(Block); + syn::custom_keyword!(NodeBlock); + syn::custom_keyword!(UncheckedExtrinsic); + syn::custom_keyword!(Pallet); + syn::custom_keyword!(Call); + syn::custom_keyword!(Storage); + syn::custom_keyword!(Event); + syn::custom_keyword!(Error); + syn::custom_keyword!(Config); + syn::custom_keyword!(Origin); + syn::custom_keyword!(Inherent); + syn::custom_keyword!(ValidateUnsigned); + syn::custom_keyword!(FreezeReason); + syn::custom_keyword!(HoldReason); + syn::custom_keyword!(LockId); + syn::custom_keyword!(SlashReason); + syn::custom_keyword!(exclude_parts); + syn::custom_keyword!(use_parts); + syn::custom_keyword!(expanded); } /// Declaration of a runtime. @@ -88,359 +82,339 @@ mod keyword { /// implicit. #[derive(Debug)] pub enum RuntimeDeclaration { - Implicit(ImplicitRuntimeDeclaration), - Explicit(ExplicitRuntimeDeclaration), - ExplicitExpanded(ExplicitRuntimeDeclaration), + Implicit(ImplicitRuntimeDeclaration), + Explicit(ExplicitRuntimeDeclaration), + ExplicitExpanded(ExplicitRuntimeDeclaration), } impl ToTokens for RuntimeDeclaration { - fn to_tokens(&self, tokens: &mut TokenStream) { - let group = match self { - RuntimeDeclaration::Implicit(i) => i.to_token_stream(), - RuntimeDeclaration::Explicit(_) | RuntimeDeclaration::ExplicitExpanded(_) => { - unimplemented!() - } - }; - let crt = syn::Macro { - path: parse_quote!(construct_runtime), - bang_token: Token![!](Span::call_site()), - tokens: group.clone(), - delimiter: syn::MacroDelimiter::Paren(delim_token!(Parenthesis, group)), - }; - tokens.extend(crt.into_token_stream()); - } + fn to_tokens(&self, tokens: &mut TokenStream) { + let group = match self { + RuntimeDeclaration::Implicit(i) => i.to_token_stream(), + RuntimeDeclaration::Explicit(_) | RuntimeDeclaration::ExplicitExpanded(_) => { + unimplemented!() + }, + }; + let crt = syn::Macro { + path: parse_quote!(construct_runtime), + bang_token: Token![!](Span::call_site()), + tokens: group.clone(), + delimiter: syn::MacroDelimiter::Paren(delim_token!(Parenthesis, group)), + }; + tokens.extend(crt.into_token_stream()); + } } /// Declaration of a runtime with some pallet with implicit declaration of parts. #[derive(Debug)] pub struct ImplicitRuntimeDeclaration { - pub name: Ident, - pub where_section: Option, - pub pallets: Vec, + pub name: Ident, + pub where_section: Option, + pub pallets: Vec, } impl ToTokens for ImplicitRuntimeDeclaration { - fn to_tokens(&self, tokens: &mut TokenStream) { - let (name, where_section) = (&self.name, &self.where_section); - tokens.extend(quote!( + fn to_tokens(&self, tokens: &mut TokenStream) { + let (name, where_section) = (&self.name, &self.where_section); + tokens.extend(quote!( pub struct #name #where_section)); - let mut pallets = TokenStream::new(); - for p in &self.pallets { - pallets.extend(p.to_token_stream()); - } - tokens.append(Group::new(Delimiter::Brace, pallets)); - } + let mut pallets = TokenStream::new(); + for p in &self.pallets { + pallets.extend(p.to_token_stream()); + } + tokens.append(Group::new(Delimiter::Brace, pallets)); + } } /// Declaration of a runtime with all pallet having explicit declaration of parts. #[derive(Debug)] pub struct ExplicitRuntimeDeclaration { - pub name: Ident, - pub where_section: Option, - pub pallets: Vec, - pub pallets_token: token::Brace, + pub name: Ident, + pub where_section: Option, + pub pallets: Vec, + pub pallets_token: token::Brace, } impl Parse for RuntimeDeclaration { - fn parse(input: ParseStream) -> Result { - input.parse::()?; - - // Support either `enum` or `struct`. - if input.peek(Token![struct]) { - input.parse::()?; - } else { - input.parse::()?; - } - - let name = input.parse::()?; - let where_section = if input.peek(token::Where) { - Some(input.parse()?) - } else { - None - }; - let pallets = - input.parse::>>()?; - let pallets_token = pallets.token; - - match convert_pallets(pallets.content.inner.into_iter().collect())? { - PalletsConversion::Implicit(pallets) => { - Ok(RuntimeDeclaration::Implicit(ImplicitRuntimeDeclaration { - name, - where_section, - pallets, - })) - } - PalletsConversion::Explicit(pallets) => { - Ok(RuntimeDeclaration::Explicit(ExplicitRuntimeDeclaration { - name, - where_section, - pallets, - pallets_token, - })) - } - PalletsConversion::ExplicitExpanded(pallets) => Ok( - RuntimeDeclaration::ExplicitExpanded(ExplicitRuntimeDeclaration { - name, - where_section, - pallets, - pallets_token, - }), - ), - } - } + fn parse(input: ParseStream) -> Result { + input.parse::()?; + + // Support either `enum` or `struct`. + if input.peek(Token![struct]) { + input.parse::()?; + } else { + input.parse::()?; + } + + let name = input.parse::()?; + let where_section = if input.peek(token::Where) { Some(input.parse()?) } else { None }; + let pallets = + input.parse::>>()?; + let pallets_token = pallets.token; + + match convert_pallets(pallets.content.inner.into_iter().collect())? { + PalletsConversion::Implicit(pallets) => { + Ok(RuntimeDeclaration::Implicit(ImplicitRuntimeDeclaration { + name, + where_section, + pallets, + })) + }, + PalletsConversion::Explicit(pallets) => { + Ok(RuntimeDeclaration::Explicit(ExplicitRuntimeDeclaration { + name, + where_section, + pallets, + pallets_token, + })) + }, + PalletsConversion::ExplicitExpanded(pallets) => { + Ok(RuntimeDeclaration::ExplicitExpanded(ExplicitRuntimeDeclaration { + name, + where_section, + pallets, + pallets_token, + })) + }, + } + } } #[derive(Debug)] pub struct WhereSection { - pub span: Span, - pub block: syn::TypePath, - pub node_block: syn::TypePath, - pub unchecked_extrinsic: syn::TypePath, + pub span: Span, + pub block: syn::TypePath, + pub node_block: syn::TypePath, + pub unchecked_extrinsic: syn::TypePath, } impl ToTokens for WhereSection { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(quote!()); - } + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(quote!()); + } } impl Parse for WhereSection { - fn parse(input: ParseStream) -> Result { - input.parse::()?; - - let mut definitions = Vec::new(); - while !input.peek(token::Brace) { - let definition: WhereDefinition = input.parse()?; - definitions.push(definition); - if !input.peek(Token![,]) { - if !input.peek(token::Brace) { - return Err(input.error("Expected `,` or `{`")); - } - break; - } - input.parse::()?; - } - let block = remove_kind(input, WhereKind::Block, &mut definitions)?.value; - let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value; - let unchecked_extrinsic = - remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value; - if let Some(WhereDefinition { - ref kind_span, - ref kind, - .. - }) = definitions.first() - { - let msg = format!( - "`{:?}` was declared above. Please use exactly one declaration for `{:?}`.", - kind, kind - ); - return Err(Error::new(*kind_span, msg)); - } - Ok(Self { - span: input.span(), - block, - node_block, - unchecked_extrinsic, - }) - } + fn parse(input: ParseStream) -> Result { + input.parse::()?; + + let mut definitions = Vec::new(); + while !input.peek(token::Brace) { + let definition: WhereDefinition = input.parse()?; + definitions.push(definition); + if !input.peek(Token![,]) { + if !input.peek(token::Brace) { + return Err(input.error("Expected `,` or `{`")); + } + break; + } + input.parse::()?; + } + let block = remove_kind(input, WhereKind::Block, &mut definitions)?.value; + let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value; + let unchecked_extrinsic = + remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value; + if let Some(WhereDefinition { ref kind_span, ref kind, .. }) = definitions.first() { + let msg = format!( + "`{:?}` was declared above. Please use exactly one declaration for `{:?}`.", + kind, kind + ); + return Err(Error::new(*kind_span, msg)); + } + Ok(Self { span: input.span(), block, node_block, unchecked_extrinsic }) + } } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum WhereKind { - Block, - NodeBlock, - UncheckedExtrinsic, + Block, + NodeBlock, + UncheckedExtrinsic, } #[derive(Debug)] pub struct WhereDefinition { - pub kind_span: Span, - pub kind: WhereKind, - pub value: syn::TypePath, + pub kind_span: Span, + pub kind: WhereKind, + pub value: syn::TypePath, } impl Parse for WhereDefinition { - fn parse(input: ParseStream) -> Result { - let lookahead = input.lookahead1(); - let (kind_span, kind) = if lookahead.peek(keyword::Block) { - (input.parse::()?.span(), WhereKind::Block) - } else if lookahead.peek(keyword::NodeBlock) { - ( - input.parse::()?.span(), - WhereKind::NodeBlock, - ) - } else if lookahead.peek(keyword::UncheckedExtrinsic) { - ( - input.parse::()?.span(), - WhereKind::UncheckedExtrinsic, - ) - } else { - return Err(lookahead.error()); - }; - - Ok(Self { - kind_span, - kind, - value: { - let _: Token![=] = input.parse()?; - input.parse()? - }, - }) - } + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + let (kind_span, kind) = if lookahead.peek(keyword::Block) { + (input.parse::()?.span(), WhereKind::Block) + } else if lookahead.peek(keyword::NodeBlock) { + (input.parse::()?.span(), WhereKind::NodeBlock) + } else if lookahead.peek(keyword::UncheckedExtrinsic) { + (input.parse::()?.span(), WhereKind::UncheckedExtrinsic) + } else { + return Err(lookahead.error()); + }; + + Ok(Self { + kind_span, + kind, + value: { + let _: Token![=] = input.parse()?; + input.parse()? + }, + }) + } } /// The declaration of a pallet. #[derive(Debug, Clone)] pub struct PalletDeclaration { - /// Span for current pallet - pub span: Span, - /// Is this pallet fully expanded? - pub is_expanded: bool, - /// The name of the pallet, e.g.`System` in `System: frame_system`. - pub name: Ident, - /// Optional attributes tagged right above a pallet declaration. - pub attrs: Vec, - /// Optional fixed index, e.g. `MyPallet ... = 3,`. - pub index: Option, - /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. - pub path: PalletPath, - /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. - pub instance: Option, - /// The declared pallet parts, - /// e.g. `Some([Pallet, Call])` for `System: system::{Pallet, Call}` - /// or `None` for `System: system`. - pub pallet_parts: Option>, - /// The specified parts, either use_parts or exclude_parts. - pub specified_parts: SpecifiedParts, + /// Span for current pallet + pub span: Span, + /// Is this pallet fully expanded? + pub is_expanded: bool, + /// The name of the pallet, e.g.`System` in `System: frame_system`. + pub name: Ident, + /// Optional attributes tagged right above a pallet declaration. + pub attrs: Vec, + /// Optional fixed index, e.g. `MyPallet ... = 3,`. + pub index: Option, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. + pub path: PalletPath, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. + pub instance: Option, + /// The declared pallet parts, + /// e.g. `Some([Pallet, Call])` for `System: system::{Pallet, Call}` + /// or `None` for `System: system`. + pub pallet_parts: Option>, + /// The specified parts, either use_parts or exclude_parts. + pub specified_parts: SpecifiedParts, } impl ToTokens for PalletDeclaration { - fn to_tokens(&self, tokens: &mut TokenStream) { - let PalletDeclaration { name, path, .. } = self; - tokens.extend(quote!(#name )); - if let Some(instance) = &self.instance { - tokens.extend(quote!(: #path::<#instance>)); - } else { - tokens.extend(quote!(: #path)) - } - if let Some(idx) = self.index { - let idx = format!(" = {},", idx); - // This means no help from rustfmt - tokens.extend(TokenStream::from_str(&idx)); - // If we want rustfmt we would have to handroll our own solution or forgo indices - // (which is bad and probably not what the developer wants which is to delete code) - // tokens.extend(quote!(,)); - } else { - tokens.append(Punct::new(',', Spacing::Alone)); - } - } + fn to_tokens(&self, tokens: &mut TokenStream) { + let PalletDeclaration { name, path, .. } = self; + tokens.extend(quote!(#name )); + if let Some(instance) = &self.instance { + tokens.extend(quote!(: #path::<#instance>)); + } else { + tokens.extend(quote!(: #path)) + } + if let Some(idx) = self.index { + let idx = format!(" = {},", idx); + // This means no help from rustfmt + tokens.extend(TokenStream::from_str(&idx)); + // If we want rustfmt we would have to handroll our own solution or forgo indices + // (which is bad and probably not what the developer wants which is to delete code) + // tokens.extend(quote!(,)); + } else { + tokens.append(Punct::new(',', Spacing::Alone)); + } + } } /// The possible declaration of pallet parts to use. #[derive(Debug, Clone)] pub enum SpecifiedParts { - /// Use all the pallet parts except those specified. - Exclude(Vec), - /// Use only the specified pallet parts. - Use(Vec), - /// Use the all the pallet parts. - All, + /// Use all the pallet parts except those specified. + Exclude(Vec), + /// Use only the specified pallet parts. + Use(Vec), + /// Use the all the pallet parts. + All, } impl Parse for PalletDeclaration { - fn parse(input: ParseStream) -> Result { - let attrs = input.call(Attribute::parse_outer)?; - let span = input.span(); - let name = input.parse()?; - let _: Token![:] = input.parse()?; - let path = input.parse()?; - - // Parse for instance. - let instance = if input.peek(Token![::]) && input.peek3(Token![<]) { - let _: Token![::] = input.parse()?; - let _: Token![<] = input.parse()?; - let res = Some(input.parse()?); - let _: Token![>] = input.parse()?; - res - } else if !(input.peek(Token![::]) && input.peek3(token::Brace)) - && !input.peek(keyword::expanded) - && !input.peek(keyword::exclude_parts) - && !input.peek(keyword::use_parts) - && !input.peek(Token![=]) - && !input.peek(Token![,]) - && !input.is_empty() - { - return Err(input.error( + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let span = input.span(); + let name = input.parse()?; + let _: Token![:] = input.parse()?; + let path = input.parse()?; + + // Parse for instance. + let instance = if input.peek(Token![::]) && input.peek3(Token![<]) { + let _: Token![::] = input.parse()?; + let _: Token![<] = input.parse()?; + let res = Some(input.parse()?); + let _: Token![>] = input.parse()?; + res + } else if !(input.peek(Token![::]) && input.peek3(token::Brace)) + && !input.peek(keyword::expanded) + && !input.peek(keyword::exclude_parts) + && !input.peek(keyword::use_parts) + && !input.peek(Token![=]) + && !input.peek(Token![,]) + && !input.is_empty() + { + return Err(input.error( "Unexpected tokens, expected one of `::$ident` `::{`, `exclude_parts`, `use_parts`, `=`, `,`", )); - } else { - None - }; - - // Check if the pallet is fully expanded. - let (is_expanded, extra_parts) = if input.peek(keyword::expanded) { - let _: keyword::expanded = input.parse()?; - let _: Token![::] = input.parse()?; - (true, parse_pallet_parts(input)?) - } else { - (false, vec![]) - }; - - // Parse for explicit parts - let pallet_parts = if input.peek(Token![::]) && input.peek3(token::Brace) { - let _: Token![::] = input.parse()?; - let mut parts = parse_pallet_parts(input)?; - parts.extend(extra_parts.into_iter()); - Some(parts) - } else if !input.peek(keyword::exclude_parts) - && !input.peek(keyword::use_parts) - && !input.peek(Token![=]) - && !input.peek(Token![,]) - && !input.is_empty() - { - return Err(input.error( - "Unexpected tokens, expected one of `::{`, `exclude_parts`, `use_parts`, `=`, `,`", - )); - } else { - is_expanded.then_some(extra_parts) - }; - - // Parse for specified parts - let specified_parts = if input.peek(keyword::exclude_parts) { - let _: keyword::exclude_parts = input.parse()?; - SpecifiedParts::Exclude(parse_pallet_parts_no_generic(input)?) - } else if input.peek(keyword::use_parts) { - let _: keyword::use_parts = input.parse()?; - SpecifiedParts::Use(parse_pallet_parts_no_generic(input)?) - } else if !input.peek(Token![=]) && !input.peek(Token![,]) && !input.is_empty() { - return Err(input.error("Unexpected tokens, expected one of `exclude_parts`, `=`, `,`")); - } else { - SpecifiedParts::All - }; - - // Parse for pallet index - let index = if input.peek(Token![=]) { - input.parse::()?; - let index = input.parse::()?; - let index = index.base10_parse::()?; - Some(index) - } else if !input.peek(Token![,]) && !input.is_empty() { - return Err(input.error("Unexpected tokens, expected one of `=`, `,`")); - } else { - None - }; - - Ok(Self { - span, - is_expanded, - attrs, - name, - path, - instance, - pallet_parts, - specified_parts, - index, - }) - } + } else { + None + }; + + // Check if the pallet is fully expanded. + let (is_expanded, extra_parts) = if input.peek(keyword::expanded) { + let _: keyword::expanded = input.parse()?; + let _: Token![::] = input.parse()?; + (true, parse_pallet_parts(input)?) + } else { + (false, vec![]) + }; + + // Parse for explicit parts + let pallet_parts = if input.peek(Token![::]) && input.peek3(token::Brace) { + let _: Token![::] = input.parse()?; + let mut parts = parse_pallet_parts(input)?; + parts.extend(extra_parts.into_iter()); + Some(parts) + } else if !input.peek(keyword::exclude_parts) + && !input.peek(keyword::use_parts) + && !input.peek(Token![=]) + && !input.peek(Token![,]) + && !input.is_empty() + { + return Err(input.error( + "Unexpected tokens, expected one of `::{`, `exclude_parts`, `use_parts`, `=`, `,`", + )); + } else { + is_expanded.then_some(extra_parts) + }; + + // Parse for specified parts + let specified_parts = if input.peek(keyword::exclude_parts) { + let _: keyword::exclude_parts = input.parse()?; + SpecifiedParts::Exclude(parse_pallet_parts_no_generic(input)?) + } else if input.peek(keyword::use_parts) { + let _: keyword::use_parts = input.parse()?; + SpecifiedParts::Use(parse_pallet_parts_no_generic(input)?) + } else if !input.peek(Token![=]) && !input.peek(Token![,]) && !input.is_empty() { + return Err(input.error("Unexpected tokens, expected one of `exclude_parts`, `=`, `,`")); + } else { + SpecifiedParts::All + }; + + // Parse for pallet index + let index = if input.peek(Token![=]) { + input.parse::()?; + let index = input.parse::()?; + let index = index.base10_parse::()?; + Some(index) + } else if !input.peek(Token![,]) && !input.is_empty() { + return Err(input.error("Unexpected tokens, expected one of `=`, `,`")); + } else { + None + }; + + Ok(Self { + span, + is_expanded, + attrs, + name, + path, + instance, + pallet_parts, + specified_parts, + index, + }) + } } /// A struct representing a path to a pallet. `PalletPath` is almost identical to the standard @@ -449,309 +423,300 @@ impl Parse for PalletDeclaration { /// - Path segments can only consist of identifers separated by colons #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PalletPath { - pub inner: Path, + pub inner: Path, } impl PalletPath { - pub fn module_name(&self) -> String { - self.inner - .segments - .iter() - .fold(String::new(), |mut acc, segment| { - if !acc.is_empty() { - acc.push_str("::"); - } - acc.push_str(&segment.ident.to_string()); - acc - }) - } + pub fn module_name(&self) -> String { + self.inner.segments.iter().fold(String::new(), |mut acc, segment| { + if !acc.is_empty() { + acc.push_str("::"); + } + acc.push_str(&segment.ident.to_string()); + acc + }) + } } impl Parse for PalletPath { - fn parse(input: ParseStream) -> Result { - let mut res = PalletPath { - inner: Path { - leading_colon: None, - segments: Punctuated::new(), - }, - }; - - let lookahead = input.lookahead1(); - if lookahead.peek(Token![crate]) - || lookahead.peek(Token![self]) - || lookahead.peek(Token![super]) - || lookahead.peek(Ident) - { - let ident = input.call(Ident::parse_any)?; - res.inner.segments.push(ident.into()); - } else { - return Err(lookahead.error()); - } - - while input.peek(Token![::]) && input.peek3(Ident) { - input.parse::()?; - let ident = input.parse::()?; - res.inner.segments.push(ident.into()); - } - Ok(res) - } + fn parse(input: ParseStream) -> Result { + let mut res = + PalletPath { inner: Path { leading_colon: None, segments: Punctuated::new() } }; + + let lookahead = input.lookahead1(); + if lookahead.peek(Token![crate]) + || lookahead.peek(Token![self]) + || lookahead.peek(Token![super]) + || lookahead.peek(Ident) + { + let ident = input.call(Ident::parse_any)?; + res.inner.segments.push(ident.into()); + } else { + return Err(lookahead.error()); + } + + while input.peek(Token![::]) && input.peek3(Ident) { + input.parse::()?; + let ident = input.parse::()?; + res.inner.segments.push(ident.into()); + } + Ok(res) + } } impl quote::ToTokens for PalletPath { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.inner.to_tokens(tokens); - } + fn to_tokens(&self, tokens: &mut TokenStream) { + self.inner.to_tokens(tokens); + } } /// Parse [`PalletPart`]'s from a braces enclosed list that is split by commas, e.g. /// /// `{ Call, Event }` fn parse_pallet_parts(input: ParseStream) -> Result> { - let pallet_parts: ext::Braces> = input.parse()?; + let pallet_parts: ext::Braces> = input.parse()?; - let mut resolved = HashSet::new(); - for part in pallet_parts.content.inner.iter() { - if !resolved.insert(part.name()) { - let msg = format!( - "`{}` was already declared before. Please remove the duplicate declaration", - part.name(), - ); - return Err(Error::new(part.keyword.span(), msg)); - } - } + let mut resolved = HashSet::new(); + for part in pallet_parts.content.inner.iter() { + if !resolved.insert(part.name()) { + let msg = format!( + "`{}` was already declared before. Please remove the duplicate declaration", + part.name(), + ); + return Err(Error::new(part.keyword.span(), msg)); + } + } - Ok(pallet_parts.content.inner.into_iter().collect()) + Ok(pallet_parts.content.inner.into_iter().collect()) } #[derive(Debug, Clone)] pub enum PalletPartKeyword { - Pallet(keyword::Pallet), - Call(keyword::Call), - Storage(keyword::Storage), - Event(keyword::Event), - Error(keyword::Error), - Config(keyword::Config), - Origin(keyword::Origin), - Inherent(keyword::Inherent), - ValidateUnsigned(keyword::ValidateUnsigned), - FreezeReason(keyword::FreezeReason), - HoldReason(keyword::HoldReason), - LockId(keyword::LockId), - SlashReason(keyword::SlashReason), + Pallet(keyword::Pallet), + Call(keyword::Call), + Storage(keyword::Storage), + Event(keyword::Event), + Error(keyword::Error), + Config(keyword::Config), + Origin(keyword::Origin), + Inherent(keyword::Inherent), + ValidateUnsigned(keyword::ValidateUnsigned), + FreezeReason(keyword::FreezeReason), + HoldReason(keyword::HoldReason), + LockId(keyword::LockId), + SlashReason(keyword::SlashReason), } impl Parse for PalletPartKeyword { - fn parse(input: ParseStream) -> Result { - let lookahead = input.lookahead1(); - - if lookahead.peek(keyword::Pallet) { - Ok(Self::Pallet(input.parse()?)) - } else if lookahead.peek(keyword::Call) { - Ok(Self::Call(input.parse()?)) - } else if lookahead.peek(keyword::Storage) { - Ok(Self::Storage(input.parse()?)) - } else if lookahead.peek(keyword::Event) { - Ok(Self::Event(input.parse()?)) - } else if lookahead.peek(keyword::Error) { - Ok(Self::Error(input.parse()?)) - } else if lookahead.peek(keyword::Config) { - Ok(Self::Config(input.parse()?)) - } else if lookahead.peek(keyword::Origin) { - Ok(Self::Origin(input.parse()?)) - } else if lookahead.peek(keyword::Inherent) { - Ok(Self::Inherent(input.parse()?)) - } else if lookahead.peek(keyword::ValidateUnsigned) { - Ok(Self::ValidateUnsigned(input.parse()?)) - } else if lookahead.peek(keyword::FreezeReason) { - Ok(Self::FreezeReason(input.parse()?)) - } else if lookahead.peek(keyword::HoldReason) { - Ok(Self::HoldReason(input.parse()?)) - } else if lookahead.peek(keyword::LockId) { - Ok(Self::LockId(input.parse()?)) - } else if lookahead.peek(keyword::SlashReason) { - Ok(Self::SlashReason(input.parse()?)) - } else { - Err(lookahead.error()) - } - } + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + + if lookahead.peek(keyword::Pallet) { + Ok(Self::Pallet(input.parse()?)) + } else if lookahead.peek(keyword::Call) { + Ok(Self::Call(input.parse()?)) + } else if lookahead.peek(keyword::Storage) { + Ok(Self::Storage(input.parse()?)) + } else if lookahead.peek(keyword::Event) { + Ok(Self::Event(input.parse()?)) + } else if lookahead.peek(keyword::Error) { + Ok(Self::Error(input.parse()?)) + } else if lookahead.peek(keyword::Config) { + Ok(Self::Config(input.parse()?)) + } else if lookahead.peek(keyword::Origin) { + Ok(Self::Origin(input.parse()?)) + } else if lookahead.peek(keyword::Inherent) { + Ok(Self::Inherent(input.parse()?)) + } else if lookahead.peek(keyword::ValidateUnsigned) { + Ok(Self::ValidateUnsigned(input.parse()?)) + } else if lookahead.peek(keyword::FreezeReason) { + Ok(Self::FreezeReason(input.parse()?)) + } else if lookahead.peek(keyword::HoldReason) { + Ok(Self::HoldReason(input.parse()?)) + } else if lookahead.peek(keyword::LockId) { + Ok(Self::LockId(input.parse()?)) + } else if lookahead.peek(keyword::SlashReason) { + Ok(Self::SlashReason(input.parse()?)) + } else { + Err(lookahead.error()) + } + } } impl PalletPartKeyword { - /// Returns the name of `Self`. - fn name(&self) -> &'static str { - match self { - Self::Pallet(_) => "Pallet", - Self::Call(_) => "Call", - Self::Storage(_) => "Storage", - Self::Event(_) => "Event", - Self::Error(_) => "Error", - Self::Config(_) => "Config", - Self::Origin(_) => "Origin", - Self::Inherent(_) => "Inherent", - Self::ValidateUnsigned(_) => "ValidateUnsigned", - Self::FreezeReason(_) => "FreezeReason", - Self::HoldReason(_) => "HoldReason", - Self::LockId(_) => "LockId", - Self::SlashReason(_) => "SlashReason", - } - } - - /// Returns `true` if this pallet part is allowed to have generic arguments. - fn allows_generic(&self) -> bool { - Self::all_generic_arg().iter().any(|n| *n == self.name()) - } - - /// Returns the names of all pallet parts that allow to have a generic argument. - fn all_generic_arg() -> &'static [&'static str] { - &["Event", "Error", "Origin", "Config"] - } + /// Returns the name of `Self`. + fn name(&self) -> &'static str { + match self { + Self::Pallet(_) => "Pallet", + Self::Call(_) => "Call", + Self::Storage(_) => "Storage", + Self::Event(_) => "Event", + Self::Error(_) => "Error", + Self::Config(_) => "Config", + Self::Origin(_) => "Origin", + Self::Inherent(_) => "Inherent", + Self::ValidateUnsigned(_) => "ValidateUnsigned", + Self::FreezeReason(_) => "FreezeReason", + Self::HoldReason(_) => "HoldReason", + Self::LockId(_) => "LockId", + Self::SlashReason(_) => "SlashReason", + } + } + + /// Returns `true` if this pallet part is allowed to have generic arguments. + fn allows_generic(&self) -> bool { + Self::all_generic_arg().iter().any(|n| *n == self.name()) + } + + /// Returns the names of all pallet parts that allow to have a generic argument. + fn all_generic_arg() -> &'static [&'static str] { + &["Event", "Error", "Origin", "Config"] + } } impl ToTokens for PalletPartKeyword { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - Self::Pallet(inner) => inner.to_tokens(tokens), - Self::Call(inner) => inner.to_tokens(tokens), - Self::Storage(inner) => inner.to_tokens(tokens), - Self::Event(inner) => inner.to_tokens(tokens), - Self::Error(inner) => inner.to_tokens(tokens), - Self::Config(inner) => inner.to_tokens(tokens), - Self::Origin(inner) => inner.to_tokens(tokens), - Self::Inherent(inner) => inner.to_tokens(tokens), - Self::ValidateUnsigned(inner) => inner.to_tokens(tokens), - Self::FreezeReason(inner) => inner.to_tokens(tokens), - Self::HoldReason(inner) => inner.to_tokens(tokens), - Self::LockId(inner) => inner.to_tokens(tokens), - Self::SlashReason(inner) => inner.to_tokens(tokens), - } - } + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Self::Pallet(inner) => inner.to_tokens(tokens), + Self::Call(inner) => inner.to_tokens(tokens), + Self::Storage(inner) => inner.to_tokens(tokens), + Self::Event(inner) => inner.to_tokens(tokens), + Self::Error(inner) => inner.to_tokens(tokens), + Self::Config(inner) => inner.to_tokens(tokens), + Self::Origin(inner) => inner.to_tokens(tokens), + Self::Inherent(inner) => inner.to_tokens(tokens), + Self::ValidateUnsigned(inner) => inner.to_tokens(tokens), + Self::FreezeReason(inner) => inner.to_tokens(tokens), + Self::HoldReason(inner) => inner.to_tokens(tokens), + Self::LockId(inner) => inner.to_tokens(tokens), + Self::SlashReason(inner) => inner.to_tokens(tokens), + } + } } #[derive(Debug, Clone)] pub struct PalletPart { - pub keyword: PalletPartKeyword, - pub generics: syn::Generics, + pub keyword: PalletPartKeyword, + pub generics: syn::Generics, } impl Parse for PalletPart { - fn parse(input: ParseStream) -> Result { - let keyword: PalletPartKeyword = input.parse()?; - - let generics: syn::Generics = input.parse()?; - if !generics.params.is_empty() && !keyword.allows_generic() { - let valid_generics = PalletPart::format_names(PalletPartKeyword::all_generic_arg()); - let msg = format!( - "`{}` is not allowed to have generics. \ + fn parse(input: ParseStream) -> Result { + let keyword: PalletPartKeyword = input.parse()?; + + let generics: syn::Generics = input.parse()?; + if !generics.params.is_empty() && !keyword.allows_generic() { + let valid_generics = PalletPart::format_names(PalletPartKeyword::all_generic_arg()); + let msg = format!( + "`{}` is not allowed to have generics. \ Only the following pallets are allowed to have generics: {}.", - keyword.name(), - valid_generics, - ); - return Err(syn::Error::new(keyword.span(), msg)); - } + keyword.name(), + valid_generics, + ); + return Err(syn::Error::new(keyword.span(), msg)); + } - Ok(Self { keyword, generics }) - } + Ok(Self { keyword, generics }) + } } impl PalletPart { - pub fn format_names(names: &[&'static str]) -> String { - let res: Vec<_> = names.iter().map(|s| format!("`{}`", s)).collect(); - res.join(", ") - } + pub fn format_names(names: &[&'static str]) -> String { + let res: Vec<_> = names.iter().map(|s| format!("`{}`", s)).collect(); + res.join(", ") + } - /// The name of this pallet part. - pub fn name(&self) -> &'static str { - self.keyword.name() - } + /// The name of this pallet part. + pub fn name(&self) -> &'static str { + self.keyword.name() + } } fn remove_kind( - input: ParseStream, - kind: WhereKind, - definitions: &mut Vec, + input: ParseStream, + kind: WhereKind, + definitions: &mut Vec, ) -> Result { - if let Some(pos) = definitions.iter().position(|d| d.kind == kind) { - Ok(definitions.remove(pos)) - } else { - let msg = format!( - "Missing associated type for `{:?}`. Add `{:?}` = ... to where section.", - kind, kind - ); - Err(input.error(msg)) - } + if let Some(pos) = definitions.iter().position(|d| d.kind == kind) { + Ok(definitions.remove(pos)) + } else { + let msg = format!( + "Missing associated type for `{:?}`. Add `{:?}` = ... to where section.", + kind, kind + ); + Err(input.error(msg)) + } } /// The declaration of a part without its generics #[derive(Debug, Clone)] pub struct PalletPartNoGeneric { - keyword: PalletPartKeyword, + keyword: PalletPartKeyword, } impl Parse for PalletPartNoGeneric { - fn parse(input: ParseStream) -> Result { - Ok(Self { - keyword: input.parse()?, - }) - } + fn parse(input: ParseStream) -> Result { + Ok(Self { keyword: input.parse()? }) + } } /// Parse [`PalletPartNoGeneric`]'s from a braces enclosed list that is split by commas, e.g. /// /// `{ Call, Event }` fn parse_pallet_parts_no_generic(input: ParseStream) -> Result> { - let pallet_parts: ext::Braces> = - input.parse()?; + let pallet_parts: ext::Braces> = + input.parse()?; - let mut resolved = HashSet::new(); - for part in pallet_parts.content.inner.iter() { - if !resolved.insert(part.keyword.name()) { - let msg = format!( - "`{}` was already declared before. Please remove the duplicate declaration", - part.keyword.name(), - ); - return Err(Error::new(part.keyword.span(), msg)); - } - } + let mut resolved = HashSet::new(); + for part in pallet_parts.content.inner.iter() { + if !resolved.insert(part.keyword.name()) { + let msg = format!( + "`{}` was already declared before. Please remove the duplicate declaration", + part.keyword.name(), + ); + return Err(Error::new(part.keyword.span(), msg)); + } + } - Ok(pallet_parts.content.inner.into_iter().collect()) + Ok(pallet_parts.content.inner.into_iter().collect()) } /// The final definition of a pallet with the resulting fixed index and explicit parts. #[derive(Debug, Clone)] pub struct Pallet { - /// Span for current pallet - pub span: Span, - /// Is this pallet fully expanded? - pub is_expanded: bool, - /// The name of the pallet, e.g.`System` in `System: frame_system`. - pub name: Ident, - /// Either automatically infered, or defined (e.g. `MyPallet ... = 3,`). - pub index: u8, - /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. - pub path: PalletPath, - /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. - pub instance: Option, - /// The pallet parts to use for the pallet. - pub pallet_parts: Vec, - /// Expressions specified inside of a #[cfg] attribute. - pub cfg_pattern: Vec, + /// Span for current pallet + pub span: Span, + /// Is this pallet fully expanded? + pub is_expanded: bool, + /// The name of the pallet, e.g.`System` in `System: frame_system`. + pub name: Ident, + /// Either automatically infered, or defined (e.g. `MyPallet ... = 3,`). + pub index: u8, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. + pub path: PalletPath, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. + pub instance: Option, + /// The pallet parts to use for the pallet. + pub pallet_parts: Vec, + /// Expressions specified inside of a #[cfg] attribute. + pub cfg_pattern: Vec, } impl Pallet { - /// Get resolved pallet parts - pub fn pallet_parts(&self) -> &[PalletPart] { - &self.pallet_parts - } + /// Get resolved pallet parts + pub fn pallet_parts(&self) -> &[PalletPart] { + &self.pallet_parts + } - /// Find matching parts - pub fn find_part(&self, name: &str) -> Option<&PalletPart> { - self.pallet_parts.iter().find(|part| part.name() == name) - } + /// Find matching parts + pub fn find_part(&self, name: &str) -> Option<&PalletPart> { + self.pallet_parts.iter().find(|part| part.name() == name) + } - /// Return whether pallet contains part - pub fn exists_part(&self, name: &str) -> bool { - self.find_part(name).is_some() - } + /// Return whether pallet contains part + pub fn exists_part(&self, name: &str) -> bool { + self.find_part(name).is_some() + } } /// Result of a conversion of a declaration of pallets. @@ -764,26 +729,26 @@ impl Pallet { /// +----------+ +----------+ +------------------+ /// ``` enum PalletsConversion { - /// Pallets implicitely declare parts. - /// - /// `System: frame_system`. - Implicit(Vec), - /// Pallets explicitly declare parts. - /// - /// `System: frame_system::{Pallet, Call}` - /// - /// However, for backwards compatibility with Polkadot/Kusama - /// we must propagate some other parts to the pallet by default. - Explicit(Vec), - /// Pallets explicitly declare parts that are fully expanded. - /// - /// This is the end state that contains extra parts included by - /// default by Subtrate. - /// - /// `System: frame_system expanded::{Error} ::{Pallet, Call}` - /// - /// For this example, the `Pallet`, `Call` and `Error` parts are collected. - ExplicitExpanded(Vec), + /// Pallets implicitely declare parts. + /// + /// `System: frame_system`. + Implicit(Vec), + /// Pallets explicitly declare parts. + /// + /// `System: frame_system::{Pallet, Call}` + /// + /// However, for backwards compatibility with Polkadot/Kusama + /// we must propagate some other parts to the pallet by default. + Explicit(Vec), + /// Pallets explicitly declare parts that are fully expanded. + /// + /// This is the end state that contains extra parts included by + /// default by Subtrate. + /// + /// `System: frame_system expanded::{Error} ::{Pallet, Call}` + /// + /// For this example, the `Pallet`, `Call` and `Error` parts are collected. + ExplicitExpanded(Vec), } /// Convert from the parsed pallet declaration to their final information. @@ -792,168 +757,157 @@ enum PalletsConversion { /// pallet using same rules as rust for fieldless enum. I.e. implicit are assigned number /// incrementedly from last explicit or 0. fn convert_pallets(pallets: Vec) -> syn::Result { - if pallets.iter().any(|pallet| pallet.pallet_parts.is_none()) { - return Ok(PalletsConversion::Implicit(pallets)); - } - - let mut indices = HashMap::new(); - let mut last_index: Option = None; - let mut names = HashMap::new(); - let mut is_expanded = true; - - let pallets = pallets - .into_iter() - .map(|pallet| { - let final_index = match pallet.index { - Some(i) => i, - None => last_index - .map_or(Some(0), |i| i.checked_add(1)) - .ok_or_else(|| { - let msg = "Pallet index doesn't fit into u8, index is 256"; - syn::Error::new(pallet.name.span(), msg) - })?, - }; - - last_index = Some(final_index); - - if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) { - let msg = format!( - "Pallet indices are conflicting: Both pallets {} and {} are at index {}", - used_pallet, pallet.name, final_index, - ); - let mut err = syn::Error::new(used_pallet.span(), &msg); - err.combine(syn::Error::new(pallet.name.span(), msg)); - return Err(err); - } - - if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) { - let msg = "Two pallets with the same name!"; - - let mut err = syn::Error::new(used_pallet, &msg); - err.combine(syn::Error::new(pallet.name.span(), &msg)); - return Err(err); - } - - let mut pallet_parts = pallet.pallet_parts.expect("Checked above"); - - let available_parts = pallet_parts - .iter() - .map(|part| part.keyword.name()) - .collect::>(); - - // Check parts are correctly specified - match &pallet.specified_parts { - SpecifiedParts::Exclude(parts) | SpecifiedParts::Use(parts) => { - for part in parts { - if !available_parts.contains(part.keyword.name()) { - let msg = format!( - "Invalid pallet part specified, the pallet `{}` doesn't have the \ + if pallets.iter().any(|pallet| pallet.pallet_parts.is_none()) { + return Ok(PalletsConversion::Implicit(pallets)); + } + + let mut indices = HashMap::new(); + let mut last_index: Option = None; + let mut names = HashMap::new(); + let mut is_expanded = true; + + let pallets = pallets + .into_iter() + .map(|pallet| { + let final_index = match pallet.index { + Some(i) => i, + None => last_index.map_or(Some(0), |i| i.checked_add(1)).ok_or_else(|| { + let msg = "Pallet index doesn't fit into u8, index is 256"; + syn::Error::new(pallet.name.span(), msg) + })?, + }; + + last_index = Some(final_index); + + if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) { + let msg = format!( + "Pallet indices are conflicting: Both pallets {} and {} are at index {}", + used_pallet, pallet.name, final_index, + ); + let mut err = syn::Error::new(used_pallet.span(), &msg); + err.combine(syn::Error::new(pallet.name.span(), msg)); + return Err(err); + } + + if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) { + let msg = "Two pallets with the same name!"; + + let mut err = syn::Error::new(used_pallet, &msg); + err.combine(syn::Error::new(pallet.name.span(), &msg)); + return Err(err); + } + + let mut pallet_parts = pallet.pallet_parts.expect("Checked above"); + + let available_parts = + pallet_parts.iter().map(|part| part.keyword.name()).collect::>(); + + // Check parts are correctly specified + match &pallet.specified_parts { + SpecifiedParts::Exclude(parts) | SpecifiedParts::Use(parts) => { + for part in parts { + if !available_parts.contains(part.keyword.name()) { + let msg = format!( + "Invalid pallet part specified, the pallet `{}` doesn't have the \ `{}` part. Available parts are: {}.", - pallet.name, - part.keyword.name(), - pallet_parts.iter().fold(String::new(), |fold, part| { - if fold.is_empty() { - format!("`{}`", part.keyword.name()) - } else { - format!("{}, `{}`", fold, part.keyword.name()) - } - }) - ); - return Err(syn::Error::new(part.keyword.span(), msg)); - } - } - } - SpecifiedParts::All => (), - } - - // Set only specified parts. - match pallet.specified_parts { - SpecifiedParts::Exclude(excluded_parts) => pallet_parts.retain(|part| { - !excluded_parts - .iter() - .any(|excluded_part| excluded_part.keyword.name() == part.keyword.name()) - }), - SpecifiedParts::Use(used_parts) => pallet_parts.retain(|part| { - used_parts - .iter() - .any(|use_part| use_part.keyword.name() == part.keyword.name()) - }), - SpecifiedParts::All => (), - } - - let cfg_pattern = pallet - .attrs - .iter() - .map(|attr| { - if attr - .path() - .segments - .first() - .map_or(false, |s| s.ident != "cfg") - { - let msg = "Unsupported attribute, only #[cfg] is supported on pallet \ + pallet.name, + part.keyword.name(), + pallet_parts.iter().fold(String::new(), |fold, part| { + if fold.is_empty() { + format!("`{}`", part.keyword.name()) + } else { + format!("{}, `{}`", fold, part.keyword.name()) + } + }) + ); + return Err(syn::Error::new(part.keyword.span(), msg)); + } + } + }, + SpecifiedParts::All => (), + } + + // Set only specified parts. + match pallet.specified_parts { + SpecifiedParts::Exclude(excluded_parts) => pallet_parts.retain(|part| { + !excluded_parts + .iter() + .any(|excluded_part| excluded_part.keyword.name() == part.keyword.name()) + }), + SpecifiedParts::Use(used_parts) => pallet_parts.retain(|part| { + used_parts.iter().any(|use_part| use_part.keyword.name() == part.keyword.name()) + }), + SpecifiedParts::All => (), + } + + let cfg_pattern = pallet + .attrs + .iter() + .map(|attr| { + if attr.path().segments.first().map_or(false, |s| s.ident != "cfg") { + let msg = "Unsupported attribute, only #[cfg] is supported on pallet \ declarations in `construct_runtime`"; - return Err(syn::Error::new(attr.span(), msg)); - } - - attr.parse_args_with(|input: syn::parse::ParseStream| { - // Required, otherwise the parse stream doesn't advance and will result in - // an error. - let input = input.parse::()?; - cfg_expr::Expression::parse(&input.to_string()) - .map_err(|e| syn::Error::new(attr.span(), e.to_string())) - }) - }) - .collect::>>()?; - - is_expanded &= pallet.is_expanded; - - Ok(Pallet { - span: pallet.span, - is_expanded: pallet.is_expanded, - name: pallet.name, - index: final_index, - path: pallet.path, - instance: pallet.instance, - cfg_pattern, - pallet_parts, - }) - }) - .collect::>>()?; - - if is_expanded { - Ok(PalletsConversion::ExplicitExpanded(pallets)) - } else { - Ok(PalletsConversion::Explicit(pallets)) - } + return Err(syn::Error::new(attr.span(), msg)); + } + + attr.parse_args_with(|input: syn::parse::ParseStream| { + // Required, otherwise the parse stream doesn't advance and will result in + // an error. + let input = input.parse::()?; + cfg_expr::Expression::parse(&input.to_string()) + .map_err(|e| syn::Error::new(attr.span(), e.to_string())) + }) + }) + .collect::>>()?; + + is_expanded &= pallet.is_expanded; + + Ok(Pallet { + span: pallet.span, + is_expanded: pallet.is_expanded, + name: pallet.name, + index: final_index, + path: pallet.path, + instance: pallet.instance, + cfg_pattern, + pallet_parts, + }) + }) + .collect::>>()?; + + if is_expanded { + Ok(PalletsConversion::ExplicitExpanded(pallets)) + } else { + Ok(PalletsConversion::Explicit(pallets)) + } } pub fn check_pallet_number(input: proc_macro2::TokenStream, pallet_num: usize) -> Result<()> { - let max_pallet_num = { - if cfg!(feature = "tuples-96") { - 96 - } else if cfg!(feature = "tuples-128") { - 128 - } else { - 64 - } - }; - - if pallet_num > max_pallet_num { - let no_feature = max_pallet_num == 128; - return Err(syn::Error::new( - input.span(), - format!( - "{} To increase this limit, enable the tuples-{} feature of [frame_support]. {}", - "The number of pallets exceeds the maximum number of tuple elements.", - max_pallet_num + 32, - if no_feature { - "If the feature does not exist - it needs to be implemented." - } else { - "" - }, - ), - )); - } - - Ok(()) + let max_pallet_num = { + if cfg!(feature = "tuples-96") { + 96 + } else if cfg!(feature = "tuples-128") { + 128 + } else { + 64 + } + }; + + if pallet_num > max_pallet_num { + let no_feature = max_pallet_num == 128; + return Err(syn::Error::new( + input.span(), + format!( + "{} To increase this limit, enable the tuples-{} feature of [frame_support]. {}", + "The number of pallets exceeds the maximum number of tuple elements.", + max_pallet_num + 32, + if no_feature { + "If the feature does not exist - it needs to be implemented." + } else { + "" + }, + ), + )); + } + + Ok(()) } diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index 60b455e2..ff9d3b46 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -1,81 +1,74 @@ use crate::{ - engines::generator::PalletItem, - helpers::{resolve_pallet_path, sanitize}, + engines::generator::PalletItem, + helpers::{resolve_pallet_path, sanitize}, }; use std::{fs, path::PathBuf}; // use super::{pallet_entry::AddPalletEntry, PalletEngine}; pub fn create_pallet_template( - path: Option, - config: TemplatePalletConfig, + path: Option, + config: TemplatePalletConfig, ) -> anyhow::Result<()> { - let target = resolve_pallet_path(path); - // TODO : config.name might use `-` or use snake_case. We want to use pallet_template for the pallet dirs - // and PalletTemplate for the runtime macro - // TODO: this can be further polished (edge cases: no pallet prefix.) - let pallet_name = config.name.clone(); - let pallet_path = target.join(pallet_name.clone()); - sanitize(&pallet_path)?; - generate_pallet_structure(&target, &pallet_name)?; - // todo let pallet_module_name = ... ; - render_pallet(pallet_name, config, &pallet_path)?; - Ok(()) + let target = resolve_pallet_path(path); + // TODO : config.name might use `-` or use snake_case. We want to use pallet_template for the pallet dirs + // and PalletTemplate for the runtime macro + // TODO: this can be further polished (edge cases: no pallet prefix.) + let pallet_name = config.name.clone(); + let pallet_path = target.join(pallet_name.clone()); + sanitize(&pallet_path)?; + generate_pallet_structure(&target, &pallet_name)?; + // todo let pallet_module_name = ... ; + render_pallet(pallet_name, config, &pallet_path)?; + Ok(()) } #[derive(clap::Args, Clone)] pub struct TemplatePalletConfig { - #[arg(short, long, default_value_t = String::from("template"))] - pub name: String, - #[arg(short, long, default_value_t = String::from("author"))] - pub authors: String, - #[arg(short, long, default_value_t = String::from("description"))] - pub description: String, + #[arg(short, long, default_value_t = String::from("template"))] + pub name: String, + #[arg(short, long, default_value_t = String::from("author"))] + pub authors: String, + #[arg(short, long, default_value_t = String::from("description"))] + pub description: String, } /// Generate a pallet folder and file structure fn generate_pallet_structure(target: &PathBuf, pallet_name: &str) -> anyhow::Result<()> { - use fs::{create_dir, File}; - let (pallet, src) = ( - target.join(pallet_name), - target.join(pallet_name.to_string() + "/src"), - ); - // println!("source = > {}", src.display()); - create_dir(&pallet)?; - create_dir(&src)?; - File::create(format!("{}/Cargo.toml", pallet.display()))?; - File::create(format!("{}/lib.rs", src.display()))?; - File::create(format!("{}/benchmarking.rs", src.display()))?; - File::create(format!("{}/tests.rs", src.display()))?; - File::create(format!("{}/mock.rs", src.display()))?; - Ok(()) + use fs::{create_dir, File}; + let (pallet, src) = (target.join(pallet_name), target.join(pallet_name.to_string() + "/src")); + // println!("source = > {}", src.display()); + create_dir(&pallet)?; + create_dir(&src)?; + File::create(format!("{}/Cargo.toml", pallet.display()))?; + File::create(format!("{}/lib.rs", src.display()))?; + File::create(format!("{}/benchmarking.rs", src.display()))?; + File::create(format!("{}/tests.rs", src.display()))?; + File::create(format!("{}/mock.rs", src.display()))?; + Ok(()) } fn render_pallet( - pallet_name: String, - config: TemplatePalletConfig, - pallet_path: &PathBuf, + pallet_name: String, + config: TemplatePalletConfig, + pallet_path: &PathBuf, ) -> anyhow::Result<()> { - // let pallet_name = pallet_name.replace('-', "_"); - use crate::engines::generator::{ - PalletBenchmarking, PalletCargoToml, PalletLib, PalletMock, PalletTests, - }; - // Todo `module` must be of the form Template if pallet_name : `pallet_template` - let pallet: Vec> = vec![ - Box::new(PalletCargoToml { - name: pallet_name.clone(), - authors: config.authors, - description: config.description, - }), - Box::new(PalletLib {}), - Box::new(PalletBenchmarking {}), - Box::new(PalletMock { - module: pallet_name.clone(), - }), - Box::new(PalletTests { - module: pallet_name, - }), - ]; - for item in pallet { - item.execute(pallet_path)?; - } - Ok(()) + // let pallet_name = pallet_name.replace('-', "_"); + use crate::engines::generator::{ + PalletBenchmarking, PalletCargoToml, PalletLib, PalletMock, PalletTests, + }; + // Todo `module` must be of the form Template if pallet_name : `pallet_template` + let pallet: Vec> = vec![ + Box::new(PalletCargoToml { + name: pallet_name.clone(), + authors: config.authors, + description: config.description, + }), + Box::new(PalletLib {}), + Box::new(PalletBenchmarking {}), + Box::new(PalletMock { module: pallet_name.clone() }), + Box::new(PalletTests { module: pallet_name }), + ]; + for item in pallet { + item.execute(pallet_path)?; + } + Ok(()) } diff --git a/src/main.rs b/src/main.rs index 0e3109d8..b9fc16d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,8 +45,8 @@ enum Commands { #[clap(alias = "t")] Test(commands::test::TestArgs), #[clap(alias = "a")] - /// Add a pallet to the runtime - Add(commands::add::AddArgs), + /// Add a pallet to the runtime + Add(commands::add::AddArgs), } #[tokio::main] @@ -81,7 +81,7 @@ async fn main() -> Result<()> { #[cfg(feature = "contract")] commands::test::TestCommands::Contract(cmd) => cmd.execute(), }, - Commands::Add(args) => args.execute(), + Commands::Add(args) => args.execute(), } } From 19c76372f256eabe9852bbfc60c87d6df18e86fc Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 17 Mar 2024 11:52:58 +0530 Subject: [PATCH 32/57] fix inaccurate import cursor --- src/engines/pallet_engine/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 852fefbe..7f1ff804 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -405,7 +405,7 @@ impl PalletEngine { /// `State::Init` or `State::Import` fn insert_import(&mut self, import_stmt: (TokenStream, usize)) -> anyhow::Result<()> { self.append_tokens(import_stmt.0); - self.imports.last_import += import_stmt.1; + self.cursor += import_stmt.1; Ok(()) } /// Insert configuartion for a pallet - only for pallet-template atm From 5a0e6b48b8c3d370cbaf9c0820764942edad15af Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 17 Mar 2024 12:47:22 +0530 Subject: [PATCH 33/57] add now checks for uncommitted changes --- src/commands/add/mod.rs | 3 +-- src/engines/pallet_engine/mod.rs | 6 +++++- src/helpers.rs | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 25967759..5d097791 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -58,14 +58,13 @@ impl AddPallet { }, None => { // TODO: Fetch runtime either from cache - // Fix: This is a placeholder path, should not be used unimplemented!( "provide a runtime path until feat:cache is implemented: --runtime " ); }, }; let pallet = match self { - AddPallet::Template => format!("pallet-parachain-template"), + AddPallet::Template => "pallet-parachain-template".to_string(), AddPallet::Frame(FrameArgs { .. }) => { eprintln!("Sorry, frame pallets cannot be added right now"); std::process::exit(1); diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 7f1ff804..4c0b0f6d 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -20,7 +20,7 @@ mod steps; mod template; use crate::commands::add::AddPallet; -use crate::helpers::write_to_file; +use crate::helpers::{is_git_repo_with_commits, write_to_file}; use anyhow::{anyhow, bail, Context}; use dependency::{Dependency, Features}; use log::warn; @@ -46,6 +46,10 @@ pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; // Todo: Add option to source from cli let dep = TomlEditor::from(&runtime_path); + // Check if workspace has uncommitted changes, if yes, abort + if !is_git_repo_with_commits(dep.runtime.parent().unwrap().parent().unwrap()) { + bail!("Workspace has uncommitted changes, aborting pallet addition"); + } let steps = step_builder(pallet)?; run_steps(pe, dep, steps) } diff --git a/src/helpers.rs b/src/helpers.rs index ed60b605..aee8619c 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -80,3 +80,25 @@ pub(crate) fn resolve_pallet_path(path: Option) -> PathBuf { } } } + +pub(crate) fn is_git_repo_with_commits(repo_path: &Path) -> bool { + match Repository::open(repo_path) { + Ok(repo) => { + let mut status_opts = git2::StatusOptions::new(); + status_opts.include_untracked(true); + let statuses = repo.statuses(Some(&mut status_opts)).unwrap(); + + // Check if there are no changes to commit + if !statuses.iter().any(|s| s.status() != git2::Status::CURRENT) { + true + } else { + println!("Repository has uncommitted changes."); + false + } + }, + Err(e) => { + eprintln!("Failed to open repository: {}", e); + false + }, + } +} From b1225685922f75793923c9b972aa02d3d8dfec9b Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 17 Mar 2024 13:57:04 +0530 Subject: [PATCH 34/57] feature["parachain"] gate add --- src/commands/add/mod.rs | 1 + src/main.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 5d097791..f2800cc9 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "parachain")] use std::path::PathBuf; use crate::engines::pallet_engine; diff --git a/src/main.rs b/src/main.rs index f0fc27a0..cbf17ea1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,6 +46,7 @@ enum Commands { #[clap(alias = "t")] #[cfg(feature = "contract")] Test(commands::test::TestArgs), + #[cfg(feature = "parachain")] #[clap(alias = "a")] /// Add a pallet to the runtime Add(commands::add::AddArgs), @@ -83,6 +84,7 @@ async fn main() -> Result<()> { Commands::Test(args) => match &args.command { commands::test::TestCommands::Contract(cmd) => cmd.execute(), }, + #[cfg(feature = "parachain")] Commands::Add(args) => args.execute(), } } From 9ff13182b7295a27af8b3421f39761f42507c3ea Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 17 Mar 2024 14:11:24 +0530 Subject: [PATCH 35/57] optional deps for add-pallet --- Cargo.toml | 30 +++++++++++++++++++++--------- src/helpers.rs | 1 + 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8c519418..a684eb14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,19 +28,16 @@ tempfile = "3.8" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } url = { version = "2.5", optional = true } walkdir = "2.4" -frame-support-procedural-tools = "9.0.0" -proc-macro2 = { version = "1.0.70", features = ["span-locations"] } -quote = "1.0.33" -syn = { version = "2.0.52", features = ["full"] } -cfg-expr = "0.15.5" -prettyplease = "0.2.15" toml_edit = { version = "0.22.7" } # contracts contract-build = { version = "4.0.0-rc.3", optional = true } contract-extrinsics = { version = "4.0.0-rc.3", optional = true } sp-core = { version = "30.0.0", optional = true } -subxt-signer = { version = "0.34.0", features = ["subxt", "sr25519"], optional = true } +subxt-signer = { version = "0.34.0", features = [ + "subxt", + "sr25519", +], optional = true } subxt = { version = "0.34.0", optional = true } ink_env = { version = "5.0.0-rc.2", optional = true } sp-weights = { version = "29.0.0", optional = true } @@ -56,7 +53,15 @@ symlink = { version = "0.1", optional = true } tracing-subscriber = { version = "0.3", optional = true } zombienet-sdk = { git = "https://github.com/r0gue-io/zombienet-sdk", branch = "pop", optional = true } zombienet-support = { git = "https://github.com/r0gue-io/zombienet-sdk", branch = "pop", optional = true } -uuid = { version = "1.7.0", features = ["v4"] } +uuid = { version = "1.7.0", features = ["v4"], optional = true } +frame-support-procedural-tools = { version = "9.0.0", optional = true } +proc-macro2 = { version = "1.0.70", features = [ + "span-locations", +], optional = true } +quote = { version = "1.0.33", optional = true } +syn = { version = "2.0.52", features = ["full"], optional = true } +cfg-expr = { version = "0.15.5", optional = true } +prettyplease = { version = "0.2.15", optional = true } [features] default = ["contract", "parachain"] @@ -79,5 +84,12 @@ parachain = [ "dep:tracing-subscriber", "dep:url", "dep:zombienet-sdk", - "dep:zombienet-support" + "dep:zombienet-support", + "uuid", + "frame-support-procedural-tools", + "proc-macro2", + "quote", + "syn", + "cfg-expr", + "prettyplease", ] diff --git a/src/helpers.rs b/src/helpers.rs index adc1a367..532f4f22 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,3 +1,4 @@ +#![allow(unused)] use anyhow::Result; use cliclack::{log, outro_cancel}; use git2::Repository; From 1bb0385e42dea083a26e4b3b359d429764c9a402 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Sun, 17 Mar 2024 14:18:00 +0530 Subject: [PATCH 36/57] add note for add test failure --- tests/add.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/add.rs b/tests/add.rs index bcf92fa1..c3de2e7f 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -3,6 +3,7 @@ use std::fs; use std::path::PathBuf; use tempdir::TempDir; +#[ignore = "TomlEditor expects to find a parachain project structure initialized with git"] #[test] fn add_parachain_pallet_template() { let temp_dir = TempDir::new("add-pallet-test").unwrap(); From 33c2a95d847ac72c54acc3bcf838965addfc3325 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 18 Mar 2024 13:56:19 +0530 Subject: [PATCH 37/57] modify add-pallet test --- tests/add.rs | 39 ++- tests/add/lib.rs | 779 ----------------------------------------------- 2 files changed, 27 insertions(+), 791 deletions(-) delete mode 100644 tests/add/lib.rs diff --git a/tests/add.rs b/tests/add.rs index c3de2e7f..6d5f8433 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -1,25 +1,40 @@ use assert_cmd::Command; use std::fs; -use std::path::PathBuf; use tempdir::TempDir; -#[ignore = "TomlEditor expects to find a parachain project structure initialized with git"] +#[ignore = "test fails to run"] #[test] fn add_parachain_pallet_template() { let temp_dir = TempDir::new("add-pallet-test").unwrap(); - let output = temp_dir.path().join("test_lib.rs"); - let source_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/add/lib.rs"); - println!("source file : {:?}", source_file); - fs::copy(&source_file, &output).unwrap(); + // Setup new parachain Command::cargo_bin("pop") .unwrap() - .args(&["add", "pallet", "template", "-r", "test_lib.rs"]) - .current_dir(&temp_dir) + .args(&["new", "parachain", "testchain"]) .assert() .success(); - let contents = fs::read_to_string(&output).unwrap(); - assert_eq!(contents.matches("pub use pallet_parachain_template;").count(), 1); - assert_eq!(contents.matches("impl pallet_parachain_template::Config for Runtime {").count(), 1); - assert_eq!(contents.matches("Template: pallet_parachain_template").count(), 1); + println!("{:?}", temp_dir.path().display()); + // Add pallet-parachain-template + Command::cargo_bin("pop") + .unwrap() + .args(&["add", "pallet", "template", "-r", "runtime/src/lib.rs"]) + .current_dir(&temp_dir.path().join("testchain")) + .assert() + .success(); + + let runtime_contents = + fs::read_to_string(&temp_dir.path().join("testchain/runtime/src/lib.rs")).unwrap(); + let runtime_manifest = + fs::read_to_string(&temp_dir.path().join("testchain/runtime/Cargo.toml")).unwrap(); + + assert_eq!(runtime_contents.matches("pub use pallet_parachain_template;").count(), 1); + assert_eq!( + runtime_contents + .matches("impl pallet_parachain_template::Config for Runtime {") + .count(), + 1 + ); + assert_eq!(runtime_contents.matches("Template: pallet_parachain_template").count(), 1); + + assert_eq!(runtime_manifest.matches("pallet-parachain-template").count(), 3); } diff --git a/tests/add/lib.rs b/tests/add/lib.rs deleted file mode 100644 index 44936443..00000000 --- a/tests/add/lib.rs +++ /dev/null @@ -1,779 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -mod weights; -pub mod xcm_config; - -use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; -use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; -use smallvec::smallvec; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, -}; - -use sp_std::prelude::*; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; - -use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; -use frame_support::{ - construct_runtime, - dispatch::DispatchClass, - genesis_builder_helper::{build_config, create_default_config}, - parameter_types, - traits::{ - ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, TransformOrigin, - }, - weights::{ - constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight, WeightToFeeCoefficient, - WeightToFeeCoefficients, WeightToFeePolynomial, - }, - PalletId, -}; -use frame_system::{ - limits::{BlockLength, BlockWeights}, - EnsureRoot, -}; -use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; -use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; -pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; -pub use sp_runtime::{MultiAddress, Perbill, Permill}; -use xcm_config::{RelayLocation, XcmOriginToTransactDispatchOrigin}; - -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; - -// Polkadot imports -use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; - -use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; - -// XCM Imports -use xcm::latest::prelude::BodyId; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// Balance of an account. -pub type Balance = u128; - -/// Index of a transaction in the chain. -pub type Nonce = u32; - -/// A hash of some data used by the chain. -pub type Hash = sp_core::H256; - -/// An index to a block. -pub type BlockNumber = u32; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Block header type as expected by this runtime. -pub type Header = generic::Header; - -/// Block type as expected by this runtime. -pub type Block = generic::Block; - -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; - -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; - -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, -); - -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; - -/// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; - -/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the -/// node's balance type. -/// -/// This should typically create a mapping between the following ranges: -/// - `[0, MAXIMUM_BLOCK_WEIGHT]` -/// - `[Balance::min, Balance::max]` -/// -/// Yet, it can be used for any other sort of change to weight-fee. Some examples being: -/// - Setting it to `0` will essentially disable the weight fee. -/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: - // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT - let p = MILLIUNIT / 10; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know -/// the specifics of the runtime. They can then be made to be agnostic over specific formats -/// of data like extrinsics, allowing for them to continue syncing the network through upgrades -/// to even the core data structures. -pub mod opaque { - use super::*; - use sp_runtime::{ - generic, - traits::{BlakeTwo256, Hash as HashT}, - }; - - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; - /// Opaque block header type. - pub type Header = generic::Header; - /// Opaque block type. - pub type Block = generic::Block; - /// Opaque block identifier type. - pub type BlockId = generic::BlockId; - /// Opaque block hash type. - pub type Hash = ::Output; -} - -impl_opaque_keys! { - pub struct SessionKeys { - pub aura: Aura, - } -} - -#[sp_version::runtime_version] -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("template-parachain"), - impl_name: create_runtime_str!("template-parachain"), - authoring_version: 1, - spec_version: 1, - impl_version: 0, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, - state_version: 1, -}; - -/// This determines the average expected block time that we are targeting. -/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. -/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked -/// up by `pallet_aura` to implement `fn slot_duration()`. -/// -/// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 12000; - -// NOTE: Currently it is not possible to change the slot duration after the chain has started. -// Attempting to do so will brick block production. -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// Time is measured by number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - -// Unit = the base number of indivisible units for balances -pub const UNIT: Balance = 1_000_000_000_000; -pub const MILLIUNIT: Balance = 1_000_000_000; -pub const MICROUNIT: Balance = 1_000_000; - -/// The existential deposit. Set to 1/10 of the Connected Relay Chain. -pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; - -/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is -/// used to limit the maximal weight of a single extrinsic. -const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); - -/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by -/// `Operational` extrinsics. -const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); - -/// We allow for 0.5 of a second of compute with a 12 second average block time. -const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( - WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), - cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64, -); - -/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included -/// into the relay chain. -const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1; -/// How many parachain blocks are processed by the relay chain per parent. Limits the -/// number of blocks authored per slot. -const BLOCK_PROCESSING_VELOCITY: u32 = 1; -/// Relay chain slot duration, in milliseconds. -const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; - -/// The version information used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } -} - -parameter_types! { - pub const Version: RuntimeVersion = VERSION; - - // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. - // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the - // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize - // the lazy contract deletion. - pub RuntimeBlockLength: BlockLength = - BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() - .base_block(BlockExecutionWeight::get()) - .for_class(DispatchClass::all(), |weights| { - weights.base_extrinsic = ExtrinsicBaseWeight::get(); - }) - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Operational transactions have some extra reserved space, so that they - // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT - ); - }) - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); - pub const SS58Prefix: u16 = 42; -} - -// Configure FRAME pallets to include in runtime. - -impl frame_system::Config for Runtime { - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = BlakeTwo256; - /// The block type. - type Block = Block; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; - type WeightInfo = (); -} - -impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (CollatorSelection,); -} - -parameter_types! { - pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; -} - -impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; - /// The type for recording an account's balance. - type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type RuntimeFreezeReason = RuntimeFreezeReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; -} - -parameter_types! { - /// Relay Chain `TransactionByteFee` / 10 - pub const TransactionByteFee: Balance = 10 * MICROUNIT; -} - -impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type OperationalFeeMultiplier = ConstU8<5>; -} - -impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type WeightInfo = (); -} - -parameter_types! { - pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; -} - -impl cumulus_pallet_parachain_system::Config for Runtime { - type WeightInfo = (); - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; - type OutboundXcmpMessageSource = XcmpQueue; - type DmpQueue = frame_support::traits::EnqueueWithOrigin; - type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; - type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; - type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< - Runtime, - RELAY_CHAIN_SLOT_DURATION_MILLIS, - BLOCK_PROCESSING_VELOCITY, - UNINCLUDED_SEGMENT_CAPACITY, - >; -} - -impl parachain_info::Config for Runtime {} - -parameter_types! { - pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; -} - -impl pallet_message_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor< - cumulus_primitives_core::AggregateMessageOrigin, - >; - #[cfg(not(feature = "runtime-benchmarks"))] - type MessageProcessor = xcm_builder::ProcessXcmMessage< - AggregateMessageOrigin, - xcm_executor::XcmExecutor, - RuntimeCall, - >; - type Size = u32; - // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: - type QueueChangeHandler = NarrowOriginToSibling; - type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; - type MaxStale = sp_core::ConstU32<8>; - type ServiceWeight = MessageQueueServiceWeight; -} - -impl cumulus_pallet_aura_ext::Config for Runtime {} - -impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - // Enqueue XCMP messages from siblings for later processing. - type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); - type PriceForSiblingDelivery = NoPriceForMessageDelivery; -} - -parameter_types! { - pub const Period: u32 = 6 * HOURS; - pub const Offset: u32 = 0; -} - -impl pallet_session::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ValidatorId = ::AccountId; - // we don't have stash and controller, thus we don't need the convert as well. - type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = CollatorSelection; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; - type WeightInfo = (); -} - -impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = ConstU32<100_000>; - type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] - type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; -} - -parameter_types! { - pub const PotId: PalletId = PalletId(*b"PotStake"); - pub const SessionLength: BlockNumber = 6 * HOURS; - // StakingAdmin pluralistic body. - pub const StakingAdminBodyId: BodyId = BodyId::Defense; -} - -/// We allow root and the StakingAdmin to execute privileged collator selection operations. -pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< - EnsureRoot, - EnsureXcm>, ->; - -impl pallet_collator_selection::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type UpdateOrigin = CollatorSelectionUpdateOrigin; - type PotId = PotId; - type MaxCandidates = ConstU32<100>; - type MinEligibleCollators = ConstU32<4>; - type MaxInvulnerables = ConstU32<20>; - // should be a multiple of session or things will get inconsistent - type KickThreshold = Period; - type ValidatorId = ::AccountId; - type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ValidatorRegistration = Session; - type WeightInfo = (); -} - -construct_runtime!( - pub enum Runtime - { - // System support stuff. - System: frame_system = 0, - ParachainSystem: cumulus_pallet_parachain_system = 1, - Timestamp: pallet_timestamp = 2, - ParachainInfo: parachain_info = 3, - - // Monetary stuff. - Balances: pallet_balances = 10, - TransactionPayment: pallet_transaction_payment = 11, - - // Governance - Sudo: pallet_sudo = 15, - - // Collator support. The order of these 4 are important and shall not change. - Authorship: pallet_authorship = 20, - CollatorSelection: pallet_collator_selection = 21, - Session: pallet_session = 22, - Aura: pallet_aura = 23, - AuraExt: cumulus_pallet_aura_ext = 24, - - // XCM helpers. - XcmpQueue: cumulus_pallet_xcmp_queue = 30, - PolkadotXcm: pallet_xcm = 31, - CumulusXcm: cumulus_pallet_xcm = 32, - MessageQueue: pallet_message_queue = 33, - } -); - -#[cfg(feature = "runtime-benchmarks")] -mod benches { - frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_balances, Balances] - [pallet_session, SessionBench::] - [pallet_timestamp, Timestamp] - [pallet_message_queue, MessageQueue] - [pallet_sudo, Sudo] - [pallet_collator_selection, CollatorSelection] - [cumulus_pallet_parachain_system, ParachainSystem] - [cumulus_pallet_xcmp_queue, XcmpQueue] - ); -} - -impl_runtime_apis! { - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) - } - - fn authorities() -> Vec { - Aura::authorities().into_inner() - } - } - - impl sp_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl sp_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Runtime::metadata().into()) - } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } - } - - impl sp_block_builder::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { - Executive::apply_extrinsic(extrinsic) - } - - fn finalize_block() -> ::Header { - Executive::finalize_block() - } - - fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents( - block: Block, - data: sp_inherents::InherentData, - ) -> sp_inherents::CheckInherentsResult { - data.check_extrinsics(&block) - } - } - - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction( - source: TransactionSource, - tx: ::Extrinsic, - block_hash: ::Hash, - ) -> TransactionValidity { - Executive::validate_transaction(source, tx, block_hash) - } - } - - impl sp_offchain::OffchainWorkerApi for Runtime { - fn offchain_worker(header: &::Header) { - Executive::offchain_worker(header) - } - } - - impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - SessionKeys::generate(seed) - } - - fn decode_session_keys( - encoded: Vec, - ) -> Option, KeyTypeId)>> { - SessionKeys::decode_into_raw_public_keys(&encoded) - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Nonce { - System::account_nonce(account) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { - fn query_info( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - fn query_fee_details( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment::FeeDetails { - TransactionPayment::query_fee_details(uxt, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi - for Runtime - { - fn query_call_info( - call: RuntimeCall, - len: u32, - ) -> pallet_transaction_payment::RuntimeDispatchInfo { - TransactionPayment::query_call_info(call, len) - } - fn query_call_fee_details( - call: RuntimeCall, - len: u32, - ) -> pallet_transaction_payment::FeeDetails { - TransactionPayment::query_call_fee_details(call, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - impl cumulus_primitives_core::CollectCollationInfo for Runtime { - fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { - ParachainSystem::collect_collation_info(header) - } - } - - #[cfg(feature = "try-runtime")] - impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { - let weight = Executive::try_runtime_upgrade(checks).unwrap(); - (weight, RuntimeBlockWeights::get().max_block) - } - - fn execute_block( - block: Block, - state_root_check: bool, - signature_check: bool, - select: frame_try_runtime::TryStateSelect, - ) -> Weight { - // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to - // have a backtrace here. - Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() - } - } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn benchmark_metadata(extra: bool) -> ( - Vec, - Vec, - ) { - use frame_benchmarking::{Benchmarking, BenchmarkList}; - use frame_support::traits::StorageInfoTrait; - use frame_system_benchmarking::Pallet as SystemBench; - use cumulus_pallet_session_benchmarking::Pallet as SessionBench; - - let mut list = Vec::::new(); - list_benchmarks!(list, extra); - - let storage_info = AllPalletsWithSystem::storage_info(); - (list, storage_info) - } - - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; - - use frame_system_benchmarking::Pallet as SystemBench; - impl frame_system_benchmarking::Config for Runtime { - fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { - ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); - Ok(()) - } - - fn verify_set_code() { - System::assert_last_event(cumulus_pallet_parachain_system::Event::::ValidationFunctionStored.into()); - } - } - - use cumulus_pallet_session_benchmarking::Pallet as SessionBench; - impl cumulus_pallet_session_benchmarking::Config for Runtime {} - - use frame_support::traits::WhitelistedStorageKeys; - let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - add_benchmarks!(params, batches); - - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } - Ok(batches) - } - } - - impl sp_genesis_builder::GenesisBuilder for Runtime { - fn create_default_config() -> Vec { - create_default_config::() - } - - fn build_config(config: Vec) -> sp_genesis_builder::Result { - build_config::(config) - } - } -} - -cumulus_pallet_parachain_system::register_validate_block! { - Runtime = Runtime, - BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, -} From 3c55dac8313fd236359c272d61d718c74e128cdf Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 18 Mar 2024 14:19:03 +0530 Subject: [PATCH 38/57] test fails due to unclean git state on pop new parachain --- tests/add.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/add.rs b/tests/add.rs index 6d5f8433..03f7d022 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -2,18 +2,17 @@ use assert_cmd::Command; use std::fs; use tempdir::TempDir; -#[ignore = "test fails to run"] +#[ignore = "test fails due to no git commit on `pop new parachain`"] #[test] fn add_parachain_pallet_template() { let temp_dir = TempDir::new("add-pallet-test").unwrap(); // Setup new parachain Command::cargo_bin("pop") .unwrap() + .current_dir(&temp_dir) .args(&["new", "parachain", "testchain"]) .assert() - .success(); - - println!("{:?}", temp_dir.path().display()); + .success(); // Add pallet-parachain-template Command::cargo_bin("pop") .unwrap() From 799625796ad7ad42c6963572aef80168685b4545 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 18 Mar 2024 15:01:01 +0530 Subject: [PATCH 39/57] manually invoke git, then run add-pallet --- tests/add.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/tests/add.rs b/tests/add.rs index 03f7d022..d89ff29f 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -1,8 +1,8 @@ use assert_cmd::Command; use std::fs; use tempdir::TempDir; +use toml_edit::DocumentMut; -#[ignore = "test fails due to no git commit on `pop new parachain`"] #[test] fn add_parachain_pallet_template() { let temp_dir = TempDir::new("add-pallet-test").unwrap(); @@ -12,12 +12,19 @@ fn add_parachain_pallet_template() { .current_dir(&temp_dir) .args(&["new", "parachain", "testchain"]) .assert() - .success(); + .success(); + // Git setup + use duct::cmd; + cmd!("git", "add", ".").dir(&temp_dir.path().join("testchain")).run().unwrap(); + cmd!("git", "commit", "--no-gpg-sign", "-m", "Initialized testchain") + .dir(&temp_dir.path().join("testchain")) + .run() + .unwrap(); // Add pallet-parachain-template Command::cargo_bin("pop") .unwrap() - .args(&["add", "pallet", "template", "-r", "runtime/src/lib.rs"]) - .current_dir(&temp_dir.path().join("testchain")) + .args(&["add", "pallet", "template", "-r", "testchain/runtime/src/lib.rs"]) + .current_dir(&temp_dir.path()) .assert() .success(); @@ -25,7 +32,7 @@ fn add_parachain_pallet_template() { fs::read_to_string(&temp_dir.path().join("testchain/runtime/src/lib.rs")).unwrap(); let runtime_manifest = fs::read_to_string(&temp_dir.path().join("testchain/runtime/Cargo.toml")).unwrap(); - + // Check runtime entries assert_eq!(runtime_contents.matches("pub use pallet_parachain_template;").count(), 1); assert_eq!( runtime_contents @@ -34,6 +41,14 @@ fn add_parachain_pallet_template() { 1 ); assert_eq!(runtime_contents.matches("Template: pallet_parachain_template").count(), 1); - - assert_eq!(runtime_manifest.matches("pallet-parachain-template").count(), 3); + // Check runtime manifest entries + let toml = runtime_manifest.parse::().unwrap(); + assert!(toml["dependencies"]["pallet-parachain-template"].is_value()); + let std = toml["features"]["std"].as_value().unwrap().as_array().unwrap(); + assert_eq!( + std.iter() + .filter(|val| val.as_str().unwrap() == "pallet-parachain-template/std") + .count(), + 1 + ); } From c6d1991c0e167a58a6f425e06c44471879b794be Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 18 Mar 2024 15:01:37 +0530 Subject: [PATCH 40/57] comments --- src/engines/pallet_engine/mod.rs | 44 +++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 4c0b0f6d..ad9363e2 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -45,7 +45,7 @@ use toml_edit::DocumentMut; pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; // Todo: Add option to source from cli - let dep = TomlEditor::from(&runtime_path); + let dep = TomlEditor::infer(&runtime_path); // Check if workspace has uncommitted changes, if yes, abort if !is_git_repo_with_commits(dep.runtime.parent().unwrap().parent().unwrap()) { bail!("Workspace has uncommitted changes, aborting pallet addition"); @@ -60,24 +60,44 @@ struct TomlEditor { node: PathBuf, } impl TomlEditor { - /// Use default values for runtime/Cargo.toml and ../node/Cargo.toml - fn from(runtime_path: &Path) -> Self { + fn new(runtime: &Path, node: &Path) -> Self { + Self { runtime: runtime.to_path_buf(), node: node.to_path_buf() } + } + /// Infer a given runtime and node manifest paths from the given runtime path + /// runtime -> ../Cargo.toml + /// node -> ../node/Cargo.toml + fn infer(runtime_path: &Path) -> Self { let runtime_manifest = runtime_path.parent().unwrap().parent().unwrap().join("Cargo.toml"); let node_manifest = runtime_path - .parent() + .parent() // src .unwrap() - .parent() + .parent() // runtime .unwrap() - .parent() + .parent() // workspace .unwrap() .join("node/Cargo.toml"); // println!("{} {}", runtime_manifest.display(), node_manifest.display()); Self { runtime: runtime_manifest, node: node_manifest } } - // fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { - - // self.inject(&self.node, dep) - // } + /// Inject a dependency into the node manifest + fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { + let mut s = String::new(); + let mut f = BufReader::new(File::open(&self.node)?); + f.read_to_string(&mut s) + .context("Dependency Injection: Failed to read node:Cargo.toml")?; + let doc = s.parse::().context("Cannot parse toml")?; + let updated_doc = self.inject(doc, dep)?.to_string(); + use std::io::Write; + let mut file = OpenOptions::new() + .write(true) + .truncate(true) + .create(false) + .open(&self.node) + .unwrap(); + file.write_all(updated_doc.as_bytes()) + .context("failed to update node:Cargo.toml") + } + /// Inject a dependency into the runtime manifest fn inject_runtime(&self, dep: Dependency) -> anyhow::Result<()> { let mut s = String::new(); let mut f = BufReader::new(File::open(&self.runtime)?); @@ -103,8 +123,8 @@ impl TomlEditor { t["version"] = value("1.0.0"); t["default-features"] = value(default_features); doc["dependencies"]["pallet-parachain-template"] = value(t.into_inline_table()); - for feat in features { - match feat { + for feature in features { + match feature { Features::Std => { // features let std = doc["features"]["std"].as_value_mut().expect("feature std not found"); From 1d92314fbdcd91fb12a8907956e5236dbd42272d Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 19 Mar 2024 15:03:29 +0530 Subject: [PATCH 41/57] separate dependency module --- Cargo.lock | 1 + Cargo.toml | 2 +- src/engines/pallet_engine/dependency.rs | 91 +++++++++++++++++++++++++ src/engines/pallet_engine/mod.rs | 47 +------------ src/engines/pallet_engine/steps.rs | 2 +- tests/add.rs | 1 + 6 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 src/engines/pallet_engine/dependency.rs diff --git a/Cargo.lock b/Cargo.lock index e8ff5af9..54030fa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5460,6 +5460,7 @@ dependencies = [ "proc-macro2", "quote", "reqwest", + "semver 1.0.22", "serde", "serde_json", "sp-core 30.0.0", diff --git a/Cargo.toml b/Cargo.toml index a684eb14..db21a534 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ console = "0.15" duct = "0.13" git2 = "0.18" log = "0.4" -# semver = "1.0.20" +semver = "1.0.20" strum = "0.26" strum_macros = "0.26" tempfile = "3.8" diff --git a/src/engines/pallet_engine/dependency.rs b/src/engines/pallet_engine/dependency.rs new file mode 100644 index 00000000..8547345a --- /dev/null +++ b/src/engines/pallet_engine/dependency.rs @@ -0,0 +1,91 @@ +//! Dependency representations for Pallets +use strum_macros::{Display, EnumString}; + +#[derive(EnumString, Display, Debug)] +pub(super) enum Features { + #[strum(serialize = "std")] + Std, + #[strum(serialize = "runtime-benchmarks")] + RuntimeBenchmarks, + #[strum(serialize = "try-runtime")] + TryRuntime, + /// Custom feature + Custom(String), +} +#[derive(Display, Debug)] +pub(super) enum Location { + /// Local path is form `path = "X"` + Local(std::path::PathBuf), + /// `git = {url}` + Git(reqwest::Url), + /// String should be of format `version = "X"` + CratesIO(semver::Version), +} +impl From for Location { + fn from(url: reqwest::Url) -> Self { + Self::Git(url) + } +} +impl From for Location { + fn from(path: std::path::PathBuf) -> Self { + Self::Local(path) + } +} +impl<'a> From<&'a std::path::Path> for Location { + fn from(path: &'a std::path::Path) -> Self { + Self::Local(path.to_path_buf()) + } +} +impl From for Location { + fn from(version: semver::Version) -> Self { + Self::CratesIO(version) + } +} +impl Into for Location { + fn into(self) -> String { + match self { + Location::Local(path) => format!("path = \"{}\"", path.display()), + Location::Git(url) => format!("git = \"{}\"", url), + Location::CratesIO(version) => format!("version = \"{}\"", version), + } + } +} +impl Into for Location { + fn into(self) -> toml_edit::Value { + Into::::into(self).into() + } +} + +#[derive(Debug)] +pub(super) struct Dependency { + pub(super) features: Vec, + /// Maybe local path, git url, or from crates.io in which case we will use this for version + pub(super) path: Location, + pub(super) default_features: bool, +} + +impl Dependency { + /// Create dependencies required for adding a local pallet-parachain-template to runtime + /// ..$(runtime)/pallets/pallet-parachain-template + pub(super) fn local_template_runtime() -> Self { + Self { + features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], + // TODO hardcode for now + path: std::path::Path::new("../pallets/pallet-parachain-template") + .to_path_buf() + .into(), + default_features: false, + } + } + // TODO: Remove code - Node doesn't require template pallet deps by default + // but this maybe desirable for custom pallets. + // /// Create dependencies required for adding a pallet-parachain-template to node + // pub(super) fn template_node() -> Self { + // Self { + // features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], + // // TODO hardcode for now + // path: format!("../pallets/pallet-parachain-template"), + // default_features: true, + // } + // } +} diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index ad9363e2..c402f467 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -18,6 +18,7 @@ mod pallet_entry; mod parser; mod steps; mod template; +mod dependency; use crate::commands::add::AddPallet; use crate::helpers::{is_git_repo_with_commits, write_to_file}; @@ -586,49 +587,3 @@ impl PalletEngine { Ok(()) } } -// TODO -mod dependency { - use strum_macros::{Display, EnumString}; - - #[derive(EnumString, Display, Debug)] - pub(in crate::engines::pallet_engine) enum Features { - #[strum(serialize = "std")] - Std, - #[strum(serialize = "runtime-benchmarks")] - RuntimeBenchmarks, - #[strum(serialize = "try-runtime")] - TryRuntime, - Custom(String), - } - #[derive(Debug)] - pub(in crate::engines::pallet_engine) struct Dependency { - pub(in crate::engines::pallet_engine) features: Vec, - /// Maybe local path, git url, or from crates.io in which case we will use this for version - pub(in crate::engines::pallet_engine) path: String, - pub(in crate::engines::pallet_engine) default_features: bool, - } - - impl Dependency { - /// Create dependencies required for adding a pallet-parachain-template to runtime - pub(in crate::engines::pallet_engine) fn template_runtime() -> Self { - log::warn!("Using default path for pallet-parachain-template `pallets/pallet-parachain-template`"); - Self { - features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], - // TODO hardcode for now - path: format!("../pallets/pallet-parachain-template"), - default_features: false, - } - } - // TODO: Remove code - Node doesn't require template pallet deps by default - // but this maybe desirable for custom pallets. - // /// Create dependencies required for adding a pallet-parachain-template to node - // pub(in crate::engines::pallet_engine) fn template_node() -> Self { - // Self { - // features: vec![Features::RuntimeBenchmarks, Features::TryRuntime], - // // TODO hardcode for now - // path: format!("../pallets/pallet-parachain-template"), - // default_features: true, - // } - // } - } -} diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 2be48bdb..6dbe090f 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -66,7 +66,7 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - steps.push(RuntimePalletDependency(Dependency::template_runtime())); + steps.push(RuntimePalletDependency(Dependency::local_template_runtime())); }, AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; diff --git a/tests/add.rs b/tests/add.rs index d89ff29f..60d8a5bf 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -18,6 +18,7 @@ fn add_parachain_pallet_template() { cmd!("git", "add", ".").dir(&temp_dir.path().join("testchain")).run().unwrap(); cmd!("git", "commit", "--no-gpg-sign", "-m", "Initialized testchain") .dir(&temp_dir.path().join("testchain")) + .stdout_null() .run() .unwrap(); // Add pallet-parachain-template From 5f806d8d782b30192b699552d9d8bf6963d7398f Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 19 Mar 2024 17:26:11 +0530 Subject: [PATCH 42/57] generalize dependency injection --- src/engines/pallet_engine/dependency.rs | 68 ++++++++++++++++++++----- src/engines/pallet_engine/mod.rs | 17 +++---- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/src/engines/pallet_engine/dependency.rs b/src/engines/pallet_engine/dependency.rs index 8547345a..c74d1c90 100644 --- a/src/engines/pallet_engine/dependency.rs +++ b/src/engines/pallet_engine/dependency.rs @@ -1,4 +1,5 @@ //! Dependency representations for Pallets +use std::path; use strum_macros::{Display, EnumString}; #[derive(EnumString, Display, Debug)] @@ -12,28 +13,38 @@ pub(super) enum Features { /// Custom feature Custom(String), } -#[derive(Display, Debug)] +#[derive(Display, Debug, Clone)] pub(super) enum Location { /// Local path is form `path = "X"` - Local(std::path::PathBuf), + Local(std::path::PathBuf, Option), /// `git = {url}` - Git(reqwest::Url), + Git(reqwest::Url, Option), /// String should be of format `version = "X"` CratesIO(semver::Version), } impl From for Location { fn from(url: reqwest::Url) -> Self { - Self::Git(url) + Self::Git(url, None) } } impl From for Location { fn from(path: std::path::PathBuf) -> Self { - Self::Local(path) + Self::Local(path, None) + } +} +impl From<(std::path::PathBuf, semver::Version)> for Location { + fn from(info: (std::path::PathBuf, semver::Version)) -> Self { + Self::Local(info.0, Some(info.1)) } } impl<'a> From<&'a std::path::Path> for Location { fn from(path: &'a std::path::Path) -> Self { - Self::Local(path.to_path_buf()) + Self::Local(path.to_path_buf(), None) + } +} +impl<'a> From<(&'a std::path::Path, semver::Version)> for Location { + fn from(info: (&'a std::path::Path, semver::Version)) -> Self { + Self::Local(info.0.to_path_buf(), Some(info.1.into())) } } impl From for Location { @@ -44,36 +55,67 @@ impl From for Location { impl Into for Location { fn into(self) -> String { match self { - Location::Local(path) => format!("path = \"{}\"", path.display()), - Location::Git(url) => format!("git = \"{}\"", url), - Location::CratesIO(version) => format!("version = \"{}\"", version), + Location::Local(path, Some(version)) => { + format!("{{ path = \"{}\", version = \"{}\" }}", path.display(), version) + }, + Location::Local(path, _) => format!("{{ path = \"{}\" }}", path.display()), + Location::Git(url, Some(version)) => { + format!("{{ git = \"{}\", version = \"{}\" }}", url, version) + }, + Location::Git(url, _) => format!("{{ git = \"{}\" }}", url), + Location::CratesIO(version) => format!("{{ version = \"{}\" }}", version), } } } impl Into for Location { fn into(self) -> toml_edit::Value { - Into::::into(self).into() + let s = Into::::into(self); + let t = s + .parse::() + .expect("Location String parse as Toml Value failed"); + toml_edit::Value::InlineTable( + t.as_inline_table().expect(" Parsed Location -> ILT cast infallible").to_owned(), + ) } } #[derive(Debug)] pub(super) struct Dependency { + /// Name for the dependency + pub(super) name: String, + /// Additional features that need to be enabled. Format -> {name}/{feature} pub(super) features: Vec, /// Maybe local path, git url, or from crates.io in which case we will use this for version pub(super) path: Location, + /// Default features such as `std` are disabled by default for runtime pallet dependencies pub(super) default_features: bool, } impl Dependency { + /// Generate the main dependency as an inline table + pub(super) fn entry(&self) -> toml_edit::InlineTable { + let mut t = toml_edit::Table::new(); + let location = Into::::into(self.path.clone()); + t.extend( + location + .as_inline_table() + .expect("Location to String should produce valid inline table") + .to_owned(), + ); + t["default-features"] = toml_edit::value(self.default_features); + t.into_inline_table() + } /// Create dependencies required for adding a local pallet-parachain-template to runtime /// ..$(runtime)/pallets/pallet-parachain-template pub(super) fn local_template_runtime() -> Self { Self { + name: format!("pallet-parachain-template"), features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], // TODO hardcode for now - path: std::path::Path::new("../pallets/pallet-parachain-template") - .to_path_buf() - .into(), + path: ( + std::path::Path::new("../pallets/pallet-parachain-template").to_path_buf(), + semver::Version::new(1, 0, 0), + ).into(), default_features: false, } } diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index c402f467..b96581c9 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -14,11 +14,11 @@ //! //! It is the goal of this module, to answer all of these questions. +mod dependency; mod pallet_entry; mod parser; mod steps; mod template; -mod dependency; use crate::commands::add::AddPallet; use crate::helpers::{is_git_repo_with_commits, write_to_file}; @@ -116,35 +116,32 @@ impl TomlEditor { file.write_all(updated_doc.as_bytes()) .context("failed to update runtime:Cargo.toml") } + /// Inject a dependency to a DocumentMut representation of a toml file fn inject(&self, mut doc: DocumentMut, dep: Dependency) -> anyhow::Result { use toml_edit::{value, Item, Table}; - let Dependency { features, path, default_features } = dep; - let mut t = Table::new(); - t["path"] = value(Into::::into(path)); - t["version"] = value("1.0.0"); - t["default-features"] = value(default_features); - doc["dependencies"]["pallet-parachain-template"] = value(t.into_inline_table()); + doc["dependencies"][&dep.name] = value(dep.entry()); + let Dependency { name, features, .. } = dep; for feature in features { match feature { Features::Std => { // features let std = doc["features"]["std"].as_value_mut().expect("feature std not found"); let arr = std.as_array_mut().unwrap(); - arr.push_formatted("pallet-parachain-template/std".into()); + arr.push_formatted(format!("{}/std", name).into()); }, Features::RuntimeBenchmarks => { let rt_bnch = doc["features"]["runtime-benchmarks"] .as_value_mut() .expect("feature runtime-benchmarks not found"); let arr = rt_bnch.as_array_mut().unwrap(); - arr.push_formatted("pallet-parachain-template/runtime-benchmarks".into()); + arr.push_formatted(format!("{}/runtime-benchmarks", name).into()); }, Features::TryRuntime => { let try_rt = doc["features"]["try-runtime"] .as_value_mut() .expect("feature try-runtime not found"); let arr = try_rt.as_array_mut().unwrap(); - arr.push_formatted("pallet-parachain-template/try-runtime".into()); + arr.push_formatted(format!("{}/try-runtime", name).into()); }, Features::Custom(_) => unimplemented!("Custom features not supported yet"), } From 41761877210883aeb096cc9315365d239da4c272 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Tue, 19 Mar 2024 17:32:40 +0530 Subject: [PATCH 43/57] git config for CI --- .github/workflows/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e6b32796..bff096c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ on: env: CARGO_TERM_COLOR: always - + GITHUB_ACTOR: pop-cli jobs: build: @@ -28,6 +28,11 @@ jobs: cache-on-failure: true cache-all-crates: true + - name: Setup git config + run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + - uses: actions/checkout@v3 - name: Check Feature Contracts Excl. run: cargo check --no-default-features --features contract From f5ff852f167bc089349387cca9c902bf38ae9d82 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 20 Mar 2024 14:58:20 +0530 Subject: [PATCH 44/57] fix issue #67 --- src/engines/pallet_engine/dependency.rs | 3 +- src/engines/pallet_engine/mod.rs | 44 +++++++++++++++++-------- src/helpers.rs | 16 ++++----- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/engines/pallet_engine/dependency.rs b/src/engines/pallet_engine/dependency.rs index c74d1c90..9dd787bc 100644 --- a/src/engines/pallet_engine/dependency.rs +++ b/src/engines/pallet_engine/dependency.rs @@ -111,8 +111,9 @@ impl Dependency { Self { name: format!("pallet-parachain-template"), features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], - // TODO hardcode for now path: ( + // TODO hardcode for now + // The reason is, `pop new pallet` places a new pallet on $(workspace_root)/pallets std::path::Path::new("../pallets/pallet-parachain-template").to_path_buf(), semver::Version::new(1, 0, 0), ).into(), diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index b96581c9..cb82f848 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -46,9 +46,10 @@ use toml_edit::DocumentMut; pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { let mut pe = PalletEngine::new(&runtime_path)?; // Todo: Add option to source from cli - let dep = TomlEditor::infer(&runtime_path); + let dep = TomlEditor::infer(&runtime_path)?; // Check if workspace has uncommitted changes, if yes, abort - if !is_git_repo_with_commits(dep.runtime.parent().unwrap().parent().unwrap()) { + if !is_git_repo_with_commits(&dep.workspace)? { + cliclack::log::error(format!("Workspace -> {}", dep.workspace.display())); bail!("Workspace has uncommitted changes, aborting pallet addition"); } let steps = step_builder(pallet)?; @@ -56,29 +57,44 @@ pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { } #[derive(Default)] struct TomlEditor { - // workspace: PathBuf, + /// Path to workspace toml file + workspace: PathBuf, + /// Path to runtime toml file runtime: PathBuf, + /// Path to node toml file node: PathBuf, } impl TomlEditor { - fn new(runtime: &Path, node: &Path) -> Self { - Self { runtime: runtime.to_path_buf(), node: node.to_path_buf() } + fn new(workspace: &Path, runtime: &Path, node: &Path) -> Self { + Self { + workspace: workspace.to_path_buf(), + runtime: runtime.to_path_buf(), + node: node.to_path_buf(), + } } /// Infer a given runtime and node manifest paths from the given runtime path - /// runtime -> ../Cargo.toml - /// node -> ../node/Cargo.toml - fn infer(runtime_path: &Path) -> Self { - let runtime_manifest = runtime_path.parent().unwrap().parent().unwrap().join("Cargo.toml"); - let node_manifest = runtime_path + /// runtime -> ../Cargo.toml + /// node -> ../../node/Cargo.toml + /// workspace -> ../../Cargo.toml + fn infer(runtime_path: &Path) -> anyhow::Result { + let runtime_path = fs::canonicalize(runtime_path).with_context(|| { + format!("Failed to resolve {} into absolute path", runtime_path.display()) + })?; + let workspace_manifest = runtime_path .parent() // src .unwrap() .parent() // runtime .unwrap() - .parent() // workspace - .unwrap() - .join("node/Cargo.toml"); + .parent() + .unwrap(); // workspace + let runtime_manifest = workspace_manifest.join("runtime/Cargo.toml"); + let node_manifest = workspace_manifest.join("node/Cargo.toml"); // println!("{} {}", runtime_manifest.display(), node_manifest.display()); - Self { runtime: runtime_manifest, node: node_manifest } + Ok(Self { + workspace: workspace_manifest.to_path_buf(), + runtime: runtime_manifest, + node: node_manifest, + }) } /// Inject a dependency into the node manifest fn inject_node(&self, dep: Dependency) -> anyhow::Result<()> { diff --git a/src/helpers.rs b/src/helpers.rs index 532f4f22..084f9be7 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -83,24 +83,24 @@ pub(crate) fn resolve_pallet_path(path: Option) -> PathBuf { } } -pub(crate) fn is_git_repo_with_commits(repo_path: &Path) -> bool { +pub(crate) fn is_git_repo_with_commits(repo_path: &Path) -> anyhow::Result { match Repository::open(repo_path) { Ok(repo) => { let mut status_opts = git2::StatusOptions::new(); - status_opts.include_untracked(true); - let statuses = repo.statuses(Some(&mut status_opts)).unwrap(); + status_opts.include_untracked(false); + let statuses = repo.statuses(Some(&mut status_opts))?; // Check if there are no changes to commit - if !statuses.iter().any(|s| s.status() != git2::Status::CURRENT) { + Ok(if !statuses.iter().any(|s| s.status() != git2::Status::CURRENT) { true } else { - println!("Repository has uncommitted changes."); + log::warning(format!("Repository has uncommitted changes.")); false - } + }) }, Err(e) => { - eprintln!("Failed to open repository: {}", e); - false + log::error(format!("Failed to open repository: {}", e)); + Err(e.into()) }, } } From 96401edf1440c589cae9b2f39106b17cb7dbdb8b Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 20 Mar 2024 15:00:26 +0530 Subject: [PATCH 45/57] fmt --- src/engines/pallet_engine/dependency.rs | 3 ++- src/engines/pallet_engine/parser.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/engines/pallet_engine/dependency.rs b/src/engines/pallet_engine/dependency.rs index 9dd787bc..2670bee6 100644 --- a/src/engines/pallet_engine/dependency.rs +++ b/src/engines/pallet_engine/dependency.rs @@ -116,7 +116,8 @@ impl Dependency { // The reason is, `pop new pallet` places a new pallet on $(workspace_root)/pallets std::path::Path::new("../pallets/pallet-parachain-template").to_path_buf(), semver::Version::new(1, 0, 0), - ).into(), + ) + .into(), default_features: false, } } diff --git a/src/engines/pallet_engine/parser.rs b/src/engines/pallet_engine/parser.rs index 3a7f85f0..26c139be 100644 --- a/src/engines/pallet_engine/parser.rs +++ b/src/engines/pallet_engine/parser.rs @@ -300,9 +300,9 @@ impl ToTokens for PalletDeclaration { let idx = format!(" = {},", idx); // This means no help from rustfmt tokens.extend(TokenStream::from_str(&idx)); - // If we want rustfmt we would have to handroll our own solution or forgo indices - // (which is bad and probably not what the developer wants which is to delete code) - // tokens.extend(quote!(,)); + // If we want rustfmt we would have to handroll our own solution or forgo indices + // (which is bad and probably not what the developer wants which is to delete code) + // tokens.extend(quote!(,)); } else { tokens.append(Punct::new(',', Spacing::Alone)); } From 215b02837039d19300969e964914ad335f05ca49 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 20 Mar 2024 16:07:57 +0530 Subject: [PATCH 46/57] review fixes --- src/engines/pallet_engine/mod.rs | 1 - src/engines/pallet_engine/template.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index cb82f848..bdb6c9a4 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -89,7 +89,6 @@ impl TomlEditor { .unwrap(); // workspace let runtime_manifest = workspace_manifest.join("runtime/Cargo.toml"); let node_manifest = workspace_manifest.join("node/Cargo.toml"); - // println!("{} {}", runtime_manifest.display(), node_manifest.display()); Ok(Self { workspace: workspace_manifest.to_path_buf(), runtime: runtime_manifest, diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index ff9d3b46..4891697c 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -35,7 +35,6 @@ pub struct TemplatePalletConfig { fn generate_pallet_structure(target: &PathBuf, pallet_name: &str) -> anyhow::Result<()> { use fs::{create_dir, File}; let (pallet, src) = (target.join(pallet_name), target.join(pallet_name.to_string() + "/src")); - // println!("source = > {}", src.display()); create_dir(&pallet)?; create_dir(&src)?; File::create(format!("{}/Cargo.toml", pallet.display()))?; From 354116e7b85893c1f9a1e0f8cbab31f0da00bc15 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 20 Mar 2024 16:11:20 +0530 Subject: [PATCH 47/57] review fixes 2 --- src/commands/add/mod.rs | 6 +++--- src/engines/pallet_engine/template.rs | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index f2800cc9..736f8762 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -11,10 +11,10 @@ use console::style; pub(crate) struct AddArgs { #[command(subcommand)] commands: AddCommands, - #[arg(global = true, short, long)] + #[arg(global = true, short, long = "runtime")] /// Runtime path; for example: `sub0/runtime/src/lib.rs` /// Runtime cargo manifest path will be inferred as `(parent of lib.rs)/Cargo.toml` - pub(crate) runtime: Option, + pub(crate) runtime_path: Option, } #[derive(Subcommand)] #[command(subcommand_required = true)] @@ -43,7 +43,7 @@ pub(crate) struct FrameArgs { impl AddArgs { pub(crate) fn execute(&self) -> anyhow::Result<()> { match self.commands { - AddCommands::Pallet(ref cmd) => cmd.clone().execute(&self.runtime), + AddCommands::Pallet(ref cmd) => cmd.clone().execute(&self.runtime_path), } } } diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index 4891697c..a10a7cb9 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -4,7 +4,6 @@ use crate::{ }; use std::{fs, path::PathBuf}; -// use super::{pallet_entry::AddPalletEntry, PalletEngine}; pub fn create_pallet_template( path: Option, From 99f4b6482b30575342759d0b12b815c7e007fe1a Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 21 Mar 2024 13:05:00 +0530 Subject: [PATCH 48/57] review fixes 3 + fix add_new_line cursor --- src/engines/pallet_engine/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index bdb6c9a4..4af9217c 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -44,7 +44,6 @@ use toml_edit::DocumentMut; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { - let mut pe = PalletEngine::new(&runtime_path)?; // Todo: Add option to source from cli let dep = TomlEditor::infer(&runtime_path)?; // Check if workspace has uncommitted changes, if yes, abort @@ -52,6 +51,7 @@ pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { cliclack::log::error(format!("Workspace -> {}", dep.workspace.display())); bail!("Workspace has uncommitted changes, aborting pallet addition"); } + let mut pe = PalletEngine::new(&runtime_path)?; let steps = step_builder(pallet)?; run_steps(pe, dep, steps) } @@ -419,7 +419,7 @@ impl PalletEngine { let mut file = OpenOptions::new().append(true).open(&self.output)?; let newlines: String = std::iter::repeat('\n').take(n).collect(); let rs = file.write_all(format!("{newlines}").as_bytes())?; - self.cursor += 1; + self.cursor += n; Ok(rs) } /// Append raw tokens to `output` file, cursor should be handled by caller From 159b998ee0fef1dd94016340136a9e7eef6cf11b Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 21 Mar 2024 13:29:45 +0530 Subject: [PATCH 49/57] use pallet-parachain-template path relative to workspace root --- src/engines/pallet_engine/dependency.rs | 18 ++++++++++-------- src/engines/pallet_engine/mod.rs | 10 +++++----- src/engines/pallet_engine/steps.rs | 10 ++++++++-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/engines/pallet_engine/dependency.rs b/src/engines/pallet_engine/dependency.rs index 2670bee6..502fd5bd 100644 --- a/src/engines/pallet_engine/dependency.rs +++ b/src/engines/pallet_engine/dependency.rs @@ -1,5 +1,5 @@ //! Dependency representations for Pallets -use std::path; +use std::path::{self, Path, PathBuf}; use strum_macros::{Display, EnumString}; #[derive(EnumString, Display, Debug)] @@ -105,20 +105,22 @@ impl Dependency { t["default-features"] = toml_edit::value(self.default_features); t.into_inline_table() } - /// Create dependencies required for adding a local pallet-parachain-template to runtime - /// ..$(runtime)/pallets/pallet-parachain-template - pub(super) fn local_template_runtime() -> Self { + /// Create dependencies required for adding a local pallet to runtime + /// $(workspace_root)/pallets/pallet-name + // Todo: Some values are hardcoded for now as this only deals with the pallet-parachain-template + // Should be moved to args once that's not the case + pub(super) fn local_template_runtime(pallet_name: &'static str, workspace: &PathBuf) -> Self { + let name = format!("{pallet_name}"); Self { - name: format!("pallet-parachain-template"), features: vec![Features::RuntimeBenchmarks, Features::TryRuntime, Features::Std], path: ( - // TODO hardcode for now // The reason is, `pop new pallet` places a new pallet on $(workspace_root)/pallets - std::path::Path::new("../pallets/pallet-parachain-template").to_path_buf(), + workspace.join("pallets/").join(&name).to_path_buf(), semver::Version::new(1, 0, 0), ) - .into(), + .into(), default_features: false, + name, } } // TODO: Remove code - Node doesn't require template pallet deps by default diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index 4af9217c..bfc0bf0c 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -45,15 +45,15 @@ use toml_edit::DocumentMut; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { // Todo: Add option to source from cli - let dep = TomlEditor::infer(&runtime_path)?; + let te = TomlEditor::infer(&runtime_path)?; // Check if workspace has uncommitted changes, if yes, abort - if !is_git_repo_with_commits(&dep.workspace)? { - cliclack::log::error(format!("Workspace -> {}", dep.workspace.display())); + if !is_git_repo_with_commits(&te.workspace)? { + cliclack::log::error(format!("Workspace -> {}", te.workspace.display())); bail!("Workspace has uncommitted changes, aborting pallet addition"); } let mut pe = PalletEngine::new(&runtime_path)?; - let steps = step_builder(pallet)?; - run_steps(pe, dep, steps) + let steps = step_builder(pallet, &te)?; + run_steps(pe, te, steps) } #[derive(Default)] struct TomlEditor { diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 6dbe090f..6c77320a 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -34,7 +34,10 @@ pub(super) enum Steps { /// The pallet engine state expects to go as edits would, i.e. top to bottom lexically /// So it makes sense for any given file, to first include an import, then items that refer to it /// In case of a pallet, you'd always put `RuntimePalletImport`, `RuntimePalletConfiguration`, `ConstructRuntimeEntry` in that order. -pub(super) fn step_builder(pallet: AddPallet) -> Result> { +pub(super) fn step_builder( + pallet: AddPallet, + &TomlEditor { ref workspace, .. }: &TomlEditor, +) -> Result> { let mut steps: Vec = vec![]; match pallet { // Adding a pallet-parachain-template requires 5 distinct steps @@ -66,7 +69,10 @@ pub(super) fn step_builder(pallet: AddPallet) -> Result> { // TODO (high priority): implement name conflict resolution strategy "Template", ))); - steps.push(RuntimePalletDependency(Dependency::local_template_runtime())); + steps.push(RuntimePalletDependency(Dependency::local_template_runtime( + "pallet-parachain-template", + workspace, + ))); }, AddPallet::Frame(_) => unimplemented!("Frame pallets not yet implemented"), }; From 4309bb2613591c300ace87999efaace85bcbd867 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 21 Mar 2024 15:36:52 +0530 Subject: [PATCH 50/57] fix order for pallet-engine construction --- src/engines/pallet_engine/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index bfc0bf0c..ab8fc05e 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -44,6 +44,7 @@ use toml_edit::DocumentMut; /// The main entry point into the engine. pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { + let mut pe = PalletEngine::new(&runtime_path)?; // Todo: Add option to source from cli let te = TomlEditor::infer(&runtime_path)?; // Check if workspace has uncommitted changes, if yes, abort @@ -51,7 +52,6 @@ pub fn execute(pallet: AddPallet, runtime_path: PathBuf) -> anyhow::Result<()> { cliclack::log::error(format!("Workspace -> {}", te.workspace.display())); bail!("Workspace has uncommitted changes, aborting pallet addition"); } - let mut pe = PalletEngine::new(&runtime_path)?; let steps = step_builder(pallet, &te)?; run_steps(pe, te, steps) } From 036384458cedfe3071c4c63c82aa6d27ecbf245a Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 21 Mar 2024 15:47:08 +0530 Subject: [PATCH 51/57] include checks for try-runtime and runtime-benchmarks features in runtime manifest --- tests/add.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/add.rs b/tests/add.rs index 60d8a5bf..5831cda9 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -52,4 +52,18 @@ fn add_parachain_pallet_template() { .count(), 1 ); + let rt_bench = toml["features"]["runtime-benchmarks"].as_value().unwrap().as_array().unwrap(); + assert_eq!( + rt_bench.iter() + .filter(|val| val.as_str().unwrap() == "pallet-parachain-template/runtime-benchmarks") + .count(), + 1 + ); + let try_rt = toml["features"]["try-runtime"].as_value().unwrap().as_array().unwrap(); + assert_eq!( + try_rt.iter() + .filter(|val| val.as_str().unwrap() == "pallet-parachain-template/try-runtime") + .count(), + 1 + ); } From 7e7478d8ea0d0be87a69a2755e7840425f4c2975 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Thu, 21 Mar 2024 09:30:43 +0000 Subject: [PATCH 52/57] fix(deps): remove deprecated dependency As per https://crates.io/crates/tempdir, tempdir was deprecated ages ago with functionality moved into tempfile which already exists as a dependency. Primary motivation was a security advisory triggered by dependabot. --- Cargo.lock | 554 +++++++++++++++----------------- Cargo.toml | 1 - src/engines/contract_engine.rs | 3 +- src/engines/parachain_engine.rs | 3 +- tests/add.rs | 4 +- 5 files changed, 268 insertions(+), 297 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54030fa3..50d7d297 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "ark-bls12-377" @@ -400,7 +400,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -443,7 +443,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -494,7 +494,7 @@ dependencies = [ "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "slab", ] @@ -518,7 +518,7 @@ checksum = "bc19683171f287921f2405677dd2ed2549c3b3bda697a563ebc3a121ace2aba1" dependencies = [ "async-lock 3.3.0", "blocking", - "futures-lite 2.2.0", + "futures-lite 2.3.0", ] [[package]] @@ -543,18 +543,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock 3.3.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "parking", "polling 3.5.0", - "rustix 0.38.31", + "rustix 0.38.32", "slab", "tracing", "windows-sys 0.52.0", @@ -597,9 +597,9 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" dependencies = [ - "async-io 2.3.1", + "async-io 2.3.2", "blocking", - "futures-lite 2.2.0", + "futures-lite 2.3.0", ] [[package]] @@ -615,7 +615,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.48.0", ] @@ -626,14 +626,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "451e3cf68011bd56771c79db04a9e333095ab6349f7e47592b788e9b98720cc8" dependencies = [ "async-channel 2.2.0", - "async-io 2.3.1", + "async-io 2.3.2", "async-lock 3.3.0", "async-signal", "blocking", "cfg-if", "event-listener 5.2.0", - "futures-lite 2.2.0", - "rustix 0.38.31", + "futures-lite 2.3.0", + "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -643,13 +643,13 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.3.1", + "async-io 2.3.2", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.31", + "rustix 0.38.32", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -663,13 +663,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -746,13 +746,22 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64-simd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" +dependencies = [ + "simd-abstraction", +] + [[package]] name = "base64-simd" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" dependencies = [ - "outref", + "outref 0.5.1", "vsimd", ] @@ -764,9 +773,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" dependencies = [ "serde", ] @@ -825,9 +834,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -930,7 +939,7 @@ dependencies = [ "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "piper", "tracing", ] @@ -999,7 +1008,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "syn_derive", ] @@ -1029,9 +1038,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1065,9 +1074,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] @@ -1243,9 +1252,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.2" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" dependencies = [ "clap_builder", "clap_derive", @@ -1265,14 +1274,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1403,9 +1412,9 @@ checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" [[package]] name = "contract-build" -version = "4.0.0-rc.4" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0cace153488962932541d89bc7e8e515cf1c4606ea45fe55826d59505078fa4" +checksum = "a1419d360c4519b3995a7e390f0f6a72a386c2cfb9a187f1114a3e9c719e02c1" dependencies = [ "anyhow", "blake2", @@ -1416,7 +1425,7 @@ dependencies = [ "contract-metadata", "crossterm", "duct", - "heck", + "heck 0.5.0", "hex", "impl-serde", "parity-scale-codec", @@ -1426,12 +1435,12 @@ dependencies = [ "semver 1.0.22", "serde", "serde_json", - "strum 0.26.1", + "strum 0.26.2", "tempfile", "term_size", "tokio", "tokio-stream", - "toml 0.8.10", + "toml 0.8.12", "tracing", "url", "uzers", @@ -1443,9 +1452,9 @@ dependencies = [ [[package]] name = "contract-extrinsics" -version = "4.0.0-rc.4" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74055aad722db419082ac0615daa2f4b6099f20eddb78213dc17bc06fc4943bc" +checksum = "fc0cd1533705bd07c376992b9dfc31751da41376450da0481f6c89f864d7847a" dependencies = [ "anyhow", "blake2", @@ -1477,9 +1486,9 @@ dependencies = [ [[package]] name = "contract-metadata" -version = "4.0.0-rc.4" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ab6d50dbdba63b7c4e61ca9830252c69e0e507a20f2f74fc2c6b6582e3bf1" +checksum = "7b31736c09a0d23fec6263686d4bce595634faeed1875520fecf191985f7a2db" dependencies = [ "anyhow", "impl-serde", @@ -1491,9 +1500,9 @@ dependencies = [ [[package]] name = "contract-transcode" -version = "4.0.0-rc.4" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf881647e38164a63be6dfed4af4ce2bf418c4464fc8cb15eb495292c149dc3" +checksum = "0e17348a8e977b53dbdc8fde57861726f98fbb89eee36d8884c85b9838769430" dependencies = [ "anyhow", "base58", @@ -1605,7 +1614,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "crossterm_winapi", "libc", "mio", @@ -1733,7 +1742,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1760,7 +1769,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1777,7 +1786,7 @@ checksum = "70b5b86cf65fa0626d85720619d80b288013477a91a0389fa8bc716bf4903ad1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1825,7 +1834,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1847,7 +1856,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1969,7 +1978,7 @@ dependencies = [ "serde_json", "serde_v8", "smallvec", - "sourcemap 7.0.1", + "sourcemap 7.1.1", "tokio", "url", "v8", @@ -2081,7 +2090,7 @@ dependencies = [ "quote", "strum 0.25.0", "strum_macros 0.25.3", - "syn 2.0.52", + "syn 2.0.53", "thiserror", ] @@ -2128,7 +2137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a054195576d4629bb1dde11756d8ba980f6a7c2805d3f21c83dfde8d0d4bd6f6" dependencies = [ "async-trait", - "base64-simd", + "base64-simd 0.8.0", "bytes", "deno_core", "encoding_rs", @@ -2302,7 +2311,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2332,9 +2341,9 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.52", + "syn 2.0.53", "termcolor", - "toml 0.8.10", + "toml 0.8.12", "walkdir", ] @@ -2515,7 +2524,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -2622,7 +2631,7 @@ dependencies = [ "prettier-please", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2681,9 +2690,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" [[package]] name = "filetime" @@ -2783,7 +2792,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2794,7 +2803,7 @@ checksum = "d9c078db2242ea7265faa486004e7fd8daaf1a577cfcac0070ce55d926922883" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2806,7 +2815,7 @@ dependencies = [ "pmutil", "proc-macro2", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2828,12 +2837,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "funty" version = "2.0.0" @@ -2906,9 +2909,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "fastrand 2.0.1", "futures-core", @@ -2925,7 +2928,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3045,11 +3048,11 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git2" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "libgit2-sys", "log", @@ -3071,9 +3074,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -3138,6 +3141,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -3277,12 +3286,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", + "futures-core", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -3583,18 +3592,18 @@ dependencies = [ [[package]] name = "ink_allocator" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4509501e7eaee3988cc7f22a044f3be6599c8532a303b80b0c5761c8d940e413" +checksum = "5cee56055bac6d928d425e944c5f3b69baa33c9635822fd1c00cd4afc70fde3e" dependencies = [ "cfg-if", ] [[package]] name = "ink_engine" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1967c441dd9cca93af1cea6601115b8ac5a596befd01090ddf68607259dc57" +checksum = "4f357e2e867f4e222ffc4015a6e61d1073548de89f70a4e36a8b0385562777fa" dependencies = [ "blake2", "derive_more", @@ -3608,9 +3617,9 @@ dependencies = [ [[package]] name = "ink_env" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff8e745688bfe87f6d5ecb39ad3e3d712465a756f4a7b76fd9214b8310061c" +checksum = "42cec50b7e4f8406aab25801b015d3802a52d76cfbe48ce11cfb4200fa88e296" dependencies = [ "blake2", "cfg-if", @@ -3638,9 +3647,9 @@ dependencies = [ [[package]] name = "ink_metadata" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7a6dbb5dee1ed28e022cd99866ae426cae4e8172d66f40349fe1c022034579" +checksum = "a98fcc0ff9292ff68c7ee7b84c93533c9ff13859ec3b148faa822e2da9954fe6" dependencies = [ "derive_more", "impl-serde", @@ -3655,18 +3664,18 @@ dependencies = [ [[package]] name = "ink_prelude" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfed647babce3e9f2ca528866b16edce8156b49550fa971bf11e52410239703" +checksum = "ea1734d058c80aa72e59c8ae75624fd8a51791efba21469f273156c0f4cad5c9" dependencies = [ "cfg-if", ] [[package]] name = "ink_primitives" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22dcad2912e7faadd116fc7952956c87225fe751a99da77d051a83d8fa404ca7" +checksum = "11ec35ef7f45e67a53b6142d7e7f18e6d9292d76c3a2a1da14cf8423e481813d" dependencies = [ "derive_more", "ink_prelude", @@ -3679,9 +3688,9 @@ dependencies = [ [[package]] name = "ink_storage_traits" -version = "5.0.0-rc.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "782122a6be4e7a0022d4e9ad70d99311adc64402635731436d26bbee5eb3c590" +checksum = "83ce49e3d2935fc1ec3e73117119712b187d3123339f6a31624e92f75fa2293d" dependencies = [ "ink_metadata", "ink_prelude", @@ -3756,7 +3765,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4251,7 +4260,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "999ec70441b2fb35355076726a6bc466c932e9bdc66f6a11c6c0aa17c7ab9be0" dependencies = [ - "bs58 0.5.0", + "bs58 0.5.1", "ed25519-dalek", "hkdf", "multihash", @@ -4290,7 +4299,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall", ] @@ -4411,7 +4420,7 @@ checksum = "adf157a4dc5a29b7b464aa8fe7edeff30076e07e13646a1c3874f58477dc99f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4508,7 +4517,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.31", + "rustix 0.38.32", ] [[package]] @@ -4670,9 +4679,9 @@ dependencies = [ [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" @@ -4680,7 +4689,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "libc", ] @@ -4885,7 +4894,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -4902,7 +4911,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4948,6 +4957,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "outref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" + [[package]] name = "outref" version = "0.5.1" @@ -5154,7 +5169,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5198,7 +5213,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5227,7 +5242,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5314,7 +5329,7 @@ checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5336,7 +5351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" dependencies = [ "polkavm-derive-impl 0.5.0", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5357,7 +5372,7 @@ dependencies = [ "polkavm-common 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5369,7 +5384,7 @@ dependencies = [ "polkavm-common 0.8.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5379,7 +5394,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15e85319a0d5129dc9f021c62607e0804f5fb777a05cdda44d750ac0732def66" dependencies = [ "polkavm-derive-impl 0.8.0", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5407,7 +5422,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.32", "tracing", "windows-sys 0.52.0", ] @@ -5465,16 +5480,15 @@ dependencies = [ "serde_json", "sp-core 30.0.0", "sp-weights", - "strum 0.26.1", - "strum_macros 0.26.1", + "strum 0.26.2", + "strum_macros 0.26.2", "subxt 0.34.0", "subxt-signer 0.34.0", "symlink", - "syn 2.0.52", - "tempdir", + "syn 2.0.53", "tempfile", "tokio", - "toml_edit 0.22.7", + "toml_edit 0.22.9", "tracing-subscriber 0.3.18", "url", "uuid", @@ -5535,7 +5549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" dependencies = [ "proc-macro2", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5545,7 +5559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5630,7 +5644,7 @@ checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" dependencies = [ "proc-macro-rules-macros", "proc-macro2", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5642,14 +5656,14 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -5713,19 +5727,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" @@ -5770,21 +5771,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -5812,15 +5798,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -5858,7 +5835,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5905,15 +5882,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rend" version = "0.4.2" @@ -5925,9 +5893,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.25" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", @@ -6143,11 +6111,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys 0.4.13", @@ -6380,9 +6348,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "2ef2175c2907e7c8bc0a9c3f86aeb5ec1f3b275300ad58a44d0c3ae379a5e52e" dependencies = [ "bitvec", "cfg-if", @@ -6395,9 +6363,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "634d9b8eb8fd61c5cdd3390d9b2132300a7e7618955b98b8416f118c1b4e144f" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", @@ -6414,7 +6382,7 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.52", + "syn 2.0.53", "thiserror", ] @@ -6696,7 +6664,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -6730,7 +6698,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -6771,9 +6739,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" dependencies = [ "base64 0.21.7", "chrono", @@ -6788,9 +6756,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ "indexmap 2.2.5", "itoa", @@ -6939,6 +6907,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-abstraction" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" +dependencies = [ + "outref 0.1.0", +] + [[package]] name = "simdutf8" version = "0.1.4" @@ -6959,9 +6936,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -6974,9 +6951,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smartstring" @@ -7021,12 +6998,12 @@ dependencies = [ "async-channel 2.2.0", "async-executor", "async-fs 2.1.1", - "async-io 2.3.1", + "async-io 2.3.2", "async-lock 3.3.0", "async-net 2.0.0", "async-process 2.1.0", "blocking", - "futures-lite 2.2.0", + "futures-lite 2.3.0", ] [[package]] @@ -7041,7 +7018,7 @@ dependencies = [ "base64 0.21.7", "bip39", "blake2-rfc", - "bs58 0.5.0", + "bs58 0.5.1", "chacha20", "crossbeam-queue", "derive_more", @@ -7049,7 +7026,7 @@ dependencies = [ "either", "event-listener 3.1.0", "fnv", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "futures-util", "hashbrown 0.14.3", "hex", @@ -7074,7 +7051,7 @@ dependencies = [ "serde_json", "sha2 0.10.8", "sha3", - "siphasher 1.0.0", + "siphasher 1.0.1", "slab", "smallvec", "soketto", @@ -7096,7 +7073,7 @@ dependencies = [ "base64 0.21.7", "bip39", "blake2-rfc", - "bs58 0.5.0", + "bs58 0.5.1", "chacha20", "crossbeam-queue", "derive_more", @@ -7104,7 +7081,7 @@ dependencies = [ "either", "event-listener 4.0.3", "fnv", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "futures-util", "hashbrown 0.14.3", "hex", @@ -7129,7 +7106,7 @@ dependencies = [ "serde_json", "sha2 0.10.8", "sha3", - "siphasher 1.0.0", + "siphasher 1.0.1", "slab", "smallvec", "soketto", @@ -7154,7 +7131,7 @@ dependencies = [ "event-listener 3.1.0", "fnv", "futures-channel", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "futures-util", "hashbrown 0.14.3", "hex", @@ -7168,7 +7145,7 @@ dependencies = [ "rand_chacha 0.3.1", "serde", "serde_json", - "siphasher 1.0.0", + "siphasher 1.0.1", "slab", "smol 1.3.0", "smoldot 0.14.0", @@ -7190,7 +7167,7 @@ dependencies = [ "event-listener 4.0.3", "fnv", "futures-channel", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "futures-util", "hashbrown 0.14.3", "hex", @@ -7204,7 +7181,7 @@ dependencies = [ "rand_chacha 0.3.1", "serde", "serde_json", - "siphasher 1.0.0", + "siphasher 1.0.1", "slab", "smol 2.0.0", "smoldot 0.16.0", @@ -7264,17 +7241,18 @@ dependencies = [ [[package]] name = "sourcemap" -version = "7.0.1" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10da010a590ed2fa9ca8467b00ce7e9c5a8017742c0c09c45450efc172208c4b" +checksum = "e7768edd06c02535e0d50653968f46e1e0d3aa54742190d35dd9466f59de9c71" dependencies = [ + "base64-simd 0.7.0", "data-encoding", "debugid", "if_chain", "rustc_version 0.2.3", "serde", "serde_json", - "unicode-id", + "unicode-id-start", "url", ] @@ -7364,7 +7342,7 @@ dependencies = [ "bitflags 1.3.2", "blake2", "bounded-collections 0.2.0", - "bs58 0.5.0", + "bs58 0.5.1", "dyn-clonable", "ed25519-zebra 3.1.0", "futures", @@ -7463,7 +7441,7 @@ checksum = "f12dae7cf6c1e825d13ffd4ce16bd9309db7c539929d0302b4443ed451a9f4e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7474,7 +7452,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7624,7 +7602,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7638,7 +7616,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7822,9 +7800,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.46.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1114ee5900b8569bbc8b1a014a942f937b752af4b44f4607430b5f86cedaac0" +checksum = "4743ce898933fbff7bbf414f497c459a782d496269644b3d650a398ae6a487ba" dependencies = [ "Inflector", "num-format", @@ -7870,7 +7848,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7902,11 +7880,11 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ - "strum_macros 0.26.1", + "strum_macros 0.26.2", ] [[package]] @@ -7915,7 +7893,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -7928,24 +7906,24 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] name = "strum_macros" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8043,7 +8021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12800ad6128b4bfc93d2af89b7d368bff7ea2f6604add35f96f6a8c06c7f9abf" dependencies = [ "frame-metadata 16.0.0", - "heck", + "heck 0.4.1", "hex", "jsonrpsee 0.20.3", "parity-scale-codec", @@ -8051,7 +8029,7 @@ dependencies = [ "quote", "scale-info", "subxt-metadata 0.33.0", - "syn 2.0.52", + "syn 2.0.53", "thiserror", "tokio", ] @@ -8063,7 +8041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0e58c3f88651cff26aa52bae0a0a85f806a2e923a20eb438c16474990743ea" dependencies = [ "frame-metadata 16.0.0", - "heck", + "heck 0.4.1", "hex", "jsonrpsee 0.21.0", "parity-scale-codec", @@ -8072,7 +8050,7 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata 0.34.0", - "syn 2.0.52", + "syn 2.0.53", "thiserror", "tokio", ] @@ -8121,7 +8099,7 @@ dependencies = [ "parity-scale-codec", "proc-macro-error", "subxt-codegen 0.33.0", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8136,7 +8114,7 @@ dependencies = [ "quote", "scale-typegen", "subxt-codegen 0.34.0", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8269,7 +8247,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8278,7 +8256,7 @@ version = "0.110.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c3d416121da2d56bcbd1b1623725a68890af4552fef0c6d1e4bfa92776ccd6a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "is-macro", "num-bigint", "phf", @@ -8319,7 +8297,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8364,7 +8342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d74ca42a400257d8563624122813c1849c3d87e7abe3b9b2ed7514c76f64ad2f" dependencies = [ "better_scoped_tls", - "bitflags 2.4.2", + "bitflags 2.5.0", "indexmap 1.9.3", "once_cell", "phf", @@ -8404,7 +8382,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8509,7 +8487,7 @@ dependencies = [ "pmutil", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8521,7 +8499,7 @@ dependencies = [ "pmutil", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8545,7 +8523,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8567,9 +8545,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -8585,7 +8563,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8596,20 +8574,20 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "system-configuration" -version = "0.6.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 2.4.2", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", @@ -8638,16 +8616,6 @@ version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -dependencies = [ - "rand 0.4.6", - "remove_dir_all", -] - [[package]] name = "tempfile" version = "3.10.1" @@ -8656,7 +8624,7 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.0.1", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -8707,22 +8675,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8837,7 +8805,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -8885,9 +8853,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -8936,14 +8904,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.7", + "toml_edit 0.22.9", ] [[package]] @@ -8992,9 +8960,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ "indexmap 2.2.5", "serde", @@ -9027,7 +8995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "bytes", "futures-core", "futures-util", @@ -9073,7 +9041,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -9361,6 +9329,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" +[[package]] +name = "unicode-id-start" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f73150333cb58412db36f2aca8f2875b013049705cc77b94ded70a1ab1f5da" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -9406,9 +9380,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "unsigned-varint" @@ -9461,9 +9435,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom 0.2.12", "serde", @@ -9612,7 +9586,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-shared", ] @@ -9646,7 +9620,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9917,7 +9891,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.31", + "rustix 0.38.32", ] [[package]] @@ -9929,7 +9903,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -10234,7 +10208,7 @@ checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", "linux-raw-sys 0.4.13", - "rustix 0.38.31", + "rustix 0.38.32", ] [[package]] @@ -10266,7 +10240,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -10286,7 +10260,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index db21a534..07560a52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ path = "src/main.rs" [dev-dependencies] assert_cmd = "2.0.14" -tempdir = "0.3.7" [dependencies] anyhow = "1.0" diff --git a/src/engines/contract_engine.rs b/src/engines/contract_engine.rs index b4cf3d5a..b8e27b5a 100644 --- a/src/engines/contract_engine.rs +++ b/src/engines/contract_engine.rs @@ -171,11 +171,10 @@ pub async fn dry_run_call( mod tests { use super::*; use std::fs; - use tempdir; #[test] fn test_create_smart_contract() -> Result<(), Box> { - let temp_dir = tempdir::TempDir::new("test_folder")?; + let temp_dir = tempfile::tempdir()?; let result: anyhow::Result<()> = create_smart_contract("test".to_string(), &Some(PathBuf::from(temp_dir.path()))); assert!(result.is_ok()); diff --git a/src/engines/parachain_engine.rs b/src/engines/parachain_engine.rs index fcd9a821..ad9c7680 100644 --- a/src/engines/parachain_engine.rs +++ b/src/engines/parachain_engine.rs @@ -81,11 +81,10 @@ pub fn build_parachain(path: &Option) -> anyhow::Result<()> { mod tests { use super::*; use std::{env::current_dir, fs}; - use tempdir; #[test] fn test_instantiate_template_dir_base() -> Result<(), Box> { - let temp_dir = tempdir::TempDir::new("base_template")?; + let temp_dir = tempfile::tempdir()?; let config = Config { symbol: "DOT".to_string(), decimals: 18, diff --git a/tests/add.rs b/tests/add.rs index 5831cda9..d752aa29 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -1,11 +1,11 @@ use assert_cmd::Command; use std::fs; -use tempdir::TempDir; +use tempfile::tempdir; use toml_edit::DocumentMut; #[test] fn add_parachain_pallet_template() { - let temp_dir = TempDir::new("add-pallet-test").unwrap(); + let temp_dir = tempdir().unwrap(); // Setup new parachain Command::cargo_bin("pop") .unwrap() From 6f7ddd82dff5c34c1d3e68005fd0f3cf3f814e59 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Fri, 22 Mar 2024 10:54:20 +0530 Subject: [PATCH 53/57] remove todo comment for name-conflict-resolution-strategy --- src/engines/pallet_engine/steps.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/engines/pallet_engine/steps.rs b/src/engines/pallet_engine/steps.rs index 6c77320a..2560a547 100644 --- a/src/engines/pallet_engine/steps.rs +++ b/src/engines/pallet_engine/steps.rs @@ -66,7 +66,6 @@ pub(super) fn step_builder( // Path "pallet_parachain_template", // Pallet name - // TODO (high priority): implement name conflict resolution strategy "Template", ))); steps.push(RuntimePalletDependency(Dependency::local_template_runtime( From a9398266958322ecc99ec48c70dc78408a8eebba Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 27 Mar 2024 14:56:45 +0530 Subject: [PATCH 54/57] remove commented code --- src/engines/pallet_engine/mod.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/engines/pallet_engine/mod.rs b/src/engines/pallet_engine/mod.rs index ab8fc05e..c822e843 100644 --- a/src/engines/pallet_engine/mod.rs +++ b/src/engines/pallet_engine/mod.rs @@ -577,25 +577,6 @@ impl PalletEngine { entry = format!("\t\t{}: {},", name, path); } self.insert_str_runtime(&entry)?; - // match &mut self.details.declaration { - // RuntimeDeclaration::Implicit(i) => { - // let mut ultimate = i - // .pallets - // .last() - // .ok_or(anyhow!("Fatal: No pallets defined in construct_runtime!"))? - // .clone(); - // ultimate.index = new_pallet.index; - // ultimate.path.inner.segments[0].ident = new_pallet.path; - // ultimate.name = new_pallet.name; - // i.pallets.push(ultimate); - // }, - // RuntimeDeclaration::Explicit(e) => { - // todo!() - // }, - // RuntimeDeclaration::ExplicitExpanded(e) => { - // todo!() - // }, - // }; Ok(()) } } From 0754e6abdfe687d4b82f7642c79473072ac5110e Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Wed, 27 Mar 2024 15:04:58 +0530 Subject: [PATCH 55/57] add help msg for add pallet --- src/commands/add/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/add/mod.rs b/src/commands/add/mod.rs index 736f8762..4cdd11cc 100644 --- a/src/commands/add/mod.rs +++ b/src/commands/add/mod.rs @@ -20,6 +20,7 @@ pub(crate) struct AddArgs { #[command(subcommand_required = true)] pub(crate) enum AddCommands { #[command(subcommand)] + /// Add a pallet #[clap(alias = "p")] Pallet(AddPallet), } From 44eed89631b82c6ec7de605dd8b6742ceb3e26d3 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 1 Apr 2024 13:47:57 +0530 Subject: [PATCH 56/57] fmt --- src/engines/pallet_engine/dependency.rs | 2 +- src/engines/pallet_engine/template.rs | 1 - tests/add.rs | 6 ++++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/engines/pallet_engine/dependency.rs b/src/engines/pallet_engine/dependency.rs index 502fd5bd..2e52fd11 100644 --- a/src/engines/pallet_engine/dependency.rs +++ b/src/engines/pallet_engine/dependency.rs @@ -118,7 +118,7 @@ impl Dependency { workspace.join("pallets/").join(&name).to_path_buf(), semver::Version::new(1, 0, 0), ) - .into(), + .into(), default_features: false, name, } diff --git a/src/engines/pallet_engine/template.rs b/src/engines/pallet_engine/template.rs index b25fa5e3..4b84165a 100644 --- a/src/engines/pallet_engine/template.rs +++ b/src/engines/pallet_engine/template.rs @@ -4,7 +4,6 @@ use crate::{ }; use std::{fs, path::PathBuf}; - pub fn create_pallet_template( path: Option, config: TemplatePalletConfig, diff --git a/tests/add.rs b/tests/add.rs index d752aa29..fafd3c5d 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -54,14 +54,16 @@ fn add_parachain_pallet_template() { ); let rt_bench = toml["features"]["runtime-benchmarks"].as_value().unwrap().as_array().unwrap(); assert_eq!( - rt_bench.iter() + rt_bench + .iter() .filter(|val| val.as_str().unwrap() == "pallet-parachain-template/runtime-benchmarks") .count(), 1 ); let try_rt = toml["features"]["try-runtime"].as_value().unwrap().as_array().unwrap(); assert_eq!( - try_rt.iter() + try_rt + .iter() .filter(|val| val.as_str().unwrap() == "pallet-parachain-template/try-runtime") .count(), 1 From e6733e5ab9c6bb90b743d24e98f07374dfc5edd4 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 8 Apr 2024 12:21:11 +0530 Subject: [PATCH 57/57] rename test --- tests/{add.rs => add_pallet.rs} | 8 -------- 1 file changed, 8 deletions(-) rename tests/{add.rs => add_pallet.rs} (87%) diff --git a/tests/add.rs b/tests/add_pallet.rs similarity index 87% rename from tests/add.rs rename to tests/add_pallet.rs index fafd3c5d..7410bfd4 100644 --- a/tests/add.rs +++ b/tests/add_pallet.rs @@ -13,14 +13,6 @@ fn add_parachain_pallet_template() { .args(&["new", "parachain", "testchain"]) .assert() .success(); - // Git setup - use duct::cmd; - cmd!("git", "add", ".").dir(&temp_dir.path().join("testchain")).run().unwrap(); - cmd!("git", "commit", "--no-gpg-sign", "-m", "Initialized testchain") - .dir(&temp_dir.path().join("testchain")) - .stdout_null() - .run() - .unwrap(); // Add pallet-parachain-template Command::cargo_bin("pop") .unwrap()