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

Bug/93 update vec to bounded vec #95

Merged
merged 17 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
77 changes: 40 additions & 37 deletions pallets/rmrk-core/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,24 @@ use sp_runtime::{
// Randomness to generate NFT virtual accounts
pub const SALT_RMRK_NFT: &[u8; 8] = b"RmrkNft/";

impl<T: Config> Priority<StringLimitOf<T>, T::AccountId> for Pallet<T>
impl<T: Config> Priority<StringLimitOf<T>, T::AccountId, BoundedVec<ResourceId, T::MaxPriorities>>
for Pallet<T>
where
T: pallet_uniques::Config<ClassId = CollectionId, InstanceId = NftId>,
{
fn priority_set(
_sender: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
priorities: Vec<Vec<u8>>,
priorities: BoundedVec<ResourceId, T::MaxPriorities>,
) -> DispatchResult {
// TODO : Check NFT lock status
let mut bounded_priorities = Vec::<BoundedVec<u8, T::StringLimit>>::new();
for priority in priorities {
let bounded_priority = Self::to_bounded_string(priority)?;
bounded_priorities.push(bounded_priority);
for _ in Priorities::<T>::drain_prefix((collection_id, nft_id)) {}
let mut priority_index = 0;
for resource_id in priorities {
Priorities::<T>::insert((collection_id, nft_id, resource_id), priority_index);
priority_index += 1;
}
Priorities::<T>::insert(collection_id, nft_id, bounded_priorities);
Self::deposit_event(Event::PrioritySet { collection_id, nft_id });
Ok(())
}
Expand Down Expand Up @@ -56,7 +57,13 @@ where
}
}

impl<T: Config> Resource<BoundedVec<u8, T::StringLimit>, T::AccountId, BoundedResource<T::ResourceSymbolLimit>> for Pallet<T>
impl<T: Config>
Resource<
BoundedVec<u8, T::StringLimit>,
T::AccountId,
BoundedResource<T::ResourceSymbolLimit>,
BoundedVec<PartId, T::PartsLimit>,
> for Pallet<T>
where
T: pallet_uniques::Config<ClassId = CollectionId, InstanceId = NftId>,
{
Expand All @@ -71,7 +78,7 @@ where
slot: Option<SlotId>,
license: Option<BoundedVec<u8, T::StringLimit>>,
thumb: Option<BoundedVec<u8, T::StringLimit>>,
parts: Option<Vec<PartId>>,
parts: Option<BoundedVec<PartId, T::PartsLimit>>,
) -> DispatchResult {
let (root_owner, _) = Pallet::<T>::lookup_root_owner(collection_id, nft_id)?;

Expand All @@ -82,7 +89,11 @@ where
thumb.is_none();
ensure!(!empty, Error::<T>::EmptyResource);

let res = ResourceInfo::<BoundedVec<u8, T::ResourceSymbolLimit>, BoundedVec<u8, T::StringLimit>> {
let res = ResourceInfo::<
BoundedVec<u8, T::ResourceSymbolLimit>,
BoundedVec<u8, T::StringLimit>,
BoundedVec<PartId, T::PartsLimit>,
> {
id: resource_id.clone(),
base,
src,
Expand Down Expand Up @@ -197,7 +208,7 @@ where
) -> sp_std::result::Result<(CollectionId, NftId), DispatchError> {
let nft_id = Self::get_next_nft_id(collection_id)?;
let collection = Self::collections(collection_id).ok_or(Error::<T>::CollectionUnknown)?;

// Prevent minting when next NFT id is greater than the collection max.
if let Some(max) = collection.max {
ensure!(nft_id < max, Error::<T>::CollectionFullOrLocked);
Expand All @@ -208,10 +219,16 @@ where

let owner_as_maybe_account = AccountIdOrCollectionNftTuple::AccountId(owner.clone());

let nft = NftInfo { owner: owner_as_maybe_account, recipient, royalty, metadata, equipped: false };
let nft = NftInfo {
owner: owner_as_maybe_account,
recipient,
royalty,
metadata,
equipped: false,
};

Nfts::<T>::insert(collection_id, nft_id, nft);
NftsByOwner::<T>::append(owner, (collection_id, nft_id));
NftsByOwner::<T>::insert((&owner, &collection_id, &nft_id), ());

// increment nfts counter
let nfts_count = collection.nfts_count.checked_add(1).ok_or(ArithmeticError::Overflow)?;
Expand All @@ -232,11 +249,10 @@ where
ensure!(max_recursions > 0, Error::<T>::TooManyRecursions);
bmacer marked this conversation as resolved.
Show resolved Hide resolved
Nfts::<T>::remove(collection_id, nft_id);

for _ in Resources::<T>::drain_prefix((collection_id, nft_id)) {}
for _ in Resources::<T>::drain_prefix((collection_id, nft_id)) {}

let kids = Children::<T>::take((collection_id, nft_id));
for (child_collection_id, child_nft_id) in kids {
// Remove child from Children StorageMap
let c = Children::<T>::iter_prefix((collection_id, nft_id,)).count();
bmacer marked this conversation as resolved.
Show resolved Hide resolved
bmacer marked this conversation as resolved.
Show resolved Hide resolved
for ((child_collection_id, child_nft_id), _) in Children::<T>::iter_prefix((collection_id, nft_id,)) {
Pallet::<T>::remove_child((collection_id, nft_id), (child_collection_id, child_nft_id));
Self::nft_burn(child_collection_id, child_nft_id, max_recursions - 1)?;
}
Expand Down Expand Up @@ -497,7 +513,7 @@ where
/// Output:
/// - Adding a `child` to the Children StorageMap of the `parent`
pub fn add_child(parent: (CollectionId, NftId), child: (CollectionId, NftId)) {
Children::<T>::mutate(parent, |v| v.push(child));
Children::<T>::insert((parent.0, parent.1), (child.0, child.1), ());
}

/// Remove a child from a parent NFT
Expand All @@ -509,11 +525,10 @@ where
/// Output:
/// - Removing a `child` from the Children StorageMap of the `parent`
pub fn remove_child(parent: (CollectionId, NftId), child: (CollectionId, NftId)) {
Children::<T>::mutate(parent, |v| {
*v = v.iter().filter(|&nft| *nft != child).cloned().collect();
});
Children::<T>::remove((parent.0, parent.1), (child.0, child.1));
}

/// I don't think we use this at all? [delete this statement if i'm wrong or this function if not]
bmacer marked this conversation as resolved.
Show resolved Hide resolved
/// Has a child NFT present in the Children StorageMap of the parent NFT
///
/// Parameters:
Expand All @@ -523,7 +538,7 @@ where
/// Output:
/// - `bool`
pub fn has_child(parent: (CollectionId, NftId)) -> bool {
!Children::<T>::get(parent).is_empty()
Children::<T>::iter_prefix_values(parent).count() != 0
}

/// Check whether a NFT is descends from a suspected parent NFT
Expand Down Expand Up @@ -568,6 +583,7 @@ where
}
}

/// I don't think we use this at all? [delete this line if untrue, or this function if true]
bmacer marked this conversation as resolved.
Show resolved Hide resolved
/// `recursive_burn` function will recursively call itself to burn the NFT and all the children
/// of the NFT. Any caller functions must be #[transactional]
///
Expand All @@ -582,26 +598,13 @@ where
) -> DispatchResult {
ensure!(max_recursions > 0, Error::<T>::TooManyRecursions);
Nfts::<T>::remove(collection_id, nft_id);
let kids = Children::<T>::take((collection_id, nft_id));
for (child_collection_id, child_nft_id) in kids {

for ((child_collection_id, child_nft_id), _) in Children::<T>::iter_prefix((collection_id, nft_id,)) {
Pallet::<T>::recursive_burn(child_collection_id, child_nft_id, max_recursions - 1)?;
}
Ok(())
}

pub fn to_bounded_string(name: Vec<u8>) -> Result<BoundedVec<u8, T::StringLimit>, Error<T>> {
name.try_into().map_err(|_| Error::<T>::TooLong)
}

pub fn to_optional_bounded_string(
name: Option<Vec<u8>>,
) -> Result<Option<BoundedVec<u8, T::StringLimit>>, Error<T>> {
Ok(match name {
Some(n) => Some(Self::to_bounded_string(n)?),
None => None,
})
}

pub fn get_next_nft_id(collection_id: CollectionId) -> Result<NftId, Error<T>> {
NextNftId::<T>::try_mutate(collection_id, |id| {
let current_id = *id;
Expand Down
62 changes: 43 additions & 19 deletions pallets/rmrk-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use frame_support::{
use frame_system::ensure_signed;

use sp_runtime::{traits::StaticLookup, DispatchError, Permill};
use sp_std::{convert::TryInto, vec::Vec};
use sp_std::convert::TryInto;

use rmrk_traits::{
primitives::*, AccountIdOrCollectionNftTuple, Collection, CollectionInfo, Nft, NftInfo,
Expand All @@ -30,7 +30,11 @@ pub type InstanceInfoOf<T> = NftInfo<
<T as frame_system::Config>::AccountId,
BoundedVec<u8, <T as pallet_uniques::Config>::StringLimit>,
>;
pub type ResourceOf<T, R> = ResourceInfo::<BoundedVec<u8, R>, BoundedVec<u8, <T as pallet_uniques::Config>::StringLimit>>;
pub type ResourceOf<T, R, P> = ResourceInfo::<
BoundedVec<u8, R>,
BoundedVec<u8, <T as pallet_uniques::Config>::StringLimit>,
BoundedVec<PartId, P>
>;

pub type StringLimitOf<T> = BoundedVec<u8, <T as pallet_uniques::Config>::StringLimit>;

Expand Down Expand Up @@ -62,6 +66,15 @@ pub mod pallet {
/// The maximum resource symbol length
#[pallet::constant]
type ResourceSymbolLimit: Get<u32>;

/// The maximum number of parts each resource may have
#[pallet::constant]
type PartsLimit: Get<u32>;

/// The maximum number of resources that can be included in a setpriority extrinsic
#[pallet::constant]
type MaxPriorities: Get<u32>;

}

#[pallet::storage]
Expand All @@ -86,8 +99,16 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn get_nfts_by_owner)]
/// Stores collections info
pub type NftsByOwner<T: Config> =
StorageMap<_, Twox64Concat, T::AccountId, Vec<(CollectionId, NftId)>>;
pub type NftsByOwner<T: Config> = StorageNMap<
bmacer marked this conversation as resolved.
Show resolved Hide resolved
_,
(
NMapKey<Blake2_128Concat, T::AccountId>,
NMapKey<Blake2_128Concat, CollectionId>,
NMapKey<Blake2_128Concat, NftId>,
),
(),
OptionQuery,
>;

#[pallet::storage]
#[pallet::getter(fn nfts)]
Expand All @@ -104,21 +125,22 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn priorities)]
/// Stores priority info
pub type Priorities<T: Config> = StorageDoubleMap<
pub type Priorities<T: Config> = StorageNMap<
_,
Twox64Concat,
CollectionId,
Twox64Concat,
NftId,
Vec<BoundedVec<u8, T::StringLimit>>,
(
NMapKey<Blake2_128Concat, CollectionId>,
NMapKey<Blake2_128Concat, NftId>,
NMapKey<Blake2_128Concat, ResourceId>,
),
u32,
OptionQuery,
>;

#[pallet::storage]
#[pallet::getter(fn children)]
/// Stores nft children info
pub type Children<T: Config> =
StorageMap<_, Twox64Concat, (CollectionId, NftId), Vec<(CollectionId, NftId)>, ValueQuery>;

pub type Children<T: Config> = StorageDoubleMap<_, Twox64Concat, (CollectionId, NftId), Twox64Concat, (CollectionId, NftId), ()>;

#[pallet::storage]
#[pallet::getter(fn resources)]
/// Stores resource info
Expand All @@ -130,7 +152,7 @@ pub mod pallet {
NMapKey<Blake2_128Concat, BoundedResource<T::ResourceSymbolLimit>>
,
),
ResourceOf<T, T::ResourceSymbolLimit>,
ResourceOf<T, T::ResourceSymbolLimit, T::PartsLimit>,
OptionQuery,
>;

Expand All @@ -149,7 +171,6 @@ pub mod pallet {
>;

#[pallet::pallet]
#[pallet::without_storage_info]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

Expand Down Expand Up @@ -547,7 +568,7 @@ pub mod pallet {
slot: Option<SlotId>,
license: Option<BoundedVec<u8, T::StringLimit>>,
thumb: Option<BoundedVec<u8, T::StringLimit>>,
parts: Option<Vec<PartId>>,
parts: Option<BoundedVec<PartId, T::PartsLimit>>,
) -> DispatchResult {
let sender = ensure_signed(origin.clone())?;

Expand All @@ -562,7 +583,7 @@ pub mod pallet {
slot,
license,
thumb,
parts
parts,
)?;

Self::deposit_event(Event::ResourceAdded { nft_id, resource_id });
Expand All @@ -579,7 +600,10 @@ pub mod pallet {
resource_id: BoundedResource<T::ResourceSymbolLimit>,
) -> DispatchResult {
let sender = ensure_signed(origin.clone())?;
ensure!(Resources::<T>::get((collection_id, nft_id, resource_id.clone())).is_some(), Error::<T>::ResourceDoesntExist);
ensure!(
Resources::<T>::get((collection_id, nft_id, resource_id.clone())).is_some(),
Error::<T>::ResourceDoesntExist
);

let (owner, _) = Pallet::<T>::lookup_root_owner(collection_id, nft_id)?;
ensure!(owner == sender, Error::<T>::NoPermission);
Expand All @@ -605,7 +629,7 @@ pub mod pallet {
origin: OriginFor<T>,
collection_id: CollectionId,
nft_id: NftId,
priorities: Vec<Vec<u8>>,
priorities: BoundedVec<ResourceId, T::MaxPriorities>,
) -> DispatchResult {
let _sender = ensure_signed(origin.clone())?;
Self::priority_set(_sender, collection_id, nft_id, priorities)?;
Expand Down
7 changes: 7 additions & 0 deletions pallets/rmrk-core/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ parameter_types! {
pub MaxMetadataLength: u32 = 256;
pub const MaxRecursions: u32 = 10;
pub const ResourceSymbolLimit: u32 = 10;
pub const PartsLimit: u32 = 10;
pub const MaxPriorities: u32 = 3;
}

impl pallet_rmrk_core::Config for Test {
Expand All @@ -51,6 +53,8 @@ impl pallet_rmrk_core::Config for Test {
type ProtocolOrigin = EnsureRoot<AccountId>;
type MaxRecursions = MaxRecursions;
type ResourceSymbolLimit = ResourceSymbolLimit;
type PartsLimit = PartsLimit;
type MaxPriorities = MaxPriorities;
}

parameter_types! {
Expand Down Expand Up @@ -141,6 +145,9 @@ pub const COLLECTION_ID_0: <Test as pallet_uniques::Config>::ClassId = 0;
// pub const COLLECTION_ID_1: <Test as pallet_uniques::Config>::ClassId = 1;
pub const NFT_ID_0: <Test as pallet_uniques::Config>::InstanceId = 0;
pub const NOT_EXISTING_CLASS_ID: <Test as pallet_uniques::Config>::ClassId = 999;
pub const RESOURCE_ZERO: ResourceId = 0;
pub const RESOURCE_ONE: ResourceId = 1;
pub const RESOURCE_TWO: ResourceId = 2;

pub struct ExtBuilder;
impl Default for ExtBuilder {
Expand Down
Loading