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

Fix and migrated benchmarking of vesting from v1 to v2. #1607

Closed
wants to merge 2 commits into from
Closed
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
3,535 changes: 1,611 additions & 1,924 deletions Cargo.lock

Large diffs are not rendered by default.

244 changes: 164 additions & 80 deletions pallets/vesting/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -20,18 +20,13 @@
#![cfg(feature = "runtime-benchmarks")]

use frame_benchmarking::{account, benchmarks, whitelisted_caller};
use frame_system::{Pallet as System, RawOrigin};
use sp_runtime::traits::Bounded;

use super::*;
use crate::Pallet as Vesting;
use frame_benchmarking::v2::*;
use frame_system::RawOrigin;
use sp_runtime::traits::Bounded;

const SEED: u32 = 0;

type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;

fn add_locks<T: Config>(who: &T::AccountId, n: u8) {
for id in 0..n {
let lock_id = [id; 8];
@@ -41,190 +36,279 @@ fn add_locks<T: Config>(who: &T::AccountId, n: u8) {
}
}

fn add_vesting_schedule<T: Config>(who: &T::AccountId) -> Result<(), &'static str> {
fn add_vesting_schedule<T: Config>(who: &T::AccountId) -> Result<BalanceOf<T>, BenchmarkError> {
let locked = 100u32;
let per_block = 10u32;
let starting_block = 1u32;

System::<T>::set_block_number(0u32.into());
frame_system::Pallet::<T>::set_block_number(0u32.into());
Pallet::<T>::init_vesting_start_at(RawOrigin::Root.into(), 0u32.into())
.map_err(|_| BenchmarkError::Stop("Failed to init vesting start"))?;

Vesting::<T>::init_vesting_start_at(RawOrigin::Root.into(), 0u32.into())?;
Pallet::<T>::add_vesting_schedule(&who, locked.into(), per_block.into(), starting_block.into())
.map_err(|_| BenchmarkError::Stop("Failed to add vesting schedule"))?;

// Add schedule to avoid `NotVesting` error.
Vesting::<T>::add_vesting_schedule(
&who,
locked.into(),
per_block.into(),
starting_block.into(),
)?;
Ok(())
Ok(locked.into())
}

benchmarks! {
vest_locked {
let l in 0 .. MaxLocksOf::<T>::get();
#[benchmarks]
mod benchmarks {
use super::*;

let caller = whitelisted_caller();
#[benchmark]
fn vest_locked(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let caller: T::AccountId = account("seed", 1, 1);
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());

add_locks::<T>(&caller, l as u8);
add_vesting_schedule::<T>(&caller)?;
// At block zero, everything is vested.
System::<T>::set_block_number(BlockNumberFor::<T>::zero());

frame_system::Pallet::<T>::set_block_number(BlockNumberFor::<T>::zero());
assert_eq!(
Vesting::<T>::vesting_balance(&caller),
Pallet::<T>::vesting_balance(&caller),
Some(100u32.into()),
"Vesting schedule not added",
);
}: vest(RawOrigin::Signed(caller.clone()))
verify {
// Nothing happened since everything is still vested.

#[extrinsic_call]
vest(RawOrigin::Signed(caller.clone()));

assert_eq!(
Vesting::<T>::vesting_balance(&caller),
Pallet::<T>::vesting_balance(&caller),
Some(100u32.into()),
"Vesting schedule was removed",
);
}

vest_unlocked {
let l in 0 .. MaxLocksOf::<T>::get();
Ok(())
}

let caller = whitelisted_caller();
#[benchmark]
fn vest_unlocked(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let caller: T::AccountId = account("seed", 1, 1);
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());

add_locks::<T>(&caller, l as u8);
add_vesting_schedule::<T>(&caller)?;
// At block 20, everything is unvested.
System::<T>::set_block_number(20u32.into());

frame_system::Pallet::<T>::set_block_number(20u32.into());
assert_eq!(
Vesting::<T>::vesting_balance(&caller),
Pallet::<T>::vesting_balance(&caller),
Some(BalanceOf::<T>::zero()),
"Vesting schedule still active",
);
}: vest(RawOrigin::Signed(caller.clone()))
verify {
// Vesting schedule is removed!

#[extrinsic_call]
vest(RawOrigin::Signed(caller.clone()));

assert_eq!(
Vesting::<T>::vesting_balance(&caller),
Pallet::<T>::vesting_balance(&caller),
None,
"Vesting schedule was not removed",
);
}

vest_other_locked {
let l in 0 .. MaxLocksOf::<T>::get();
Ok(())
}

#[benchmark]
fn vest_other_locked(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let other: T::AccountId = account("other", 0, SEED);
let other_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(other.clone());
T::Currency::make_free_balance_be(&other, BalanceOf::<T>::max_value());

add_locks::<T>(&other, l as u8);
add_vesting_schedule::<T>(&other)?;
// At block zero, everything is vested.
System::<T>::set_block_number(BlockNumberFor::<T>::zero());

frame_system::Pallet::<T>::set_block_number(BlockNumberFor::<T>::zero());
assert_eq!(
Vesting::<T>::vesting_balance(&other),
Pallet::<T>::vesting_balance(&other),
Some(100u32.into()),
"Vesting schedule not added",
);

let caller: T::AccountId = whitelisted_caller();
}: vest_other(RawOrigin::Signed(caller.clone()), other_lookup)
verify {
// Nothing happened since everything is still vested.

#[extrinsic_call]
vest_other(RawOrigin::Signed(caller), other_lookup);

assert_eq!(
Vesting::<T>::vesting_balance(&other),
Pallet::<T>::vesting_balance(&other),
Some(100u32.into()),
"Vesting schedule was removed",
);
}

vest_other_unlocked {
let l in 0 .. MaxLocksOf::<T>::get();
Ok(())
}

#[benchmark]
fn vest_other_unlocked(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let other: T::AccountId = account("other", 0, SEED);
let other_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(other.clone());
T::Currency::make_free_balance_be(&other, BalanceOf::<T>::max_value());

add_locks::<T>(&other, l as u8);
add_vesting_schedule::<T>(&other)?;
// At block 20, everything is unvested.
System::<T>::set_block_number(20u32.into());

frame_system::Pallet::<T>::set_block_number(20u32.into());
assert_eq!(
Vesting::<T>::vesting_balance(&other),
Pallet::<T>::vesting_balance(&other),
Some(BalanceOf::<T>::zero()),
"Vesting schedule still active",
);

let caller: T::AccountId = whitelisted_caller();
}: vest_other(RawOrigin::Signed(caller.clone()), other_lookup)
verify {
// Vesting schedule is removed!

#[extrinsic_call]
vest_other(RawOrigin::Signed(caller), other_lookup);

assert_eq!(
Vesting::<T>::vesting_balance(&other),
Pallet::<T>::vesting_balance(&other),
None,
"Vesting schedule was not removed",
);
}

vested_transfer {
let l in 0 .. MaxLocksOf::<T>::get();
Ok(())
}

#[benchmark]
fn vested_transfer(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let caller: T::AccountId = whitelisted_caller();
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());

let target: T::AccountId = account("target", 0, SEED);
let target_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(target.clone());
let target_lookup: <T::Lookup as StaticLookup>::Source =
T::Lookup::unlookup(target.clone());

let transfer_amount = T::MinVestedTransfer::get();

let vesting_schedule = VestingInfo {
locked: transfer_amount,
per_block: 10u32.into(),
starting_block: 1u32.into(),
};
}: _(RawOrigin::Signed(caller), target_lookup, vesting_schedule)
verify {

#[extrinsic_call]
_(RawOrigin::Signed(caller), target_lookup, vesting_schedule);

assert_eq!(
T::MinVestedTransfer::get(),
T::Currency::free_balance(&target),
"Transfer didn't happen",
);
assert_eq!(
Vesting::<T>::vesting_balance(&target),
Pallet::<T>::vesting_balance(&target),
Some(T::MinVestedTransfer::get()),
"Lock not created",
);
}

force_vested_transfer {
let l in 0 .. MaxLocksOf::<T>::get();
Ok(())
}

#[benchmark]
fn force_vested_transfer(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let source: T::AccountId = account("source", 0, SEED);
let source_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(source.clone());
let source_lookup: <T::Lookup as StaticLookup>::Source =
T::Lookup::unlookup(source.clone());
T::Currency::make_free_balance_be(&source, BalanceOf::<T>::max_value());

let target: T::AccountId = account("target", 0, SEED);
let target_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(target.clone());
let target_lookup: <T::Lookup as StaticLookup>::Source =
T::Lookup::unlookup(target.clone());

let transfer_amount = T::MinVestedTransfer::get();

let vesting_schedule = VestingInfo {
locked: transfer_amount,
per_block: 10u32.into(),
starting_block: 1u32.into(),
};
}: _(RawOrigin::Root, source_lookup, target_lookup, vesting_schedule)
verify {

#[extrinsic_call]
_(
RawOrigin::Root,
source_lookup,
target_lookup,
vesting_schedule,
);

assert_eq!(
T::MinVestedTransfer::get(),
T::Currency::free_balance(&target),
"Transfer didn't happen",
);
assert_eq!(
Vesting::<T>::vesting_balance(&target),
Pallet::<T>::vesting_balance(&target),
Some(T::MinVestedTransfer::get()),
"Lock not created",
);

Ok(())
}

#[benchmark]
fn not_unlocking_merge_schedules(
l: Linear<0, { MaxLocksOf::<T>::get() }>,
s: Linear<2, { T::MAX_VESTING_SCHEDULES }>,
) -> Result<(), BenchmarkError> {
let caller: T::AccountId = account("seed", 1, 1);

T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance());

add_locks::<T>(&caller, l as u8);

add_vesting_schedule::<T>(&caller)?;
add_vesting_schedule::<T>(&caller)?;

assert_eq!(
frame_system::Pallet::<T>::block_number(),
BlockNumberFor::<T>::zero()
);
assert_eq!(
Pallet::<T>::vesting_balance(&caller),
Some(200u32.into()),
"Vesting balance should equal sum locked of all schedules",
);
assert_eq!(
Vesting::<T>::get(&caller).unwrap().len(),
2,
"There should be exactly two vesting schedules"
);

#[extrinsic_call]
merge_schedules(RawOrigin::Signed(caller.clone()), 0, 1);

let schedules = Vesting::<T>::get(&caller).unwrap();
assert_eq!(schedules.len(), 1, "Schedule count should be 1 after merge");

assert_eq!(
Pallet::<T>::vesting_balance(&caller),
Some(200u32.into()),
"Vesting balance should remain the same after merge",
);

Ok(())
}

impl_benchmark_test_suite!(
Vesting,
crate::mock::ExtBuilder::default().existential_deposit(256).build(),
Pallet,
crate::mock::ExtBuilder::default()
.existential_deposit(256)
.build(),
crate::mock::Test,
);
}
5 changes: 5 additions & 0 deletions pallets/vesting/src/mock.rs
Original file line number Diff line number Diff line change
@@ -143,3 +143,8 @@ impl ExtBuilder {
ext
}
}

#[cfg(feature = "runtime-benchmarks")]
pub fn new_test_ext_benchmark() -> sp_io::TestExternalities {
ExtBuilder::default().build()
}
481 changes: 156 additions & 325 deletions pallets/vesting/src/weights.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions runtime/bifrost-kusama/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2066,6 +2066,7 @@ mod benches {
[bifrost_vbnc_convert, VBNCConvert]
[bifrost_xcm_interface, XcmInterface]
// [bifrost_channel_commission, ChannelCommission]
[bifrost_vesting, Vesting]
);
}