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

Reference key storage api #447

Merged
merged 37 commits into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b9d419f
codegen: Update polkadot.rs
lexnv Feb 14, 2022
eb768d8
codegen: Reference key storage api
lexnv Feb 14, 2022
0419623
codegen: Regenerate polkadot.rs with reference api
lexnv Feb 14, 2022
9a2c9ca
tests: Update tests with reference interface
lexnv Feb 14, 2022
6fe8818
cli: Fix polkadot.rs license check
lexnv Feb 14, 2022
2970d05
codegen: Update polkadot.rs with copyright
lexnv Feb 14, 2022
bfc7fe1
Revert "codegen: Update polkadot.rs with copyright"
lexnv Feb 14, 2022
553573a
codegen: Implement AccountData trait in the expected order
lexnv Feb 14, 2022
cd65398
codegen: Store implementation of StorageEntry
lexnv Feb 15, 2022
9651879
codegen: Generate AccountDefaultData wrapper struct
lexnv Feb 15, 2022
9816182
codegen: Allow `Account` references
lexnv Feb 15, 2022
7c19fde
codegen: Update polkadot.rs
lexnv Feb 15, 2022
f02ccf8
codegen: Utilize AccountDefaultData instead of Account
lexnv Feb 15, 2022
7cb306a
codegen: Update polkadot.rs
lexnv Feb 15, 2022
a8d709c
tests: Update tests to utilize `Account` reference
lexnv Feb 15, 2022
e5c8db7
codegen: Rename AccountDefaultData to AccountOwned
lexnv Feb 16, 2022
8925c3f
codegen: Add comments for wrapper account
lexnv Feb 16, 2022
b06264d
codegen: Obtain vector type parameter for TypePath::Type
lexnv Feb 16, 2022
4b7806e
codegen: Use slices instead of `& std::vec` in storage API
lexnv Feb 16, 2022
508116d
codegen: Update polkadot.rs
lexnv Feb 16, 2022
f09a213
Merge remote-tracking branch 'origin/master' into 411_ref_key_storage
lexnv Feb 16, 2022
763a836
codegen: Fix documentation
lexnv Feb 16, 2022
fc352ac
tests: Remove extra reference
lexnv Feb 16, 2022
c94a21f
examples: Add staking example to exercise storage API
lexnv Feb 17, 2022
4465ef2
Merge remote-tracking branch 'origin/master' into 411_ref_key_storage
lexnv Feb 18, 2022
8b13c4c
Merge remote-tracking branch 'origin/master' into 411_temp
lexnv Mar 1, 2022
fa9f03a
codegen: Update polkadot.rs
lexnv Mar 1, 2022
d541736
tests: Update storage tests
lexnv Mar 1, 2022
2bcd009
Fix cargo clippy
lexnv Mar 1, 2022
b9e84c6
codegen: Simplify vec_type_param
lexnv Mar 1, 2022
bb97e6a
examples: Rename staking_details.rs to fetch_staking_details.rs
lexnv Mar 1, 2022
ac98865
tests: Remove dummy variable
lexnv Mar 1, 2022
6bee03b
examples: Update polkadot version
lexnv Mar 1, 2022
d485513
Apply rust-fmt
lexnv Mar 1, 2022
3420b86
Merge remote-tracking branch 'origin/master' into 411_ref_key_storage
lexnv Mar 2, 2022
a17058a
codegen: Regenerate polkadot.rs
lexnv Mar 2, 2022
66fc95a
examples: Remove comment
lexnv Mar 2, 2022
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
9 changes: 5 additions & 4 deletions codegen/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,8 @@ fn generate_default_account_data_impl(
};

// this path to the storage entry depends on storage codegen.
let storage_entry_path = quote!(self::system::storage::Account);
// AccountDefaultData contains the same data as Account does, but without references.
let storage_entry_path = quote!(self::system::storage::AccountDefaultData);

Some(quote! {
/// The default storage entry from which to fetch an account nonce, required for
Expand All @@ -454,12 +455,12 @@ fn generate_default_account_data_impl(
type AccountId = #account_id_ty;
type Index = #account_nonce_ty;

fn nonce(result: &<Self::StorageEntry as ::subxt::StorageEntry>::Value) -> Self::Index {
result.nonce
}
fn storage_entry(account_id: Self::AccountId) -> Self::StorageEntry {
#storage_entry_path(account_id)
}
fn nonce(result: &<Self::StorageEntry as ::subxt::StorageEntry>::Value) -> Self::Index {
result.nonce
}
}
})
}
Expand Down
70 changes: 55 additions & 15 deletions codegen/src/api/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ fn generate_storage_entry_fns(
storage_entry: &StorageEntryMetadata<PortableForm>,
) -> (TokenStream2, TokenStream2) {
let entry_struct_ident = format_ident!("{}", storage_entry.name);
let (fields, entry_struct, constructor, key_impl) = match storage_entry.ty {
let is_account_wrapper = pallet.name == "System" && storage_entry.name == "Account";
let wrapper_struct_ident = format_ident!("{}DefaultData", storage_entry.name);
Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpicking: I'm not super fond of the name AccountDefaultData; I'd lean towards something like AccountOwned I guess.. but I'm not too fussed :D

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

AccountOwned sounds better :D Thanks

let (fields, entry_struct, constructor, key_impl, should_ref) = match storage_entry.ty
{
StorageEntryType::Plain(_) => {
let entry_struct = quote!( pub struct #entry_struct_ident; );
let constructor = quote!( #entry_struct_ident );
let key_impl = quote!(::subxt::StorageEntryKey::Plain);
(vec![], entry_struct, constructor, key_impl)
(vec![], entry_struct, constructor, key_impl, false)
}
StorageEntryType::Map {
ref key,
Expand Down Expand Up @@ -120,7 +123,7 @@ fn generate_storage_entry_fns(
fields.iter().map(|(_, field_type)| field_type);
let field_names = fields.iter().map(|(field_name, _)| field_name);
let entry_struct = quote! {
pub struct #entry_struct_ident( #( pub #tuple_struct_fields ),* );
pub struct #entry_struct_ident <'a>( #( pub &'a #tuple_struct_fields ),* );
};
let constructor =
quote!( #entry_struct_ident( #( #field_names ),* ) );
Expand All @@ -135,13 +138,28 @@ fn generate_storage_entry_fns(
vec![ #( #keys ),* ]
)
};
(fields, entry_struct, constructor, key_impl)
(fields, entry_struct, constructor, key_impl, true)
}
_ => {
let (lifetime_param, lifetime_ref) = (quote!(<'a>), quote!(&'a));

let ty_path = type_gen.resolve_type_path(key.id(), &[]);
let fields = vec![(format_ident!("_0"), ty_path.clone())];
// `::system::storage::Account` was utilized as associated type `StorageEntry`
// for `::subxt::AccountData` implementation of generated `DefaultAccountData`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// for `::subxt::AccountData` implementation of generated `DefaultAccountData`.
// for `::subxt::AccountData` implementation by the generated `DefaultAccountData`.

// Due to changes in the storage API, `::system::storage::Account` cannot be
// used without specifying a lifetime. To satisfy `::subxt::AccountData`
// implementation, a non-reference wrapper `AccountDefaultData` is generated.
let wrapper_struct = if is_account_wrapper {
quote!(
pub struct #wrapper_struct_ident ( pub #ty_path );
)
} else {
quote!()
};
let entry_struct = quote! {
pub struct #entry_struct_ident( pub #ty_path );
pub struct #entry_struct_ident #lifetime_param( pub #lifetime_ref #ty_path );
#wrapper_struct
};
let constructor = quote!( #entry_struct_ident(_0) );
let hasher = hashers.get(0).unwrap_or_else(|| {
Expand All @@ -152,7 +170,7 @@ fn generate_storage_entry_fns(
vec![ ::subxt::StorageMapKey::new(&self.0, #hasher) ]
)
};
(fields, entry_struct, constructor, key_impl)
(fields, entry_struct, constructor, key_impl, true)
}
}
}
Expand All @@ -178,25 +196,47 @@ fn generate_storage_entry_fns(
}
};

let (lifetime_param, reference, anon_lifetime) = if should_ref {
(quote!(<'a>), quote!(&), quote!(<'_>))
} else {
(quote!(), quote!(), quote!())
};

let storage_entry_impl = quote! (
const PALLET: &'static str = #pallet_name;
const STORAGE: &'static str = #storage_name;
type Value = #storage_entry_value_ty;
fn key(&self) -> ::subxt::StorageEntryKey {
#key_impl
}
);

let wrapper_entry_impl = if is_account_wrapper {
quote!(
impl ::subxt::StorageEntry for #wrapper_struct_ident {
#storage_entry_impl
}
)
} else {
quote!()
};

let storage_entry_type = quote! {
#entry_struct

impl ::subxt::StorageEntry for #entry_struct_ident {
const PALLET: &'static str = #pallet_name;
const STORAGE: &'static str = #storage_name;
type Value = #storage_entry_value_ty;
fn key(&self) -> ::subxt::StorageEntryKey {
#key_impl
}
impl ::subxt::StorageEntry for #entry_struct_ident #anon_lifetime {
#storage_entry_impl
}

#wrapper_entry_impl
};

let client_iter_fn = if matches!(storage_entry.ty, StorageEntryType::Map { .. }) {
quote! (
pub async fn #fn_name_iter(
&self,
hash: ::core::option::Option<T::Hash>,
) -> ::core::result::Result<::subxt::KeyIter<'a, T, #entry_struct_ident>, ::subxt::BasicError> {
) -> ::core::result::Result<::subxt::KeyIter<'a, T, #entry_struct_ident #lifetime_param>, ::subxt::BasicError> {
self.client.storage().iter(hash).await
}
)
Expand All @@ -206,7 +246,7 @@ fn generate_storage_entry_fns(

let key_args = fields
.iter()
.map(|(field_name, field_type)| quote!( #field_name: #field_type ));
.map(|(field_name, field_type)| quote!( #field_name: #reference #field_type ));
let client_fns = quote! {
pub async fn #fn_name(
&self,
Expand Down
Loading