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

Feature/fruniques benchmarks #46

Merged
merged 2 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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