Skip to content

Commit

Permalink
Merge pull request #46 from hashed-io/feature/fruniques_benchmarks
Browse files Browse the repository at this point in the history
Feature/fruniques benchmarks
  • Loading branch information
sebastianmontero authored Apr 24, 2024
2 parents 09ba7bf + d5bfb59 commit fbe0057
Show file tree
Hide file tree
Showing 8 changed files with 748 additions and 70 deletions.
17 changes: 0 additions & 17 deletions .github/workflows/gpt-commit-summarizer.yml

This file was deleted.

42 changes: 0 additions & 42 deletions .github/workflows/opencommit.yml

This file was deleted.

1 change: 1 addition & 0 deletions pallets/afloat/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ impl pallet_fruniques::Config for Test {
type MaxParentsInCollection = MaxParentsInCollection;
type MaxAttributes = MaxAttributes;
type Rbac = RBAC;
type WeightInfo = ();
}

parameter_types! {
Expand Down
222 changes: 222 additions & 0 deletions pallets/fruniques/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#![cfg(feature = "runtime-benchmarks")]

use super::*;
use crate::{types::*, Pallet as Fruniques};
use frame_benchmarking::v2::*;
use frame_support::{
assert_err, assert_ok,
pallet_prelude::*,
traits::{Currency, Get},
};
use frame_system::RawOrigin;
use scale_info::prelude::*;

const SEED: u32 = 0;

fn create_sized_description<T: Config>(
size: u32,
) -> BoundedVec<u8, <T as pallet_uniques::Config>::StringLimit> {
let v = vec![0; size as usize];
BoundedVec::<u8, <T as pallet_uniques::Config>::StringLimit>::try_from(v).unwrap()
}

fn create_sized_attributes<T: Config>(a: u32, k: u32, v: u32) -> Attributes<T> {
let vk = vec![0; k as usize];
let vv = vec![0; v as usize];
let attribute_keys =
BoundedVec::<u8, <T as pallet_uniques::Config>::KeyLimit>::try_from(vk).unwrap();
let attribute_values =
BoundedVec::<u8, <T as pallet_uniques::Config>::ValueLimit>::try_from(vv).unwrap();
let mut attributes = Attributes::<T>::default();
for _ in 0..a {
let _ = attributes.try_push((attribute_keys.clone(), attribute_values.clone()));
}
attributes
}

fn create_parent_info<T: Config>(
collection_id: u32,
parent_id: u32,
parent_percentage: u32,
is_hierarchical: bool,
) -> ParentInfoCall<T>
where
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = ItemId>,
{
ParentInfoCall { collection_id, parent_id, parent_percentage, is_hierarchical }
}

fn create_destroy_witness<T: Config>() -> pallet_uniques::DestroyWitness {
pallet_uniques::DestroyWitness { items: 0, item_metadatas: 0, attributes: 0 }
}

fn do_initial_setup<T: Config>() -> DispatchResult
where
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = ItemId>,
{
let freezer_acc: T::AccountId = account("freezer", 0, SEED);
assert!(Freezer::<T>::get().is_none());
Fruniques::<T>::initial_setup(RawOrigin::Root.into(), freezer_acc.clone())
}

fn do_create_collection<T: Config>() -> DispatchResult
where
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = ItemId>,
{
let desc = create_sized_description::<T>(<T as pallet_uniques::Config>::StringLimit::get());
let acc: T::AccountId = account("user", 0, SEED);

let max_balance = <T as pallet_uniques::Config>::Currency::total_issuance();
<T as pallet_uniques::Config>::Currency::make_free_balance_be(&acc, max_balance);
Fruniques::<T>::create_collection(RawOrigin::Signed(acc).into(), desc)
}

fn do_spawn<T: Config>() -> DispatchResult
where
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = ItemId>,
{
let acc: T::AccountId = account("user", 0, SEED);
let class_id = 0;
let attributes = create_sized_attributes::<T>(1, 1, 1);
let desc = create_sized_description::<T>(<T as pallet_uniques::Config>::StringLimit::get());
Fruniques::<T>::spawn(RawOrigin::Signed(acc).into(), class_id, desc, Some(attributes), None)
}

#[benchmarks(where T: Config , T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = ItemId> + pallet_rbac::Config)]
mod benchmarks {
use super::*;

#[benchmark]
fn initial_setup() {
let freezer_acc: T::AccountId = account("freezer", 0, SEED);
assert!(Freezer::<T>::get().is_none());
#[extrinsic_call]
_(RawOrigin::Root, freezer_acc.clone());
assert!(Freezer::<T>::get().unwrap() == freezer_acc);
}

#[benchmark]
fn create_collection(d: Linear<1, { <T as pallet_uniques::Config>::StringLimit::get() }>) {
let acc: T::AccountId = account("user", 0, SEED);
let max_balance = <T as pallet_uniques::Config>::Currency::total_issuance();
<T as pallet_uniques::Config>::Currency::make_free_balance_be(&acc, max_balance);
assert_ok!(do_initial_setup::<T>());
let description = create_sized_description::<T>(d);
assert_eq!(description.len() as u32, d);
assert_eq!(NextCollection::<T>::get(), 0);
#[extrinsic_call]
_(RawOrigin::Signed(acc), description);
assert_eq!(NextCollection::<T>::get(), 1);
}

#[benchmark]
fn set_attributes(a: Linear<1, { <T as Config>::MaxAttributes::get() }>) {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
assert_ok!(do_spawn::<T>());
let acc: T::AccountId = account("user", 0, SEED);
let class_id = 0;
let item_id = 0;
let attributes = create_sized_attributes::<T>(a, 1, 1);
#[extrinsic_call]
_(RawOrigin::Signed(acc), class_id, item_id, attributes);
}

#[benchmark]
fn spawn(
d: Linear<1, { <T as pallet_uniques::Config>::StringLimit::get() }>,
a: Linear<0, { <T as Config>::MaxAttributes::get() }>,
) {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
assert_ok!(do_spawn::<T>());

let parent_info = create_parent_info::<T>(0, 0, 99, true);
let acc: T::AccountId = account("user", 0, SEED);
let class_id = 0;
assert!(FruniqueInfo::<T>::get(class_id, 1).is_none());
let attributes = create_sized_attributes::<T>(a, 1, 1);
let description = create_sized_description::<T>(d);
#[extrinsic_call]
_(RawOrigin::Signed(acc), class_id, description, Some(attributes), Some(parent_info));
assert!(FruniqueInfo::<T>::get(class_id, 1).is_some());
}

#[benchmark]
fn verify_extrinsic() {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
assert_ok!(do_spawn::<T>());
let acc: T::AccountId = account("user", 0, SEED);
let class_id = 0;
let item_id = 0;
assert_eq!(FruniqueInfo::<T>::get(class_id, item_id).unwrap().verified, false);

// block is used here since there's a name collision between the verify extrinsic and the
// verify macro
#[block]
{
assert_ok!(Fruniques::<T>::verify(RawOrigin::Signed(acc).into(), class_id, item_id));
}

assert_eq!(FruniqueInfo::<T>::get(class_id, item_id).unwrap().verified, true);
}

#[benchmark]
fn invite() {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
assert_ok!(do_spawn::<T>());
let acc: T::AccountId = account("user", 0, SEED);
let class_id = 0;
let invitee: T::AccountId = account("invitee", 0, SEED);
assert_err!(
Fruniques::<T>::is_authorized(invitee.clone(), class_id, Permission::Mint),
pallet_rbac::pallet::Error::<T>::NotAuthorized
);
#[extrinsic_call]
_(RawOrigin::Signed(acc.clone()), class_id, invitee);
assert_ok!(Fruniques::<T>::is_authorized(acc.clone(), class_id, Permission::Mint));
}

#[benchmark]
fn force_set_counter() {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
let class_id = 0;
let item_id = 420;
assert!(NextFrunique::<T>::get(class_id.clone()) == 0);
#[extrinsic_call]
_(RawOrigin::Root, class_id, Some(item_id));
assert!(NextFrunique::<T>::get(class_id) == 420);
}

#[benchmark]
fn force_destroy_collection() {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
let class_id = 0;
assert_eq!(Fruniques::<T>::collection_exists(&class_id), true);
let destroy_witness = create_destroy_witness::<T>();
#[extrinsic_call]
_(RawOrigin::Root, class_id.clone(), destroy_witness, None);
assert_eq!(Fruniques::<T>::collection_exists(&class_id), false);
}

#[benchmark]
fn kill_storage() {
assert_ok!(do_initial_setup::<T>());
assert_ok!(do_create_collection::<T>());
assert_ok!(do_spawn::<T>());
assert_eq!(NextCollection::<T>::get(), 1);
#[extrinsic_call]
_(RawOrigin::Root);
assert_eq!(NextCollection::<T>::get(), 0);
}

impl_benchmark_test_suite! {
Fruniques,
crate::mock::new_test_ext_benchmarks(),
crate::mock::Test,
}
}
26 changes: 15 additions & 11 deletions pallets/fruniques/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ mod mock;
#[cfg(test)]
mod tests;

// #[cfg(feature = "runtime-benchmarks")]
// mod benchmarking;
mod benchmarking;

mod functions;
pub mod migration;
pub mod types;

pub mod weights;
use weights::WeightInfo;

#[frame_support::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -50,6 +52,8 @@ pub mod pallet {
// #[pallet::constant]
// type PalletId: Get<PalletId>;
type Rbac: RoleBasedAccessControl<Self::AccountId>;

type WeightInfo: WeightInfo;
}

#[pallet::pallet]
Expand Down Expand Up @@ -208,7 +212,7 @@ pub mod pallet {
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = ItemId>,
{
#[pallet::call_index(1)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(10))]
#[pallet::weight(<T as Config>::WeightInfo::initial_setup())]
pub fn initial_setup(origin: OriginFor<T>, freezer: T::AccountId) -> DispatchResult {
//Transfer the balance
T::RemoveOrigin::ensure_origin(origin.clone())?;
Expand All @@ -227,7 +231,7 @@ pub mod pallet {
/// - `origin`: The origin of the transaction.
/// - `metadata`: The title of the collection.
#[pallet::call_index(2)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::create_collection(metadata.len() as u32))]
pub fn create_collection(
origin: OriginFor<T>,
metadata: CollectionDescription<T>,
Expand All @@ -249,7 +253,7 @@ pub mod pallet {
/// - `instance_id` must be a valid instance of the asset class.
/// - `attributes` must be a list of pairs of `key` and `value`.
#[pallet::call_index(3)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::set_attributes(attributes.len() as u32))]
pub fn set_attributes(
origin: OriginFor<T>,
class_id: T::CollectionId,
Expand Down Expand Up @@ -285,7 +289,7 @@ pub mod pallet {
/// - `attributes` An array of attributes (key, value) to be added to the NFT.
/// - `parent_info` Optional value needed for the NFT division.
#[pallet::call_index(4)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(4))]
#[pallet::weight(<T as Config>::WeightInfo::spawn(metadata.len() as u32, attributes.clone().unwrap_or_default().len() as u32))]
pub fn spawn(
origin: OriginFor<T>,
class_id: CollectionId,
Expand Down Expand Up @@ -360,7 +364,7 @@ pub mod pallet {
/// - `class_id` must be a valid class of the asset class.
/// - `instance_id` must be a valid instance of the asset class.
#[pallet::call_index(5)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::verify_extrinsic())]
pub fn verify(
origin: OriginFor<T>,
class_id: CollectionId,
Expand Down Expand Up @@ -407,7 +411,7 @@ pub mod pallet {
/// collaborator. The user will be able to create NFTs in the collection.
/// The user will be able to add attributes to the NFTs in the collection.
#[pallet::call_index(6)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::invite())]
pub fn invite(
origin: OriginFor<T>,
class_id: CollectionId,
Expand Down Expand Up @@ -435,7 +439,7 @@ pub mod pallet {
/// directly. This function it's not expected to be used in production as it can lead to
/// unexpected results.
#[pallet::call_index(7)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::force_set_counter())]
pub fn force_set_counter(
origin: OriginFor<T>,
class_id: T::CollectionId,
Expand Down Expand Up @@ -471,7 +475,7 @@ pub mod pallet {
/// directly. This function it's not expected to be used in production as it can lead to
/// unexpected results.
#[pallet::call_index(8)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::force_destroy_collection())]
pub fn force_destroy_collection(
origin: OriginFor<T>,
class_id: T::CollectionId,
Expand Down Expand Up @@ -500,7 +504,7 @@ pub mod pallet {
/// ### Considerations:
/// - This function is only available to the `admin` with sudo access.
#[pallet::call_index(9)]
#[pallet::weight(Weight::from_parts(10_000,0) + T::DbWeight::get().writes(1))]
#[pallet::weight(<T as Config>::WeightInfo::kill_storage())]
pub fn kill_storage(origin: OriginFor<T>) -> DispatchResult {
T::RemoveOrigin::ensure_origin(origin.clone())?;
<Freezer<T>>::kill();
Expand Down
Loading

0 comments on commit fbe0057

Please sign in to comment.