-
Notifications
You must be signed in to change notification settings - Fork 86
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
IT: rewards to generic framework. Remove previous non-generic IT utilities #1805
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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>() { | ||
Comment on lines
+25
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be really cool having this as a procedural macro: #[test_for_runtimes(all)]
fn block_rewards_api() {
// ...
} I think it should not be complicated, and we can leave this much more legible There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be awesome! |
||
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(); | ||
Comment on lines
+122
to
+125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't call this in @wischli, do you have any idea why this happens? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In terms of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks so much for this answer @wischli, it helps me a lot! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wischli, do you think we should align this for all runtimes? Why we are not using collator allowlist for dev? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Functionally, it does not make sense to me to add an extra gate to collators for our dev runtime IMO. I suppose the only achievement for us would be that this test works for all runtimes? I definitely dont want to block your proposal, just questioning the effort. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nono, it's not needed for the test; we can discriminate the behavior per runtime (at least it seems so by now). I asked because |
||
} | ||
|
||
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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW, I've been playing with this and I've substituted If you have some thoughts against it @wischli , I can revert this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thats a perfect replacement and upgrade! Thanks a lot. |
||
|
||
/* 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(); | ||
*/ | ||
Comment on lines
+139
to
+160
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 99% of developers can not fix this nor saying what's happening here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have a solution at hand right now, would have to debug that myself. Can look into that next week, if desired. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks William. My guess is that something weird is happening with the |
||
|
||
/* // 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() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it, thanks!