Skip to content

Commit

Permalink
IT: rewards to generic framework. Remove previous non-generic IT util…
Browse files Browse the repository at this point in the history
…ities (#1805)

* test working

* clear previous testing framework

* give support for altair and centrifuge
  • Loading branch information
lemunozm authored Apr 19, 2024
1 parent 430fbe9 commit 97cb823
Show file tree
Hide file tree
Showing 32 changed files with 386 additions and 2,656 deletions.
2 changes: 1 addition & 1 deletion ci/run-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ case $TARGET in
;;

test-integration)
cargo test --release --package runtime-integration-tests --features fast-runtime
cargo test --release --package runtime-integration-tests
;;

lint-fmt)
Expand Down
8 changes: 4 additions & 4 deletions runtime/altair/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ use runtime_common::{
GAS_LIMIT_STORAGE_GROWTH_RATIO, WEIGHT_PER_GAS,
},
fees::{DealWithFees, FeeToTreasury, WeightToFee},
gateway,
gateway, instances,
liquidity_pools::LiquidityPoolsMessage,
oracle::{
Feeder, OracleConverterBridge, OracleRatioProvider, OracleRatioProviderLocalAssetExtension,
Expand Down Expand Up @@ -1208,7 +1208,7 @@ parameter_types! {
pub const RewardCurrency: CurrencyId = CurrencyId::Native;
}

impl pallet_rewards::Config<pallet_rewards::Instance1> for Runtime {
impl pallet_rewards::Config<instances::BlockRewards> for Runtime {
type Currency = Tokens;
type CurrencyId = CurrencyId;
type GroupId = u32;
Expand Down Expand Up @@ -2309,14 +2309,14 @@ impl_runtime_apis! {
impl runtime_common::apis::RewardsApi<Block, AccountId, Balance, CurrencyId> for Runtime {
fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec<CurrencyId> {
match domain {
runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance1>::list_currencies(&account_id),
runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::<Runtime, instances::BlockRewards>::list_currencies(&account_id),
_ => vec![],
}
}

fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option<Balance> {
match domain {
runtime_common::apis::RewardDomain::Block => <pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance1> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
runtime_common::apis::RewardDomain::Block => <pallet_rewards::Pallet::<Runtime, instances::BlockRewards> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
_ => None,
}
}
Expand Down
8 changes: 4 additions & 4 deletions runtime/centrifuge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ use runtime_common::{
GAS_LIMIT_STORAGE_GROWTH_RATIO, WEIGHT_PER_GAS,
},
fees::{DealWithFees, FeeToTreasury, WeightToFee},
gateway,
gateway, instances,
liquidity_pools::LiquidityPoolsMessage,
oracle::{
Feeder, OracleConverterBridge, OracleRatioProvider, OracleRatioProviderLocalAssetExtension,
Expand Down Expand Up @@ -1222,7 +1222,7 @@ parameter_types! {
pub const RewardCurrency: CurrencyId = CurrencyId::Native;
}

impl pallet_rewards::Config<pallet_rewards::Instance1> for Runtime {
impl pallet_rewards::Config<instances::BlockRewards> for Runtime {
type Currency = Tokens;
type CurrencyId = CurrencyId;
type GroupId = u32;
Expand Down Expand Up @@ -2357,14 +2357,14 @@ impl_runtime_apis! {
impl runtime_common::apis::RewardsApi<Block, AccountId, Balance, CurrencyId> for Runtime {
fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec<CurrencyId> {
match domain {
runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance1>::list_currencies(&account_id),
runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::<Runtime, instances::BlockRewards>::list_currencies(&account_id),
_ => vec![],
}
}

fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option<Balance> {
match domain {
runtime_common::apis::RewardDomain::Block => <pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance1> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
runtime_common::apis::RewardDomain::Block => <pallet_rewards::Pallet::<Runtime, instances::BlockRewards> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
_ => None,
}
}
Expand Down
5 changes: 5 additions & 0 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ use sp_runtime::{
};
use sp_std::marker::PhantomData;

pub mod instances {
/// The rewards associated to block rewards
pub type BlockRewards = pallet_rewards::Instance1;
}

parameter_types! {
/// The native currency identifier of our currency id enum
/// to be used for Get<CurrencyId> types.
Expand Down
8 changes: 4 additions & 4 deletions runtime/development/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ use runtime_common::{
GAS_LIMIT_STORAGE_GROWTH_RATIO, WEIGHT_PER_GAS,
},
fees::{DealWithFees, FeeToTreasury, WeightToFee},
gateway,
gateway, instances,
liquidity_pools::LiquidityPoolsMessage,
oracle::{
Feeder, OracleConverterBridge, OracleRatioProvider, OracleRatioProviderLocalAssetExtension,
Expand Down Expand Up @@ -1707,7 +1707,7 @@ impl pallet_liquidity_rewards::Config for Runtime {
type WeightInfo = ();
}

impl pallet_rewards::Config<pallet_rewards::Instance1> for Runtime {
impl pallet_rewards::Config<instances::BlockRewards> for Runtime {
type Currency = Tokens;
type CurrencyId = CurrencyId;
type GroupId = u32;
Expand Down Expand Up @@ -2396,14 +2396,14 @@ impl_runtime_apis! {
impl runtime_common::apis::RewardsApi<Block, AccountId, Balance, CurrencyId> for Runtime {
fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec<CurrencyId> {
match domain {
runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance1>::list_currencies(&account_id),
runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::<Runtime, instances::BlockRewards>::list_currencies(&account_id),
runtime_common::apis::RewardDomain::Liquidity => pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance2>::list_currencies(&account_id),
}
}

fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option<Balance> {
match domain {
runtime_common::apis::RewardDomain::Block => <pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance1> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
runtime_common::apis::RewardDomain::Block => <pallet_rewards::Pallet::<Runtime, instances::BlockRewards> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
runtime_common::apis::RewardDomain::Liquidity => <pallet_rewards::Pallet::<Runtime, pallet_rewards::Instance2> as cfg_traits::rewards::AccountRewards<AccountId>>::compute_reward(currency_id, &account_id).ok(),
}
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ pallet-xcm-transactor = { workspace = true, features = ["std"] }
parachain-info = { workspace = true, features = ["std"] }

[features]
# There is no need for integration test to add new features.
# Just add the required ones to default:
default = [
"development-runtime/instant-voting",
]

fast-runtime = ["development-runtime/fast-runtime"]
216 changes: 216 additions & 0 deletions runtime/integration-tests/src/generic/cases/block_rewards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
use cfg_primitives::{AccountId, CFG};
use cfg_traits::rewards::{AccountRewards, CurrencyGroupChange, DistributedRewards};
use cfg_types::tokens::CurrencyId;
use frame_support::{assert_ok, dispatch::RawOrigin};
use runtime_common::{
apis::{runtime_decl_for_rewards_api::RewardsApiV1, RewardDomain},
instances::BlockRewards,
};
use sp_runtime::traits::{Get, Zero};

use crate::{
generic::{
config::{Runtime, RuntimeKind},
env::Env,
envs::runtime_env::RuntimeEnv,
utils,
utils::{
currency::cfg,
genesis::{self, Genesis},
},
},
utils::accounts::{default_accounts, Keyring},
};

crate::test_for_runtimes!(all, block_rewards_api);
fn block_rewards_api<T: Runtime>() {
const STAKER: Keyring = Keyring::Alice;

RuntimeEnv::<T>::default().parachain_state_mut(|| {
let group_id = 1u32;
let amount = 100 * CFG;

utils::give_balance::<T>(STAKER.id(), T::ExistentialDeposit::get() + amount);

assert_ok!(pallet_rewards::Pallet::<T, BlockRewards>::attach_currency(
CurrencyId::Native,
group_id,
));

assert_ok!(pallet_rewards::Pallet::<T, BlockRewards>::deposit_stake(
CurrencyId::Native,
&STAKER.id(),
amount,
));

assert_ok!(
pallet_rewards::Pallet::<T, BlockRewards>::distribute_reward(200 * CFG, [group_id])
);

assert_eq!(
T::Api::list_currencies(RewardDomain::Block, STAKER.id()),
vec![CurrencyId::Native]
);

assert_eq!(
T::Api::compute_reward(RewardDomain::Block, CurrencyId::Native, STAKER.id()),
Some(200 * CFG)
)
});
}

crate::test_for_runtimes!(
[development, altair, centrifuge],
collator_list_synchronized
);
fn collator_list_synchronized<T: Runtime>() {
RuntimeEnv::<T>::from_parachain_storage(
Genesis::default()
.add(genesis::balances::<T>(
T::ExistentialDeposit::get() + cfg(100),
))
.add(genesis::invulnerables::<T>(vec![Keyring::Admin]))
.add(genesis::session_keys::<T>())
.add(genesis::block_rewards::<T>(vec![Keyring::Admin]))
.storage(),
)
.parachain_state_mut(|| {
let collators_1 = vec![Keyring::Alice.id(), Keyring::Bob.id()];
let collators_2 = vec![
Keyring::Charlie.id(),
Keyring::Dave.id(),
Keyring::Eve.id(),
Keyring::Ferdie.id(),
];

// altair and centrifuge use collator_allowlist,
// so we need to add the accounts there for them.
if T::KIND == RuntimeKind::Altair || T::KIND == RuntimeKind::Centrifuge {
for account in default_accounts() {
assert_ok!(pallet_collator_allowlist::Pallet::<T>::add(
RawOrigin::Root.into(),
account.id()
));
}
}

// SESSION 0 -> 1;
apply_and_check_session::<T>(1, collators_1.clone(), vec![]);

// SESSION 1 -> 2;
apply_and_check_session::<T>(3, collators_2.clone(), vec![]);

// SESSION 2 -> 3;
apply_and_check_session::<T>(7, vec![], vec![Keyring::Alice.id()]);

assert!(collators_1.iter().all(|c| has_reward::<T>(c)));
assert!(collators_2.iter().all(|c| !has_reward::<T>(c)));

// SESSION 3 -> 4;
apply_and_check_session::<T>(6, vec![], vec![]);

assert!(collators_2.iter().all(|c| has_reward::<T>(c)));
});
}

fn apply_and_check_session<T: Runtime>(
collator_count: u32,
joining: Vec<AccountId>,
leaving: Vec<AccountId>,
) {
for collator in &joining {
pallet_collator_selection::Pallet::<T>::register_as_candidate(
RawOrigin::Signed(collator.clone()).into(),
)
.unwrap();
}

for collator in &leaving {
pallet_collator_selection::Pallet::<T>::leave_intent(
RawOrigin::Signed(collator.clone()).into(),
)
.unwrap();
}

frame_system::Pallet::<T>::reset_events();

pallet_session::Pallet::<T>::rotate_session();

/* TODO: pending to fix. Why try_into() fails getting the reward_event::GroupRewarded?
// The event exists in this list:
dbg!(frame_system::Pallet::<T>::events())
// But not in in this list (that is the implementation of find_event()),
// so try_into returns an Err for it.
dbg!(frame_system::Pallet::<T>::events()
.into_iter()
.rev()
.find_map(|record| record.event.try_into().ok())
.flatten());
// But later, if manually I create the event as follows:
let e = T::RuntimeEventExt::from(pallet_rewards::Event::<T, BlockRewards>::GroupRewarded {
group_id: 1,
amount: 2,
});
// And I call try_into(), it works.
let re: pallet_rewards::Event<T, BlockRewards> = e.try_into().ok().unwrap();
*/

/* // Uncomment once fix the above issue
utils::find_event::<T, _, _>(|e| match e {
pallet_rewards::Event::<_, BlockRewards>::GroupRewarded { .. } => Some(true),
_ => None,
})
.unwrap();
*/

utils::find_event::<T, _, _>(|e| match e {
pallet_block_rewards::Event::NewSession { .. } => Some(true),
_ => None,
})
.unwrap();

// Checks post applying new session:

assert_eq!(
pallet_block_rewards::Pallet::<T>::active_session_data().collator_count,
collator_count,
);

if !joining.is_empty() || !leaving.is_empty() {
assert_eq!(
pallet_block_rewards::Pallet::<T>::next_session_changes().collator_count,
Some(collator_count + joining.len() as u32 - leaving.len() as u32)
);
}

let next_collators = pallet_block_rewards::Pallet::<T>::next_session_changes().collators;
assert_eq!(*next_collators.inc, joining);
assert_eq!(*next_collators.out, leaving);

assert!(joining.iter().all(|c| !is_staked::<T>(c)));
assert!(joining.iter().all(|c| is_candidate::<T>(c)));
assert!(leaving.iter().all(|c| is_staked::<T>(c)));
assert!(leaving.iter().all(|c| !is_candidate::<T>(c)));
}

fn has_reward<T: Runtime>(collator: &AccountId) -> bool {
!pallet_rewards::Pallet::<T, BlockRewards>::compute_reward(T::StakeCurrencyId::get(), collator)
.unwrap()
.is_zero()
}

fn is_staked<T: Runtime>(collator: &AccountId) -> bool {
!pallet_rewards::Pallet::<T, BlockRewards>::account_stake(T::StakeCurrencyId::get(), collator)
.is_zero()
}

fn is_candidate<T: Runtime>(collator: &AccountId) -> bool {
pallet_collator_selection::Pallet::<T>::candidates()
.into_iter()
.find(|c| c.who == *collator)
.is_some()
}
Loading

0 comments on commit 97cb823

Please sign in to comment.