Skip to content
This repository has been archived by the owner on Sep 22, 2022. It is now read-only.

Commit

Permalink
New QuotaCalculationStrategy impl
Browse files Browse the repository at this point in the history
provide an implementation of QuotaCalculationStrategy that works with eligible accounts rather than locked token information
  • Loading branch information
TarekkMA committed Mar 15, 2022
1 parent 675be7f commit e00310e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 24 deletions.
28 changes: 26 additions & 2 deletions pallets/free-calls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ pub mod pallet {
//TODO: remove this after we integrate locking tokens
#[pallet::constant]
type AccountsSetLimit: Get<u32>;

/// Amount of free quota granted to eligible accounts.
//TODO: remove this after we integrate locking tokens
#[pallet::constant]
type FreeQuotaPerEligibleAccount: Get<NumberOfCalls>;
}

/// Retrieves the size of `T::WindowsConfig` to be used for `BoundedVec` declaration.
Expand Down Expand Up @@ -295,7 +300,7 @@ pub mod pallet {
}

let locked_info = <LockedInfoByAccount<T>>::get(consumer.clone());
let quota = match T::QuotaCalculationStrategy::calculate(current_block, locked_info) {
let quota = match T::QuotaCalculationStrategy::calculate(consumer.clone(), current_block, locked_info) {
Some(quota) if quota > 0 => quota,
_ => return None,
};
Expand Down Expand Up @@ -373,7 +378,26 @@ pub mod pallet {


pub trait QuotaCalculationStrategy<T: Config> {
fn calculate(current_block: T::BlockNumber, locked_info: Option<LockedInfoOf<T>>) -> Option<NumberOfCalls>;
fn calculate(
consumer: T::AccountId,
current_block: T::BlockNumber,
locked_info: Option<LockedInfoOf<T>>
) -> Option<NumberOfCalls>;
}

//TODO: remove this after we integrate locking tokens
impl<T: Config> QuotaCalculationStrategy<T> for () {
fn calculate(
consumer: T::AccountId,
_current_block: T::BlockNumber,
_locked_info: Option<LockedInfoOf<T>>
) -> Option<NumberOfCalls> {
if EligibleAccounts::<T>::get(consumer) {
Some(T::FreeQuotaPerEligibleAccount::get())
} else {
None
}
}
}
}

Expand Down
13 changes: 10 additions & 3 deletions pallets/free-calls/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::test_pallet;
use frame_support::{
parameter_types,
};
use frame_support::pallet_prelude::ConstU32;
use frame_support::traits::{Contains};
use frame_system as system;
use frame_system::{EnsureRoot};
Expand Down Expand Up @@ -118,8 +119,8 @@ impl test_pallet::Config for Test {
type CallFilterFn = fn(&Call) -> bool;
static DEFAULT_CALL_FILTER_FN: CallFilterFn = |_| true;

type QuotaCalculationFn<T> = fn(<T as frame_system::Config>::BlockNumber, Option<LockedInfoOf<T>>) -> Option<NumberOfCalls>;
static DEFAULT_QUOTA_CALCULATION_FN: QuotaCalculationFn<Test> = |current_block, locked_info| {
type QuotaCalculationFn<T> = fn(<T as frame_system::Config>::AccountId, <T as frame_system::Config>::BlockNumber, Option<LockedInfoOf<T>>) -> Option<NumberOfCalls>;
static DEFAULT_QUOTA_CALCULATION_FN: QuotaCalculationFn<Test> = |consumer, current_block, locked_info| {
return Some(10);
};

Expand Down Expand Up @@ -148,13 +149,18 @@ impl Contains<Call> for TestCallFilter {
pub struct TestQuotaCalculation;
impl pallet_free_calls::QuotaCalculationStrategy<Test> for TestQuotaCalculation {
fn calculate(
consumer: <Test as frame_system::Config>::AccountId,
current_block: <Test as frame_system::Config>::BlockNumber,
locked_info: Option<LockedInfoOf<Test>>
) -> Option<NumberOfCalls> {
QUOTA_CALCULATION.with(|strategy| strategy.borrow()(current_block, locked_info))
QUOTA_CALCULATION.with(|strategy| strategy.borrow()(consumer, current_block, locked_info))
}
}

parameter_types! {
pub const FreeQuotaPerEligibleAccount: NumberOfCalls = 100;
}

impl pallet_free_calls::Config for Test {
type Event = Event;
type Call = Call;
Expand All @@ -163,6 +169,7 @@ impl pallet_free_calls::Config for Test {
type WeightInfo = ();
type QuotaCalculationStrategy = TestQuotaCalculation;
type AccountsSetLimit = AccountsSetLimit;
type FreeQuotaPerEligibleAccount = FreeQuotaPerEligibleAccount;
}

pub struct ExtBuilder {
Expand Down
27 changes: 17 additions & 10 deletions pallets/free-calls/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ fn dummy() {
.windows_config(vec![
WindowConfig::new(1, QuotaToWindowRatio::new(1)),
])
.quota_calculation(|_, _| 100.into())
.quota_calculation(|_, _, _| 100.into())
.build().execute_with(|| {
let consumer: AccountId = account("Consumer", 2, 1);

Expand All @@ -302,7 +302,7 @@ fn dummy() {
.windows_config(vec![
WindowConfig::new(1, QuotaToWindowRatio::new(1)),
])
.quota_calculation(|_, _| None)
.quota_calculation(|_, _, _| None)
.build().execute_with(|| {
let consumer: AccountId = account("Consumer", 2, 1);

Expand All @@ -317,16 +317,19 @@ fn dummy() {
#[test]
fn locked_token_info_and_current_block_number_will_be_passed_to_the_calculation_strategy() {
thread_local! {
static CAPTURED_CONSUMER: RefCell<Option<AccountId>> = RefCell::new(None);
static CAPTURED_LOCKED_TOKENS: RefCell<Option<LockedInfoOf<Test>>> = RefCell::new(None);
static CAPTURED_CURRENT_BLOCK: RefCell<Option<BlockNumber>> = RefCell::new(None);
}

let get_captured_consumer = || CAPTURED_CONSUMER.with(|x| x.borrow().clone());
let get_captured_locked_tokens = || CAPTURED_LOCKED_TOKENS.with(|x| x.borrow().clone());
let get_captured_current_block = || CAPTURED_CURRENT_BLOCK.with(|x| x.borrow().clone());

ExtBuilder::default()
.windows_config(vec![WindowConfig::new(1, QuotaToWindowRatio::new(1))])
.quota_calculation(|current_block, locked_tokens| {
.quota_calculation(|consumer, current_block, locked_tokens| {
CAPTURED_CONSUMER.with(|x| *x.borrow_mut() = Some(consumer));
CAPTURED_LOCKED_TOKENS.with(|x| *x.borrow_mut() = locked_tokens.clone());
CAPTURED_CURRENT_BLOCK.with(|x| *x.borrow_mut() = Some(current_block));

Expand All @@ -336,13 +339,15 @@ fn locked_token_info_and_current_block_number_will_be_passed_to_the_calculation_
.execute_with(|| {
let consumer: AccountId = account("Consumer", 0, 0);

assert_eq!(get_captured_consumer(), None);
assert_eq!(get_captured_locked_tokens(), None);
assert_eq!(get_captured_current_block(), None);

TestUtils::set_block_number(11);

TestUtils::assert_try_free_call_works(consumer.clone(), Declined(OutOfQuota));

assert_eq!(get_captured_consumer(), Some(consumer.clone()));
assert_eq!(get_captured_locked_tokens(), None);
assert_eq!(get_captured_current_block(), Some(11));

Expand All @@ -356,18 +361,20 @@ fn locked_token_info_and_current_block_number_will_be_passed_to_the_calculation_

TestUtils::assert_try_free_call_works(consumer.clone(), Granted(Succeeded));

assert_eq!(get_captured_consumer(), Some(consumer.clone()));
assert_eq!(get_captured_locked_tokens(), Some(locked_info.clone()));
assert_eq!(get_captured_current_block(), Some(55));


//// change locked info and try again
//// change locked info and try again, and change consumer

let new_locked_info = TestUtils::random_locked_info();
<LockedInfoByAccount<Test>>::insert(consumer.clone(), new_locked_info.clone());

// Block number is still 55 and quota is 1
TestUtils::assert_try_free_call_works(consumer.clone(), Declined(OutOfQuota));

assert_eq!(get_captured_consumer(), Some(consumer.clone()));
assert_eq!(get_captured_locked_tokens(), Some(new_locked_info));
assert_ne!(get_captured_locked_tokens(), Some(locked_info));
assert_eq!(get_captured_current_block(), Some(55));
Expand All @@ -385,7 +392,7 @@ fn boxed_call_will_be_passed_to_the_call_filter() {

ExtBuilder::default()
.windows_config(vec![WindowConfig::new(1, QuotaToWindowRatio::new(1))])
.quota_calculation(|_, _| Some(10))
.quota_calculation(|_, _, _| Some(10))
.call_filter(|call| {
CAPTURED_CALL.with(|x| *x.borrow_mut() = call.clone().into());
true
Expand Down Expand Up @@ -444,7 +451,7 @@ fn denied_if_call_filter_returns_false() {
ExtBuilder::default()
.windows_config(vec![WindowConfig::new(1, QuotaToWindowRatio::new(1))])
.call_filter(|_| ALLOW_CALLS.with(|b| b.borrow().clone()))
.quota_calculation(|_,_| Some(1000))
.quota_calculation(|_, _,_| Some(1000))
.build()
.execute_with(|| {
let consumer: AccountId = account("Consumer", 0, 0);
Expand Down Expand Up @@ -569,7 +576,7 @@ fn donot_exceed_the_allowed_quota_with_one_window() {
.windows_config(vec![
WindowConfig::new(20, QuotaToWindowRatio::new(1)),
])
.quota_calculation(|_, _| 5.into())
.quota_calculation(|_, _, _| 5.into())
.build()
.execute_with(|| {
let storage = TestUtils::capture_stats_storage();
Expand Down Expand Up @@ -610,7 +617,7 @@ fn donot_exceed_the_allowed_quota_with_one_window() {
fn consumer_with_quota_but_no_previous_usages() {
ExtBuilder::default()
.windows_config(vec![ WindowConfig::new(100, QuotaToWindowRatio::new(1)) ])
.quota_calculation(|_, _| Some(100))
.quota_calculation(|_, _, _| Some(100))
.build()
.execute_with(|| {
TestUtils::set_block_number(315);
Expand Down Expand Up @@ -656,7 +663,7 @@ fn consumer_with_quota_but_no_previous_usages() {
fn consumer_with_quota_and_have_previous_usages() {
ExtBuilder::default()
.windows_config(vec![ WindowConfig::new(50, QuotaToWindowRatio::new(1)) ])
.quota_calculation(|_, _| Some(34))
.quota_calculation(|_, _, _| Some(34))
.build()
.execute_with(|| {
let consumer: AccountId = account("Consumer", 0, 0);
Expand Down Expand Up @@ -722,7 +729,7 @@ fn consumer_with_quota_and_have_previous_usages() {
#[test]
fn testing_scenario_1() {
ExtBuilder::default()
.quota_calculation(|_,_| Some(55))
.quota_calculation(|_, _,_| Some(55))
.windows_config(vec![
WindowConfig::new(100, QuotaToWindowRatio::new(1)),
WindowConfig::new(20, QuotaToWindowRatio::new(3)),
Expand Down
17 changes: 10 additions & 7 deletions runtime/src/free_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub struct FreeCallsCalculationStrategy;
impl Default for FreeCallsCalculationStrategy { fn default() -> Self { Self } }
impl pallet_free_calls::QuotaCalculationStrategy<Runtime> for FreeCallsCalculationStrategy {
fn calculate(
consumer: <Runtime as frame_system::Config>::AccountId,
current_block: <Runtime as frame_system::Config>::BlockNumber,
locked_info: Option<LockedInfoOf<Runtime>>
) -> Option<NumberOfCalls> {
Expand Down Expand Up @@ -136,6 +137,7 @@ impl pallet_free_calls::QuotaCalculationStrategy<Runtime> for FreeCallsCalculati

#[cfg(test)]
mod tests {
use frame_benchmarking::account;
use pallet_locker_mirror::LockedInfoOf;
use pallet_free_calls::{NumberOfCalls, QuotaCalculationStrategy};
use crate::*;
Expand Down Expand Up @@ -228,37 +230,38 @@ mod tests {
};

///////////////////////////////////////
let consumer = || account("Dummy Consumer", 0, 0);

// no locked_info will returns none
assert_eq!(
FreeCallsCalculationStrategy::calculate(current_block, None),
FreeCallsCalculationStrategy::calculate(consumer(), current_block, None),
None,
);
assert_eq!(
FreeCallsCalculationStrategy::calculate(before_current_block, None),
FreeCallsCalculationStrategy::calculate(consumer(),before_current_block, None),
None,
);
assert_eq!(
FreeCallsCalculationStrategy::calculate(after_current_block, None),
FreeCallsCalculationStrategy::calculate(consumer(),after_current_block, None),
None,
);

assert_eq!(
FreeCallsCalculationStrategy::calculate(current_block, Some(locked_info)),
FreeCallsCalculationStrategy::calculate(consumer(),current_block, Some(locked_info)),
expected_quota,
);

// test expiration
assert_eq!(
FreeCallsCalculationStrategy::calculate(current_block, Some(locked_info_just_expired)),
FreeCallsCalculationStrategy::calculate(consumer(),current_block, Some(locked_info_just_expired)),
None,
);
assert_eq!(
FreeCallsCalculationStrategy::calculate(current_block, Some(locked_info_expired)),
FreeCallsCalculationStrategy::calculate(consumer(),current_block, Some(locked_info_expired)),
None,
);
assert_eq!(
FreeCallsCalculationStrategy::calculate(current_block, Some(locked_info_not_yet_expired)),
FreeCallsCalculationStrategy::calculate(consumer(),current_block, Some(locked_info_not_yet_expired)),
expected_quota,
);

Expand Down
6 changes: 4 additions & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub mod constants;
mod free_calls;

use constants::{currency::*, time::*};
use pallet_free_calls::WindowConfig;
use pallet_free_calls::{NumberOfCalls, WindowConfig};

/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
Expand Down Expand Up @@ -445,6 +445,7 @@ impl Contains<Call> for BaseFilter {

parameter_types! {
pub WindowsConfig: Vec<WindowConfig<BlockNumber>> = FREE_CALLS_WINDOWS_CONFIG.to_vec();
pub const FreeQuotaPerEligibleAccount: NumberOfCalls = 100;
}

impl pallet_free_calls::Config for Runtime {
Expand All @@ -453,8 +454,9 @@ impl pallet_free_calls::Config for Runtime {
type WindowsConfig = WindowsConfig;
type CallFilter = FreeCallsFilter;
type WeightInfo = ();
type QuotaCalculationStrategy = FreeCallsCalculationStrategy;
type QuotaCalculationStrategy = ();
type AccountsSetLimit = AccountsSetLimit;
type FreeQuotaPerEligibleAccount = FreeQuotaPerEligibleAccount;
}

impl pallet_locker_mirror::Config for Runtime {
Expand Down

0 comments on commit e00310e

Please sign in to comment.