Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Use scale-encode and scale-decode to encode and decode based on metadata #842

Merged
merged 42 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
4b0b734
WIP EncodeAsType and DecodeAsType
jsdw Feb 13, 2023
8b5c0d8
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Feb 13, 2023
74628ec
remove silly cli experiment code
jsdw Feb 14, 2023
0c90a80
Get things finally compiling with EncodeAsType and DecodeAsType
jsdw Feb 14, 2023
ee69471
update codegen test and WrapperKeepOpaque proper impl (in case it sho…
jsdw Feb 14, 2023
9e3ca60
fix tests
jsdw Feb 15, 2023
a116517
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Feb 21, 2023
f3dab46
accomodate scale-value changes
jsdw Feb 21, 2023
7ccfe92
starting to migrate to EncodeAsType/DecodeAsType
jsdw Feb 23, 2023
083d271
static event decoding and tx encoding to use DecodeAsFields/EncodeAsF…
jsdw Feb 24, 2023
550a314
some tidy up and add decode(skip) attrs where needed
jsdw Feb 27, 2023
3258e83
fix root event decoding
jsdw Feb 28, 2023
4bbec39
#[codec(skip)] will do, and combine map_key stuff into storage_addres…
jsdw Feb 28, 2023
4767097
fmt and clippy
jsdw Feb 28, 2023
7087c35
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Feb 28, 2023
1d4f3ee
update Cargo.lock
jsdw Feb 28, 2023
ee88037
remove patched scale-encode
jsdw Feb 28, 2023
6f70c29
bump scale-encode to 0.1 and remove unused dep in testing crate
jsdw Feb 28, 2023
e5b538c
update deps and use released scale-decode
jsdw Mar 13, 2023
4260492
update scale-value to latest to remove git branch
jsdw Mar 13, 2023
fbd5443
Apply suggestions from code review
jsdw Mar 13, 2023
7c0168f
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 13, 2023
d9849b3
Merge branch 'jsdw-scale-encode-decode' of github.com:paritytech/subx…
jsdw Mar 13, 2023
891800b
remove sorting in derives/attr generation; spit them out in order given
jsdw Mar 15, 2023
f5d0c58
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 15, 2023
53f2687
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 15, 2023
a252b67
re-add derive sorting; it's a hashmap
jsdw Mar 16, 2023
b38ae8e
StaticTxPayload and DynamicTxPayload rolled into single Payload struct
jsdw Mar 15, 2023
0131eda
StaticStorageAddress and DynamicStorageAddress into single Address st…
jsdw Mar 16, 2023
9b8f846
Fix storage address byte retrieval
jsdw Mar 17, 2023
6c25474
StaticConstantAddress and DynamicConstantAddress => Address
jsdw Mar 17, 2023
1b1ab02
Simplify storage codegen to fix test
jsdw Mar 17, 2023
756cad2
Add comments
jsdw Mar 17, 2023
c377ff7
Alias to RuntimeEvent rather than making another, and prep for substi…
jsdw Mar 17, 2023
02e4b93
remove unnecessary clone
jsdw Mar 17, 2023
7e4ea8d
Fix docs and failing UI test
jsdw Mar 18, 2023
902ec2a
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 20, 2023
bf6a01c
root_bytes -> to_root_bytes
jsdw Mar 20, 2023
e94c0b7
document error case in StorageClient::address_bytes()
jsdw Mar 21, 2023
c92d3aa
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 21, 2023
f78f27a
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 21, 2023
5c62777
Merge branch 'master' into jsdw-scale-encode-decode
jsdw Mar 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 134 additions & 137 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion codegen/src/api/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub fn generate_constants(

Ok(quote! {
#docs
pub fn #fn_name(&self) -> #crate_path::constants::StaticConstantAddress<#crate_path::metadata::DecodeStaticType<#return_ty>> {
pub fn #fn_name(&self) -> #crate_path::constants::StaticConstantAddress<#return_ty> {
#crate_path::constants::StaticConstantAddress::new(
#pallet_name,
#constant_name,
Expand Down
44 changes: 36 additions & 8 deletions codegen/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,24 +338,52 @@ impl RuntimeGenerator {
})
.collect::<Result<Vec<_>, 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 outer_event_variants_and_match_arms = self.metadata.pallets.iter().filter_map(|p| {
let variant_name_str = &p.name;
let variant_name = format_ident!("{}", variant_name_str);
let mod_name = format_ident!("{}", variant_name_str.to_string().to_snake_case());
let index = proc_macro2::Literal::u8_unsuffixed(p.index);

p.event.as_ref().map(|_| {
quote! {
// The variant name to go into the event enum:
let outer_event_variant = quote! {
#[codec(index = #index)]
#variant_name(#mod_name::Event),
}
};

// An 'if' arm for the RootEvent impl to match this variant name:
let outer_event_match_arm = quote! {
if pallet_name == #variant_name_str {
ascjones marked this conversation as resolved.
Show resolved Hide resolved
return Ok(Event::#variant_name(#mod_name::Event::decode_with_metadata(
&mut &*pallet_bytes,
pallet_ty,
metadata
)?));
}
};

(outer_event_variant, outer_event_match_arm)
})
});
}).collect::<Vec<_>>();

let outer_event_variants =
outer_event_variants_and_match_arms.iter().map(|v| &v.0);
let outer_event_match_arms =
outer_event_variants_and_match_arms.iter().map(|v| &v.1);

let outer_event = quote! {
#default_derives
pub enum Event {
#( #outer_event_variants )*
}

impl #crate_path::events::RootEvent for Event {
fn root_event(pallet_bytes: &[u8], pallet_name: &str, pallet_ty: u32, metadata: &#crate_path::Metadata) -> Result<Self, #crate_path::Error> {
use #crate_path::metadata::DecodeWithMetadata;
#( #outer_event_match_arms )*
Err(#crate_path::ext::scale_decode::Error::custom(format!("Pallet name '{}' not found in root Event enum", pallet_name)).into())
}
}
};

let mod_ident = &item_mod_ir.ident;
Expand Down Expand Up @@ -443,10 +471,10 @@ impl RuntimeGenerator {
}

/// check whether the Client you are using is aligned with the statically generated codegen.
pub fn validate_codegen<T: ::subxt::Config, C: ::subxt::client::OfflineClientT<T>>(client: &C) -> Result<(), ::subxt::error::MetadataError> {
pub fn validate_codegen<T: #crate_path::Config, C: #crate_path::client::OfflineClientT<T>>(client: &C) -> Result<(), #crate_path::error::MetadataError> {
let runtime_metadata_hash = client.metadata().metadata_hash(&PALLETS);
if runtime_metadata_hash != [ #(#metadata_hash,)* ] {
Err(::subxt::error::MetadataError::IncompatibleMetadata)
Err(#crate_path::error::MetadataError::IncompatibleMetadata)
} else {
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions codegen/src/api/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ fn generate_storage_entry_fns(
#docs
pub fn #fn_name_root(
&self,
) -> #crate_path::storage::address::StaticStorageAddress::<#crate_path::metadata::DecodeStaticType<#storage_entry_value_ty>, (), #is_defaultable_type, #is_iterable_type> {
) -> #crate_path::storage::address::StaticStorageAddress::<#storage_entry_value_ty, (), #is_defaultable_type, #is_iterable_type> {
#crate_path::storage::address::StaticStorageAddress::new(
#pallet_name,
#storage_name,
Expand All @@ -252,7 +252,7 @@ fn generate_storage_entry_fns(
pub fn #fn_name(
&self,
#( #key_args, )*
) -> #crate_path::storage::address::StaticStorageAddress::<#crate_path::metadata::DecodeStaticType<#storage_entry_value_ty>, #crate_path::storage::address::Yes, #is_defaultable_type, #is_iterable_type> {
) -> #crate_path::storage::address::StaticStorageAddress::<#storage_entry_value_ty, #crate_path::storage::address::Yes, #is_defaultable_type, #is_iterable_type> {
#crate_path::storage::address::StaticStorageAddress::new(
#pallet_name,
#storage_name,
Expand Down
69 changes: 56 additions & 13 deletions codegen/src/types/derives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use crate::CratePath;
use syn::{
parse_quote,
punctuated::Punctuated,
Path,
};

Expand All @@ -21,7 +20,7 @@ pub struct DerivesRegistry {
}

impl DerivesRegistry {
/// Creates a new `DeviceRegistry` with the supplied `crate_path`.
/// Creates a new `DerivesRegistry` with the supplied `crate_path`.
///
/// The `crate_path` denotes the `subxt` crate access path in the
/// generated code.
Expand Down Expand Up @@ -61,23 +60,27 @@ impl DerivesRegistry {
/// - Any user-defined derives for all types via `generated_type_derives`
/// - Any user-defined derives for this specific type
pub fn resolve(&self, ty: &syn::TypePath) -> Derives {
let mut defaults = self.default_derives.derives.clone();
let mut resolved_derives = self.default_derives.clone();
if let Some(specific) = self.specific_type_derives.get(ty) {
defaults.extend(specific.derives.iter().cloned());
resolved_derives.extend_from(specific.clone());
}
Derives { derives: defaults }
resolved_derives
}
}

#[derive(Debug, Clone)]
pub struct Derives {
derives: HashSet<syn::Path>,
attributes: HashSet<syn::Attribute>,
}

impl FromIterator<syn::Path> for Derives {
fn from_iter<T: IntoIterator<Item = Path>>(iter: T) -> Self {
let derives = iter.into_iter().collect();
Self { derives }
Self {
derives,
attributes: HashSet::new(),
}
}
}

Expand All @@ -86,26 +89,55 @@ impl Derives {
/// to the set of default derives that reside in `subxt`.
pub fn new(crate_path: &CratePath) -> Self {
let mut derives = HashSet::new();
let mut attributes = HashSet::new();

derives.insert(syn::parse_quote!(#crate_path::ext::scale_encode::EncodeAsType));
ascjones marked this conversation as resolved.
Show resolved Hide resolved
let encode_crate_path =
quote::quote! { #crate_path::ext::scale_encode }.to_string();
attributes.insert(
syn::parse_quote!(#[encode_as_type(crate_path = #encode_crate_path)]),
);
derives.insert(syn::parse_quote!(#crate_path::ext::scale_decode::DecodeAsType));
let decode_crate_path =
quote::quote! { #crate_path::ext::scale_decode }.to_string();
attributes.insert(
syn::parse_quote!(#[decode_as_type(crate_path = #decode_crate_path)]),
);

derives.insert(syn::parse_quote!(#crate_path::ext::codec::Encode));
derives.insert(syn::parse_quote!(#crate_path::ext::codec::Decode));
derives.insert(syn::parse_quote!(Debug));
Self { derives }

Self {
derives,
attributes,
}
}

/// Extend this set of `Derives` from another.
pub fn extend_from(&mut self, other: Derives) {
self.derives.extend(other.derives.into_iter());
self.attributes.extend(other.attributes.into_iter());
}

/// Add `#crate_path::ext::codec::CompactAs` to the derives.
pub fn insert_codec_compact_as(&mut self, crate_path: &CratePath) {
self.insert(parse_quote!(#crate_path::ext::codec::CompactAs));
self.insert_derive(parse_quote!(#crate_path::ext::codec::CompactAs));
}

pub fn append(&mut self, derives: impl Iterator<Item = syn::Path>) {
for derive in derives {
self.insert(derive)
self.insert_derive(derive)
}
}

pub fn insert(&mut self, derive: syn::Path) {
pub fn insert_derive(&mut self, derive: syn::Path) {
self.derives.insert(derive);
}

pub fn insert_attribute(&mut self, attribute: syn::Attribute) {
self.attributes.insert(attribute);
}
}

impl quote::ToTokens for Derives {
Expand All @@ -117,10 +149,21 @@ impl quote::ToTokens for Derives {
.to_string()
.cmp(&quote::quote!(#b).to_string())
jsdw marked this conversation as resolved.
Show resolved Hide resolved
});
let derives: Punctuated<syn::Path, syn::Token![,]> =
sorted.iter().cloned().collect();

tokens.extend(quote::quote! {
#[derive(#( #sorted ),*)]
})
}
if !self.attributes.is_empty() {
let mut sorted = self.attributes.iter().cloned().collect::<Vec<_>>();
sorted.sort_by(|a, b| {
quote::quote!(#a)
.to_string()
.cmp(&quote::quote!(#b).to_string())
});

tokens.extend(quote::quote! {
#[derive(#derives)]
#( #sorted )*
})
}
}
Expand Down
Loading