From c31b5ba3b03c4ca7aa0284a3ce5bc67c2e8501b3 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 07 Apr 2022 10:14:50 +0000 Subject: [PATCH] feat: implement collection nesting rules field --- --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -192,7 +192,10 @@ type CrossTokenAddressMapping: TokenAddressMapping; } + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); @@ -393,6 +396,22 @@ #[pallet::storage] pub type DummyStorageValue = StorageValue; + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_runtime_upgrade() -> Weight { + let mut weight = 0; + + if StorageVersion::get::>() < StorageVersion::new(1) { + use up_data_structs::{CollectionVersion1, CollectionVersion2}; + >::translate_values::, _>(|v| { + Some(CollectionVersion2::from(v)) + }); + } + + weight + } + } } impl Pallet { --- a/primitives/data-structs/Cargo.toml +++ b/primitives/data-structs/Cargo.toml @@ -24,6 +24,7 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" } derivative = "2.2.0" +struct-versioning = { path = "../../crates/struct-versioning" } [features] default = ["std"] --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -248,6 +248,7 @@ } } +#[struct_versioning::versioned(version = 2, upper)] #[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Collection { @@ -265,7 +266,12 @@ pub offchain_schema: BoundedVec>, pub schema_version: SchemaVersion, pub sponsorship: SponsorshipState, - pub limits: CollectionLimits, // Collection private restrictions + + #[version(..2)] + pub limits: CollectionLimitsVersion1, // Collection private restrictions + #[version(2.., upper(limits.into()))] + pub limits: CollectionLimitsVersion2, + #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] pub variable_on_chain_schema: BoundedVec>, #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] @@ -321,6 +327,7 @@ } /// All fields are wrapped in `Option`s, where None means chain default +#[struct_versioning::versioned(version = 2, upper)] #[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct CollectionLimits { @@ -338,6 +345,9 @@ pub owner_can_transfer: Option, pub owner_can_destroy: Option, pub transfers_enabled: Option, + + #[version(2.., upper(None))] + pub nesting_rule: Option, } impl CollectionLimits { @@ -384,6 +394,26 @@ SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)), } } + pub fn nesting_rule(&self) -> &NestingRule { + static DEFAULT: NestingRule = NestingRule::Owner; + self.nesting_rule.as_ref().unwrap_or(&DEFAULT) + } +} + +#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +#[derivative(Debug)] +pub enum NestingRule { + /// No one can nest tokens + Disabled, + /// Owner can nest any tokens + Owner, + /// Owner can nest tokens from specified collections + OwnerRestricted( + #[cfg_attr(feature = "serde1", serde(with = "bounded_set_serde"))] + #[derivative(Debug(format_with = "bounded_set_debug"))] + BoundedBTreeSet>, + ), } #[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)] @@ -482,6 +512,50 @@ (&v as &BTreeMap).fmt(f) } +#[cfg(feature = "serde1")] +#[allow(dead_code)] +mod bounded_set_serde { + use core::convert::TryFrom; + use sp_std::collections::btree_set::BTreeSet; + use frame_support::{traits::Get, storage::bounded_btree_set::BoundedBTreeSet}; + use serde::{ + ser::{self, Serialize}, + de::{self, Deserialize, Error}, + }; + pub fn serialize( + value: &BoundedBTreeSet, + serializer: D, + ) -> Result + where + D: ser::Serializer, + K: Serialize + Ord, + { + (value as &BTreeSet<_>).serialize(serializer) + } + + pub fn deserialize<'de, D, K, S>(deserializer: D) -> Result, D::Error> + where + D: de::Deserializer<'de>, + K: de::Deserialize<'de> + Ord, + S: Get, + { + let map = >::deserialize(deserializer)?; + let len = map.len(); + TryFrom::try_from(map).map_err(|_| D::Error::invalid_length(len, &"lesser size")) + } +} + +fn bounded_set_debug( + v: &BoundedBTreeSet, + f: &mut fmt::Formatter, +) -> Result<(), fmt::Error> +where + K: fmt::Debug + Ord, +{ + use core::fmt::Debug; + (&v as &BTreeSet).fmt(f) +} + #[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] #[derivative(Debug)] -- gitstuff