From f4adbcd21ad637ed941c8264daa7e433e477caaf Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Sep 2021 12:17:05 +0200 Subject: [PATCH 1/5] fix wrapper opaque --- frame/support/src/traits/misc.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 82c5512ac15c5..3051fb102e6d2 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -17,8 +17,9 @@ //! Smaller traits used in FRAME which don't need their own file. -use crate::{dispatch::Parameter, TypeInfo}; +use crate::dispatch::Parameter; use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen}; +use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_runtime::{traits::Block as BlockT, DispatchError}; use sp_std::vec::Vec; @@ -384,7 +385,7 @@ impl, const T: u32> EstimateCallFee for /// /// The encoding is the encoding of `T` prepended with the compact encoding of its size in bytes. /// Thus the encoded value can be decoded as a `Vec`. -#[derive(Debug, Eq, PartialEq, Default, Clone, MaxEncodedLen, TypeInfo)] +#[derive(Debug, Eq, PartialEq, Default, Clone)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct WrapperOpaque(pub T); @@ -392,8 +393,7 @@ impl EncodeLike for WrapperOpaque {} impl Encode for WrapperOpaque { fn size_hint(&self) -> usize { - // Compact usually takes at most 4 bytes - self.0.size_hint().saturating_add(4) + self.0.size_hint().saturating_add(>::max_encoded_len()) } fn encode_to(&self, dest: &mut O) { @@ -425,6 +425,28 @@ impl From for WrapperOpaque { } } +impl MaxEncodedLen for WrapperOpaque { + fn max_encoded_len() -> usize { + // Note: this can be improved if `T::max_encoded_len` is small. + // E.g. if T max encoded len is 4, then the compact encoding of its encoded length is 1. + >::max_encoded_len().saturating_add(T::max_encoded_len()) + } +} + +impl TypeInfo for WrapperOpaque { + type Identity = Self; + fn type_info() -> Type { + Type::builder() + .path(Path::new("WrapperOpaque", module_path!())) + .type_params(vec![TypeParameter::new("T", Some(meta_type::()))]) + .composite( + Fields::unnamed() + .field(|f| f.compact::().type_name("EncodedLengthOfT")) + .field(|f| f.ty::().type_name("T")), + ) + } +} + #[cfg(test)] mod test { use super::*; @@ -438,5 +460,6 @@ mod test { assert_eq!(decoded_from_vec_u8, 3u32); let decoded = >::decode(&mut &encoded[..]).unwrap(); assert_eq!(decoded.0, 3u32); + assert_eq!(>::max_encoded_len(), 5 + 4); } } From dafb3861b885670ffd0bf78d84327655fa7a0f5d Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Sep 2021 12:33:23 +0200 Subject: [PATCH 2/5] fix compilation --- frame/support/src/traits/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 3051fb102e6d2..a194a5386b2f1 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -21,7 +21,7 @@ use crate::dispatch::Parameter; use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen}; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_runtime::{traits::Block as BlockT, DispatchError}; -use sp_std::vec::Vec; +use sp_std::prelude::*; /// Anything that can have a `::len()` method. pub trait Len { From 5f0718626783285161a28a87189ff586b4fe3b36 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Sep 2021 17:09:56 +0200 Subject: [PATCH 3/5] improve more precise implementation --- frame/support/src/traits/misc.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index a194a5386b2f1..41595e6facdf1 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -427,9 +427,18 @@ impl From for WrapperOpaque { impl MaxEncodedLen for WrapperOpaque { fn max_encoded_len() -> usize { - // Note: this can be improved if `T::max_encoded_len` is small. - // E.g. if T max encoded len is 4, then the compact encoding of its encoded length is 1. - >::max_encoded_len().saturating_add(T::max_encoded_len()) + let t_max_len = T::max_encoded_len(); + + // See scale encoding https://substrate.dev/docs/en/knowledgebase/advanced/codec + if t_max_len < 64 { + t_max_len + 1 + } else if t_max_len < 2usize.pow(14) { + t_max_len + 2 + } else if t_max_len < 2usize.pow(30) { + t_max_len + 4 + } else { + >::max_encoded_len().saturating_add(T::max_encoded_len()) + } } } @@ -459,7 +468,16 @@ mod test { let decoded_from_vec_u8 = u32::decode(&mut &vec_u8[..]).unwrap(); assert_eq!(decoded_from_vec_u8, 3u32); let decoded = >::decode(&mut &encoded[..]).unwrap(); + assert_eq!(decoded.0, 3u32); - assert_eq!(>::max_encoded_len(), 5 + 4); + + assert_eq!(>::max_encoded_len(), 63 + 1); + assert_eq!(>::max_encoded_len(), WrapperOpaque([0u8; 63]).encode().len()); + + assert_eq!(>::max_encoded_len(), 64 + 2); + assert_eq!(>::max_encoded_len(), WrapperOpaque([0u8; 64]).encode().len()); + + assert_eq!(>::max_encoded_len(), 2usize.pow(14) - 1 + 2); + assert_eq!(>::max_encoded_len(), 2usize.pow(14) + 4); } } From 5c2c140d4dd9d5a2b8f4815b9f642dcac633f984 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Sep 2021 17:11:45 +0200 Subject: [PATCH 4/5] spacing --- frame/support/src/traits/misc.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 41595e6facdf1..2527a84bb1c85 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -468,7 +468,6 @@ mod test { let decoded_from_vec_u8 = u32::decode(&mut &vec_u8[..]).unwrap(); assert_eq!(decoded_from_vec_u8, 3u32); let decoded = >::decode(&mut &encoded[..]).unwrap(); - assert_eq!(decoded.0, 3u32); assert_eq!(>::max_encoded_len(), 63 + 1); From 65669acf7a6dfe951d7164cd569a0f87ff316f2c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 28 Sep 2021 17:11:56 +0200 Subject: [PATCH 5/5] fmt --- frame/support/src/traits/misc.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 2527a84bb1c85..a040f8575abd2 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -471,12 +471,21 @@ mod test { assert_eq!(decoded.0, 3u32); assert_eq!(>::max_encoded_len(), 63 + 1); - assert_eq!(>::max_encoded_len(), WrapperOpaque([0u8; 63]).encode().len()); + assert_eq!( + >::max_encoded_len(), + WrapperOpaque([0u8; 63]).encode().len() + ); assert_eq!(>::max_encoded_len(), 64 + 2); - assert_eq!(>::max_encoded_len(), WrapperOpaque([0u8; 64]).encode().len()); - - assert_eq!(>::max_encoded_len(), 2usize.pow(14) - 1 + 2); + assert_eq!( + >::max_encoded_len(), + WrapperOpaque([0u8; 64]).encode().len() + ); + + assert_eq!( + >::max_encoded_len(), + 2usize.pow(14) - 1 + 2 + ); assert_eq!(>::max_encoded_len(), 2usize.pow(14) + 4); } }