Allow to specify some max number of values for storages in pallet macro. (#8735)

* implement max_values + storages info

* some formatting + doc

* rename StoragesInfo -> PalletStorageInfo

* merge both StorageInfoTrait and PalletStorageInfo

I think it is more future proof. In the future some storage could make
use of multiple prefix. Like one to store how much value has been
inserted, etc...

* Update frame/support/procedural/src/storage/parse.rs

Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>

* Update frame/support/procedural/src/storage/storage_struct.rs

Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>

* Fix max_size using hasher information

hasher now expose `max_len` which allows to computes their maximum len.
For hasher without concatenation, it is the size of the hash part,
for hasher with concatenation, it is the size of the hash part + max
encoded len of the key.

* fix tests

* fix ui tests

Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>
This commit is contained in:
Guillaume Thiolliere
2021-05-17 15:44:24 +02:00
committed by GitHub
parent 59f34ab8bc
commit 9bf62ef65d
26 changed files with 1161 additions and 149 deletions
+108 -6
View File
@@ -19,6 +19,7 @@ use frame_support::{
weights::{DispatchInfo, DispatchClass, Pays, GetDispatchInfo},
traits::{
GetCallName, OnInitialize, OnFinalize, OnRuntimeUpgrade, GetPalletVersion, OnGenesis,
MaxEncodedLen,
},
dispatch::{UnfilteredDispatchable, Parameter},
storage::unhashed,
@@ -47,10 +48,10 @@ impl From<SomeType6> for u64 { fn from(_t: SomeType6) -> Self { 0u64 } }
pub struct SomeType7;
impl From<SomeType7> for u64 { fn from(_t: SomeType7) -> Self { 0u64 } }
pub trait SomeAssociation1 { type _1: Parameter; }
pub trait SomeAssociation1 { type _1: Parameter + MaxEncodedLen; }
impl SomeAssociation1 for u64 { type _1 = u64; }
pub trait SomeAssociation2 { type _2: Parameter; }
pub trait SomeAssociation2 { type _2: Parameter + MaxEncodedLen; }
impl SomeAssociation2 for u64 { type _2 = u64; }
#[frame_support::pallet]
@@ -100,6 +101,7 @@ pub mod pallet {
#[pallet::pallet]
#[pallet::generate_store(pub(crate) trait Store)]
#[pallet::generate_storage_info]
pub struct Pallet<T>(_);
#[pallet::hooks]
@@ -209,13 +211,15 @@ pub mod pallet {
StorageMap<_, Blake2_128Concat, u8, u16, ValueQuery, MyDefault<T>>;
#[pallet::storage]
pub type Map2<T> = StorageMap<_, Twox64Concat, u16, u32>;
pub type Map2<T> = StorageMap<_, Twox64Concat, u16, u32, OptionQuery, GetDefault, ConstU32<3>>;
#[pallet::storage]
pub type DoubleMap<T> = StorageDoubleMap<_, Blake2_128Concat, u8, Twox64Concat, u16, u32>;
#[pallet::storage]
pub type DoubleMap2<T> = StorageDoubleMap<_, Twox64Concat, u16, Blake2_128Concat, u32, u64>;
pub type DoubleMap2<T> = StorageDoubleMap<
_, Twox64Concat, u16, Blake2_128Concat, u32, u64, OptionQuery, GetDefault, ConstU32<5>,
>;
#[pallet::storage]
#[pallet::getter(fn nmap)]
@@ -230,6 +234,9 @@ pub mod pallet {
NMapKey<Blake2_128Concat, u32>,
),
u64,
OptionQuery,
GetDefault,
ConstU32<11>,
>;
#[pallet::storage]
@@ -240,7 +247,8 @@ pub mod pallet {
#[cfg(feature = "conditional-storage")]
#[pallet::storage]
#[pallet::getter(fn conditional_map)]
pub type ConditionalMap<T> = StorageMap<_, Twox64Concat, u16, u32>;
pub type ConditionalMap<T> =
StorageMap<_, Twox64Concat, u16, u32, OptionQuery, GetDefault, ConstU32<12>>;
#[cfg(feature = "conditional-storage")]
#[pallet::storage]
@@ -560,7 +568,7 @@ fn pallet_expand_deposit_event() {
#[test]
fn storage_expand() {
use frame_support::pallet_prelude::*;
use frame_support::StoragePrefixedMap;
use frame_support::storage::StoragePrefixedMap;
fn twox_64_concat(d: &[u8]) -> Vec<u8> {
let mut v = twox_64(d).to_vec();
@@ -966,3 +974,97 @@ fn test_pallet_info_access() {
assert_eq!(<Example as frame_support::traits::PalletInfoAccess>::index(), 1);
assert_eq!(<Example2 as frame_support::traits::PalletInfoAccess>::index(), 2);
}
#[test]
fn test_storage_info() {
use frame_support::{
StorageHasher,
traits::{StorageInfoTrait, StorageInfo},
pallet_prelude::*,
};
let prefix = |pallet_name, storage_name| {
let mut res = [0u8; 32];
res[0..16].copy_from_slice(&Twox128::hash(pallet_name));
res[16..32].copy_from_slice(&Twox128::hash(storage_name));
res
};
assert_eq!(
Example::storage_info(),
vec![
StorageInfo {
prefix: prefix(b"Example", b"ValueWhereClause"),
max_values: Some(1),
max_size: Some(8),
},
StorageInfo {
prefix: prefix(b"Example", b"Value"),
max_values: Some(1),
max_size: Some(4),
},
StorageInfo {
prefix: prefix(b"Example", b"Map"),
max_values: None,
max_size: Some(3 + 16),
},
StorageInfo {
prefix: prefix(b"Example", b"Map2"),
max_values: Some(3),
max_size: Some(6 + 8),
},
StorageInfo {
prefix: prefix(b"Example", b"DoubleMap"),
max_values: None,
max_size: Some(7 + 16 + 8),
},
StorageInfo {
prefix: prefix(b"Example", b"DoubleMap2"),
max_values: Some(5),
max_size: Some(14 + 8 + 16),
},
StorageInfo {
prefix: prefix(b"Example", b"NMap"),
max_values: None,
max_size: Some(5 + 16),
},
StorageInfo {
prefix: prefix(b"Example", b"NMap2"),
max_values: Some(11),
max_size: Some(14 + 8 + 16),
},
#[cfg(feature = "conditional-storage")]
{
StorageInfo {
prefix: prefix(b"Example", b"ConditionalValue"),
max_values: Some(1),
max_size: Some(4),
}
},
#[cfg(feature = "conditional-storage")]
{
StorageInfo {
prefix: prefix(b"Example", b"ConditionalMap"),
max_values: Some(12),
max_size: Some(6 + 8),
}
},
#[cfg(feature = "conditional-storage")]
{
StorageInfo {
prefix: prefix(b"Example", b"ConditionalDoubleMap"),
max_values: None,
max_size: Some(7 + 16 + 8),
}
},
#[cfg(feature = "conditional-storage")]
{
StorageInfo {
prefix: prefix(b"Example", b"ConditionalNMap"),
max_values: None,
max_size: Some(7 + 16 + 8),
}
},
],
);
}