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

Free calls pallet #181

Closed
wants to merge 79 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
9fa1b4a
Free calls pallet
TarekkMA Jan 11, 2022
cef635b
Update pallet docs
TarekkMA Jan 11, 2022
7b7ee9e
Update pallet docs
TarekkMA Jan 11, 2022
dbfa654
ignore zero ratio and zero period config
TarekkMA Jan 13, 2022
e467596
rename dir
TarekkMA Jan 13, 2022
3a41200
revert formatting changes
TarekkMA Jan 13, 2022
a132cf1
small formatting
TarekkMA Jan 13, 2022
7e5d7e3
Add QuotaChanged event
TarekkMA Jan 18, 2022
ea15b37
feedback comments
TarekkMA Jan 19, 2022
a3187e1
Update runtime/src/lib.rs
TarekkMA Jan 19, 2022
17c42ab
Update runtime/Cargo.toml
TarekkMA Jan 19, 2022
463d802
move config filtering into a separate function
TarekkMA Jan 19, 2022
c0c1187
rename WindowStats
TarekkMA Jan 19, 2022
6559e7c
add free-calls types.json
TarekkMA Jan 20, 2022
423854c
Move configs from vec to const slice
TarekkMA Jan 21, 2022
9c7c1de
Return false on zero period/ratio
TarekkMA Jan 24, 2022
bac8a86
Check on compile-time that the configs are optimized and correct
TarekkMA Jan 24, 2022
c35d620
Remove check on each dipatch call
TarekkMA Jan 24, 2022
b48b47b
Optionally update account stats
TarekkMA Jan 24, 2022
c16811c
SignedExtension
TarekkMA Jan 24, 2022
d236787
Benchmarking for free-calls
TarekkMA Jan 25, 2022
859d50e
Add a CallFilter
TarekkMA Jan 26, 2022
e3f3472
Small fix for mocks.rs
TarekkMA Jan 26, 2022
dc28b13
Add locked mirror pallet
TarekkMA Jan 26, 2022
9fdd790
Add locker mirror to the runtime
TarekkMA Jan 26, 2022
bd8a5c8
Link locker mirror with free_calls pallet
TarekkMA Jan 26, 2022
ffe2493
Fix free_calls benchmarking.rs
TarekkMA Jan 27, 2022
be8ad9d
Add benchmarkings for LockerMirror
TarekkMA Jan 27, 2022
ac9a44a
fix comment to be a doc
TarekkMA Jan 27, 2022
b978aa3
Add some testing to locker-mirror
TarekkMA Jan 27, 2022
fc3128a
Naming fixes w/ Mr Beef
siman Jan 27, 2022
69414fb
Add BLOCK in time constants mod
TarekkMA Jan 28, 2022
9cd6ff4
allow non_snake_case
TarekkMA Jan 28, 2022
7c159b8
rename account to consumers
TarekkMA Jan 28, 2022
cdb2eef
Merge branch 'tarekkma/free-calls' of https://github.com/TarekkMA/sub…
TarekkMA Jan 28, 2022
dfffd10
Fix time constants
TarekkMA Jan 28, 2022
fb93a5b
Rename to WindowType
TarekkMA Jan 28, 2022
175449f
rename can_be_called
TarekkMA Jan 28, 2022
f0eea4a
rename to OracleOrigin
TarekkMA Jan 28, 2022
6de4935
Pass LockedInfo object to the extrinsic
TarekkMA Jan 31, 2022
821e46a
Add a LockedInfoOf type
TarekkMA Jan 31, 2022
fe73bdb
refactor accounts to functions
TarekkMA Jan 31, 2022
3e457f3
tests to locker-mirror
TarekkMA Jan 31, 2022
fb7d0a0
locker-mirror tests
TarekkMA Jan 31, 2022
990c026
locker-mirror tests
TarekkMA Feb 1, 2022
a23b8b9
locker-mirror tests
TarekkMA Feb 1, 2022
9c3e1ec
add non-zero for QuotaToWindowRatio
TarekkMA Feb 1, 2022
5e1039f
move to ExtBuilder
TarekkMA Feb 2, 2022
2a08434
customize oracle origin for each test
TarekkMA Feb 3, 2022
b4f72a7
add const_panic
TarekkMA Feb 3, 2022
edf4546
const_panic not needed for new rust versions
TarekkMA Feb 3, 2022
2daf90b
fix benchmarking test
TarekkMA Feb 3, 2022
a14485f
fix benchmarking test & make WindowsConfig as Vec
TarekkMA Feb 3, 2022
9166ae2
start testing free-calls pallet
TarekkMA Feb 3, 2022
1c5dc45
free-calls tests
TarekkMA Feb 3, 2022
340b2e6
free-calls tests
TarekkMA Feb 3, 2022
656ffaf
free-calls tests
TarekkMA Feb 3, 2022
fa92bff
free-calls tests
TarekkMA Feb 3, 2022
2f557c2
free-call testing_scenario_1
TarekkMA Feb 4, 2022
122ed40
test refactorings
TarekkMA Feb 4, 2022
191dad3
test refactorings
TarekkMA Feb 4, 2022
8b1f6b6
fix QuotaCalculationStrategy
TarekkMA Feb 7, 2022
89d8d6d
refactored can_make_free_call
TarekkMA Feb 7, 2022
6b6eb6a
Use BoundedVec & refactorings
TarekkMA Feb 7, 2022
9ca4494
Fix weight calculation
TarekkMA Feb 7, 2022
58858dd
Test try_free_call dispatchable
TarekkMA Feb 8, 2022
2116eaf
Refactor testing to test the dispatchable
TarekkMA Feb 8, 2022
4934e5d
Add doc about FreeCallsPrevalidation
TarekkMA Feb 8, 2022
599f10f
separate update stats from check free calls
TarekkMA Feb 8, 2022
3fd66cf
test the call filter
TarekkMA Feb 8, 2022
d0ca3bd
test the call filter
TarekkMA Feb 8, 2022
745f4ec
rename Outcome to Scenario
TarekkMA Feb 8, 2022
e576e72
use bool_to_option
TarekkMA Feb 9, 2022
5060fa5
add note about free calls filter
TarekkMA Feb 9, 2022
4cf11ff
last processed parachain event
TarekkMA Feb 9, 2022
9979464
Add new calculation strategy
TarekkMA Feb 9, 2022
48d9df9
Change LockedInfo struct
TarekkMA Feb 10, 2022
113699e
New QuotaCalculationStrategy
TarekkMA Feb 11, 2022
3d3ef21
Signed Ext testing
TarekkMA Feb 11, 2022
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
Prev Previous commit
Next Next commit
Test try_free_call dispatchable
  • Loading branch information
TarekkMA committed Feb 8, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 58858ddaa96708beca5d9e3fa5d8514e1fb3d66d
4 changes: 4 additions & 0 deletions pallets/free-calls/src/lib.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@

use codec::{Decode, Encode};
use frame_support::ensure;
use frame_support::log::info;
use frame_support::traits::IsSubType;
use sp_runtime::{
traits::{DispatchInfoOf, SignedExtension, Saturating},
@@ -29,6 +30,9 @@ mod mock;
#[cfg(test)]
mod tests;

#[cfg(test)]
mod test_pallet;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
mod weights;
25 changes: 23 additions & 2 deletions pallets/free-calls/src/mock.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,9 @@ use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup}, testing::Header, Storage
};

use crate as pallet_free_calls;
pub use crate as pallet_free_calls;

use crate::test_pallet;

use frame_support::{
parameter_types,
@@ -52,6 +54,7 @@ frame_support::construct_runtime!(
FreeCalls: pallet_free_calls::{Pallet, Call, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
LockerMirror: pallet_locker_mirror::{Pallet, Call, Storage, Event<T>},
TestPallet: test_pallet::{Pallet, Call, Storage, Event<T>},
}
);

@@ -60,8 +63,22 @@ parameter_types! {
pub const SS58Prefix: u8 = 28;
}

pub struct TestBaseCallFilter;
impl Contains<Call> for TestBaseCallFilter {
fn contains(c: &Call) -> bool {
match *c {
Call::FreeCalls(_) => true,
// For benchmarking, this acts as a noop call
Call::System(frame_system::Call::remark { .. }) => true,
// For tests
Call::TestPallet(_) => true,
_ => false,
}
}
}

impl system::Config for Test {
type BaseCallFilter = ();
type BaseCallFilter = TestBaseCallFilter;
type BlockWeights = ();
type BlockLength = ();
type Origin = Origin;
@@ -110,6 +127,10 @@ impl pallet_locker_mirror::Config for Test {
type WeightInfo = ();
}

impl test_pallet::Config for Test {
type Event = Event;
}

////// Free Call Dependencies


70 changes: 70 additions & 0 deletions pallets/free-calls/src/test_pallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! Just a dummy pallet to use during the tests
#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_support::weights::PostDispatchInfo;
use frame_system::pallet_prelude::*;

#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}

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


#[pallet::storage]
#[pallet::getter(fn something)]
pub type Something<T> = StorageValue<_, u32>;


#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
ValueStored(u32, T::AccountId),
}

#[pallet::error]
pub enum Error<T> {
DoNotCallMe,
DoNotSendZero,
}


#[pallet::call]
impl<T: Config> Pallet<T> {

#[pallet::weight(10_000)]
pub fn store_value(origin: OriginFor<T>, something: u32) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;

ensure!(something != 0, Error::<T>::DoNotSendZero);

// Update storage.
<Something<T>>::put(something);

// Emit an event.
Self::deposit_event(Event::ValueStored(something, who));

Ok(PostDispatchInfo {
actual_weight: Some(50_000),
pays_fee: Pays::Yes,
})
}

#[pallet::weight(10_000)]
pub fn cause_error(origin: OriginFor<T>) -> DispatchResult {
let _who = ensure_signed(origin)?;

ensure!(false, Error::<T>::DoNotCallMe);

Ok(())
}
}
}
209 changes: 202 additions & 7 deletions pallets/free-calls/src/tests.rs
Original file line number Diff line number Diff line change
@@ -2,16 +2,25 @@ use std::borrow::Borrow;
use std::cell::RefCell;
use std::convert::TryInto;
use frame_benchmarking::account;
use frame_support::{assert_err, assert_ok, BoundedVec};
use frame_system::EventRecord;
use frame_support::{assert_err, assert_noop, assert_ok, assert_storage_noop, BoundedVec, debug};
use frame_support::log::info;
use frame_support::weights::{extract_actual_weight, Pays, PostDispatchInfo};
use frame_system::{EventRecord, Events};
use pallet_locker_mirror::{BalanceOf, LockedInfoByAccount, LockedInfoOf};
use crate::mock::*;
use rand::Rng;
use sp_core::crypto::UncheckedInto;
use sp_runtime::testing::H256;
use subsocial_primitives::Block;
use crate::{ConsumerStats, ConsumerStatsVec, NumberOfCalls, pallet as free_calls, Pallet, QuotaToWindowRatio, ShouldUpdateConsumerStats, WindowConfig};
use crate::{ConsumerStats, ConsumerStatsVec, NumberOfCalls, pallet as free_calls, Pallet, QuotaToWindowRatio, ShouldUpdateConsumerStats, test_pallet, WindowConfig};
use crate::WindowStatsByConsumer;
use frame_support::weights::GetDispatchInfo;
use crate::test_pallet::Something;
use crate::weights::WeightInfo;
pub use sp_io::{self, storage::root as storage_root};
use test_pallet::Call as TestPalletCall;
use frame_system::Call as SystemCall;
use sp_runtime::traits::{Dispatchable};

pub struct TestUtils;
impl TestUtils {
@@ -20,7 +29,28 @@ impl TestUtils {
}

pub fn system_events() -> Vec<EventRecord<Event, H256>> {
<frame_system::Pallet<Test>>::events()
<Events<Test>>::get()
}

pub fn clear_system_events() {
<Events<Test>>::kill();
assert!(TestUtils::system_events().is_empty());
}

pub fn take_n_system_events(n: usize) -> Vec<Event> {
assert!(TestUtils::system_events().len() >= n);

let mut v: Vec<Event> = vec![];
<Events<Test>>::mutate(|events| {
for _ in 0..n {
v.push(events.pop().unwrap().event);
}
});

// restore order
v.reverse();

v
}

pub fn capture_stats_storage() -> Vec<(AccountId, Vec<ConsumerStats<BlockNumber>>)> {
@@ -66,6 +96,10 @@ impl TestUtils {
assert!(TestUtils::compare_ignore_order(&old_storage, &TestUtils::capture_stats_storage()))
}

pub fn assert_storage_have_change(old_storage: Vec<(AccountId, Vec<ConsumerStats<BlockNumber>>)>) {
assert!(!TestUtils::compare_ignore_order(&old_storage, &TestUtils::capture_stats_storage()))
}

pub fn assert_no_new_events() {
assert!(TestUtils::system_events().is_empty());
}
@@ -83,6 +117,131 @@ impl TestUtils {

return true;
}

pub fn assert_try_free_call_granted_and_succeed(consumer: <Test as frame_system::Config>::AccountId) {
let something = 121;

// just a dummy call that should succeed
let call: Box<Call> = Box::new(Call::TestPallet(TestPalletCall::<Test>::store_value(something)));

TestUtils::clear_system_events();

let stats_storage = TestUtils::capture_stats_storage();

let result = <Pallet<Test>>::try_free_call(Origin::signed(consumer), call.clone());

TestUtils::assert_storage_have_change(stats_storage);

// The free call should not return any error
assert_ok!(result);

let result: PostDispatchInfo = result.unwrap();

assert_eq!(
result.pays_fee,
Pays::No,
"The caller should not pay",
);

// check that storage mutation is applied
assert_eq!(
<Something<Test>>::get(),
Some(something),
"Something storage should have mutated to have {}", something,
);

let mut events: Vec<Event> = TestUtils::take_n_system_events(2);
assert!(TestUtils::system_events().is_empty(), "Only 2 events should be emitted");

assert_eq!(
events.pop().unwrap(),
Event::from(pallet_free_calls::Event::FreeCallResult(consumer.clone(), Ok(()))),
);

assert_eq!(
events.pop().unwrap(),
Event::from(test_pallet::Event::ValueStored(something, consumer.clone())),
);
}


pub fn assert_try_free_call_granted_and_failed(consumer: <Test as frame_system::Config>::AccountId) {
let old_something = <Something<Test>>::get();
let something = 0;

// just a dummy call that should succeed
let call: Box<Call> = Box::new(Call::TestPallet(TestPalletCall::<Test>::store_value(something)));

TestUtils::clear_system_events();

let stats_storage = TestUtils::capture_stats_storage();

let result = <Pallet<Test>>::try_free_call(Origin::signed(consumer), call.clone());

TestUtils::assert_storage_have_change(stats_storage);

// The free call should not return any error
assert_ok!(result);

let result: PostDispatchInfo = result.unwrap();

assert_eq!(
result.pays_fee,
Pays::No,
"The caller should not pay",
);

// check that storage mutation is not applied
assert_eq!(
<Something<Test>>::get(),
old_something,
"nothing should be changed",
);

let mut events: Vec<Event> = TestUtils::take_n_system_events(1);
assert!(TestUtils::system_events().is_empty(), "Only 1 events should be emitted");

assert_eq!(
events.pop().unwrap(),
Event::from(pallet_free_calls::Event::FreeCallResult(consumer.clone(), Err(test_pallet::Error::<Test>::DoNotSendZero.into()))),
);
}


pub fn assert_try_free_call_declined(consumer: <Test as frame_system::Config>::AccountId) {
let old_something = <Something<Test>>::get();
let something = 234;

// just a dummy call that should succeed
let call: Box<Call> = Box::new(Call::TestPallet(TestPalletCall::<Test>::store_value(something)));

TestUtils::clear_system_events();


assert_storage_noop!({
let result = <Pallet<Test>>::try_free_call(Origin::signed(consumer), call.clone());
assert_ok!(result);

// The free call should not return any error

let result: PostDispatchInfo = result.unwrap();

assert_eq!(
result.pays_fee,
Pays::No,
"The caller should not pay",
);

// check that storage mutation is not applied
assert_eq!(
<Something<Test>>::get(),
old_something,
"nothing should be changed",
);

assert!(TestUtils::system_events().is_empty(), "No events should be emitted");
});
}
}

////////////////// Begin Testing ///////////////////////
@@ -91,11 +250,47 @@ impl TestUtils {
fn dummy() {
// just make sure everything is okay
ExtBuilder::default()
.build()
.execute_with(|| {
assert_eq!(1 + 1, 2);

// events are empty at the start
assert!(TestUtils::system_events().is_empty());
});

ExtBuilder::default()
.windows_config(vec![
WindowConfig::new(1, QuotaToWindowRatio::new(1)),
])
.quota_calculation(|_, _| 100.into())
.build().execute_with(|| {
assert_eq!(1 + 1, 2);
let consumer: AccountId = account("Consumer", 2, 1);

// events are empty at the start
assert!(TestUtils::system_events().is_empty());
let can_have_free_call = <Pallet<Test>>::can_make_free_call(
&consumer,
ShouldUpdateConsumerStats::NO,
);
assert!(can_have_free_call);

TestUtils::assert_try_free_call_granted_and_succeed(consumer.clone());
TestUtils::assert_try_free_call_granted_and_failed(consumer.clone());
});

ExtBuilder::default()
.windows_config(vec![
WindowConfig::new(1, QuotaToWindowRatio::new(1)),
])
.quota_calculation(|_, _| None)
.build().execute_with(|| {
let consumer: AccountId = account("Consumer", 2, 1);

let can_have_free_call = <Pallet<Test>>::can_make_free_call(
&consumer,
ShouldUpdateConsumerStats::NO,
);
assert_eq!(can_have_free_call, false);

TestUtils::assert_try_free_call_declined(consumer.clone());
});
}