From 4dbbd16386fbadc1ead673368c25b736a1888c12 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 23 Mar 2023 16:35:57 +0200 Subject: [PATCH 01/29] Update cargo.lock to use scale-info v2.4.0 Signed-off-by: Alexandru Vasile --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9152cc762..ea2da10dfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2623,9 +2623,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "001cf62ece89779fd16105b5f515ad0e5cedcd5440d3dd806bb067978e7c3608" +checksum = "61471dff9096de1d8b2319efed7162081e96793f5ebb147e50db10d50d648a4d" dependencies = [ "bitvec", "cfg-if", @@ -2637,9 +2637,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "303959cf613a6f6efd19ed4b4ad5bf79966a13352716299ad532cfb115f4205c" +checksum = "219580e803a66b3f05761fd06f1f879a872444e49ce23f73694d26e5a954c7e6" dependencies = [ "proc-macro-crate", "proc-macro2", From 99934de84ba114e355f3c25aadd5605c827c0bf1 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 23 Mar 2023 19:33:37 +0200 Subject: [PATCH 02/29] metadata: Retain only a subset of the metadata Signed-off-by: Alexandru Vasile --- metadata/src/lib.rs | 2 + metadata/src/retain.rs | 209 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 metadata/src/retain.rs diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index 9b197049fe..afb2103812 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -8,6 +8,8 @@ use frame_metadata::{ use scale_info::{form::PortableForm, Field, PortableRegistry, TypeDef, Variant}; use std::collections::HashSet; +pub mod retain; + /// Internal byte representation for various metadata types utilized for /// generating deterministic hashes between different rust versions. #[repr(u8)] diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs new file mode 100644 index 0000000000..db340dbeb8 --- /dev/null +++ b/metadata/src/retain.rs @@ -0,0 +1,209 @@ +// Copyright 2019-2022 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or GPL-3.0. +// see LICENSE for license details. + +//! Utility functions to generate a subset of the metadata. + +use frame_metadata::{ExtrinsicMetadata, PalletMetadata, RuntimeMetadataV14, StorageEntryType}; +use scale_info::{form::PortableForm, interner::UntrackedSymbol}; +use std::{ + any::TypeId, + collections::{BTreeMap, HashSet}, +}; + +// Extra types used by subxt that must be retained in the metadata. +const DISPATCH_ERROR: &'static str = "DispatchError"; +const RUNTIME_EVENT: &'static str = "RuntimeEvent"; + +/// Collect all type IDs needed to represent the provided pallet. +fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut HashSet) { + if let Some(storage) = &pallet.storage { + for entry in &storage.entries { + match entry.ty { + StorageEntryType::Plain(ty) => { + type_ids.insert(ty.id()); + } + StorageEntryType::Map { key, value, .. } => { + type_ids.insert(key.id()); + type_ids.insert(value.id()); + } + } + } + } + + if let Some(calls) = &pallet.calls { + type_ids.insert(calls.ty.id()); + } + + if let Some(event) = &pallet.event { + type_ids.insert(event.ty.id()); + } + + for constant in &pallet.constants { + type_ids.insert(constant.ty.id()); + } + + if let Some(error) = &pallet.error { + type_ids.insert(error.ty.id()); + } +} + +/// Collect all type IDs needed to represent the extrinsic metadata. +fn collect_extrinsic_types( + extrinsic: &ExtrinsicMetadata, + type_ids: &mut HashSet, +) { + type_ids.insert(extrinsic.ty.id()); + + for signed in &extrinsic.signed_extensions { + type_ids.insert(signed.ty.id()); + type_ids.insert(signed.additional_signed.id()); + } +} + +/// Update the given type using the new type ID from the portable registry. +/// +/// # Panics +/// +/// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. +fn update_type(ty: &mut UntrackedSymbol, map_ids: &BTreeMap) { + let old_id = ty.id(); + let new_id = map_ids.get(&old_id).expect(&format!( + "PortableRegistry did not retain type id {old_id}. This is a bug. Please open an issue." + )); + *ty = (*new_id).into(); +} + +/// Update all type IDs of the provided pallet using the new type IDs from the portable registry. +fn update_pallet_types(pallet: &mut PalletMetadata, map_ids: &BTreeMap) { + if let Some(storage) = &mut pallet.storage { + for entry in &mut storage.entries { + match &mut entry.ty { + StorageEntryType::Plain(ty) => { + update_type(ty, map_ids); + } + StorageEntryType::Map { key, value, .. } => { + update_type(key, map_ids); + update_type(value, map_ids); + } + } + } + } + + if let Some(calls) = &mut pallet.calls { + update_type(&mut calls.ty, map_ids); + } + + if let Some(event) = &mut pallet.event { + update_type(&mut event.ty, map_ids); + } + + for constant in &mut pallet.constants { + update_type(&mut constant.ty, map_ids); + } + + if let Some(error) = &mut pallet.error { + update_type(&mut error.ty, map_ids); + } +} + +/// Update all type IDs of the provided extrinsic metadata using the new type IDs from the portable registry. +fn update_extrinsic_types( + extrinsic: &mut ExtrinsicMetadata, + map_ids: &BTreeMap, +) { + update_type(&mut extrinsic.ty, map_ids); + + for signed in &mut extrinsic.signed_extensions { + update_type(&mut signed.ty, map_ids); + update_type(&mut signed.additional_signed, map_ids); + } +} + +/// Generate a subset of the metadata that contains only the +/// types needed to represent the provided pallets. +/// +/// # Note +/// +/// Used to strip metadata of unneeded information and to reduce the +/// binary size. +/// +/// # Panics +/// +/// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. +pub fn retain_metadata_pallets(metadata: &mut RuntimeMetadataV14, mut filter: F) +where + F: FnMut(&PalletMetadata) -> bool, +{ + let mut type_ids = HashSet::new(); + + // Collect all types needed to represent the provided pallets. + metadata.pallets.retain(|pallet| { + if filter(pallet) { + collect_pallet_types(pallet, &mut type_ids); + true + } else { + false + } + }); + + collect_extrinsic_types(&metadata.extrinsic, &mut type_ids); + type_ids.insert(metadata.ty.id()); + + // Additionally, subxt depends on the `RuntimeError` and `DispatchError`. + for ty in metadata.types.types() { + let Some(ident) = ty.ty().path().ident() else { + continue + }; + if ident == DISPATCH_ERROR || ident == RUNTIME_EVENT { + type_ids.insert(ty.id()); + } + } + + // Keep only the needed IDs in the portable registry. + let map_ids = metadata.types.retain(|id| type_ids.contains(&id)); + + // Update the metadata types to their new IDs in the registry. + for pallets in &mut metadata.pallets { + update_pallet_types(pallets, &map_ids); + } + + update_extrinsic_types(&mut metadata.extrinsic, &map_ids); + update_type(&mut metadata.ty, &map_ids); +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::Decode; + use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed, RuntimeMetadataV14}; + use std::{fs, path::Path}; + + fn load_metadata() -> RuntimeMetadataV14 { + let bytes = fs::read(Path::new("../artifacts/polkadot_metadata.scale")) + .expect("Cannot read metadata blob"); + let meta: RuntimeMetadataPrefixed = + Decode::decode(&mut &*bytes).expect("Cannot decode scale metadata"); + + match meta.1 { + RuntimeMetadata::V14(v14) => v14, + _ => panic!("Unsupported metadata version {:?}", meta.1), + } + } + + #[test] + fn retain_one_pallet() { + let metadata_cache = load_metadata(); + + // Retain one pallet at a time ensuring the test does not panic. + for pallet in &metadata_cache.pallets { + let mut metadata = metadata_cache.clone(); + retain_metadata_pallets(&mut metadata, |filter_pallet| { + filter_pallet.name == pallet.name + }); + + assert_eq!(metadata.pallets.len(), 1); + assert_eq!(metadata.pallets.get(0).unwrap().name, pallet.name); + } + } +} From 3f0f55fd091817ce1b128c28a418344ae1ed7774 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Fri, 24 Mar 2023 16:22:57 +0200 Subject: [PATCH 03/29] codegen: Generate top level Event Signed-off-by: Alexandru Vasile --- codegen/src/api/mod.rs | 51 +++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index ecda5ee512..7306a084b4 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -294,12 +294,13 @@ impl RuntimeGenerator { ) -> Result { let item_mod_attrs = item_mod.attrs.clone(); let item_mod_ir = ir::ItemMod::try_from(item_mod)?; + let default_derives = derives.default_derives(); let type_gen = TypeGenerator::new( &self.metadata.types, "runtime_types", type_substitutes, - derives, + derives.clone(), crate_path.clone(), should_gen_docs, ); @@ -317,28 +318,6 @@ impl RuntimeGenerator { }) .collect::>(); - // Get the path to the `Runtime` struct. We assume that the same path contains - // RuntimeCall and RuntimeEvent. - let runtime_type_id = self.metadata.ty.id(); - let runtime_path_segments = self - .metadata - .types - .resolve(runtime_type_id) - .ok_or(CodegenError::TypeNotFound(runtime_type_id))? - .path() - .namespace() - .iter() - .map(|part| syn::PathSegment::from(format_ident!("{}", part))); - let runtime_path_suffix = syn::Path { - leading_colon: None, - segments: syn::punctuated::Punctuated::from_iter(runtime_path_segments), - }; - let runtime_path = if runtime_path_suffix.segments.is_empty() { - quote!(#types_mod_ident) - } else { - quote!(#types_mod_ident::#runtime_path_suffix) - }; - // Pallet names and their length are used to create PALLETS array. // The array is used to identify the pallets composing the metadata for // validation of just those pallets. @@ -403,6 +382,26 @@ impl RuntimeGenerator { }) .collect::, CodegenError>>()?; + let outer_event_variants = self.metadata.pallets.iter().filter_map(|p| { + let variant_name = format_ident!("{}", p.name); + let mod_name = format_ident!("{}", p.name.to_string().to_snake_case()); + let index = proc_macro2::Literal::u8_unsuffixed(p.index); + + p.event.as_ref().map(|_| { + quote! { + #[codec(index = #index)] + #variant_name(#mod_name::Event), + } + }) + }); + + let outer_event = quote! { + #default_derives + pub enum Event { + #( #outer_event_variants )* + } + }; + let root_event_if_arms = self.metadata.pallets.iter().filter_map(|p| { let variant_name_str = &p.name; let variant_name = format_ident!("{}", variant_name_str); @@ -461,14 +460,10 @@ impl RuntimeGenerator { // Identify the pallets composing the static metadata by name. pub static PALLETS: [&str; #pallet_names_len] = [ #(#pallet_names,)* ]; - /// The statically generated runtime call type. - pub type Call = #runtime_path::RuntimeCall; - /// The error type returned when there is a runtime issue. pub type DispatchError = #types_mod_ident::sp_runtime::DispatchError; - // Make the runtime event type easily accessible, and impl RootEvent to help decode into it. - pub type Event = #runtime_path::RuntimeEvent; + #outer_event impl #crate_path::events::RootEvent for Event { fn root_event(pallet_bytes: &[u8], pallet_name: &str, pallet_ty: u32, metadata: &#crate_path::Metadata) -> Result { From 704c5128f8f03fc6f73fdbb5522254dfa6e93c32 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Fri, 24 Mar 2023 16:26:47 +0200 Subject: [PATCH 04/29] metadata: Only retain DispatchError Signed-off-by: Alexandru Vasile --- metadata/src/retain.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index db340dbeb8..1dee66f14b 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -11,10 +11,6 @@ use std::{ collections::{BTreeMap, HashSet}, }; -// Extra types used by subxt that must be retained in the metadata. -const DISPATCH_ERROR: &'static str = "DispatchError"; -const RUNTIME_EVENT: &'static str = "RuntimeEvent"; - /// Collect all type IDs needed to represent the provided pallet. fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut HashSet) { if let Some(storage) = &pallet.storage { @@ -130,7 +126,8 @@ fn update_extrinsic_types( /// /// # Panics /// -/// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. +/// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types, +/// or the metadata does not contain the "sp_runtime::DispatchError" type. pub fn retain_metadata_pallets(metadata: &mut RuntimeMetadataV14, mut filter: F) where F: FnMut(&PalletMetadata) -> bool, @@ -151,14 +148,14 @@ where type_ids.insert(metadata.ty.id()); // Additionally, subxt depends on the `RuntimeError` and `DispatchError`. - for ty in metadata.types.types() { - let Some(ident) = ty.ty().path().ident() else { - continue - }; - if ident == DISPATCH_ERROR || ident == RUNTIME_EVENT { - type_ids.insert(ty.id()); - } - } + let dispatch_error_ty = metadata + .types + .types() + .iter() + .find(|ty| ty.ty().path().segments() == ["sp_runtime", "DispatchError"]) + .expect("Metadata must contain sp_runtime::DispatchError"); + + type_ids.insert(dispatch_error_ty.id()); // Keep only the needed IDs in the portable registry. let map_ids = metadata.types.retain(|id| type_ids.contains(&id)); From d49c8019ee825136c06ddf528394e20cc579b384 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Fri, 24 Mar 2023 16:28:18 +0200 Subject: [PATCH 05/29] metadata: Export just the retain method Signed-off-by: Alexandru Vasile --- metadata/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index afb2103812..7b04f19ee4 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -8,7 +8,8 @@ use frame_metadata::{ use scale_info::{form::PortableForm, Field, PortableRegistry, TypeDef, Variant}; use std::collections::HashSet; -pub mod retain; +mod retain; +pub use retain::retain_metadata_pallets; /// Internal byte representation for various metadata types utilized for /// generating deterministic hashes between different rust versions. From 5ebab478ec5d5eb538b88e9fefb62a61e3fdc82e Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Fri, 24 Mar 2023 17:53:22 +0200 Subject: [PATCH 06/29] cli: Retain pallets Signed-off-by: Alexandru Vasile --- cli/src/commands/metadata.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/cli/src/commands/metadata.rs b/cli/src/commands/metadata.rs index 46f7c5cae6..bf285346c0 100644 --- a/cli/src/commands/metadata.rs +++ b/cli/src/commands/metadata.rs @@ -4,11 +4,12 @@ use clap::Parser as ClapParser; use color_eyre::eyre; -use frame_metadata::RuntimeMetadataPrefixed; +use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; use jsonrpsee::client_transport::ws::Uri; -use scale::Decode; +use scale::{Decode, Encode}; use std::io::{self, Write}; use subxt_codegen::utils::fetch_metadata_hex; +use subxt_metadata::retain_metadata_pallets; /// Download metadata from a substrate node, for use with `subxt` codegen. #[derive(Debug, ClapParser)] @@ -24,25 +25,45 @@ pub struct Opts { /// The format of the metadata to display: `json`, `hex` or `bytes`. #[clap(long, short, default_value = "bytes")] format: String, + /// Generate a subset of the metadata that contains only the + /// types needed to represent the provided pallets. + #[clap(long, use_value_delimiter = true, value_parser)] + retain_pallets: Option>, } pub async fn run(opts: Opts) -> color_eyre::Result<()> { let hex_data = fetch_metadata_hex(&opts.url).await?; + let bytes = hex::decode(hex_data.trim_start_matches("0x"))?; + let mut metadata = ::decode(&mut &bytes[..])?; + + if let Some(pallets) = opts.retain_pallets { + let metadata_v14 = match &mut metadata.1 { + RuntimeMetadata::V14(metadata_v14) => metadata_v14, + _ => { + return Err(eyre::eyre!( + "Unsupported metadata version {:?}, expected V14.", + metadata.1 + )) + } + }; + + retain_metadata_pallets(metadata_v14, |pallet| pallets.contains(&pallet.name)); + } + match opts.format.as_str() { "json" => { - let bytes = hex::decode(hex_data.trim_start_matches("0x"))?; - let metadata = ::decode(&mut &bytes[..])?; let json = serde_json::to_string_pretty(&metadata)?; println!("{json}"); Ok(()) } "hex" => { + let hex_data = format!("0x{:?}", hex::encode(metadata.encode())); println!("{hex_data}"); Ok(()) } "bytes" => { - let bytes = hex::decode(hex_data.trim_start_matches("0x"))?; + let bytes = metadata.encode(); Ok(io::stdout().write_all(&bytes)?) } _ => Err(eyre::eyre!( From 47e9163cbab7f316a74182358682c5592cb0a222 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Fri, 24 Mar 2023 18:20:36 +0200 Subject: [PATCH 07/29] metadata: Do not include extrinsic metadata Signed-off-by: Alexandru Vasile --- metadata/src/retain.rs | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index 1dee66f14b..49a2f04bf7 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -4,7 +4,7 @@ //! Utility functions to generate a subset of the metadata. -use frame_metadata::{ExtrinsicMetadata, PalletMetadata, RuntimeMetadataV14, StorageEntryType}; +use frame_metadata::{PalletMetadata, RuntimeMetadataV14, StorageEntryType}; use scale_info::{form::PortableForm, interner::UntrackedSymbol}; use std::{ any::TypeId, @@ -44,19 +44,6 @@ fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut Ha } } -/// Collect all type IDs needed to represent the extrinsic metadata. -fn collect_extrinsic_types( - extrinsic: &ExtrinsicMetadata, - type_ids: &mut HashSet, -) { - type_ids.insert(extrinsic.ty.id()); - - for signed in &extrinsic.signed_extensions { - type_ids.insert(signed.ty.id()); - type_ids.insert(signed.additional_signed.id()); - } -} - /// Update the given type using the new type ID from the portable registry. /// /// # Panics @@ -103,19 +90,6 @@ fn update_pallet_types(pallet: &mut PalletMetadata, map_ids: &BTre } } -/// Update all type IDs of the provided extrinsic metadata using the new type IDs from the portable registry. -fn update_extrinsic_types( - extrinsic: &mut ExtrinsicMetadata, - map_ids: &BTreeMap, -) { - update_type(&mut extrinsic.ty, map_ids); - - for signed in &mut extrinsic.signed_extensions { - update_type(&mut signed.ty, map_ids); - update_type(&mut signed.additional_signed, map_ids); - } -} - /// Generate a subset of the metadata that contains only the /// types needed to represent the provided pallets. /// @@ -144,9 +118,6 @@ where } }); - collect_extrinsic_types(&metadata.extrinsic, &mut type_ids); - type_ids.insert(metadata.ty.id()); - // Additionally, subxt depends on the `RuntimeError` and `DispatchError`. let dispatch_error_ty = metadata .types @@ -164,9 +135,6 @@ where for pallets in &mut metadata.pallets { update_pallet_types(pallets, &map_ids); } - - update_extrinsic_types(&mut metadata.extrinsic, &map_ids); - update_type(&mut metadata.ty, &map_ids); } #[cfg(test)] From 19eec1fe7b397b97bf1d6a2f9bca3e75fd87068d Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Fri, 24 Mar 2023 19:05:50 +0200 Subject: [PATCH 08/29] retain: Fix clippy Signed-off-by: Alexandru Vasile --- metadata/src/retain.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index 49a2f04bf7..a1582bac36 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -51,9 +51,9 @@ fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut Ha /// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. fn update_type(ty: &mut UntrackedSymbol, map_ids: &BTreeMap) { let old_id = ty.id(); - let new_id = map_ids.get(&old_id).expect(&format!( - "PortableRegistry did not retain type id {old_id}. This is a bug. Please open an issue." - )); + let new_id = map_ids + .get(&old_id) + .unwrap_or_else(|| panic!("PortableRegistry did not retain type id {old_id}. This is a bug. Please open an issue.")); *ty = (*new_id).into(); } From 725a2e5f8339a795892dbbd2df19e49330ae3a9b Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Mar 2023 14:32:22 +0300 Subject: [PATCH 09/29] test-runtime: Generate per pallet metadata and rs file Signed-off-by: Alexandru Vasile --- Cargo.lock | 2 ++ testing/test-runtime/Cargo.toml | 2 ++ testing/test-runtime/build.rs | 51 ++++++++++++++++++++++++++++++++- testing/test-runtime/src/lib.rs | 3 ++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ea2da10dfd..7622555ad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3561,10 +3561,12 @@ dependencies = [ name = "test-runtime" version = "0.27.1" dependencies = [ + "heck", "jsonrpsee", "parity-scale-codec", "sp-runtime", "subxt", + "subxt-metadata", "tokio", "which", ] diff --git a/testing/test-runtime/Cargo.toml b/testing/test-runtime/Cargo.toml index 77312e2e9c..bb43e2aca3 100644 --- a/testing/test-runtime/Cargo.toml +++ b/testing/test-runtime/Cargo.toml @@ -14,3 +14,5 @@ subxt = { path = "../../subxt" } tokio = { version = "1.26", features = ["macros", "rt-multi-thread"] } which = "4.4.0" jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport"] } +subxt-metadata = { path = "../../metadata" } +heck = "0.4.1" diff --git a/testing/test-runtime/build.rs b/testing/test-runtime/build.rs index c86bc0e86a..9aafa6b107 100644 --- a/testing/test-runtime/build.rs +++ b/testing/test-runtime/build.rs @@ -2,6 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +use heck::ToSnakeCase; use std::{ env, fs, net::TcpListener, @@ -10,6 +11,9 @@ use std::{ process::Command, thread, time, }; +use subxt::ext::codec::{Decode, Encode}; +use subxt::ext::frame_metadata::RuntimeMetadataPrefixed; +use subxt_metadata::retain_metadata_pallets; static SUBSTRATE_BIN_ENV_VAR: &str = "SUBSTRATE_NODE_PATH"; @@ -76,7 +80,7 @@ async fn run() { // Save metadata to a file: let out_dir = env::var_os("OUT_DIR").unwrap(); let metadata_path = Path::new(&out_dir).join("metadata.scale"); - fs::write(&metadata_path, metadata_bytes.0).expect("Couldn't write metadata output"); + fs::write(&metadata_path, metadata_bytes.0.clone()).expect("Couldn't write metadata output"); // Write out our expression to generate the runtime API to a file. Ideally, we'd just write this code // in lib.rs, but we must pass a string literal (and not `concat!(..)`) as an arg to `runtime_metadata_path`, @@ -96,6 +100,51 @@ async fn run() { let runtime_path = Path::new(&out_dir).join("runtime.rs"); fs::write(runtime_path, runtime_api_contents).expect("Couldn't write runtime rust output"); + let metadata_prefixed: RuntimeMetadataPrefixed = + Decode::decode(&mut &metadata_bytes.0[..]).expect("Could not decode metadata bytes"); + + let metadata_v14 = match &metadata_prefixed.1 { + subxt::ext::frame_metadata::RuntimeMetadata::V14(metadata) => metadata, + _ => panic!("Unsupported metadata version. Only V14 is supported currently"), + }; + + let mut runtime_api_pallets_contents = String::new(); + let mut index = 0; + for pallet in &metadata_v14.pallets { + index += 1; + if index == 1024 { + break; + } + + let mut pallet_metadata = metadata_v14.clone(); + retain_metadata_pallets(&mut pallet_metadata, |pallet_filter| { + pallet_filter.name == pallet.name + }); + + let metadata_path = Path::new(&out_dir).join(format!("metadata_{}.scale", pallet.name)); + + runtime_api_pallets_contents += &format!( + r#" + #[subxt::subxt( + runtime_metadata_path = "{}", + derive_for_all_types = "Eq, PartialEq", + )] + pub mod node_runtime_{} {{}} + "#, + metadata_path + .to_str() + .expect("Path to metadata should be stringifiable"), + pallet.name.to_snake_case(), + ); + + let meta_prefixed: RuntimeMetadataPrefixed = pallet_metadata.into(); + fs::write(metadata_path, &meta_prefixed.encode()) + .expect("Couldn't write pallet metadata output"); + } + let runtime_pallets_path = Path::new(&out_dir).join("runtime_pallets.rs"); + fs::write(runtime_pallets_path, runtime_api_pallets_contents) + .expect("Couldn't write runtime pallets rust output"); + let substrate_path = which::which(substrate_bin).expect("Cannot resolve path to substrate binary"); diff --git a/testing/test-runtime/src/lib.rs b/testing/test-runtime/src/lib.rs index c1058e58c3..b4b9698c41 100644 --- a/testing/test-runtime/src/lib.rs +++ b/testing/test-runtime/src/lib.rs @@ -8,3 +8,6 @@ pub static METADATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/metadata.scale")); include!(concat!(env!("OUT_DIR"), "/runtime.rs")); +// For each pallet metadata is stripped to contain only that specific pallet. +// Ensure the generated modules out of those pallets compiles correctly. +include!(concat!(env!("OUT_DIR"), "/runtime_pallets.rs")); From 8515b1e64dd1577b2c5b204a6876555b13b11afd Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Mar 2023 15:12:53 +0300 Subject: [PATCH 10/29] ui-tests: Check per metadata generated files Signed-off-by: Alexandru Vasile --- Cargo.lock | 1 + metadata/src/retain.rs | 2 +- testing/ui-tests/Cargo.toml | 1 + testing/ui-tests/src/lib.rs | 8 +++++++- testing/ui-tests/src/utils/mod.rs | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7622555ad8..9634065a3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3898,6 +3898,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "subxt", + "subxt-metadata", "trybuild", ] diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index a1582bac36..dc065d6698 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2022 Parity Technologies (UK) Ltd. +// Copyright 2019-2023 Parity Technologies (UK) Ltd. // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. diff --git a/testing/ui-tests/Cargo.toml b/testing/ui-tests/Cargo.toml index 1ce5b9979f..e5f839be79 100644 --- a/testing/ui-tests/Cargo.toml +++ b/testing/ui-tests/Cargo.toml @@ -14,3 +14,4 @@ scale-info = { version = "2.3.0", features = ["bit-vec"] } frame-metadata = "15.0.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full", "bit-vec"] } subxt = { path = "../../subxt" } +subxt-metadata = { path = "../../metadata" } diff --git a/testing/ui-tests/src/lib.rs b/testing/ui-tests/src/lib.rs index d9cee8c3fa..7e90211faa 100644 --- a/testing/ui-tests/src/lib.rs +++ b/testing/ui-tests/src/lib.rs @@ -15,7 +15,7 @@ mod dispatch_errors; mod storage; mod utils; -use crate::utils::MetadataTestRunner; +use crate::utils::{MetadataTestRunner, PalletMetadataTestRunner}; // Each of these tests leads to some rust code being compiled and // executed to test that compilation is successful (or errors in the @@ -46,6 +46,12 @@ fn ui_tests() { "array_dispatch_error", dispatch_errors::metadata_array_dispatch_error(), )); + + // Ensure the generate per pallet metadata compiles. + let mut p = PalletMetadataTestRunner::new(); + while let Some(path) = p.next_test() { + t.pass(path); + } } #[test] diff --git a/testing/ui-tests/src/utils/mod.rs b/testing/ui-tests/src/utils/mod.rs index 7b4a145192..537af2ab66 100644 --- a/testing/ui-tests/src/utils/mod.rs +++ b/testing/ui-tests/src/utils/mod.rs @@ -4,6 +4,7 @@ pub mod dispatch_error; mod metadata_test_runner; +mod pallet_metadata_test_runner; use frame_metadata::{ v14::RuntimeMetadataV14, ExtrinsicMetadata, PalletMetadata, PalletStorageMetadata, @@ -12,6 +13,7 @@ use frame_metadata::{ use scale_info::{meta_type, IntoPortable, TypeInfo}; pub use metadata_test_runner::MetadataTestRunner; +pub use pallet_metadata_test_runner::PalletMetadataTestRunner; /// Given some pallet metadata, generate a [`RuntimeMetadataPrefixed`] struct. /// We default to a useless extrinsic type, and register a fake `DispatchError` From a8d368bdcdbd639bf2b7975ffcd5b42806e4dfdb Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Mar 2023 15:13:11 +0300 Subject: [PATCH 11/29] Revert "test-runtime: Generate per pallet metadata and rs file" This reverts commit 725a2e5f8339a795892dbbd2df19e49330ae3a9b. Signed-off-by: Alexandru Vasile --- Cargo.lock | 2 - testing/test-runtime/Cargo.toml | 2 - testing/test-runtime/build.rs | 51 +-------- testing/test-runtime/src/lib.rs | 3 - .../src/utils/pallet_metadata_test_runner.rs | 101 ++++++++++++++++++ 5 files changed, 102 insertions(+), 57 deletions(-) create mode 100644 testing/ui-tests/src/utils/pallet_metadata_test_runner.rs diff --git a/Cargo.lock b/Cargo.lock index 9634065a3d..60eab7c9f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3561,12 +3561,10 @@ dependencies = [ name = "test-runtime" version = "0.27.1" dependencies = [ - "heck", "jsonrpsee", "parity-scale-codec", "sp-runtime", "subxt", - "subxt-metadata", "tokio", "which", ] diff --git a/testing/test-runtime/Cargo.toml b/testing/test-runtime/Cargo.toml index bb43e2aca3..77312e2e9c 100644 --- a/testing/test-runtime/Cargo.toml +++ b/testing/test-runtime/Cargo.toml @@ -14,5 +14,3 @@ subxt = { path = "../../subxt" } tokio = { version = "1.26", features = ["macros", "rt-multi-thread"] } which = "4.4.0" jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport"] } -subxt-metadata = { path = "../../metadata" } -heck = "0.4.1" diff --git a/testing/test-runtime/build.rs b/testing/test-runtime/build.rs index 9aafa6b107..c86bc0e86a 100644 --- a/testing/test-runtime/build.rs +++ b/testing/test-runtime/build.rs @@ -2,7 +2,6 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use heck::ToSnakeCase; use std::{ env, fs, net::TcpListener, @@ -11,9 +10,6 @@ use std::{ process::Command, thread, time, }; -use subxt::ext::codec::{Decode, Encode}; -use subxt::ext::frame_metadata::RuntimeMetadataPrefixed; -use subxt_metadata::retain_metadata_pallets; static SUBSTRATE_BIN_ENV_VAR: &str = "SUBSTRATE_NODE_PATH"; @@ -80,7 +76,7 @@ async fn run() { // Save metadata to a file: let out_dir = env::var_os("OUT_DIR").unwrap(); let metadata_path = Path::new(&out_dir).join("metadata.scale"); - fs::write(&metadata_path, metadata_bytes.0.clone()).expect("Couldn't write metadata output"); + fs::write(&metadata_path, metadata_bytes.0).expect("Couldn't write metadata output"); // Write out our expression to generate the runtime API to a file. Ideally, we'd just write this code // in lib.rs, but we must pass a string literal (and not `concat!(..)`) as an arg to `runtime_metadata_path`, @@ -100,51 +96,6 @@ async fn run() { let runtime_path = Path::new(&out_dir).join("runtime.rs"); fs::write(runtime_path, runtime_api_contents).expect("Couldn't write runtime rust output"); - let metadata_prefixed: RuntimeMetadataPrefixed = - Decode::decode(&mut &metadata_bytes.0[..]).expect("Could not decode metadata bytes"); - - let metadata_v14 = match &metadata_prefixed.1 { - subxt::ext::frame_metadata::RuntimeMetadata::V14(metadata) => metadata, - _ => panic!("Unsupported metadata version. Only V14 is supported currently"), - }; - - let mut runtime_api_pallets_contents = String::new(); - let mut index = 0; - for pallet in &metadata_v14.pallets { - index += 1; - if index == 1024 { - break; - } - - let mut pallet_metadata = metadata_v14.clone(); - retain_metadata_pallets(&mut pallet_metadata, |pallet_filter| { - pallet_filter.name == pallet.name - }); - - let metadata_path = Path::new(&out_dir).join(format!("metadata_{}.scale", pallet.name)); - - runtime_api_pallets_contents += &format!( - r#" - #[subxt::subxt( - runtime_metadata_path = "{}", - derive_for_all_types = "Eq, PartialEq", - )] - pub mod node_runtime_{} {{}} - "#, - metadata_path - .to_str() - .expect("Path to metadata should be stringifiable"), - pallet.name.to_snake_case(), - ); - - let meta_prefixed: RuntimeMetadataPrefixed = pallet_metadata.into(); - fs::write(metadata_path, &meta_prefixed.encode()) - .expect("Couldn't write pallet metadata output"); - } - let runtime_pallets_path = Path::new(&out_dir).join("runtime_pallets.rs"); - fs::write(runtime_pallets_path, runtime_api_pallets_contents) - .expect("Couldn't write runtime pallets rust output"); - let substrate_path = which::which(substrate_bin).expect("Cannot resolve path to substrate binary"); diff --git a/testing/test-runtime/src/lib.rs b/testing/test-runtime/src/lib.rs index b4b9698c41..c1058e58c3 100644 --- a/testing/test-runtime/src/lib.rs +++ b/testing/test-runtime/src/lib.rs @@ -8,6 +8,3 @@ pub static METADATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/metadata.scale")); include!(concat!(env!("OUT_DIR"), "/runtime.rs")); -// For each pallet metadata is stripped to contain only that specific pallet. -// Ensure the generated modules out of those pallets compiles correctly. -include!(concat!(env!("OUT_DIR"), "/runtime_pallets.rs")); diff --git a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs new file mode 100644 index 0000000000..8c972bd5e6 --- /dev/null +++ b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs @@ -0,0 +1,101 @@ +// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or GPL-3.0. +// see LICENSE for license details. + +use codec::{Decode, Encode}; +use frame_metadata::{RuntimeMetadataPrefixed, RuntimeMetadataV14}; +use std::io::Read; +use subxt_metadata::retain_metadata_pallets; + +static TEST_DIR_PREFIX: &str = "subxt_generated_pallets_ui_tests_"; +static METADATA_FILE: &str = "../../../../artifacts/polkadot_metadata.scale"; + +pub struct PalletMetadataTestRunner { + metadata: RuntimeMetadataV14, + index: usize, +} + +impl PalletMetadataTestRunner { + pub fn new() -> PalletMetadataTestRunner { + let mut file = + std::fs::File::open(METADATA_FILE).expect("Cannot open metadata.scale artifact"); + + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes) + .expect("Failed to read metadata.scale file"); + + let meta: RuntimeMetadataPrefixed = + Decode::decode(&mut &*bytes).expect("Cannot decode metadata bytes"); + + let metadata = match meta.1 { + frame_metadata::RuntimeMetadata::V14(v14) => v14, + _ => panic!("Unsupported metadata version. Tests support only v14"), + }; + + PalletMetadataTestRunner { metadata, index: 0 } + } + + pub fn next_test(&mut self) -> Option { + let Some(pallet) = self.metadata.pallets.get(self.index) else { + return None + }; + let test_name = &pallet.name; + + // Increment test index to avoid overlaps. + let index = self.index; + self.index += 1; + + // Build custom metadata containing only this pallet. + let mut metadata = self.metadata.clone(); + retain_metadata_pallets(&mut metadata, |pallet_filter| { + pallet_filter.name == pallet.name + }); + + let mut tmp_dir = std::env::temp_dir(); + tmp_dir.push(format!("{TEST_DIR_PREFIX}{index}")); + + let tmp_metadata_path = { + let mut t = tmp_dir.clone(); + t.push("metadata.scale"); + t.to_string_lossy().into_owned() + }; + let tmp_rust_path = { + let mut t = tmp_dir.clone(); + t.push(format!("{test_name}.rs")); + t.to_string_lossy().into_owned() + }; + + let metadata_prefixed: RuntimeMetadataPrefixed = metadata.into(); + let encoded_metadata = metadata_prefixed.encode(); + let rust_file = format!( + r#" + use subxt; + + #[subxt::subxt(runtime_metadata_path = "{tmp_metadata_path}")] + pub mod polkadot {{}} + + fn main() {{}} + "# + ); + + std::fs::create_dir_all(&tmp_dir).expect("could not create tmp ui test dir"); + // Write metadata to tmp folder: + std::fs::write(&tmp_metadata_path, encoded_metadata).unwrap(); + // Write test file to tmp folder (it'll be moved by trybuild): + std::fs::write(&tmp_rust_path, rust_file).unwrap(); + + Some(tmp_rust_path) + } +} + +// `trybuild` runs all tests once it's dropped. So, we defer all cleanup until we +// are dropped too, to make sure that cleanup happens after tests are ran. +impl Drop for PalletMetadataTestRunner { + fn drop(&mut self) { + for i in 0..self.index { + let mut tmp_dir = std::env::temp_dir(); + tmp_dir.push(format!("{TEST_DIR_PREFIX}{i}")); + std::fs::remove_dir_all(tmp_dir).expect("cannot cleanup temp files"); + } + } +} From 36bfe9e572c22ef5254b7fcbfbcac2882628f231 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Mar 2023 18:08:12 +0300 Subject: [PATCH 12/29] ui-tests: Adjust path to metadata file Signed-off-by: Alexandru Vasile --- testing/ui-tests/src/utils/pallet_metadata_test_runner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs index 8c972bd5e6..75c31973ab 100644 --- a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs +++ b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs @@ -8,7 +8,7 @@ use std::io::Read; use subxt_metadata::retain_metadata_pallets; static TEST_DIR_PREFIX: &str = "subxt_generated_pallets_ui_tests_"; -static METADATA_FILE: &str = "../../../../artifacts/polkadot_metadata.scale"; +static METADATA_FILE: &str = "../../artifacts/polkadot_metadata.scale"; pub struct PalletMetadataTestRunner { metadata: RuntimeMetadataV14, From e90920ce16f13cf135df51ff24fc17a72e0865e2 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Mar 2023 18:18:04 +0300 Subject: [PATCH 13/29] ui-tests: Change drop order to keep `PalletMetadata` around Signed-off-by: Alexandru Vasile --- testing/ui-tests/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/ui-tests/src/lib.rs b/testing/ui-tests/src/lib.rs index 7e90211faa..e5a65a401b 100644 --- a/testing/ui-tests/src/lib.rs +++ b/testing/ui-tests/src/lib.rs @@ -23,6 +23,7 @@ use crate::utils::{MetadataTestRunner, PalletMetadataTestRunner}; #[test] fn ui_tests() { let mut m = MetadataTestRunner::default(); + let mut p = PalletMetadataTestRunner::new(); let t = trybuild::TestCases::new(); t.pass("src/correct/*.rs"); @@ -48,7 +49,6 @@ fn ui_tests() { )); // Ensure the generate per pallet metadata compiles. - let mut p = PalletMetadataTestRunner::new(); while let Some(path) = p.next_test() { t.pass(path); } From 396cc7cf5949a675130e0a6a5b51eb7881600b67 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 28 Mar 2023 13:14:54 +0300 Subject: [PATCH 14/29] Update metadata/src/retain.rs Co-authored-by: James Wilson --- metadata/src/retain.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index dc065d6698..3af21cf0b4 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -118,7 +118,8 @@ where } }); - // Additionally, subxt depends on the `RuntimeError` and `DispatchError`. + // Additionally, subxt depends on the `DispatchError`; we use the same + // logic here that is used when building our `Metadata`. let dispatch_error_ty = metadata .types .types() From cc1809f028fa52fc68d1299e0193fe6389ed7f41 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 28 Mar 2023 13:19:40 +0300 Subject: [PATCH 15/29] Address feedback Signed-off-by: Alexandru Vasile --- metadata/src/lib.rs | 6 +++--- testing/ui-tests/src/lib.rs | 2 +- testing/ui-tests/src/utils/pallet_metadata_test_runner.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index 7b04f19ee4..b3b6fa391b 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -2,15 +2,15 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +mod retain; + use frame_metadata::{ ExtrinsicMetadata, RuntimeMetadataV14, StorageEntryMetadata, StorageEntryType, }; +pub use retain::retain_metadata_pallets; use scale_info::{form::PortableForm, Field, PortableRegistry, TypeDef, Variant}; use std::collections::HashSet; -mod retain; -pub use retain::retain_metadata_pallets; - /// Internal byte representation for various metadata types utilized for /// generating deterministic hashes between different rust versions. #[repr(u8)] diff --git a/testing/ui-tests/src/lib.rs b/testing/ui-tests/src/lib.rs index e5a65a401b..1b47594114 100644 --- a/testing/ui-tests/src/lib.rs +++ b/testing/ui-tests/src/lib.rs @@ -49,7 +49,7 @@ fn ui_tests() { )); // Ensure the generate per pallet metadata compiles. - while let Some(path) = p.next_test() { + while let Some(path) = p.path_to_next_ui_test() { t.pass(path); } } diff --git a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs index 75c31973ab..af69c87c3b 100644 --- a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs +++ b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs @@ -35,7 +35,7 @@ impl PalletMetadataTestRunner { PalletMetadataTestRunner { metadata, index: 0 } } - pub fn next_test(&mut self) -> Option { + pub fn path_to_next_ui_test(&mut self) -> Option { let Some(pallet) = self.metadata.pallets.get(self.index) else { return None }; From 5a3c81dd57b7d16ffb4e8ea53a003545325c53b8 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Mar 2023 19:14:23 +0300 Subject: [PATCH 16/29] retain: Keep extrinsic type Signed-off-by: Alexandru Vasile --- metadata/src/retain.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index 3af21cf0b4..0e067c60cb 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -4,7 +4,7 @@ //! Utility functions to generate a subset of the metadata. -use frame_metadata::{PalletMetadata, RuntimeMetadataV14, StorageEntryType}; +use frame_metadata::{ExtrinsicMetadata, PalletMetadata, RuntimeMetadataV14, StorageEntryType}; use scale_info::{form::PortableForm, interner::UntrackedSymbol}; use std::{ any::TypeId, @@ -44,6 +44,19 @@ fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut Ha } } +/// Collect all type IDs needed to represent the extrinsic metadata. +fn collect_extrinsic_types( + extrinsic: &ExtrinsicMetadata, + type_ids: &mut HashSet, +) { + type_ids.insert(extrinsic.ty.id()); + + for signed in &extrinsic.signed_extensions { + type_ids.insert(signed.ty.id()); + type_ids.insert(signed.additional_signed.id()); + } +} + /// Update the given type using the new type ID from the portable registry. /// /// # Panics @@ -90,6 +103,19 @@ fn update_pallet_types(pallet: &mut PalletMetadata, map_ids: &BTre } } +/// Update all type IDs of the provided extrinsic metadata using the new type IDs from the portable registry. +fn update_extrinsic_types( + extrinsic: &mut ExtrinsicMetadata, + map_ids: &BTreeMap, +) { + update_type(&mut extrinsic.ty, map_ids); + + for signed in &mut extrinsic.signed_extensions { + update_type(&mut signed.ty, map_ids); + update_type(&mut signed.additional_signed, map_ids); + } +} + /// Generate a subset of the metadata that contains only the /// types needed to represent the provided pallets. /// @@ -117,6 +143,8 @@ where false } }); + collect_extrinsic_types(&metadata.extrinsic, &mut type_ids); + type_ids.insert(metadata.ty.id()); // Additionally, subxt depends on the `DispatchError`; we use the same // logic here that is used when building our `Metadata`. @@ -136,6 +164,9 @@ where for pallets in &mut metadata.pallets { update_pallet_types(pallets, &map_ids); } + + update_extrinsic_types(&mut metadata.extrinsic, &map_ids); + update_type(&mut metadata.ty, &map_ids); } #[cfg(test)] From 4a71546d10f7efb27a4d8690480e18a2db452b61 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 28 Mar 2023 13:39:09 +0300 Subject: [PATCH 17/29] cli: Introduce `MetadataSource` Signed-off-by: Alexandru Vasile --- cli/src/commands/mod.rs | 1 + cli/src/commands/utils.rs | 48 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 cli/src/commands/utils.rs diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs index 4ff1876522..077ad33fdd 100644 --- a/cli/src/commands/mod.rs +++ b/cli/src/commands/mod.rs @@ -5,4 +5,5 @@ pub mod codegen; pub mod compatibility; pub mod metadata; +mod utils; pub mod version; diff --git a/cli/src/commands/utils.rs b/cli/src/commands/utils.rs new file mode 100644 index 0000000000..e8b71c350f --- /dev/null +++ b/cli/src/commands/utils.rs @@ -0,0 +1,48 @@ +// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// This file is dual-licensed as Apache-2.0 or GPL-3.0. +// see LICENSE for license details. + +use std::{fs, io::Read, path::PathBuf}; + +use color_eyre::eyre; +use subxt_codegen::utils::Uri; + +// The source of the metadata. +pub enum MetadataSource { + // Metadata is loaded from a file. + FilePath(PathBuf), + // Metadata is downloaded from a runtime node. + Uri(Uri), +} + +impl MetadataSource { + /// Constructs a new [`MetadataSource`]. + pub fn new(url: Option, file: Option) -> color_eyre::Result { + if let Some(file) = file { + if url.is_some() { + eyre::bail!("specify one of `--url` or `--file` but not both") + }; + + return Ok(Self::FilePath(file)); + } + let url = url.unwrap_or_else(|| { + "http://localhost:9933" + .parse::() + .expect("default url is valid") + }); + Ok(Self::Uri(url)) + } + + /// Fetch the metadata bytes. + pub async fn fetch(&self) -> color_eyre::Result> { + match &self { + Self::FilePath(path) => { + let mut file = fs::File::open(path)?; + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes)?; + Ok(bytes) + } + Self::Uri(url) => Ok(subxt_codegen::utils::fetch_metadata_bytes(url).await?), + } + } +} From a663236264876d067c45d69bed1f4d4cbe194c6e Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 28 Mar 2023 13:44:54 +0300 Subject: [PATCH 18/29] cli: Use `MetadataSource` helper Signed-off-by: Alexandru Vasile --- cli/src/commands/codegen.rs | 24 +++++------------------- cli/src/commands/metadata.rs | 31 ++++++++++++++++--------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/cli/src/commands/codegen.rs b/cli/src/commands/codegen.rs index 3137b28029..73b0c62e32 100644 --- a/cli/src/commands/codegen.rs +++ b/cli/src/commands/codegen.rs @@ -3,11 +3,12 @@ // see LICENSE for license details. use clap::Parser as ClapParser; -use color_eyre::eyre; use jsonrpsee::client_transport::ws::Uri; -use std::{fs, io::Read, path::PathBuf}; +use std::path::PathBuf; use subxt_codegen::{DerivesRegistry, TypeSubstitutes}; +use super::utils::MetadataSource; + /// Generate runtime API client code from metadata. /// /// # Example (with code formatting) @@ -52,23 +53,8 @@ fn derive_for_type_parser(src: &str) -> Result<(String, String), String> { } pub async fn run(opts: Opts) -> color_eyre::Result<()> { - let bytes = if let Some(file) = opts.file.as_ref() { - if opts.url.is_some() { - eyre::bail!("specify one of `--url` or `--file` but not both") - }; - - let mut file = fs::File::open(file)?; - let mut bytes = Vec::new(); - file.read_to_end(&mut bytes)?; - bytes - } else { - let url = opts.url.unwrap_or_else(|| { - "http://localhost:9933" - .parse::() - .expect("default url is valid") - }); - subxt_codegen::utils::fetch_metadata_bytes(&url).await? - }; + let source = MetadataSource::new(opts.url, opts.file)?; + let bytes = source.fetch().await?; codegen( &bytes, diff --git a/cli/src/commands/metadata.rs b/cli/src/commands/metadata.rs index bf285346c0..137955a7e5 100644 --- a/cli/src/commands/metadata.rs +++ b/cli/src/commands/metadata.rs @@ -7,37 +7,38 @@ use color_eyre::eyre; use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; use jsonrpsee::client_transport::ws::Uri; use scale::{Decode, Encode}; -use std::io::{self, Write}; -use subxt_codegen::utils::fetch_metadata_hex; +use std::{ + io::{self, Write}, + path::PathBuf, +}; use subxt_metadata::retain_metadata_pallets; +use super::utils::MetadataSource; + /// Download metadata from a substrate node, for use with `subxt` codegen. #[derive(Debug, ClapParser)] pub struct Opts { - /// The url of the substrate node to query for metadata. - #[clap( - name = "url", - long, - value_parser, - default_value = "http://localhost:9933" - )] - url: Uri, + /// The url of the substrate node to query for metadata for codegen. + #[clap(name = "url", long, value_parser)] + url: Option, + /// The path to the encoded metadata file. + #[clap(short, long, value_parser)] + file: Option, /// The format of the metadata to display: `json`, `hex` or `bytes`. #[clap(long, short, default_value = "bytes")] format: String, /// Generate a subset of the metadata that contains only the /// types needed to represent the provided pallets. #[clap(long, use_value_delimiter = true, value_parser)] - retain_pallets: Option>, + pallets: Option>, } pub async fn run(opts: Opts) -> color_eyre::Result<()> { - let hex_data = fetch_metadata_hex(&opts.url).await?; - - let bytes = hex::decode(hex_data.trim_start_matches("0x"))?; + let source = MetadataSource::new(opts.url, opts.file)?; + let bytes = source.fetch().await?; let mut metadata = ::decode(&mut &bytes[..])?; - if let Some(pallets) = opts.retain_pallets { + if let Some(pallets) = opts.pallets { let metadata_v14 = match &mut metadata.1 { RuntimeMetadata::V14(metadata_v14) => metadata_v14, _ => { From d8b982425f0745904b991ea328f52841dd64c243 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 29 Mar 2023 14:44:55 +0300 Subject: [PATCH 19/29] cli: Use `FileOrUrl` flatten command argument Signed-off-by: Alexandru Vasile --- cli/src/commands/codegen.rs | 15 +++-------- cli/src/commands/metadata.rs | 19 ++++---------- cli/src/commands/utils.rs | 49 ++++++++++++++++-------------------- 3 files changed, 31 insertions(+), 52 deletions(-) diff --git a/cli/src/commands/codegen.rs b/cli/src/commands/codegen.rs index 73b0c62e32..6b18822fb1 100644 --- a/cli/src/commands/codegen.rs +++ b/cli/src/commands/codegen.rs @@ -3,11 +3,9 @@ // see LICENSE for license details. use clap::Parser as ClapParser; -use jsonrpsee::client_transport::ws::Uri; -use std::path::PathBuf; use subxt_codegen::{DerivesRegistry, TypeSubstitutes}; -use super::utils::MetadataSource; +use super::utils::FileOrUrl; /// Generate runtime API client code from metadata. /// @@ -16,12 +14,8 @@ use super::utils::MetadataSource; /// `subxt codegen | rustfmt --edition=2018 --emit=stdout` #[derive(Debug, ClapParser)] pub struct Opts { - /// The url of the substrate node to query for metadata for codegen. - #[clap(name = "url", long, value_parser)] - url: Option, - /// The path to the encoded metadata file. - #[clap(short, long, value_parser)] - file: Option, + #[command(flatten)] + file_or_url: FileOrUrl, /// Additional derives #[clap(long = "derive")] derives: Vec, @@ -53,8 +47,7 @@ fn derive_for_type_parser(src: &str) -> Result<(String, String), String> { } pub async fn run(opts: Opts) -> color_eyre::Result<()> { - let source = MetadataSource::new(opts.url, opts.file)?; - let bytes = source.fetch().await?; + let bytes = opts.file_or_url.fetch().await?; codegen( &bytes, diff --git a/cli/src/commands/metadata.rs b/cli/src/commands/metadata.rs index 137955a7e5..d98894a0d1 100644 --- a/cli/src/commands/metadata.rs +++ b/cli/src/commands/metadata.rs @@ -5,25 +5,17 @@ use clap::Parser as ClapParser; use color_eyre::eyre; use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; -use jsonrpsee::client_transport::ws::Uri; use scale::{Decode, Encode}; -use std::{ - io::{self, Write}, - path::PathBuf, -}; +use std::io::{self, Write}; use subxt_metadata::retain_metadata_pallets; -use super::utils::MetadataSource; +use super::utils::FileOrUrl; /// Download metadata from a substrate node, for use with `subxt` codegen. #[derive(Debug, ClapParser)] pub struct Opts { - /// The url of the substrate node to query for metadata for codegen. - #[clap(name = "url", long, value_parser)] - url: Option, - /// The path to the encoded metadata file. - #[clap(short, long, value_parser)] - file: Option, + #[command(flatten)] + file_or_url: FileOrUrl, /// The format of the metadata to display: `json`, `hex` or `bytes`. #[clap(long, short, default_value = "bytes")] format: String, @@ -34,8 +26,7 @@ pub struct Opts { } pub async fn run(opts: Opts) -> color_eyre::Result<()> { - let source = MetadataSource::new(opts.url, opts.file)?; - let bytes = source.fetch().await?; + let bytes = opts.file_or_url.fetch().await?; let mut metadata = ::decode(&mut &bytes[..])?; if let Some(pallets) = opts.pallets { diff --git a/cli/src/commands/utils.rs b/cli/src/commands/utils.rs index e8b71c350f..89b1b28a43 100644 --- a/cli/src/commands/utils.rs +++ b/cli/src/commands/utils.rs @@ -2,47 +2,42 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +use clap::Args; use std::{fs, io::Read, path::PathBuf}; use color_eyre::eyre; use subxt_codegen::utils::Uri; -// The source of the metadata. -pub enum MetadataSource { - // Metadata is loaded from a file. - FilePath(PathBuf), - // Metadata is downloaded from a runtime node. - Uri(Uri), +/// The source of the metadata. +#[derive(Debug, Args)] +pub struct FileOrUrl { + /// The url of the substrate node to query for metadata for codegen. + #[clap(name = "url", long, value_parser)] + url: Option, + /// The path to the encoded metadata file. + #[clap(short, long, value_parser)] + file: Option, } -impl MetadataSource { - /// Constructs a new [`MetadataSource`]. - pub fn new(url: Option, file: Option) -> color_eyre::Result { - if let Some(file) = file { - if url.is_some() { +impl FileOrUrl { + /// Fetch the metadata bytes. + pub async fn fetch(&self) -> color_eyre::Result> { + if let Some(path) = &self.file { + if self.url.is_some() { eyre::bail!("specify one of `--url` or `--file` but not both") }; - return Ok(Self::FilePath(file)); + let mut file = fs::File::open(path)?; + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes)?; + return Ok(bytes); } - let url = url.unwrap_or_else(|| { + + let url = self.url.clone().unwrap_or_else(|| { "http://localhost:9933" .parse::() .expect("default url is valid") }); - Ok(Self::Uri(url)) - } - - /// Fetch the metadata bytes. - pub async fn fetch(&self) -> color_eyre::Result> { - match &self { - Self::FilePath(path) => { - let mut file = fs::File::open(path)?; - let mut bytes = Vec::new(); - file.read_to_end(&mut bytes)?; - Ok(bytes) - } - Self::Uri(url) => Ok(subxt_codegen::utils::fetch_metadata_bytes(url).await?), - } + Ok(subxt_codegen::utils::fetch_metadata_bytes(&url).await?) } } From 01ff1b5cc0167f2d4e8205e032c68076face84e4 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 29 Mar 2023 18:03:24 +0300 Subject: [PATCH 20/29] retain: Do not include generic type params in retained metadata Signed-off-by: Alexandru Vasile --- metadata/src/retain.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index 0e067c60cb..01f5edf575 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -44,7 +44,21 @@ fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut Ha } } +/// Remove the generic type parameters of the type ID from the `PortableRegistry` +/// of the metadata. +fn remove_generic_type_params(metadata: &mut RuntimeMetadataV14, id: u32) { + let portable_ty = metadata.types.types.get_mut(id as usize).expect(&format!( + "Metadata does not contain extrinsic type ID {} registered; qed", + id + )); + portable_ty.ty.type_params = Vec::new(); +} + /// Collect all type IDs needed to represent the extrinsic metadata. +/// +/// Ensure that the extrinsic types from the `PortableRegistry` are trimmed +/// of the generic type parameters. Those are not needed and contain extra +/// nested type IDs that increase unnecessarily the size of the generated metadata. fn collect_extrinsic_types( extrinsic: &ExtrinsicMetadata, type_ids: &mut HashSet, @@ -143,7 +157,14 @@ where false } }); - collect_extrinsic_types(&metadata.extrinsic, &mut type_ids); + + let mut extrinsic_types = HashSet::new(); + collect_extrinsic_types(&metadata.extrinsic, &mut extrinsic_types); + for id in extrinsic_types { + remove_generic_type_params(metadata, id); + type_ids.insert(id); + } + type_ids.insert(metadata.ty.id()); // Additionally, subxt depends on the `DispatchError`; we use the same From e28bb8a3bebc1de4a66ba31e9e3655b3da3d7aff Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 29 Mar 2023 18:24:14 +0300 Subject: [PATCH 21/29] Adjust subxt to scale-info v2.5.0 Signed-off-by: Alexandru Vasile --- codegen/src/api/calls.rs | 8 ++-- codegen/src/api/constants.rs | 2 +- codegen/src/api/events.rs | 8 ++-- codegen/src/api/mod.rs | 12 +++-- codegen/src/api/storage.rs | 12 ++--- codegen/src/types/composite_def.rs | 8 ++-- codegen/src/types/mod.rs | 45 ++++++++---------- codegen/src/types/substitutes.rs | 2 +- codegen/src/types/type_def.rs | 36 +++++++------- codegen/src/types/type_path.rs | 2 +- metadata/src/lib.rs | 62 ++++++++++++------------- metadata/src/retain.rs | 42 +++++++++-------- subxt/src/constants/constants_client.rs | 2 +- subxt/src/events/events_type.rs | 2 +- subxt/src/metadata/metadata_type.rs | 44 +++++++++--------- subxt/src/storage/storage_address.rs | 10 ++-- subxt/src/storage/storage_type.rs | 8 ++-- subxt/src/utils/wrapper_opaque.rs | 6 +-- 18 files changed, 158 insertions(+), 153 deletions(-) diff --git a/codegen/src/api/calls.rs b/codegen/src/api/calls.rs index b9905e0574..20624ba487 100644 --- a/codegen/src/api/calls.rs +++ b/codegen/src/api/calls.rs @@ -37,7 +37,7 @@ pub fn generate_calls( let mut struct_defs = super::generate_structs_from_variants( type_gen, - call.ty.id(), + call.ty.id, |name| name.to_upper_camel_case().into(), "Call", crate_path, @@ -61,7 +61,7 @@ pub fn generate_calls( .unzip(), CompositeDefFields::NoFields => Default::default(), CompositeDefFields::Unnamed(_) => { - return Err(CodegenError::InvalidCallVariant(call.ty.id())) + return Err(CodegenError::InvalidCallVariant(call.ty.id)) } }; @@ -106,8 +106,8 @@ pub fn generate_calls( .into_iter() .unzip(); - let call_ty = type_gen.resolve_type(call.ty.id()); - let docs = call_ty.docs(); + let call_ty = type_gen.resolve_type(call.ty.id); + let docs = call_ty.docs; let docs = should_gen_docs .then_some(quote! { #( #[doc = #docs ] )* }) .unwrap_or_default(); diff --git a/codegen/src/api/constants.rs b/codegen/src/api/constants.rs index b75c2880a2..5c28b99cb2 100644 --- a/codegen/src/api/constants.rs +++ b/codegen/src/api/constants.rs @@ -56,7 +56,7 @@ pub fn generate_constants( return Err(CodegenError::MissingConstantMetadata(constant_name.into(), pallet_name.into())); }; - let return_ty = type_gen.resolve_type_path(constant.ty.id()); + let return_ty = type_gen.resolve_type_path(constant.ty.id); let docs = &constant.docs; let docs = should_gen_docs .then_some(quote! { #( #[doc = #docs ] )* }) diff --git a/codegen/src/api/events.rs b/codegen/src/api/events.rs index 12334f6d31..c73f236004 100644 --- a/codegen/src/api/events.rs +++ b/codegen/src/api/events.rs @@ -53,7 +53,7 @@ pub fn generate_events( let struct_defs = super::generate_structs_from_variants( type_gen, - event.ty.id(), + event.ty.id, |name| name.into(), "Event", crate_path, @@ -74,9 +74,9 @@ pub fn generate_events( } } }); - let event_type = type_gen.resolve_type_path(event.ty.id()); - let event_ty = type_gen.resolve_type(event.ty.id()); - let docs = event_ty.docs(); + let event_type = type_gen.resolve_type_path(event.ty.id); + let event_ty = type_gen.resolve_type(event.ty.id); + let docs = event_ty.docs; let docs = should_gen_docs .then_some(quote! { #( #[doc = #docs ] )* }) .unwrap_or_default(); diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 7306a084b4..028fc1f326 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -543,24 +543,26 @@ where { let ty = type_gen.resolve_type(type_id); - let scale_info::TypeDef::Variant(variant) = ty.type_def() else { + let scale_info::TypeDef::Variant(variant) = &ty.type_def else { return Err(CodegenError::InvalidType(error_message_type_name.into())) }; variant - .variants() + .variants .iter() .map(|var| { - let struct_name = variant_to_struct_name(var.name()); + let struct_name = variant_to_struct_name(&var.name); let fields = CompositeDefFields::from_scale_info_fields( struct_name.as_ref(), - var.fields(), + &var.fields, &[], type_gen, )?; - let docs = should_gen_docs.then_some(var.docs()).unwrap_or_default(); + let docs = should_gen_docs + .then_some(var.docs.as_slice()) + .unwrap_or_default(); let struct_def = CompositeDef::struct_def( &ty, struct_name.as_ref(), diff --git a/codegen/src/api/storage.rs b/codegen/src/api/storage.rs index 759a74ccf3..53e92fb0c3 100644 --- a/codegen/src/api/storage.rs +++ b/codegen/src/api/storage.rs @@ -74,17 +74,17 @@ fn generate_storage_entry_fns( let (fields, key_impl) = match &storage_entry.ty { StorageEntryType::Plain(_) => (vec![], quote!(vec![])), StorageEntryType::Map { key, .. } => { - let key_ty = type_gen.resolve_type(key.id()); - match key_ty.type_def() { + let key_ty = type_gen.resolve_type(key.id); + match &key_ty.type_def { // An N-map; return each of the keys separately. TypeDef::Tuple(tuple) => { let fields = tuple - .fields() + .fields .iter() .enumerate() .map(|(i, f)| { let field_name = format_ident!("_{}", syn::Index::from(i)); - let field_type = type_gen.resolve_type_path(f.id()); + let field_type = type_gen.resolve_type_path(f.id); (field_name, field_type) }) .collect::>(); @@ -102,7 +102,7 @@ fn generate_storage_entry_fns( } // A map with a single key; return the single key. _ => { - let ty_path = type_gen.resolve_type_path(key.id()); + let ty_path = type_gen.resolve_type_path(key.id); let fields = vec![(format_ident!("_0"), ty_path)]; let key_impl = quote! { vec![ #crate_path::storage::address::StaticStorageMapKey::new(_0.borrow()) ] @@ -125,7 +125,7 @@ fn generate_storage_entry_fns( StorageEntryType::Plain(ref ty) => ty, StorageEntryType::Map { ref value, .. } => value, }; - let storage_entry_value_ty = type_gen.resolve_type_path(storage_entry_ty.id()); + let storage_entry_value_ty = type_gen.resolve_type_path(storage_entry_ty.id); let docs = &storage_entry.docs; let docs = should_gen_docs diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index 7062f20a0b..4af99c8b97 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -52,7 +52,7 @@ impl CompositeDef { { let ty = type_gen.resolve_type(field.type_id); if matches!( - ty.type_def(), + ty.type_def, TypeDef::Primitive( TypeDefPrimitive::U8 | TypeDefPrimitive::U16 @@ -173,11 +173,11 @@ impl CompositeDefFields { let mut unnamed_fields = Vec::new(); for field in fields { - let type_path = type_gen.resolve_field_type_path(field.ty().id(), parent_type_params); + let type_path = type_gen.resolve_field_type_path(field.ty.id, parent_type_params); let field_type = - CompositeDefFieldType::new(field.ty().id(), type_path, field.type_name().cloned()); + CompositeDefFieldType::new(field.ty.id, type_path, field.type_name.clone()); - if let Some(name) = field.name() { + if let Some(name) = field.name.as_ref() { let field_name = format_ident!("{}", name); named_fields.push((field_name, field_type)) } else { diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index c6e575a00a..cfd7b2b58e 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -73,8 +73,8 @@ impl<'a> TypeGenerator<'a> { let root_mod_ident = &self.types_mod_ident; let mut root_mod = Module::new(root_mod_ident.clone(), root_mod_ident.clone()); - for ty in self.type_registry.types() { - let path = ty.ty().path(); + for ty in &self.type_registry.types { + let path = &ty.ty().path; // Don't generate a type if it was substituted - the target type might // not be in the type registry + our resolution already performs the substitution. if self.type_substitutes.for_path(path).is_some() { @@ -168,29 +168,28 @@ impl<'a> TypeGenerator<'a> { let mut ty = self.resolve_type(id); - if ty.path().ident() == Some("Cow".to_string()) { + if ty.path.ident() == Some("Cow".to_string()) { ty = self.resolve_type( - ty.type_params()[0] - .ty() + ty.type_params[0] + .ty .expect("type parameters to Cow are not expected to be skipped; qed") - .id(), + .id, ) } let params: Vec<_> = ty - .type_params() + .type_params .iter() .filter_map(|f| { - f.ty() - .map(|f| self.resolve_type_path_recurse(f.id(), false, parent_type_params)) + f.ty.map(|f| self.resolve_type_path_recurse(f.id, false, parent_type_params)) }) .collect(); - let ty = match ty.type_def() { + let ty = match &ty.type_def { TypeDef::Composite(_) | TypeDef::Variant(_) => { if let Some((path, params)) = self .type_substitutes - .for_path_with_params(ty.path(), ¶ms) + .for_path_with_params(&ty.path, ¶ms) { TypePathType::Path { path: syn::TypePath { @@ -200,41 +199,37 @@ impl<'a> TypeGenerator<'a> { params: params.to_vec(), } } else { - TypePathType::from_type_def_path( - ty.path(), - self.types_mod_ident.clone(), - params, - ) + TypePathType::from_type_def_path(&ty.path, self.types_mod_ident.clone(), params) } } TypeDef::Primitive(primitive) => TypePathType::Primitive { def: primitive.clone(), }, TypeDef::Array(arr) => TypePathType::Array { - len: arr.len() as usize, + len: arr.len as usize, of: Box::new(self.resolve_type_path_recurse( - arr.type_param().id(), + arr.type_param.id, false, parent_type_params, )), }, TypeDef::Sequence(seq) => TypePathType::Vec { of: Box::new(self.resolve_type_path_recurse( - seq.type_param().id(), + seq.type_param.id, false, parent_type_params, )), }, TypeDef::Tuple(tuple) => TypePathType::Tuple { elements: tuple - .fields() + .fields .iter() - .map(|f| self.resolve_type_path_recurse(f.id(), false, parent_type_params)) + .map(|f| self.resolve_type_path_recurse(f.id, false, parent_type_params)) .collect(), }, TypeDef::Compact(compact) => TypePathType::Compact { inner: Box::new(self.resolve_type_path_recurse( - compact.type_param().id(), + compact.type_param.id, false, parent_type_params, )), @@ -243,12 +238,12 @@ impl<'a> TypeGenerator<'a> { }, TypeDef::BitSequence(bitseq) => TypePathType::BitVec { bit_order_type: Box::new(self.resolve_type_path_recurse( - bitseq.bit_order_type().id(), + bitseq.bit_order_type.id, false, parent_type_params, )), bit_store_type: Box::new(self.resolve_type_path_recurse( - bitseq.bit_store_type().id(), + bitseq.bit_store_type.id, false, parent_type_params, )), @@ -266,7 +261,7 @@ impl<'a> TypeGenerator<'a> { /// Returns the derives to be applied to a generated type. pub fn type_derives(&self, ty: &Type) -> Result { - let joined_path = ty.path().segments().join("::"); + let joined_path = ty.path.segments.join("::"); let ty_path: syn::TypePath = syn::parse_str(&joined_path) .map_err(|e| CodegenError::InvalidTypePath(joined_path, e))?; Ok(self.derives.resolve(&ty_path)) diff --git a/codegen/src/types/substitutes.rs b/codegen/src/types/substitutes.rs index 741b5463fa..aad74a2de7 100644 --- a/codegen/src/types/substitutes.rs +++ b/codegen/src/types/substitutes.rs @@ -226,7 +226,7 @@ impl From<&syn::Path> for PathSegments { impl From<&scale_info::Path> for PathSegments { fn from(path: &scale_info::Path) -> Self { PathSegments( - path.segments() + path.segments .iter() .map(|x| x.as_ref().to_owned()) .collect(), diff --git a/codegen/src/types/type_def.rs b/codegen/src/types/type_def.rs index 340e70ab53..519c31e7c9 100644 --- a/codegen/src/types/type_def.rs +++ b/codegen/src/types/type_def.rs @@ -40,15 +40,15 @@ impl TypeDefGen { let derives = type_gen.type_derives(ty)?; let type_params = ty - .type_params() + .type_params .iter() .enumerate() - .filter_map(|(i, tp)| match tp.ty() { + .filter_map(|(i, tp)| match tp.ty { Some(ty) => { let tp_name = format_ident!("_{}", i); Some(TypeParameter { - concrete_type_id: ty.id(), - original_name: tp.name().clone(), + concrete_type_id: ty.id, + original_name: tp.name.clone(), name: tp_name, }) } @@ -58,17 +58,19 @@ impl TypeDefGen { let mut type_params = TypeDefParameters::new(type_params); - let ty_kind = match ty.type_def() { + let ty_kind = match &ty.type_def { TypeDef::Composite(composite) => { - let type_name = ty.path().ident().expect("structs should have a name"); + let type_name = ty.path.ident().expect("structs should have a name"); let fields = CompositeDefFields::from_scale_info_fields( &type_name, - composite.fields(), + &composite.fields, type_params.params(), type_gen, )?; type_params.update_unused(fields.field_types()); - let docs = should_gen_docs.then_some(ty.docs()).unwrap_or_default(); + let docs = should_gen_docs + .then_some(ty.docs.as_slice()) + .unwrap_or_default(); let composite_def = CompositeDef::struct_def( ty, &type_name, @@ -82,22 +84,24 @@ impl TypeDefGen { TypeDefGenKind::Struct(composite_def) } TypeDef::Variant(variant) => { - let type_name = ty.path().ident().expect("variants should have a name"); + let type_name = ty.path.ident().expect("variants should have a name"); let variants = variant - .variants() + .variants .iter() .map(|v| { let fields = CompositeDefFields::from_scale_info_fields( - v.name(), - v.fields(), + &v.name, + &v.fields, type_params.params(), type_gen, )?; type_params.update_unused(fields.field_types()); - let docs = should_gen_docs.then_some(v.docs()).unwrap_or_default(); - let variant_def = CompositeDef::enum_variant_def(v.name(), fields, docs); - Ok((v.index(), variant_def)) + let docs = should_gen_docs + .then_some(v.docs.as_slice()) + .unwrap_or_default(); + let variant_def = CompositeDef::enum_variant_def(&v.name, fields, docs); + Ok((v.index, variant_def)) }) .collect::, CodegenError>>()?; @@ -106,7 +110,7 @@ impl TypeDefGen { _ => TypeDefGenKind::BuiltIn, }; - let docs = ty.docs(); + let docs = ty.docs.as_slice(); let ty_docs = should_gen_docs .then_some(quote! { #( #[doc = #docs ] )* }) .unwrap_or_default(); diff --git a/codegen/src/types/type_path.rs b/codegen/src/types/type_path.rs index a0ab8f4364..3a06aae398 100644 --- a/codegen/src/types/type_path.rs +++ b/codegen/src/types/type_path.rs @@ -106,7 +106,7 @@ impl TypePathType { root_mod_ident: Ident, params: Vec, ) -> Self { - let path_segments = path.segments(); + let path_segments = path.segments.as_slice(); let path: syn::TypePath = match path_segments { [] => panic!("Type has no ident"), diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index b3b6fa391b..4a8bb87f6d 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -60,10 +60,10 @@ fn get_field_hash( field: &Field, visited_ids: &mut HashSet, ) -> [u8; 32] { - let mut bytes = get_type_hash(registry, field.ty().id(), visited_ids); + let mut bytes = get_type_hash(registry, field.ty.id, visited_ids); // XOR name and field name with the type hash if they exist - if let Some(name) = field.name() { + if let Some(name) = &field.name { bytes = xor(bytes, hash(name.as_bytes())); } @@ -77,8 +77,8 @@ fn get_variant_hash( visited_ids: &mut HashSet, ) -> [u8; 32] { // Merge our hashes of the name and each field together using xor. - let mut bytes = hash(var.name().as_bytes()); - for field in var.fields() { + let mut bytes = hash(var.name.as_bytes()); + for field in &var.fields { bytes = hash_hashes(bytes, get_field_hash(registry, field, visited_ids)) } @@ -94,14 +94,14 @@ fn get_type_def_hash( match ty_def { TypeDef::Composite(composite) => { let mut bytes = hash(&[TypeBeingHashed::Composite as u8]); - for field in composite.fields() { + for field in &composite.fields { bytes = hash_hashes(bytes, get_field_hash(registry, field, visited_ids)); } bytes } TypeDef::Variant(variant) => { let mut bytes = hash(&[TypeBeingHashed::Variant as u8]); - for var in variant.variants().iter() { + for var in &variant.variants { bytes = hash_hashes(bytes, get_variant_hash(registry, var, visited_ids)); } bytes @@ -110,12 +110,12 @@ fn get_type_def_hash( let bytes = hash(&[TypeBeingHashed::Sequence as u8]); xor( bytes, - get_type_hash(registry, sequence.type_param().id(), visited_ids), + get_type_hash(registry, sequence.type_param.id, visited_ids), ) } TypeDef::Array(array) => { // Take length into account; different length must lead to different hash. - let len_bytes = array.len().to_be_bytes(); + let len_bytes = array.len.to_be_bytes(); let bytes = hash(&[ TypeBeingHashed::Array as u8, len_bytes[0], @@ -125,13 +125,13 @@ fn get_type_def_hash( ]); xor( bytes, - get_type_hash(registry, array.type_param().id(), visited_ids), + get_type_hash(registry, array.type_param.id, visited_ids), ) } TypeDef::Tuple(tuple) => { let mut bytes = hash(&[TypeBeingHashed::Tuple as u8]); - for field in tuple.fields() { - bytes = hash_hashes(bytes, get_type_hash(registry, field.id(), visited_ids)); + for field in &tuple.fields { + bytes = hash_hashes(bytes, get_type_hash(registry, field.id, visited_ids)); } bytes } @@ -143,18 +143,18 @@ fn get_type_def_hash( let bytes = hash(&[TypeBeingHashed::Compact as u8]); xor( bytes, - get_type_hash(registry, compact.type_param().id(), visited_ids), + get_type_hash(registry, compact.type_param.id, visited_ids), ) } TypeDef::BitSequence(bitseq) => { let mut bytes = hash(&[TypeBeingHashed::BitSequence as u8]); bytes = xor( bytes, - get_type_hash(registry, bitseq.bit_order_type().id(), visited_ids), + get_type_hash(registry, bitseq.bit_order_type.id, visited_ids), ); bytes = xor( bytes, - get_type_hash(registry, bitseq.bit_store_type().id(), visited_ids), + get_type_hash(registry, bitseq.bit_store_type.id, visited_ids), ); bytes } @@ -169,7 +169,7 @@ fn get_type_hash(registry: &PortableRegistry, id: u32, visited_ids: &mut HashSet } let ty = registry.resolve(id).unwrap(); - get_type_def_hash(registry, ty.type_def(), visited_ids) + get_type_def_hash(registry, &ty.type_def, visited_ids) } /// Obtain the hash representation of a `frame_metadata::ExtrinsicMetadata`. @@ -179,20 +179,20 @@ fn get_extrinsic_hash( ) -> [u8; 32] { let mut visited_ids = HashSet::::new(); - let mut bytes = get_type_hash(registry, extrinsic.ty.id(), &mut visited_ids); + let mut bytes = get_type_hash(registry, extrinsic.ty.id, &mut visited_ids); bytes = xor(bytes, hash(&[extrinsic.version])); for signed_extension in extrinsic.signed_extensions.iter() { let mut ext_bytes = hash(signed_extension.identifier.as_bytes()); ext_bytes = xor( ext_bytes, - get_type_hash(registry, signed_extension.ty.id(), &mut visited_ids), + get_type_hash(registry, signed_extension.ty.id, &mut visited_ids), ); ext_bytes = xor( ext_bytes, get_type_hash( registry, - signed_extension.additional_signed.id(), + signed_extension.additional_signed.id, &mut visited_ids, ), ); @@ -215,7 +215,7 @@ fn get_storage_entry_hash( match &entry.ty { StorageEntryType::Plain(ty) => { - bytes = xor(bytes, get_type_hash(registry, ty.id(), visited_ids)); + bytes = xor(bytes, get_type_hash(registry, ty.id, visited_ids)); } StorageEntryType::Map { hashers, @@ -226,8 +226,8 @@ fn get_storage_entry_hash( // Cloning the hasher should essentially be a copy. bytes = hash_hashes(bytes, [hasher.clone() as u8; 32]); } - bytes = xor(bytes, get_type_hash(registry, key.id(), visited_ids)); - bytes = xor(bytes, get_type_hash(registry, value.id(), visited_ids)); + bytes = xor(bytes, get_type_hash(registry, key.id, visited_ids)); + bytes = xor(bytes, get_type_hash(registry, value.id, visited_ids)); } } @@ -277,7 +277,7 @@ pub fn get_constant_hash( .ok_or(NotFound::Item)?; // We only need to check that the type of the constant asked for matches. - let bytes = get_type_hash(&metadata.types, constant.ty.id(), &mut HashSet::new()); + let bytes = get_type_hash(&metadata.types, constant.ty.id, &mut HashSet::new()); Ok(bytes) } @@ -293,18 +293,18 @@ pub fn get_call_hash( .find(|p| p.name == pallet_name) .ok_or(NotFound::Pallet)?; - let call_id = pallet.calls.as_ref().ok_or(NotFound::Item)?.ty.id(); + let call_id = pallet.calls.as_ref().ok_or(NotFound::Item)?.ty.id; let call_ty = metadata.types.resolve(call_id).ok_or(NotFound::Item)?; - let call_variants = match call_ty.type_def() { - TypeDef::Variant(variant) => variant.variants(), + let call_variants = match &call_ty.type_def { + TypeDef::Variant(variant) => &variant.variants, _ => return Err(NotFound::Item), }; let variant = call_variants .iter() - .find(|v| v.name() == call_name) + .find(|v| v.name == call_name) .ok_or(NotFound::Item)?; // hash the specific variant representing the call we are interested in. @@ -324,26 +324,26 @@ pub fn get_pallet_hash( if let Some(calls) = &pallet.calls { bytes = xor( bytes, - get_type_hash(registry, calls.ty.id(), &mut visited_ids), + get_type_hash(registry, calls.ty.id, &mut visited_ids), ); } if let Some(ref event) = pallet.event { bytes = xor( bytes, - get_type_hash(registry, event.ty.id(), &mut visited_ids), + get_type_hash(registry, event.ty.id, &mut visited_ids), ); } for constant in pallet.constants.iter() { bytes = xor(bytes, hash(constant.name.as_bytes())); bytes = xor( bytes, - get_type_hash(registry, constant.ty.id(), &mut visited_ids), + get_type_hash(registry, constant.ty.id, &mut visited_ids), ); } if let Some(ref error) = pallet.error { bytes = xor( bytes, - get_type_hash(registry, error.ty.id(), &mut visited_ids), + get_type_hash(registry, error.ty.id, &mut visited_ids), ); } if let Some(ref storage) = pallet.storage { @@ -387,7 +387,7 @@ pub fn get_metadata_hash(metadata: &RuntimeMetadataV14) -> [u8; 32] { let mut visited_ids = HashSet::::new(); bytes.extend(get_type_hash( &metadata.types, - metadata.ty.id(), + metadata.ty.id, &mut visited_ids, )); diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index 01f5edf575..59b5161ff8 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -17,40 +17,44 @@ fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut Ha for entry in &storage.entries { match entry.ty { StorageEntryType::Plain(ty) => { - type_ids.insert(ty.id()); + type_ids.insert(ty.id); } StorageEntryType::Map { key, value, .. } => { - type_ids.insert(key.id()); - type_ids.insert(value.id()); + type_ids.insert(key.id); + type_ids.insert(value.id); } } } } if let Some(calls) = &pallet.calls { - type_ids.insert(calls.ty.id()); + type_ids.insert(calls.ty.id); } if let Some(event) = &pallet.event { - type_ids.insert(event.ty.id()); + type_ids.insert(event.ty.id); } for constant in &pallet.constants { - type_ids.insert(constant.ty.id()); + type_ids.insert(constant.ty.id); } if let Some(error) = &pallet.error { - type_ids.insert(error.ty.id()); + type_ids.insert(error.ty.id); } } /// Remove the generic type parameters of the type ID from the `PortableRegistry` /// of the metadata. fn remove_generic_type_params(metadata: &mut RuntimeMetadataV14, id: u32) { - let portable_ty = metadata.types.types.get_mut(id as usize).expect(&format!( - "Metadata does not contain extrinsic type ID {} registered; qed", - id - )); + let portable_ty = metadata + .types + .types + .get_mut(id as usize) + .unwrap_or_else(|| { + panic!("Metadata does not contain extrinsic type ID {id} registered; qed") + }); + portable_ty.ty.type_params = Vec::new(); } @@ -63,11 +67,11 @@ fn collect_extrinsic_types( extrinsic: &ExtrinsicMetadata, type_ids: &mut HashSet, ) { - type_ids.insert(extrinsic.ty.id()); + type_ids.insert(extrinsic.ty.id); for signed in &extrinsic.signed_extensions { - type_ids.insert(signed.ty.id()); - type_ids.insert(signed.additional_signed.id()); + type_ids.insert(signed.ty.id); + type_ids.insert(signed.additional_signed.id); } } @@ -77,7 +81,7 @@ fn collect_extrinsic_types( /// /// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. fn update_type(ty: &mut UntrackedSymbol, map_ids: &BTreeMap) { - let old_id = ty.id(); + let old_id = ty.id; let new_id = map_ids .get(&old_id) .unwrap_or_else(|| panic!("PortableRegistry did not retain type id {old_id}. This is a bug. Please open an issue.")); @@ -165,18 +169,18 @@ where type_ids.insert(id); } - type_ids.insert(metadata.ty.id()); + type_ids.insert(metadata.ty.id); // Additionally, subxt depends on the `DispatchError`; we use the same // logic here that is used when building our `Metadata`. let dispatch_error_ty = metadata .types - .types() + .types .iter() - .find(|ty| ty.ty().path().segments() == ["sp_runtime", "DispatchError"]) + .find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"]) .expect("Metadata must contain sp_runtime::DispatchError"); - type_ids.insert(dispatch_error_ty.id()); + type_ids.insert(dispatch_error_ty.id); // Keep only the needed IDs in the portable registry. let map_ids = metadata.types.retain(|id| type_ids.contains(&id)); diff --git a/subxt/src/constants/constants_client.rs b/subxt/src/constants/constants_client.rs index 30ef5067b3..7ecef01b0d 100644 --- a/subxt/src/constants/constants_client.rs +++ b/subxt/src/constants/constants_client.rs @@ -68,7 +68,7 @@ impl> ConstantsClient { let constant = pallet.constant(address.constant_name())?; let value = ::decode_with_metadata( &mut &*constant.value, - constant.ty.id(), + constant.ty.id, &metadata, )?; Ok(value) diff --git a/subxt/src/events/events_type.rs b/subxt/src/events/events_type.rs index d14fad46f2..9b1d8171e4 100644 --- a/subxt/src/events/events_type.rs +++ b/subxt/src/events/events_type.rs @@ -239,7 +239,7 @@ impl EventDetails { // Skip over the bytes for this field: scale_decode::visitor::decode_with_visitor( input, - field_metadata.ty().id(), + field_metadata.ty.id, &metadata.runtime_metadata().types, scale_decode::visitor::IgnoreVisitor, ) diff --git a/subxt/src/metadata/metadata_type.rs b/subxt/src/metadata/metadata_type.rs index c73013483a..c43001e9cc 100644 --- a/subxt/src/metadata/metadata_type.rs +++ b/subxt/src/metadata/metadata_type.rs @@ -380,7 +380,7 @@ impl TryFrom for Metadata { .types .resolve(type_id) .ok_or(InvalidMetadataError::MissingType(type_id))?; - if let scale_info::TypeDef::Variant(var) = ty.type_def() { + if let scale_info::TypeDef::Variant(var) = &ty.type_def { Ok(var) } else { Err(InvalidMetadataError::TypeDefNotVariant(type_id)) @@ -390,20 +390,20 @@ impl TryFrom for Metadata { .pallets .iter() .map(|pallet| { - let call_ty_id = pallet.calls.as_ref().map(|c| c.ty.id()); - let event_ty_id = pallet.event.as_ref().map(|e| e.ty.id()); + let call_ty_id = pallet.calls.as_ref().map(|c| c.ty.id); + let event_ty_id = pallet.event.as_ref().map(|e| e.ty.id); let call_metadata = pallet.calls.as_ref().map_or(Ok(HashMap::new()), |call| { - let type_def_variant = get_type_def_variant(call.ty.id())?; + let type_def_variant = get_type_def_variant(call.ty.id)?; let call_indexes = type_def_variant - .variants() + .variants .iter() .map(|v| { ( - v.name().clone(), + v.name.clone(), CallMetadata { - call_index: v.index(), - fields: v.fields().to_vec(), + call_index: v.index, + fields: v.fields.clone(), }, ) }) @@ -443,16 +443,16 @@ impl TryFrom for Metadata { for pallet in &metadata.pallets { if let Some(event) = &pallet.event { let pallet_name: Arc = pallet.name.to_string().into(); - let event_type_id = event.ty.id(); + let event_type_id = event.ty.id; let event_variant = get_type_def_variant(event_type_id)?; - for variant in event_variant.variants() { + for variant in &event_variant.variants { events.insert( - (pallet.index, variant.index()), + (pallet.index, variant.index), EventMetadata { pallet: pallet_name.clone(), - event: variant.name().to_owned(), - fields: variant.fields().to_vec(), - docs: variant.docs().to_vec(), + event: variant.name.clone(), + fields: variant.fields.clone(), + docs: variant.docs.clone(), }, ); } @@ -463,14 +463,14 @@ impl TryFrom for Metadata { for pallet in &metadata.pallets { if let Some(error) = &pallet.error { let pallet_name: Arc = pallet.name.to_string().into(); - let error_variant = get_type_def_variant(error.ty.id())?; - for variant in error_variant.variants() { + let error_variant = get_type_def_variant(error.ty.id)?; + for variant in &error_variant.variants { errors.insert( - (pallet.index, variant.index()), + (pallet.index, variant.index), ErrorMetadata { pallet: pallet_name.clone(), - error: variant.name().clone(), - docs: variant.docs().to_vec(), + error: variant.name.clone(), + docs: variant.docs.clone(), }, ); } @@ -479,10 +479,10 @@ impl TryFrom for Metadata { let dispatch_error_ty = metadata .types - .types() + .types .iter() - .find(|ty| ty.ty().path().segments() == ["sp_runtime", "DispatchError"]) - .map(|ty| ty.id()); + .find(|ty| ty.ty().path.segments == ["sp_runtime", "DispatchError"]) + .map(|ty| ty.id); Ok(Metadata { inner: Arc::new(MetadataInner { diff --git a/subxt/src/storage/storage_address.rs b/subxt/src/storage/storage_address.rs index ffb1c41927..4f52311bea 100644 --- a/subxt/src/storage/storage_address.rs +++ b/subxt/src/storage/storage_address.rs @@ -154,16 +154,16 @@ where } StorageEntryType::Map { hashers, key, .. } => { let ty = metadata - .resolve_type(key.id()) - .ok_or_else(|| StorageAddressError::TypeNotFound(key.id()))?; + .resolve_type(key.id) + .ok_or(StorageAddressError::TypeNotFound(key.id))?; // If the key is a tuple, we encode each value to the corresponding tuple type. // If the key is not a tuple, encode a single value to the key type. - let type_ids = match ty.type_def() { + let type_ids = match &ty.type_def { TypeDef::Tuple(tuple) => { - either::Either::Left(tuple.fields().iter().map(|f| f.id())) + either::Either::Left(tuple.fields.iter().map(|f| f.id)) } - _other => either::Either::Right(std::iter::once(key.id())), + _other => either::Either::Right(std::iter::once(key.id)), }; if type_ids.len() != self.storage_entry_keys.len() { diff --git a/subxt/src/storage/storage_type.rs b/subxt/src/storage/storage_type.rs index 108a95e730..8652b1b416 100644 --- a/subxt/src/storage/storage_type.rs +++ b/subxt/src/storage/storage_type.rs @@ -352,8 +352,8 @@ fn lookup_storage_return_type( /// Fetch the return type out of a [`StorageEntryType`]. fn return_type_from_storage_entry_type(entry: &StorageEntryType) -> u32 { match entry { - StorageEntryType::Plain(ty) => ty.id(), - StorageEntryType::Map { value, .. } => value.id(), + StorageEntryType::Plain(ty) => ty.id, + StorageEntryType::Map { value, .. } => value.id, } } @@ -367,8 +367,8 @@ fn decode_storage_with_metadata( let ty = &metadata.pallet(pallet_name)?.storage(storage_entry)?.ty; let id = match ty { - StorageEntryType::Plain(ty) => ty.id(), - StorageEntryType::Map { value, .. } => value.id(), + StorageEntryType::Plain(ty) => ty.id, + StorageEntryType::Map { value, .. } => value.id, }; let val = T::decode_with_metadata(bytes, id, metadata)?; diff --git a/subxt/src/utils/wrapper_opaque.rs b/subxt/src/utils/wrapper_opaque.rs index 7a1efa1cde..31ddd4dc7d 100644 --- a/subxt/src/utils/wrapper_opaque.rs +++ b/subxt/src/utils/wrapper_opaque.rs @@ -87,7 +87,7 @@ impl EncodeAsType for WrapperKeepOpaque { }; // Do a basic check that the target shape lines up. - let scale_info::TypeDef::Composite(_) = ty.type_def() else { + let scale_info::TypeDef::Composite(_) = &ty.type_def else { return Err(Error::new(ErrorKind::WrongShape { actual: Kind::Struct, expected: type_id, @@ -95,7 +95,7 @@ impl EncodeAsType for WrapperKeepOpaque { }; // Check that the name also lines up. - if ty.path().ident().as_deref() != Some("WrapperKeepOpaque") { + if ty.path.ident().as_deref() != Some("WrapperKeepOpaque") { return Err(Error::new(ErrorKind::WrongShape { actual: Kind::Struct, expected: type_id, @@ -188,7 +188,7 @@ mod test { let mut types = scale_info::Registry::new(); let id = types.register_type(&m); let portable_registry: scale_info::PortableRegistry = types.into(); - (id.id(), portable_registry) + (id.id, portable_registry) } fn roundtrips_like_scale_codec(t: T) From 2dee1767e75ef666c663f57a68c0de2d46f337e8 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 29 Mar 2023 23:08:37 +0300 Subject: [PATCH 22/29] Update scaleinfo to v2.5.0 Signed-off-by: Alexandru Vasile --- Cargo.lock | 8 ++++---- codegen/Cargo.toml | 4 ++-- metadata/Cargo.toml | 4 ++-- subxt/Cargo.toml | 4 ++-- testing/integration-tests/Cargo.toml | 2 +- testing/ui-tests/Cargo.toml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dea7bf306..696f73e0a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2623,9 +2623,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61471dff9096de1d8b2319efed7162081e96793f5ebb147e50db10d50d648a4d" +checksum = "0cfdffd972d76b22f3d7f81c8be34b2296afd3a25e0a547bd9abe340a4dbbe97" dependencies = [ "bitvec", "cfg-if", @@ -2637,9 +2637,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219580e803a66b3f05761fd06f1f879a872444e49ce23f73694d26e5a954c7e6" +checksum = "61fa974aea2d63dd18a4ec3a49d59af9f34178c73a4f56d2f18205628d00681e" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index ebac9f008c..1fd3de54d9 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -20,7 +20,7 @@ heck = "0.4.1" proc-macro2 = "1.0.54" quote = "1.0.8" syn = "1.0.109" -scale-info = "2.4.0" +scale-info = "2.5.0" subxt-metadata = { version = "0.27.1", path = "../metadata" } jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport", "http-client"] } hex = "0.4.3" @@ -29,5 +29,5 @@ thiserror = "1.0.40" [dev-dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } -scale-info = { version = "2.4.0", features = ["bit-vec"] } +scale-info = { version = "2.5.0", features = ["bit-vec"] } pretty_assertions = "1.0.0" diff --git a/metadata/Cargo.toml b/metadata/Cargo.toml index 583356345f..0ef5b94a37 100644 --- a/metadata/Cargo.toml +++ b/metadata/Cargo.toml @@ -16,13 +16,13 @@ description = "Command line utilities for checking metadata compatibility betwee [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } frame-metadata = "15.0.0" -scale-info = "2.4.0" +scale-info = "2.5.0" sp-core-hashing = "7.0.0" [dev-dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } criterion = "0.4" -scale-info = { version = "2.4.0", features = ["bit-vec"] } +scale-info = { version = "2.5.0", features = ["bit-vec"] } [lib] # Without this, libtest cli opts interfere with criteron benches: diff --git a/subxt/Cargo.toml b/subxt/Cargo.toml index c6911b7780..b77e4ab9b9 100644 --- a/subxt/Cargo.toml +++ b/subxt/Cargo.toml @@ -36,7 +36,7 @@ jsonrpsee-web = ["jsonrpsee/async-wasm-client", "jsonrpsee/client-web-transport" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } -scale-info = "2.4.0" +scale-info = "2.5.0" scale-value = "0.7.0" scale-bits = "0.3" scale-decode = "0.5.0" @@ -75,7 +75,7 @@ getrandom = { version = "0.2", features = ["js"] } [dev-dependencies] bitvec = "1" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full", "bit-vec"] } -scale-info = { version = "2.4.0", features = ["bit-vec"] } +scale-info = { version = "2.5.0", features = ["bit-vec"] } tokio = { version = "1.26", features = ["macros", "time", "rt-multi-thread"] } sp-core = { version = "18.0.0", default-features = false } sp-runtime = "20.0.0" diff --git a/testing/integration-tests/Cargo.toml b/testing/integration-tests/Cargo.toml index f4f14b72b6..0e25ab272c 100644 --- a/testing/integration-tests/Cargo.toml +++ b/testing/integration-tests/Cargo.toml @@ -22,7 +22,7 @@ frame-metadata = "15.0.0" futures = "0.3.27" hex = "0.4.3" regex = "1.7.3" -scale-info = { version = "2.4.0", features = ["bit-vec"] } +scale-info = { version = "2.5.0", features = ["bit-vec"] } sp-core = { version = "18.0.0", default-features = false } sp-runtime = "20.0.0" sp-keyring = "20.0.0" diff --git a/testing/ui-tests/Cargo.toml b/testing/ui-tests/Cargo.toml index 1fd5675a0e..21ca7e3cff 100644 --- a/testing/ui-tests/Cargo.toml +++ b/testing/ui-tests/Cargo.toml @@ -10,7 +10,7 @@ publish = false [dev-dependencies] trybuild = "1.0.79" -scale-info = { version = "2.4.0", features = ["bit-vec"] } +scale-info = { version = "2.5.0", features = ["bit-vec"] } frame-metadata = "15.0.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full", "bit-vec"] } subxt = { path = "../../subxt" } From 13cbbd667f8e6c4cf0cd7a2e2ad768155e5efd0e Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 29 Mar 2023 23:10:25 +0300 Subject: [PATCH 23/29] Remove deprecated fn Signed-off-by: Alexandru Vasile --- codegen/src/types/mod.rs | 4 ++-- subxt/src/metadata/metadata_type.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index cfd7b2b58e..14644add19 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -74,7 +74,7 @@ impl<'a> TypeGenerator<'a> { let mut root_mod = Module::new(root_mod_ident.clone(), root_mod_ident.clone()); for ty in &self.type_registry.types { - let path = &ty.ty().path; + let path = &ty.ty.path; // Don't generate a type if it was substituted - the target type might // not be in the type registry + our resolution already performs the substitution. if self.type_substitutes.for_path(path).is_some() { @@ -100,7 +100,7 @@ impl<'a> TypeGenerator<'a> { innermost_module.types.insert( path.clone(), - TypeDefGen::from_type(ty.ty(), self, &self.crate_path, self.should_gen_docs)?, + TypeDefGen::from_type(&ty.ty, self, &self.crate_path, self.should_gen_docs)?, ); } diff --git a/subxt/src/metadata/metadata_type.rs b/subxt/src/metadata/metadata_type.rs index c43001e9cc..d97c2dd159 100644 --- a/subxt/src/metadata/metadata_type.rs +++ b/subxt/src/metadata/metadata_type.rs @@ -481,7 +481,7 @@ impl TryFrom for Metadata { .types .types .iter() - .find(|ty| ty.ty().path.segments == ["sp_runtime", "DispatchError"]) + .find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"]) .map(|ty| ty.id); Ok(Metadata { From 115fbfba57a93af7319a44a6125327c1d99052c7 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 29 Mar 2023 23:26:06 +0300 Subject: [PATCH 24/29] testing: Fix clippy Signed-off-by: Alexandru Vasile --- .../integration-tests/src/codegen/codegen_documentation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/integration-tests/src/codegen/codegen_documentation.rs b/testing/integration-tests/src/codegen/codegen_documentation.rs index 0fb20a55a7..edebff9ce6 100644 --- a/testing/integration-tests/src/codegen/codegen_documentation.rs +++ b/testing/integration-tests/src/codegen/codegen_documentation.rs @@ -20,8 +20,8 @@ fn metadata_docs() -> Vec { // Inspect the metadata types and collect the documentation. let mut docs = Vec::new(); - for ty in metadata.types.types() { - docs.extend_from_slice(ty.ty().docs()); + for ty in &metadata.types.types { + docs.extend_from_slice(ty.ty.docs.as_slice()); } for pallet in metadata.pallets { From 6284f4a1bf8051a16a07d2c17653f8dae711a97e Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 30 Mar 2023 01:02:01 +0300 Subject: [PATCH 25/29] benches: Use inner fields of scale info Signed-off-by: Alexandru Vasile --- metadata/benches/bench.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/metadata/benches/bench.rs b/metadata/benches/bench.rs index 6627e2c41f..c7fd9e5fda 100644 --- a/metadata/benches/bench.rs +++ b/metadata/benches/bench.rs @@ -57,14 +57,14 @@ fn bench_get_call_hash(c: &mut Criterion) { for pallet in metadata.pallets.iter() { let pallet_name = &pallet.name; let call_type_id = match &pallet.calls { - Some(calls) => calls.ty.id(), + Some(calls) => calls.ty.id, None => continue, }; let call_type = metadata.types.resolve(call_type_id).unwrap(); - let variants = expect_variant(call_type.type_def()); + let variants = expect_variant(&call_type.type_def); - for variant in variants.variants() { - let call_name = variant.name(); + for variant in &variants.variants { + let call_name = variant.name.as_str(); let bench_name = format!("{pallet_name}/{call_name}"); group.bench_function(&bench_name, |b| { b.iter(|| get_call_hash(&metadata, &pallet.name, call_name)) From 72e828dddf598cf33107d1b8ae7eec958d385636 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 4 Apr 2023 12:35:20 +0100 Subject: [PATCH 26/29] address nits, and strip RuntimeCall type instead of trying to filter out use of it for better overall wins/clarity --- cli/src/commands/metadata.rs | 4 +- cli/src/commands/utils.rs | 42 ++++++----- metadata/src/retain.rs | 139 +++++++++++++++++++---------------- 3 files changed, 103 insertions(+), 82 deletions(-) diff --git a/cli/src/commands/metadata.rs b/cli/src/commands/metadata.rs index 7c90c595aa..fc73dbd0ae 100644 --- a/cli/src/commands/metadata.rs +++ b/cli/src/commands/metadata.rs @@ -40,7 +40,9 @@ pub async fn run(opts: Opts) -> color_eyre::Result<()> { } }; - retain_metadata_pallets(metadata_v14, |pallet| pallets.contains(&pallet.name)); + retain_metadata_pallets(metadata_v14, |pallet_name| { + pallets.iter().find(|p| &**p == pallet_name).is_some() + }); } match opts.format.as_str() { diff --git a/cli/src/commands/utils.rs b/cli/src/commands/utils.rs index 89b1b28a43..d52cb41092 100644 --- a/cli/src/commands/utils.rs +++ b/cli/src/commands/utils.rs @@ -3,41 +3,45 @@ // see LICENSE for license details. use clap::Args; -use std::{fs, io::Read, path::PathBuf}; - use color_eyre::eyre; +use std::{fs, io::Read, path::PathBuf}; use subxt_codegen::utils::Uri; /// The source of the metadata. #[derive(Debug, Args)] pub struct FileOrUrl { /// The url of the substrate node to query for metadata for codegen. - #[clap(name = "url", long, value_parser)] + #[clap(long, value_parser)] url: Option, /// The path to the encoded metadata file. - #[clap(short, long, value_parser)] + #[clap(long, value_parser)] file: Option, } impl FileOrUrl { /// Fetch the metadata bytes. pub async fn fetch(&self) -> color_eyre::Result> { - if let Some(path) = &self.file { - if self.url.is_some() { + match (&self.file, &self.url) { + // Can't provide both --file and --url + (Some(_), Some(_)) => { eyre::bail!("specify one of `--url` or `--file` but not both") - }; - - let mut file = fs::File::open(path)?; - let mut bytes = Vec::new(); - file.read_to_end(&mut bytes)?; - return Ok(bytes); + } + // Load from --file path + (Some(path), None) => { + let mut file = fs::File::open(path)?; + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes)?; + Ok(bytes) + } + // Fetch from --url + (None, Some(uri)) => Ok(subxt_codegen::utils::fetch_metadata_bytes(&uri).await?), + // Default if neither is provided; fetch from local url + (None, None) => { + let uri = "http://localhost:9933" + .parse() + .expect("default url is valid"); + Ok(subxt_codegen::utils::fetch_metadata_bytes(&uri).await?) + } } - - let url = self.url.clone().unwrap_or_else(|| { - "http://localhost:9933" - .parse::() - .expect("default url is valid") - }); - Ok(subxt_codegen::utils::fetch_metadata_bytes(&url).await?) } } diff --git a/metadata/src/retain.rs b/metadata/src/retain.rs index 59b5161ff8..67cd06a05b 100644 --- a/metadata/src/retain.rs +++ b/metadata/src/retain.rs @@ -5,7 +5,7 @@ //! Utility functions to generate a subset of the metadata. use frame_metadata::{ExtrinsicMetadata, PalletMetadata, RuntimeMetadataV14, StorageEntryType}; -use scale_info::{form::PortableForm, interner::UntrackedSymbol}; +use scale_info::{form::PortableForm, interner::UntrackedSymbol, TypeDef}; use std::{ any::TypeId, collections::{BTreeMap, HashSet}, @@ -44,50 +44,6 @@ fn collect_pallet_types(pallet: &PalletMetadata, type_ids: &mut Ha } } -/// Remove the generic type parameters of the type ID from the `PortableRegistry` -/// of the metadata. -fn remove_generic_type_params(metadata: &mut RuntimeMetadataV14, id: u32) { - let portable_ty = metadata - .types - .types - .get_mut(id as usize) - .unwrap_or_else(|| { - panic!("Metadata does not contain extrinsic type ID {id} registered; qed") - }); - - portable_ty.ty.type_params = Vec::new(); -} - -/// Collect all type IDs needed to represent the extrinsic metadata. -/// -/// Ensure that the extrinsic types from the `PortableRegistry` are trimmed -/// of the generic type parameters. Those are not needed and contain extra -/// nested type IDs that increase unnecessarily the size of the generated metadata. -fn collect_extrinsic_types( - extrinsic: &ExtrinsicMetadata, - type_ids: &mut HashSet, -) { - type_ids.insert(extrinsic.ty.id); - - for signed in &extrinsic.signed_extensions { - type_ids.insert(signed.ty.id); - type_ids.insert(signed.additional_signed.id); - } -} - -/// Update the given type using the new type ID from the portable registry. -/// -/// # Panics -/// -/// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. -fn update_type(ty: &mut UntrackedSymbol, map_ids: &BTreeMap) { - let old_id = ty.id; - let new_id = map_ids - .get(&old_id) - .unwrap_or_else(|| panic!("PortableRegistry did not retain type id {old_id}. This is a bug. Please open an issue.")); - *ty = (*new_id).into(); -} - /// Update all type IDs of the provided pallet using the new type IDs from the portable registry. fn update_pallet_types(pallet: &mut PalletMetadata, map_ids: &BTreeMap) { if let Some(storage) = &mut pallet.storage { @@ -121,6 +77,19 @@ fn update_pallet_types(pallet: &mut PalletMetadata, map_ids: &BTre } } +/// Collect all type IDs needed to represent the extrinsic metadata. +fn collect_extrinsic_types( + extrinsic: &ExtrinsicMetadata, + type_ids: &mut HashSet, +) { + type_ids.insert(extrinsic.ty.id); + + for signed in &extrinsic.signed_extensions { + type_ids.insert(signed.ty.id); + type_ids.insert(signed.additional_signed.id); + } +} + /// Update all type IDs of the provided extrinsic metadata using the new type IDs from the portable registry. fn update_extrinsic_types( extrinsic: &mut ExtrinsicMetadata, @@ -134,6 +103,52 @@ fn update_extrinsic_types( } } +/// Update the given type using the new type ID from the portable registry. +/// +/// # Panics +/// +/// Panics if the [`scale_info::PortableRegistry`] did not retain all needed types. +fn update_type(ty: &mut UntrackedSymbol, map_ids: &BTreeMap) { + let old_id = ty.id; + let new_id = map_ids + .get(&old_id) + .copied() + .unwrap_or_else(|| panic!("PortableRegistry did not retain type id {old_id}. This is a bug. Please open an issue.")); + *ty = new_id.into(); +} + +/// Strip any pallets out of the RuntimeCall type that aren't the ones we want to keep. +/// The RuntimeCall type is referenced in a bunch of places, so doing this prevents us from +/// holding on to stuff in pallets we've asked not to keep. +fn retain_pallets_in_runtime_call_type(metadata: &mut RuntimeMetadataV14, mut filter: F) +where + F: FnMut(&str) -> bool, +{ + let extrinsic_ty = metadata + .types + .types + .get_mut(metadata.extrinsic.ty.id as usize) + .expect("Metadata should contain extrinsic type in registry"); + + let Some(call_ty) = extrinsic_ty.ty.type_params + .iter_mut() + .find(|ty| ty.name == "Call") + .and_then(|ty| ty.ty) else { return }; + + let call_ty = metadata + .types + .types + .get_mut(call_ty.id as usize) + .expect("Metadata should contain Call type information"); + + let TypeDef::Variant(variant) = &mut call_ty.ty.type_def else { + panic!("Metadata Call type is expected to be a variant type"); + }; + + // Remove all variants from the call type that aren't the pallet(s) we want to keep. + variant.variants.retain(|v| filter(&v.name)); +} + /// Generate a subset of the metadata that contains only the /// types needed to represent the provided pallets. /// @@ -148,13 +163,19 @@ fn update_extrinsic_types( /// or the metadata does not contain the "sp_runtime::DispatchError" type. pub fn retain_metadata_pallets(metadata: &mut RuntimeMetadataV14, mut filter: F) where - F: FnMut(&PalletMetadata) -> bool, + F: FnMut(&str) -> bool, { let mut type_ids = HashSet::new(); - // Collect all types needed to represent the provided pallets. + // There is a special RuntimeCall type which points to all pallets and call types by default. + // This brings in a significant chunk of types. We trim this down to only include variants + // for the pallets we're retaining, to avoid this. + retain_pallets_in_runtime_call_type(metadata, &mut filter); + + // Filter our pallet list to only those pallets we want to keep. Keep hold of all + //type IDs in the pallets we're keeping. metadata.pallets.retain(|pallet| { - if filter(pallet) { + if filter(&pallet.name) { collect_pallet_types(pallet, &mut type_ids); true } else { @@ -162,16 +183,13 @@ where } }); - let mut extrinsic_types = HashSet::new(); - collect_extrinsic_types(&metadata.extrinsic, &mut extrinsic_types); - for id in extrinsic_types { - remove_generic_type_params(metadata, id); - type_ids.insert(id); - } + // Keep the extrinsic stuff referenced in our metadata. + collect_extrinsic_types(&metadata.extrinsic, &mut type_ids); + // Keep the "runtime" type ID, since it's referenced in our metadata. type_ids.insert(metadata.ty.id); - // Additionally, subxt depends on the `DispatchError`; we use the same + // Additionally, subxt depends on the `DispatchError` type existing; we use the same // logic here that is used when building our `Metadata`. let dispatch_error_ty = metadata .types @@ -179,17 +197,16 @@ where .iter() .find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"]) .expect("Metadata must contain sp_runtime::DispatchError"); - type_ids.insert(dispatch_error_ty.id); - // Keep only the needed IDs in the portable registry. + // Now, keep the type IDs we've asked for. This recursively keeps any types referenced from these. + // This will return a map from old to new type ID, because IDs may change. let map_ids = metadata.types.retain(|id| type_ids.contains(&id)); - // Update the metadata types to their new IDs in the registry. + // And finally, we can go and update all of our type IDs in the metadata as a result of this: for pallets in &mut metadata.pallets { update_pallet_types(pallets, &map_ids); } - update_extrinsic_types(&mut metadata.extrinsic, &map_ids); update_type(&mut metadata.ty, &map_ids); } @@ -220,9 +237,7 @@ mod tests { // Retain one pallet at a time ensuring the test does not panic. for pallet in &metadata_cache.pallets { let mut metadata = metadata_cache.clone(); - retain_metadata_pallets(&mut metadata, |filter_pallet| { - filter_pallet.name == pallet.name - }); + retain_metadata_pallets(&mut metadata, |pallet_name| pallet_name == pallet.name); assert_eq!(metadata.pallets.len(), 1); assert_eq!(metadata.pallets.get(0).unwrap().name, pallet.name); From 17d1976ef370620618da3394fe3fce15013bed30 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 4 Apr 2023 12:40:57 +0100 Subject: [PATCH 27/29] fix UI test --- testing/ui-tests/src/utils/pallet_metadata_test_runner.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs index af69c87c3b..a27450c9f5 100644 --- a/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs +++ b/testing/ui-tests/src/utils/pallet_metadata_test_runner.rs @@ -47,9 +47,7 @@ impl PalletMetadataTestRunner { // Build custom metadata containing only this pallet. let mut metadata = self.metadata.clone(); - retain_metadata_pallets(&mut metadata, |pallet_filter| { - pallet_filter.name == pallet.name - }); + retain_metadata_pallets(&mut metadata, |pallet_filter| pallet_filter == pallet.name); let mut tmp_dir = std::env::temp_dir(); tmp_dir.push(format!("{TEST_DIR_PREFIX}{index}")); From e6e3016ca34c11095ce6912d3cc80991270143d6 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 4 Apr 2023 12:47:13 +0100 Subject: [PATCH 28/29] move utils out of commands folder and fix clippy etc --- cli/src/commands/codegen.rs | 3 +-- cli/src/commands/metadata.rs | 5 ++--- cli/src/commands/mod.rs | 1 - cli/src/main.rs | 1 + cli/src/{commands => }/utils.rs | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) rename cli/src/{commands => }/utils.rs (98%) diff --git a/cli/src/commands/codegen.rs b/cli/src/commands/codegen.rs index 3b3864dc33..a835d50bd8 100644 --- a/cli/src/commands/codegen.rs +++ b/cli/src/commands/codegen.rs @@ -2,12 +2,11 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +use crate::utils::FileOrUrl; use clap::Parser as ClapParser; use color_eyre::eyre; use subxt_codegen::{DerivesRegistry, TypeSubstitutes, TypeSubstitutionError}; -use super::utils::FileOrUrl; - /// Generate runtime API client code from metadata. /// /// # Example (with code formatting) diff --git a/cli/src/commands/metadata.rs b/cli/src/commands/metadata.rs index fc73dbd0ae..f8d3aec83a 100644 --- a/cli/src/commands/metadata.rs +++ b/cli/src/commands/metadata.rs @@ -2,6 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +use crate::utils::FileOrUrl; use clap::Parser as ClapParser; use color_eyre::eyre; use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; @@ -9,8 +10,6 @@ use scale::{Decode, Encode}; use std::io::{self, Write}; use subxt_metadata::retain_metadata_pallets; -use super::utils::FileOrUrl; - /// Download metadata from a substrate node, for use with `subxt` codegen. #[derive(Debug, ClapParser)] pub struct Opts { @@ -41,7 +40,7 @@ pub async fn run(opts: Opts) -> color_eyre::Result<()> { }; retain_metadata_pallets(metadata_v14, |pallet_name| { - pallets.iter().find(|p| &**p == pallet_name).is_some() + pallets.iter().any(|p| &**p == pallet_name) }); } diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs index 3147482471..15660ac122 100644 --- a/cli/src/commands/mod.rs +++ b/cli/src/commands/mod.rs @@ -5,5 +5,4 @@ pub mod codegen; pub mod compatibility; pub mod metadata; -mod utils; pub mod version; diff --git a/cli/src/main.rs b/cli/src/main.rs index 54b2247fea..4ad786f7b8 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -5,6 +5,7 @@ #![deny(unused_crate_dependencies)] mod commands; +mod utils; use clap::Parser as ClapParser; /// Subxt utilities for interacting with Substrate based nodes. diff --git a/cli/src/commands/utils.rs b/cli/src/utils.rs similarity index 98% rename from cli/src/commands/utils.rs rename to cli/src/utils.rs index d52cb41092..bb039945f6 100644 --- a/cli/src/commands/utils.rs +++ b/cli/src/utils.rs @@ -34,7 +34,7 @@ impl FileOrUrl { Ok(bytes) } // Fetch from --url - (None, Some(uri)) => Ok(subxt_codegen::utils::fetch_metadata_bytes(&uri).await?), + (None, Some(uri)) => Ok(subxt_codegen::utils::fetch_metadata_bytes(uri).await?), // Default if neither is provided; fetch from local url (None, None) => { let uri = "http://localhost:9933" From 98e3684b5951eab679f6a77545ce7f7b8ead431b Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 4 Apr 2023 14:44:05 +0100 Subject: [PATCH 29/29] address nits --- cli/src/utils.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cli/src/utils.rs b/cli/src/utils.rs index bb039945f6..c5af8c9cd8 100644 --- a/cli/src/utils.rs +++ b/cli/src/utils.rs @@ -37,9 +37,7 @@ impl FileOrUrl { (None, Some(uri)) => Ok(subxt_codegen::utils::fetch_metadata_bytes(uri).await?), // Default if neither is provided; fetch from local url (None, None) => { - let uri = "http://localhost:9933" - .parse() - .expect("default url is valid"); + let uri = Uri::from_static("http://localhost:9933"); Ok(subxt_codegen::utils::fetch_metadata_bytes(&uri).await?) } }