From 5f057db22b11dc552f7b8445aa8fcdeba10eb076 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Fri, 14 May 2021 16:43:41 +0200 Subject: [PATCH 1/5] move MaxEncodedLen into its own crate --- Cargo.lock | 27 +++- Cargo.toml | 2 + frame/max-encoded-len/Cargo.toml | 33 ++++ frame/max-encoded-len/derive/Cargo.toml | 25 +++ frame/max-encoded-len/derive/src/lib.rs | 135 ++++++++++++++++ frame/max-encoded-len/src/lib.rs | 137 ++++++++++++++++ .../max-encoded-len/tests/max_encoded_len.rs | 151 ++++++++++++++++++ .../tests/max_encoded_len_ui.rs | 27 ++++ .../tests/max_encoded_len_ui/not_encode.rs | 6 + .../max_encoded_len_ui/not_encode.stderr | 13 ++ .../tests/max_encoded_len_ui/not_mel.rs | 14 ++ .../tests/max_encoded_len_ui/not_mel.stderr | 21 +++ .../tests/max_encoded_len_ui/union.rs | 10 ++ .../tests/max_encoded_len_ui/union.stderr | 11 ++ .../max_encoded_len_ui/unsupported_variant.rs | 12 ++ .../unsupported_variant.stderr | 12 ++ 16 files changed, 632 insertions(+), 4 deletions(-) create mode 100644 frame/max-encoded-len/Cargo.toml create mode 100644 frame/max-encoded-len/derive/Cargo.toml create mode 100644 frame/max-encoded-len/derive/src/lib.rs create mode 100644 frame/max-encoded-len/src/lib.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/union.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs create mode 100644 frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr diff --git a/Cargo.lock b/Cargo.lock index f11953213d01e..3dd86afe5feb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "Inflector" version = "0.11.4" @@ -3719,6 +3717,27 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "max-encoded-len" +version = "3.0.0" +dependencies = [ + "impl-trait-for-tuples", + "max-encoded-len-derive", + "parity-scale-codec", + "rustversion", + "trybuild", +] + +[[package]] +name = "max-encoded-len-derive" +version = "3.0.0" +dependencies = [ + "frame-support-procedural-tools", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -10433,9 +10452,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b" +checksum = "1768998d9a3b179411618e377dbb134c58a88cda284b0aa71c42c40660127d46" dependencies = [ "dissimilar", "glob", diff --git a/Cargo.toml b/Cargo.toml index 1b35c7181d17d..76c9d9a7b2169 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,8 @@ members = [ "frame/im-online", "frame/indices", "frame/lottery", + "frame/max-encoded-len", + "frame/max-encoded-len/derive", "frame/membership", "frame/merkle-mountain-range", "frame/merkle-mountain-range/primitives", diff --git a/frame/max-encoded-len/Cargo.toml b/frame/max-encoded-len/Cargo.toml new file mode 100644 index 0000000000000..c5ff58797038f --- /dev/null +++ b/frame/max-encoded-len/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "max-encoded-len" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Trait MaxEncodedLen bounds the max encoded length of an item." + + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +impl-trait-for-tuples = "0.2.1" +max-encoded-len-derive = { package = "max-encoded-len-derive", version = "3.0.0", path = "derive", default-features = false, optional = true } + +[dev-dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] } +rustversion = "1.0.4" +trybuild = "1.0.42" + +[features] +default = [ + "derive", + "std", +] +derive = [ + "max-encoded-len-derive", +] +std = [ + "codec/std", + "max-encoded-len-derive/std", +] diff --git a/frame/max-encoded-len/derive/Cargo.toml b/frame/max-encoded-len/derive/Cargo.toml new file mode 100644 index 0000000000000..c8d33bef1c6a5 --- /dev/null +++ b/frame/max-encoded-len/derive/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "max-encoded-len-derive" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Derive support for MaxEncodedLen" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +proc-macro = true + +[dependencies] +frame-support-procedural-tools = { version = "3.0.0", path = "../../support/procedural/tools" } +proc-macro2 = "1.0.6" +quote = "1.0.3" +syn = { version = "1.0.58", features = ["full"] } + +[features] +default = ["std"] +std = [] diff --git a/frame/max-encoded-len/derive/src/lib.rs b/frame/max-encoded-len/derive/src/lib.rs new file mode 100644 index 0000000000000..75484ad963204 --- /dev/null +++ b/frame/max-encoded-len/derive/src/lib.rs @@ -0,0 +1,135 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use frame_support_procedural_tools::generate_crate_access_2018; +use quote::{quote, quote_spanned}; +use syn::{ + Data, DeriveInput, Fields, GenericParam, Generics, TraitBound, Type, TypeParamBound, + parse_quote, spanned::Spanned, +}; + + +/// Derive `MaxEncodedLen`. +#[proc_macro_derive(MaxEncodedLen)] +pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input: DeriveInput = match syn::parse(input) { + Ok(input) => input, + Err(e) => return e.to_compile_error().into(), + }; + + let mel_trait = match max_encoded_len_trait() { + Ok(mel_trait) => mel_trait, + Err(e) => return e.to_compile_error().into(), + }; + + let name = &input.ident; + let generics = add_trait_bounds(input.generics, mel_trait.clone()); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let data_expr = data_length_expr(&input.data); + + quote::quote!( + const _: () = { + impl #impl_generics #mel_trait for #name #ty_generics #where_clause { + fn max_encoded_len() -> usize { + #data_expr + } + } + }; + ) + .into() +} + +fn max_encoded_len_trait() -> syn::Result { + let mel = generate_crate_access_2018("max-encoded-len")?; + Ok(parse_quote!(#mel::MaxEncodedLen)) +} + +// Add a bound `T: MaxEncodedLen` to every type parameter T. +fn add_trait_bounds(mut generics: Generics, mel_trait: TraitBound) -> Generics { + for param in &mut generics.params { + if let GenericParam::Type(ref mut type_param) = *param { + type_param.bounds.push(TypeParamBound::Trait(mel_trait.clone())); + } + } + generics +} + +/// generate an expression to sum up the max encoded length from several fields +fn fields_length_expr(fields: &Fields) -> proc_macro2::TokenStream { + let type_iter: Box> = match fields { + Fields::Named(ref fields) => Box::new(fields.named.iter().map(|field| &field.ty)), + Fields::Unnamed(ref fields) => Box::new(fields.unnamed.iter().map(|field| &field.ty)), + Fields::Unit => Box::new(std::iter::empty()), + }; + // expands to an expression like + // + // 0 + // .saturating_add(::max_encoded_len()) + // .saturating_add(::max_encoded_len()) + // + // We match the span of each field to the span of the corresponding + // `max_encoded_len` call. This way, if one field's type doesn't implement + // `MaxEncodedLen`, the compiler's error message will underline which field + // caused the issue. + let expansion = type_iter.map(|ty| { + quote_spanned! { + ty.span() => .saturating_add(<#ty>::max_encoded_len()) + } + }); + quote! { + 0_usize #( #expansion )* + } +} + +// generate an expression to sum up the max encoded length of each field +fn data_length_expr(data: &Data) -> proc_macro2::TokenStream { + match *data { + Data::Struct(ref data) => fields_length_expr(&data.fields), + Data::Enum(ref data) => { + // We need an expression expanded for each variant like + // + // 0 + // .max() + // .max() + // .saturating_add(1) + // + // The 1 derives from the discriminant; see + // https://github.com/paritytech/parity-scale-codec/ + // blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/derive/src/encode.rs#L211-L216 + // + // Each variant expression's sum is computed the way an equivalent struct's would be. + + let expansion = data.variants.iter().map(|variant| { + let variant_expression = fields_length_expr(&variant.fields); + quote! { + .max(#variant_expression) + } + }); + + quote! { + 0_usize #( #expansion )* .saturating_add(1) + } + } + Data::Union(ref data) => { + // https://github.com/paritytech/parity-scale-codec/ + // blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/derive/src/encode.rs#L290-L293 + syn::Error::new(data.union_token.span(), "Union types are not supported") + .to_compile_error() + } + } +} diff --git a/frame/max-encoded-len/src/lib.rs b/frame/max-encoded-len/src/lib.rs new file mode 100644 index 0000000000000..3df69f0ffc38a --- /dev/null +++ b/frame/max-encoded-len/src/lib.rs @@ -0,0 +1,137 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! `trait MaxEncodedLen` bounds the max encoded length of items. + +use codec::{Compact, Encode}; +use impl_trait_for_tuples::impl_for_tuples; +use core::{mem, marker::PhantomData}; + +#[cfg(feature = "derive")] +pub use max_encoded_len_derive::MaxEncodedLen; + +/// Items implementing `MaxEncodedLen` have a statically known maximum encoded size. +/// +/// Some containers, such as `BoundedVec`, have enforced size limits and this trait +/// can be implemented accurately. Other containers, such as `StorageMap`, do not have enforced size +/// limits. For those containers, it is necessary to make a documented assumption about the maximum +/// usage, and compute the max encoded length based on that assumption. +pub trait MaxEncodedLen: Encode { + /// Upper bound, in bytes, of the maximum encoded size of this item. + fn max_encoded_len() -> usize; +} + +macro_rules! impl_primitives { + ( $($t:ty),+ ) => { + $( + impl MaxEncodedLen for $t { + fn max_encoded_len() -> usize { + mem::size_of::<$t>() + } + } + )+ + }; +} + +impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool); + +macro_rules! impl_compact { + ($( $t:ty => $e:expr; )*) => { + $( + impl MaxEncodedLen for Compact<$t> { + fn max_encoded_len() -> usize { + $e + } + } + )* + }; +} + +impl_compact!( + // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L261 + u8 => 2; + // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L291 + u16 => 4; + // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L326 + u32 => 5; + // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L369 + u64 => 9; + // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L413 + u128 => 17; +); + +// impl_for_tuples for values 19 and higher fails because that's where the WrapperTypeEncode impl stops. +#[impl_for_tuples(18)] +impl MaxEncodedLen for Tuple { + fn max_encoded_len() -> usize { + let mut len: usize = 0; + for_tuples!( #( len = len.saturating_add(Tuple::max_encoded_len()); )* ); + len + } +} + +impl MaxEncodedLen for [T; N] { + fn max_encoded_len() -> usize { + T::max_encoded_len().saturating_mul(N) + } +} + +impl MaxEncodedLen for Option { + fn max_encoded_len() -> usize { + T::max_encoded_len().saturating_add(1) + } +} + +impl MaxEncodedLen for Result +where + T: MaxEncodedLen, + E: MaxEncodedLen, +{ + fn max_encoded_len() -> usize { + T::max_encoded_len().max(E::max_encoded_len()).saturating_add(1) + } +} + +impl MaxEncodedLen for PhantomData { + fn max_encoded_len() -> usize { + 0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + macro_rules! test_compact_length { + ($(fn $name:ident($t:ty);)*) => { + $( + #[test] + fn $name() { + assert_eq!(Compact(<$t>::MAX).encode().len(), Compact::<$t>::max_encoded_len()); + } + )* + }; + } + + test_compact_length!( + fn compact_u8(u8); + fn compact_u16(u16); + fn compact_u32(u32); + fn compact_u64(u64); + fn compact_u128(u128); + ); +} diff --git a/frame/max-encoded-len/tests/max_encoded_len.rs b/frame/max-encoded-len/tests/max_encoded_len.rs new file mode 100644 index 0000000000000..510e137aba433 --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len.rs @@ -0,0 +1,151 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for MaxEncodedLen derive macro + +#![cfg(feature = "derive")] + +use max_encoded_len::{MaxEncodedLen}; +use codec::{Compact, Encode}; + +// These structs won't even compile if the macro isn't working right. + +#[derive(Encode, MaxEncodedLen)] +struct Primitives { + bool: bool, + eight: u8, +} + +#[test] +fn primitives_max_length() { + assert_eq!(Primitives::max_encoded_len(), 2); +} + +#[derive(Encode, MaxEncodedLen)] +struct Composites { + fixed_size_array: [u8; 128], + tuple: (u128, u128), +} + +#[test] +fn composites_max_length() { + assert_eq!(Composites::max_encoded_len(), 128 + 16 + 16); +} + +#[derive(Encode, MaxEncodedLen)] +struct Generic { + one: T, + two: T, +} + +#[test] +fn generic_max_length() { + assert_eq!(Generic::::max_encoded_len(), u8::max_encoded_len() * 2); + assert_eq!(Generic::::max_encoded_len(), u32::max_encoded_len() * 2); +} + +#[derive(Encode, MaxEncodedLen)] +struct TwoGenerics { + t: T, + u: U, +} + +#[test] +fn two_generics_max_length() { + assert_eq!( + TwoGenerics::::max_encoded_len(), + u8::max_encoded_len() + u16::max_encoded_len() + ); + assert_eq!( + TwoGenerics::, [u16; 8]>::max_encoded_len(), + Compact::::max_encoded_len() + <[u16; 8]>::max_encoded_len() + ); +} + +#[derive(Encode, MaxEncodedLen)] +struct UnitStruct; + +#[test] +fn unit_struct_max_length() { + assert_eq!(UnitStruct::max_encoded_len(), 0); +} + +#[derive(Encode, MaxEncodedLen)] +struct TupleStruct(u8, u32); + +#[test] +fn tuple_struct_max_length() { + assert_eq!(TupleStruct::max_encoded_len(), u8::max_encoded_len() + u32::max_encoded_len()); +} + +#[derive(Encode, MaxEncodedLen)] +struct TupleGeneric(T, T); + +#[test] +fn tuple_generic_max_length() { + assert_eq!(TupleGeneric::::max_encoded_len(), u8::max_encoded_len() * 2); + assert_eq!(TupleGeneric::::max_encoded_len(), u32::max_encoded_len() * 2); +} + +#[derive(Encode, MaxEncodedLen)] +#[allow(unused)] +enum UnitEnum { + A, + B, +} + +#[test] +fn unit_enum_max_length() { + assert_eq!(UnitEnum::max_encoded_len(), 1); +} + +#[derive(Encode, MaxEncodedLen)] +#[allow(unused)] +enum TupleEnum { + A(u32), + B, +} + +#[test] +fn tuple_enum_max_length() { + assert_eq!(TupleEnum::max_encoded_len(), 1 + u32::max_encoded_len()); +} + +#[derive(Encode, MaxEncodedLen)] +#[allow(unused)] +enum StructEnum { + A { sixty_four: u64, one_twenty_eight: u128 }, + B, +} + +#[test] +fn struct_enum_max_length() { + assert_eq!(StructEnum::max_encoded_len(), 1 + u64::max_encoded_len() + u128::max_encoded_len()); +} + +// ensure that enums take the max of variant length, not the sum +#[derive(Encode, MaxEncodedLen)] +#[allow(unused)] +enum EnumMaxNotSum { + A(u32), + B(u32), +} + +#[test] +fn enum_max_not_sum_max_length() { + assert_eq!(EnumMaxNotSum::max_encoded_len(), 1 + u32::max_encoded_len()); +} diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui.rs b/frame/max-encoded-len/tests/max_encoded_len_ui.rs new file mode 100644 index 0000000000000..79d6d49234ff2 --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui.rs @@ -0,0 +1,27 @@ +// This file is part of Substrate. + +// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[cfg(feature = "derive")] +#[rustversion::attr(not(stable), ignore)] +#[test] +fn derive_no_bound_ui() { + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + std::env::set_var("SKIP_WASM_BUILD", "1"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/max_encoded_len_ui/*.rs"); +} diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs new file mode 100644 index 0000000000000..5e8eb6035547a --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.rs @@ -0,0 +1,6 @@ +use max_encoded_len::MaxEncodedLen; + +#[derive(MaxEncodedLen)] +struct NotEncode; + +fn main() {} diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr new file mode 100644 index 0000000000000..111e63e3f1e30 --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_encode.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `NotEncode: parity_scale_codec::codec::WrapperTypeEncode` is not satisfied + --> $DIR/not_encode.rs:3:10 + | +3 | #[derive(MaxEncodedLen)] + | ^^^^^^^^^^^^^ the trait `parity_scale_codec::codec::WrapperTypeEncode` is not implemented for `NotEncode` + | + ::: $WORKSPACE/frame/max-encoded-len/src/lib.rs + | + | pub trait MaxEncodedLen: Encode { + | ------ required by this bound in `MaxEncodedLen` + | + = note: required because of the requirements on the impl of `parity_scale_codec::codec::Encode` for `NotEncode` + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs new file mode 100644 index 0000000000000..cbaf820ff58e3 --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.rs @@ -0,0 +1,14 @@ +use codec::Encode; +use max_encoded_len::MaxEncodedLen; + +#[derive(Encode)] +struct NotMel; + +#[derive(Encode, MaxEncodedLen)] +struct Generic { + t: T, +} + +fn main() { + let _ = Generic::::max_encoded_len(); +} diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr new file mode 100644 index 0000000000000..0aabd4b2a393b --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/not_mel.stderr @@ -0,0 +1,21 @@ +error[E0599]: the function or associated item `max_encoded_len` exists for struct `Generic`, but its trait bounds were not satisfied + --> $DIR/not_mel.rs:13:29 + | +5 | struct NotMel; + | -------------- doesn't satisfy `NotMel: MaxEncodedLen` +... +8 | struct Generic { + | ----------------- + | | + | function or associated item `max_encoded_len` not found for this + | doesn't satisfy `Generic: MaxEncodedLen` +... +13 | let _ = Generic::::max_encoded_len(); + | ^^^^^^^^^^^^^^^ function or associated item cannot be called on `Generic` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NotMel: MaxEncodedLen` + which is required by `Generic: MaxEncodedLen` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/union.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/union.rs new file mode 100644 index 0000000000000..932c484b9e670 --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/union.rs @@ -0,0 +1,10 @@ +use codec::Encode; +use max_encoded_len::MaxEncodedLen; + +#[derive(Encode, MaxEncodedLen)] +union Union { + a: u8, + b: u16, +} + +fn main() {} diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr new file mode 100644 index 0000000000000..bc5519d674d9d --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/union.stderr @@ -0,0 +1,11 @@ +error: Union types are not supported + --> $DIR/union.rs:5:1 + | +5 | union Union { + | ^^^^^ + +error: Union types are not supported. + --> $DIR/union.rs:5:1 + | +5 | union Union { + | ^^^^^ diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs new file mode 100644 index 0000000000000..2fa94867471b1 --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.rs @@ -0,0 +1,12 @@ +use codec::Encode; +use max_encoded_len::MaxEncodedLen; + +#[derive(Encode)] +struct NotMel; + +#[derive(Encode, MaxEncodedLen)] +enum UnsupportedVariant { + NotMel(NotMel), +} + +fn main() {} diff --git a/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr new file mode 100644 index 0000000000000..aa10b5e4cc15e --- /dev/null +++ b/frame/max-encoded-len/tests/max_encoded_len_ui/unsupported_variant.stderr @@ -0,0 +1,12 @@ +error[E0599]: no function or associated item named `max_encoded_len` found for struct `NotMel` in the current scope + --> $DIR/unsupported_variant.rs:9:9 + | +5 | struct NotMel; + | -------------- function or associated item `max_encoded_len` not found for this +... +9 | NotMel(NotMel), + | ^^^^^^ function or associated item not found in `NotMel` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: + candidate #1: `MaxEncodedLen` From 21aa5f5142a7ddf9ca9a9bcb026c50fb1fe2a1ad Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Fri, 14 May 2021 16:52:31 +0200 Subject: [PATCH 2/5] remove MaxEncodedLen impl from frame-support --- Cargo.lock | 1 + frame/support/Cargo.toml | 2 + frame/support/procedural/src/lib.rs | 7 - .../support/procedural/src/max_encoded_len.rs | 133 ---------------- frame/support/src/traits.rs | 30 +--- frame/support/src/traits/max_encoded_len.rs | 133 ---------------- frame/support/test/tests/max_encoded_len.rs | 149 ------------------ .../support/test/tests/max_encoded_len_ui.rs | 26 --- .../tests/max_encoded_len_ui/not_encode.rs | 6 - .../max_encoded_len_ui/not_encode.stderr | 13 -- .../test/tests/max_encoded_len_ui/not_mel.rs | 14 -- .../tests/max_encoded_len_ui/not_mel.stderr | 21 --- .../test/tests/max_encoded_len_ui/union.rs | 10 -- .../tests/max_encoded_len_ui/union.stderr | 11 -- .../max_encoded_len_ui/unsupported_variant.rs | 12 -- .../unsupported_variant.stderr | 12 -- 16 files changed, 4 insertions(+), 576 deletions(-) delete mode 100644 frame/support/procedural/src/max_encoded_len.rs delete mode 100644 frame/support/src/traits/max_encoded_len.rs delete mode 100644 frame/support/test/tests/max_encoded_len.rs delete mode 100644 frame/support/test/tests/max_encoded_len_ui.rs delete mode 100644 frame/support/test/tests/max_encoded_len_ui/not_encode.rs delete mode 100644 frame/support/test/tests/max_encoded_len_ui/not_encode.stderr delete mode 100644 frame/support/test/tests/max_encoded_len_ui/not_mel.rs delete mode 100644 frame/support/test/tests/max_encoded_len_ui/not_mel.stderr delete mode 100644 frame/support/test/tests/max_encoded_len_ui/union.rs delete mode 100644 frame/support/test/tests/max_encoded_len_ui/union.stderr delete mode 100644 frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs delete mode 100644 frame/support/test/tests/max_encoded_len_ui/unsupported_variant.stderr diff --git a/Cargo.lock b/Cargo.lock index 3dd86afe5feb2..8492456cedba5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1808,6 +1808,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log", + "max-encoded-len", "once_cell", "parity-scale-codec", "parity-util-mem", diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 7b1179122b973..9c2831af83423 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } frame-metadata = { version = "13.0.0", default-features = false, path = "../metadata" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } @@ -55,6 +56,7 @@ std = [ "sp-state-machine", "frame-support-procedural/std", "log/std", + "max-encoded-len/std", ] runtime-benchmarks = [] try-runtime = [] diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 5146b8e78380e..f6a2176d777c4 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -28,7 +28,6 @@ mod debug_no_bound; mod clone_no_bound; mod partial_eq_no_bound; mod default_no_bound; -mod max_encoded_len; pub(crate) use storage::INHERENT_INSTANCE_NAME; use proc_macro::TokenStream; @@ -445,9 +444,3 @@ pub fn crate_to_pallet_version(input: TokenStream) -> TokenStream { /// The number of module instances supported by the runtime, starting at index 1, /// and up to `NUMBER_OF_INSTANCE`. pub(crate) const NUMBER_OF_INSTANCE: u8 = 16; - -/// Derive `MaxEncodedLen`. -#[proc_macro_derive(MaxEncodedLen)] -pub fn derive_max_encoded_len(input: TokenStream) -> TokenStream { - max_encoded_len::derive_max_encoded_len(input) -} diff --git a/frame/support/procedural/src/max_encoded_len.rs b/frame/support/procedural/src/max_encoded_len.rs deleted file mode 100644 index 72efa446b3f4d..0000000000000 --- a/frame/support/procedural/src/max_encoded_len.rs +++ /dev/null @@ -1,133 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use frame_support_procedural_tools::generate_crate_access_2018; -use quote::{quote, quote_spanned}; -use syn::{ - Data, DeriveInput, Fields, GenericParam, Generics, TraitBound, Type, TypeParamBound, - parse_quote, spanned::Spanned, -}; - -/// impl for `#[derive(MaxEncodedLen)]` -pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input: DeriveInput = match syn::parse(input) { - Ok(input) => input, - Err(e) => return e.to_compile_error().into(), - }; - - let mel_trait = match max_encoded_len_trait() { - Ok(mel_trait) => mel_trait, - Err(e) => return e.to_compile_error().into(), - }; - - let name = &input.ident; - let generics = add_trait_bounds(input.generics, mel_trait.clone()); - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - - let data_expr = data_length_expr(&input.data); - - quote::quote!( - const _: () = { - impl #impl_generics #mel_trait for #name #ty_generics #where_clause { - fn max_encoded_len() -> usize { - #data_expr - } - } - }; - ) - .into() -} - -fn max_encoded_len_trait() -> syn::Result { - let frame_support = generate_crate_access_2018("frame-support")?; - Ok(parse_quote!(#frame_support::traits::MaxEncodedLen)) -} - -// Add a bound `T: MaxEncodedLen` to every type parameter T. -fn add_trait_bounds(mut generics: Generics, mel_trait: TraitBound) -> Generics { - for param in &mut generics.params { - if let GenericParam::Type(ref mut type_param) = *param { - type_param.bounds.push(TypeParamBound::Trait(mel_trait.clone())); - } - } - generics -} - -/// generate an expression to sum up the max encoded length from several fields -fn fields_length_expr(fields: &Fields) -> proc_macro2::TokenStream { - let type_iter: Box> = match fields { - Fields::Named(ref fields) => Box::new(fields.named.iter().map(|field| &field.ty)), - Fields::Unnamed(ref fields) => Box::new(fields.unnamed.iter().map(|field| &field.ty)), - Fields::Unit => Box::new(std::iter::empty()), - }; - // expands to an expression like - // - // 0 - // .saturating_add(::max_encoded_len()) - // .saturating_add(::max_encoded_len()) - // - // We match the span of each field to the span of the corresponding - // `max_encoded_len` call. This way, if one field's type doesn't implement - // `MaxEncodedLen`, the compiler's error message will underline which field - // caused the issue. - let expansion = type_iter.map(|ty| { - quote_spanned! { - ty.span() => .saturating_add(<#ty>::max_encoded_len()) - } - }); - quote! { - 0_usize #( #expansion )* - } -} - -// generate an expression to sum up the max encoded length of each field -fn data_length_expr(data: &Data) -> proc_macro2::TokenStream { - match *data { - Data::Struct(ref data) => fields_length_expr(&data.fields), - Data::Enum(ref data) => { - // We need an expression expanded for each variant like - // - // 0 - // .max() - // .max() - // .saturating_add(1) - // - // The 1 derives from the discriminant; see - // https://github.com/paritytech/parity-scale-codec/ - // blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/derive/src/encode.rs#L211-L216 - // - // Each variant expression's sum is computed the way an equivalent struct's would be. - - let expansion = data.variants.iter().map(|variant| { - let variant_expression = fields_length_expr(&variant.fields); - quote! { - .max(#variant_expression) - } - }); - - quote! { - 0_usize #( #expansion )* .saturating_add(1) - } - } - Data::Union(ref data) => { - // https://github.com/paritytech/parity-scale-codec/ - // blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/derive/src/encode.rs#L290-L293 - syn::Error::new(data.union_token.span(), "Union types are not supported") - .to_compile_error() - } - } -} diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index cfac84aea865e..59ee29193e145 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -81,33 +81,5 @@ pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable}; mod voting; pub use voting::{CurrencyToVote, SaturatingCurrencyToVote, U128CurrencyToVote}; -mod max_encoded_len; -// This looks like an overlapping import/export, but it isn't: -// macros and traits live in distinct namespaces. +// for backwards-compatibility with existing imports pub use max_encoded_len::MaxEncodedLen; -/// Derive [`MaxEncodedLen`][max_encoded_len::MaxEncodedLen]. -/// -/// # Examples -/// -/// ``` -/// # use codec::Encode; -/// # use frame_support::traits::MaxEncodedLen; -/// #[derive(Encode, MaxEncodedLen)] -/// struct TupleStruct(u8, u32); -/// -/// assert_eq!(TupleStruct::max_encoded_len(), u8::max_encoded_len() + u32::max_encoded_len()); -/// ``` -/// -/// ``` -/// # use codec::Encode; -/// # use frame_support::traits::MaxEncodedLen; -/// #[derive(Encode, MaxEncodedLen)] -/// enum GenericEnum { -/// A, -/// B(T), -/// } -/// -/// assert_eq!(GenericEnum::::max_encoded_len(), u8::max_encoded_len() + u8::max_encoded_len()); -/// assert_eq!(GenericEnum::::max_encoded_len(), u8::max_encoded_len() + u128::max_encoded_len()); -/// ``` -pub use frame_support_procedural::MaxEncodedLen; diff --git a/frame/support/src/traits/max_encoded_len.rs b/frame/support/src/traits/max_encoded_len.rs deleted file mode 100644 index 2f206ddcbe11d..0000000000000 --- a/frame/support/src/traits/max_encoded_len.rs +++ /dev/null @@ -1,133 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use codec::{Compact, Encode}; -use impl_trait_for_tuples::impl_for_tuples; -use sp_std::{mem, marker::PhantomData}; -use sp_core::{H160, H256, H512}; - -/// Items implementing `MaxEncodedLen` have a statically known maximum encoded size. -/// -/// Some containers, such as `BoundedVec`, have enforced size limits and this trait -/// can be implemented accurately. Other containers, such as `StorageMap`, do not have enforced size -/// limits. For those containers, it is necessary to make a documented assumption about the maximum -/// usage, and compute the max encoded length based on that assumption. -pub trait MaxEncodedLen: Encode { - /// Upper bound, in bytes, of the maximum encoded size of this item. - fn max_encoded_len() -> usize; -} - -macro_rules! impl_primitives { - ( $($t:ty),+ ) => { - $( - impl MaxEncodedLen for $t { - fn max_encoded_len() -> usize { - mem::size_of::<$t>() - } - } - )+ - }; -} - -impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool, H160, H256, H512); - -macro_rules! impl_compact { - ($( $t:ty => $e:expr; )*) => { - $( - impl MaxEncodedLen for Compact<$t> { - fn max_encoded_len() -> usize { - $e - } - } - )* - }; -} - -impl_compact!( - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L261 - u8 => 2; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L291 - u16 => 4; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L326 - u32 => 5; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L369 - u64 => 9; - // https://github.com/paritytech/parity-scale-codec/blob/f0341dabb01aa9ff0548558abb6dcc5c31c669a1/src/compact.rs#L413 - u128 => 17; -); - -// impl_for_tuples for values 19 and higher fails because that's where the WrapperTypeEncode impl stops. -#[impl_for_tuples(18)] -impl MaxEncodedLen for Tuple { - fn max_encoded_len() -> usize { - let mut len: usize = 0; - for_tuples!( #( len = len.saturating_add(Tuple::max_encoded_len()); )* ); - len - } -} - -impl MaxEncodedLen for [T; N] { - fn max_encoded_len() -> usize { - T::max_encoded_len().saturating_mul(N) - } -} - -impl MaxEncodedLen for Option { - fn max_encoded_len() -> usize { - T::max_encoded_len().saturating_add(1) - } -} - -impl MaxEncodedLen for Result -where - T: MaxEncodedLen, - E: MaxEncodedLen, -{ - fn max_encoded_len() -> usize { - T::max_encoded_len().max(E::max_encoded_len()).saturating_add(1) - } -} - -impl MaxEncodedLen for PhantomData { - fn max_encoded_len() -> usize { - 0 - } -} - -#[cfg(test)] -mod tests { - use super::*; - - macro_rules! test_compact_length { - ($(fn $name:ident($t:ty);)*) => { - $( - #[test] - fn $name() { - assert_eq!(Compact(<$t>::MAX).encode().len(), Compact::<$t>::max_encoded_len()); - } - )* - }; - } - - test_compact_length!( - fn compact_u8(u8); - fn compact_u16(u16); - fn compact_u32(u32); - fn compact_u64(u64); - fn compact_u128(u128); - ); -} diff --git a/frame/support/test/tests/max_encoded_len.rs b/frame/support/test/tests/max_encoded_len.rs deleted file mode 100644 index e9e74929108d4..0000000000000 --- a/frame/support/test/tests/max_encoded_len.rs +++ /dev/null @@ -1,149 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests for MaxEncodedLen derive macro - -use frame_support::traits::MaxEncodedLen; -use codec::{Compact, Encode}; - -// These structs won't even compile if the macro isn't working right. - -#[derive(Encode, MaxEncodedLen)] -struct Primitives { - bool: bool, - eight: u8, -} - -#[test] -fn primitives_max_length() { - assert_eq!(Primitives::max_encoded_len(), 2); -} - -#[derive(Encode, MaxEncodedLen)] -struct Composites { - fixed_size_array: [u8; 128], - tuple: (u128, u128), -} - -#[test] -fn composites_max_length() { - assert_eq!(Composites::max_encoded_len(), 128 + 16 + 16); -} - -#[derive(Encode, MaxEncodedLen)] -struct Generic { - one: T, - two: T, -} - -#[test] -fn generic_max_length() { - assert_eq!(Generic::::max_encoded_len(), u8::max_encoded_len() * 2); - assert_eq!(Generic::::max_encoded_len(), u32::max_encoded_len() * 2); -} - -#[derive(Encode, MaxEncodedLen)] -struct TwoGenerics { - t: T, - u: U, -} - -#[test] -fn two_generics_max_length() { - assert_eq!( - TwoGenerics::::max_encoded_len(), - u8::max_encoded_len() + u16::max_encoded_len() - ); - assert_eq!( - TwoGenerics::, [u16; 8]>::max_encoded_len(), - Compact::::max_encoded_len() + <[u16; 8]>::max_encoded_len() - ); -} - -#[derive(Encode, MaxEncodedLen)] -struct UnitStruct; - -#[test] -fn unit_struct_max_length() { - assert_eq!(UnitStruct::max_encoded_len(), 0); -} - -#[derive(Encode, MaxEncodedLen)] -struct TupleStruct(u8, u32); - -#[test] -fn tuple_struct_max_length() { - assert_eq!(TupleStruct::max_encoded_len(), u8::max_encoded_len() + u32::max_encoded_len()); -} - -#[derive(Encode, MaxEncodedLen)] -struct TupleGeneric(T, T); - -#[test] -fn tuple_generic_max_length() { - assert_eq!(TupleGeneric::::max_encoded_len(), u8::max_encoded_len() * 2); - assert_eq!(TupleGeneric::::max_encoded_len(), u32::max_encoded_len() * 2); -} - -#[derive(Encode, MaxEncodedLen)] -#[allow(unused)] -enum UnitEnum { - A, - B, -} - -#[test] -fn unit_enum_max_length() { - assert_eq!(UnitEnum::max_encoded_len(), 1); -} - -#[derive(Encode, MaxEncodedLen)] -#[allow(unused)] -enum TupleEnum { - A(u32), - B, -} - -#[test] -fn tuple_enum_max_length() { - assert_eq!(TupleEnum::max_encoded_len(), 1 + u32::max_encoded_len()); -} - -#[derive(Encode, MaxEncodedLen)] -#[allow(unused)] -enum StructEnum { - A { sixty_four: u64, one_twenty_eight: u128 }, - B, -} - -#[test] -fn struct_enum_max_length() { - assert_eq!(StructEnum::max_encoded_len(), 1 + u64::max_encoded_len() + u128::max_encoded_len()); -} - -// ensure that enums take the max of variant length, not the sum -#[derive(Encode, MaxEncodedLen)] -#[allow(unused)] -enum EnumMaxNotSum { - A(u32), - B(u32), -} - -#[test] -fn enum_max_not_sum_max_length() { - assert_eq!(EnumMaxNotSum::max_encoded_len(), 1 + u32::max_encoded_len()); -} diff --git a/frame/support/test/tests/max_encoded_len_ui.rs b/frame/support/test/tests/max_encoded_len_ui.rs deleted file mode 100644 index c5c0489da924f..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui.rs +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#[rustversion::attr(not(stable), ignore)] -#[test] -fn derive_no_bound_ui() { - // As trybuild is using `cargo check`, we don't need the real WASM binaries. - std::env::set_var("SKIP_WASM_BUILD", "1"); - - let t = trybuild::TestCases::new(); - t.compile_fail("tests/max_encoded_len_ui/*.rs"); -} diff --git a/frame/support/test/tests/max_encoded_len_ui/not_encode.rs b/frame/support/test/tests/max_encoded_len_ui/not_encode.rs deleted file mode 100644 index ed6fe94471e58..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/not_encode.rs +++ /dev/null @@ -1,6 +0,0 @@ -use frame_support::traits::MaxEncodedLen; - -#[derive(MaxEncodedLen)] -struct NotEncode; - -fn main() {} diff --git a/frame/support/test/tests/max_encoded_len_ui/not_encode.stderr b/frame/support/test/tests/max_encoded_len_ui/not_encode.stderr deleted file mode 100644 index f4dbeac040843..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/not_encode.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0277]: the trait bound `NotEncode: WrapperTypeEncode` is not satisfied - --> $DIR/not_encode.rs:3:10 - | -3 | #[derive(MaxEncodedLen)] - | ^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NotEncode` - | - ::: $WORKSPACE/frame/support/src/traits/max_encoded_len.rs - | - | pub trait MaxEncodedLen: Encode { - | ------ required by this bound in `MaxEncodedLen` - | - = note: required because of the requirements on the impl of `frame_support::dispatch::Encode` for `NotEncode` - = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/max_encoded_len_ui/not_mel.rs b/frame/support/test/tests/max_encoded_len_ui/not_mel.rs deleted file mode 100644 index 6116f30e5272b..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/not_mel.rs +++ /dev/null @@ -1,14 +0,0 @@ -use codec::Encode; -use frame_support::traits::MaxEncodedLen; - -#[derive(Encode)] -struct NotMel; - -#[derive(Encode, MaxEncodedLen)] -struct Generic { - t: T, -} - -fn main() { - let _ = Generic::::max_encoded_len(); -} diff --git a/frame/support/test/tests/max_encoded_len_ui/not_mel.stderr b/frame/support/test/tests/max_encoded_len_ui/not_mel.stderr deleted file mode 100644 index 0aabd4b2a393b..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/not_mel.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0599]: the function or associated item `max_encoded_len` exists for struct `Generic`, but its trait bounds were not satisfied - --> $DIR/not_mel.rs:13:29 - | -5 | struct NotMel; - | -------------- doesn't satisfy `NotMel: MaxEncodedLen` -... -8 | struct Generic { - | ----------------- - | | - | function or associated item `max_encoded_len` not found for this - | doesn't satisfy `Generic: MaxEncodedLen` -... -13 | let _ = Generic::::max_encoded_len(); - | ^^^^^^^^^^^^^^^ function or associated item cannot be called on `Generic` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NotMel: MaxEncodedLen` - which is required by `Generic: MaxEncodedLen` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: - candidate #1: `MaxEncodedLen` diff --git a/frame/support/test/tests/max_encoded_len_ui/union.rs b/frame/support/test/tests/max_encoded_len_ui/union.rs deleted file mode 100644 index c685b6939e9b8..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/union.rs +++ /dev/null @@ -1,10 +0,0 @@ -use codec::Encode; -use frame_support::traits::MaxEncodedLen; - -#[derive(Encode, MaxEncodedLen)] -union Union { - a: u8, - b: u16, -} - -fn main() {} diff --git a/frame/support/test/tests/max_encoded_len_ui/union.stderr b/frame/support/test/tests/max_encoded_len_ui/union.stderr deleted file mode 100644 index bc5519d674d9d..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/union.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: Union types are not supported - --> $DIR/union.rs:5:1 - | -5 | union Union { - | ^^^^^ - -error: Union types are not supported. - --> $DIR/union.rs:5:1 - | -5 | union Union { - | ^^^^^ diff --git a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs b/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs deleted file mode 100644 index 675f62c168a69..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.rs +++ /dev/null @@ -1,12 +0,0 @@ -use codec::Encode; -use frame_support::traits::MaxEncodedLen; - -#[derive(Encode)] -struct NotMel; - -#[derive(Encode, MaxEncodedLen)] -enum UnsupportedVariant { - NotMel(NotMel), -} - -fn main() {} diff --git a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.stderr b/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.stderr deleted file mode 100644 index aa10b5e4cc15e..0000000000000 --- a/frame/support/test/tests/max_encoded_len_ui/unsupported_variant.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no function or associated item named `max_encoded_len` found for struct `NotMel` in the current scope - --> $DIR/unsupported_variant.rs:9:9 - | -5 | struct NotMel; - | -------------- function or associated item `max_encoded_len` not found for this -... -9 | NotMel(NotMel), - | ^^^^^^ function or associated item not found in `NotMel` - | - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `max_encoded_len`, perhaps you need to implement it: - candidate #1: `MaxEncodedLen` From f813cfac4ac614aec1bbc80e9d410aa8da96dfe0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 14 May 2021 13:24:31 -0400 Subject: [PATCH 3/5] add to assets and balances --- Cargo.lock | 3 +++ frame/assets/Cargo.toml | 2 ++ frame/balances/Cargo.toml | 2 ++ frame/max-encoded-len/Cargo.toml | 5 +++++ frame/max-encoded-len/src/lib.rs | 3 ++- 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 8492456cedba5..768737a295243 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3725,6 +3725,7 @@ dependencies = [ "impl-trait-for-tuples", "max-encoded-len-derive", "parity-scale-codec", + "primitive-types", "rustversion", "trybuild", ] @@ -4644,6 +4645,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "max-encoded-len", "pallet-balances", "parity-scale-codec", "sp-core", @@ -4754,6 +4756,7 @@ dependencies = [ "frame-support", "frame-system", "log", + "max-encoded-len", "pallet-transaction-payment", "parity-scale-codec", "sp-core", diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 7137cf1d789a2..433329af0106b 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -22,6 +22,7 @@ frame-support = { version = "3.0.0", default-features = false, path = "../suppor # `system` module provides us with all sorts of useful stuff and macros depend on it being around. frame-system = { version = "3.0.0", default-features = false, path = "../system" } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len" } [dev-dependencies] sp-core = { version = "3.0.0", path = "../../primitives/core" } @@ -38,6 +39,7 @@ std = [ "frame-support/std", "frame-system/std", "frame-benchmarking/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 116a52151583a..0245298e12c5a 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -20,6 +20,7 @@ frame-benchmarking = { version = "3.1.0", default-features = false, path = "../b frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len" } [dev-dependencies] sp-io = { version = "3.0.0", path = "../../primitives/io" } @@ -36,6 +37,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "max-encoded-len/std", ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/max-encoded-len/Cargo.toml b/frame/max-encoded-len/Cargo.toml index c5ff58797038f..22647a2493fcd 100644 --- a/frame/max-encoded-len/Cargo.toml +++ b/frame/max-encoded-len/Cargo.toml @@ -13,6 +13,7 @@ description = "Trait MaxEncodedLen bounds the max encoded length of an item." codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } impl-trait-for-tuples = "0.2.1" max-encoded-len-derive = { package = "max-encoded-len-derive", version = "3.0.0", path = "derive", default-features = false, optional = true } +primitive-types = { version = "0.9.0", default-features = false, features = ["codec"] } [dev-dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] } @@ -30,4 +31,8 @@ derive = [ std = [ "codec/std", "max-encoded-len-derive/std", + "primitive-types/std", + "primitive-types/serde", + "primitive-types/byteorder", + "primitive-types/rustc-hex", ] diff --git a/frame/max-encoded-len/src/lib.rs b/frame/max-encoded-len/src/lib.rs index 3df69f0ffc38a..1fd75e7fb30c5 100644 --- a/frame/max-encoded-len/src/lib.rs +++ b/frame/max-encoded-len/src/lib.rs @@ -20,6 +20,7 @@ use codec::{Compact, Encode}; use impl_trait_for_tuples::impl_for_tuples; use core::{mem, marker::PhantomData}; +use primitive_types::{H160, H256, H512}; #[cfg(feature = "derive")] pub use max_encoded_len_derive::MaxEncodedLen; @@ -47,7 +48,7 @@ macro_rules! impl_primitives { }; } -impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool); +impl_primitives!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool, H160, H256, H512); macro_rules! impl_compact { ($( $t:ty => $e:expr; )*) => { From 8c741c21ae1d5c51bee9e3bc9e02e71f8a05ca01 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 14 May 2021 17:31:40 -0400 Subject: [PATCH 4/5] try more fixes --- Cargo.lock | 3 ++- frame/assets/Cargo.toml | 2 -- frame/balances/Cargo.toml | 2 +- frame/max-encoded-len/Cargo.toml | 3 --- frame/max-encoded-len/tests/max_encoded_len.rs | 2 +- frame/proxy/Cargo.toml | 4 +++- primitives/runtime/Cargo.toml | 2 ++ primitives/runtime/src/traits.rs | 3 ++- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 768737a295243..eb3fc77182344 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4645,7 +4645,6 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "max-encoded-len", "pallet-balances", "parity-scale-codec", "sp-core", @@ -5283,6 +5282,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "max-encoded-len", "pallet-balances", "pallet-utility", "parity-scale-codec", @@ -9031,6 +9031,7 @@ dependencies = [ "hash256-std-hasher", "impl-trait-for-tuples", "log", + "max-encoded-len", "parity-scale-codec", "parity-util-mem", "paste 1.0.4", diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 433329af0106b..7137cf1d789a2 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -22,7 +22,6 @@ frame-support = { version = "3.0.0", default-features = false, path = "../suppor # `system` module provides us with all sorts of useful stuff and macros depend on it being around. frame-system = { version = "3.0.0", default-features = false, path = "../system" } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len" } [dev-dependencies] sp-core = { version = "3.0.0", path = "../../primitives/core" } @@ -39,7 +38,6 @@ std = [ "frame-support/std", "frame-system/std", "frame-benchmarking/std", - "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 0245298e12c5a..667724ae3d0cc 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -20,7 +20,7 @@ frame-benchmarking = { version = "3.1.0", default-features = false, path = "../b frame-support = { version = "3.0.0", default-features = false, path = "../support" } frame-system = { version = "3.0.0", default-features = false, path = "../system" } log = { version = "0.4.14", default-features = false } -max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-io = { version = "3.0.0", path = "../../primitives/io" } diff --git a/frame/max-encoded-len/Cargo.toml b/frame/max-encoded-len/Cargo.toml index 22647a2493fcd..b5f97e54ad0f0 100644 --- a/frame/max-encoded-len/Cargo.toml +++ b/frame/max-encoded-len/Cargo.toml @@ -32,7 +32,4 @@ std = [ "codec/std", "max-encoded-len-derive/std", "primitive-types/std", - "primitive-types/serde", - "primitive-types/byteorder", - "primitive-types/rustc-hex", ] diff --git a/frame/max-encoded-len/tests/max_encoded_len.rs b/frame/max-encoded-len/tests/max_encoded_len.rs index 510e137aba433..665ac8fa98a4f 100644 --- a/frame/max-encoded-len/tests/max_encoded_len.rs +++ b/frame/max-encoded-len/tests/max_encoded_len.rs @@ -19,7 +19,7 @@ #![cfg(feature = "derive")] -use max_encoded_len::{MaxEncodedLen}; +use max_encoded_len::MaxEncodedLen; use codec::{Compact, Encode}; // These structs won't even compile if the macro isn't working right. diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index d8f7afe433cb3..992d18fcc3f86 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -20,6 +20,7 @@ sp-core = { version = "3.0.0", default-features = false, path = "../../primitive sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } @@ -36,7 +37,8 @@ std = [ "frame-support/std", "frame-system/std", "sp-std/std", - "sp-io/std" + "sp-io/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7d33e7fa62d2d..646c7e4d10abe 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -29,6 +29,7 @@ impl-trait-for-tuples = "0.2.1" parity-util-mem = { version = "0.9.0", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } either = { version = "1.5", default-features = false } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } [dev-dependencies] serde_json = "1.0.41" @@ -55,4 +56,5 @@ std = [ "parity-util-mem/std", "hash256-std-hasher/std", "either/use_std", + "max-encoded-len/std", ] diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 41820d8cb4a1c..968f475f02252 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -40,6 +40,7 @@ pub use sp_arithmetic::traits::{ use sp_application_crypto::AppKey; use impl_trait_for_tuples::impl_for_tuples; use crate::DispatchResult; +use max_encoded_len::MaxEncodedLen; /// A lazy value. pub trait Lazy { @@ -386,7 +387,7 @@ impl::Output> { /// The hash type produced. type Output: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash - + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode; + + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode + MaxEncodedLen; /// Produce the hash of some byte-slice. fn hash(s: &[u8]) -> Self::Output { From da58284e990d99ad1d98b3d0e731ce165dd09eb5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 14 May 2021 17:46:56 -0400 Subject: [PATCH 5/5] fix compile --- Cargo.lock | 3 +++ bin/node/runtime/Cargo.toml | 3 +++ bin/node/runtime/src/lib.rs | 4 ++-- frame/assets/Cargo.toml | 2 ++ frame/max-encoded-len/src/lib.rs | 2 ++ primitives/core/Cargo.toml | 2 ++ primitives/core/src/crypto.rs | 3 ++- 7 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eb3fc77182344..a3c3f3b65c0e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4312,6 +4312,7 @@ dependencies = [ "frame-try-runtime", "hex-literal", "log", + "max-encoded-len", "node-primitives", "pallet-assets", "pallet-authority-discovery", @@ -4645,6 +4646,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "max-encoded-len", "pallet-balances", "parity-scale-codec", "sp-core", @@ -8806,6 +8808,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log", + "max-encoded-len", "merlin", "num-traits", "parity-scale-codec", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 512f32d66a66c..a0659db84ea11 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -87,6 +87,8 @@ pallet-transaction-payment = { version = "3.0.0", default-features = false, path pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } pallet-vesting = { version = "3.0.0", default-features = false, path = "../../../frame/vesting" } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../frame/max-encoded-len", features = [ "derive" ] } + [build-dependencies] substrate-wasm-builder = { version = "4.0.0", path = "../../../utils/wasm-builder" } @@ -159,6 +161,7 @@ std = [ "log/std", "frame-try-runtime/std", "sp-npos-elections/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 05f75b14b9603..eb544337e3795 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -33,7 +33,7 @@ use frame_support::{ }, traits::{ Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, LockIdentifier, - U128CurrencyToVote, + U128CurrencyToVote, MaxEncodedLen, }, }; use frame_system::{ @@ -252,7 +252,7 @@ parameter_types! { } /// The type used to represent the kinds of proxying allowed. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen)] pub enum ProxyType { Any, NonTransfer, diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 7137cf1d789a2..db03959616475 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -22,6 +22,7 @@ frame-support = { version = "3.0.0", default-features = false, path = "../suppor # `system` module provides us with all sorts of useful stuff and macros depend on it being around. frame-system = { version = "3.0.0", default-features = false, path = "../system" } frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../max-encoded-len", features = [ "derive" ] } [dev-dependencies] sp-core = { version = "3.0.0", path = "../../primitives/core" } @@ -38,6 +39,7 @@ std = [ "frame-support/std", "frame-system/std", "frame-benchmarking/std", + "max-encoded-len/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/frame/max-encoded-len/src/lib.rs b/frame/max-encoded-len/src/lib.rs index 1fd75e7fb30c5..13c99f4e5b0ce 100644 --- a/frame/max-encoded-len/src/lib.rs +++ b/frame/max-encoded-len/src/lib.rs @@ -17,6 +17,8 @@ //! `trait MaxEncodedLen` bounds the max encoded length of items. +#![cfg_attr(not(feature = "std"), no_std)] + use codec::{Compact, Encode}; use impl_trait_for_tuples::impl_for_tuples; use core::{mem, marker::PhantomData}; diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 3d9cf1287e051..071f6821f2930 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -40,6 +40,7 @@ parity-util-mem = { version = "0.9.0", default-features = false, features = ["pr futures = { version = "0.3.1", optional = true } dyn-clonable = { version = "0.9.0", optional = true } thiserror = { version = "1.0.21", optional = true } +max-encoded-len = { version = "3.0.0", default-features = false, path = "../../frame/max-encoded-len", features = [ "derive" ] } # full crypto ed25519-dalek = { version = "1.0.1", default-features = false, features = ["u64_backend", "alloc"], optional = true } @@ -114,6 +115,7 @@ std = [ "futures/thread-pool", "libsecp256k1/std", "dyn-clonable", + "max-encoded-len/std", ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 7446ab25ce4be..8d8b7b967ac63 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -20,6 +20,7 @@ // end::description[] use crate::{sr25519, ed25519}; +use max_encoded_len::MaxEncodedLen; use sp_std::hash::Hash; use sp_std::vec::Vec; use sp_std::str; @@ -692,7 +693,7 @@ pub trait Public: } /// An opaque 32-byte cryptographic identifier. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Hash))] pub struct AccountId32([u8; 32]);