diff --git a/ci/run-check.sh b/ci/run-check.sh index d9e866ef07..167786a49f 100755 --- a/ci/run-check.sh +++ b/ci/run-check.sh @@ -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) diff --git a/runtime/altair/src/lib.rs b/runtime/altair/src/lib.rs index 6258ffe2c9..4aa5e3bf40 100644 --- a/runtime/altair/src/lib.rs +++ b/runtime/altair/src/lib.rs @@ -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, @@ -1208,7 +1208,7 @@ parameter_types! { pub const RewardCurrency: CurrencyId = CurrencyId::Native; } -impl pallet_rewards::Config for Runtime { +impl pallet_rewards::Config for Runtime { type Currency = Tokens; type CurrencyId = CurrencyId; type GroupId = u32; @@ -2309,14 +2309,14 @@ impl_runtime_apis! { impl runtime_common::apis::RewardsApi for Runtime { fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec { match domain { - runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), + runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), _ => vec![], } } fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option { match domain { - runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), _ => None, } } diff --git a/runtime/centrifuge/src/lib.rs b/runtime/centrifuge/src/lib.rs index 226515c0bf..f31ab882d1 100644 --- a/runtime/centrifuge/src/lib.rs +++ b/runtime/centrifuge/src/lib.rs @@ -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, @@ -1222,7 +1222,7 @@ parameter_types! { pub const RewardCurrency: CurrencyId = CurrencyId::Native; } -impl pallet_rewards::Config for Runtime { +impl pallet_rewards::Config for Runtime { type Currency = Tokens; type CurrencyId = CurrencyId; type GroupId = u32; @@ -2357,14 +2357,14 @@ impl_runtime_apis! { impl runtime_common::apis::RewardsApi for Runtime { fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec { match domain { - runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), + runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), _ => vec![], } } fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option { match domain { - runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), _ => None, } } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index aa542820bb..673b2bb54d 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -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 types. diff --git a/runtime/development/src/lib.rs b/runtime/development/src/lib.rs index 18c589ce7e..b4e7b5dccc 100644 --- a/runtime/development/src/lib.rs +++ b/runtime/development/src/lib.rs @@ -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, @@ -1707,7 +1707,7 @@ impl pallet_liquidity_rewards::Config for Runtime { type WeightInfo = (); } -impl pallet_rewards::Config for Runtime { +impl pallet_rewards::Config for Runtime { type Currency = Tokens; type CurrencyId = CurrencyId; type GroupId = u32; @@ -2396,14 +2396,14 @@ impl_runtime_apis! { impl runtime_common::apis::RewardsApi for Runtime { fn list_currencies(domain: runtime_common::apis::RewardDomain, account_id: AccountId) -> Vec { match domain { - runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), + runtime_common::apis::RewardDomain::Block => pallet_rewards::Pallet::::list_currencies(&account_id), runtime_common::apis::RewardDomain::Liquidity => pallet_rewards::Pallet::::list_currencies(&account_id), } } fn compute_reward(domain: runtime_common::apis::RewardDomain, currency_id: CurrencyId, account_id: AccountId) -> Option { match domain { - runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), + runtime_common::apis::RewardDomain::Block => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), runtime_common::apis::RewardDomain::Liquidity => as cfg_traits::rewards::AccountRewards>::compute_reward(currency_id, &account_id).ok(), } } diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index c394a86de7..272647696d 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -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"] diff --git a/runtime/integration-tests/src/generic/cases/block_rewards.rs b/runtime/integration-tests/src/generic/cases/block_rewards.rs new file mode 100644 index 0000000000..dedd921592 --- /dev/null +++ b/runtime/integration-tests/src/generic/cases/block_rewards.rs @@ -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() { + const STAKER: Keyring = Keyring::Alice; + + RuntimeEnv::::default().parachain_state_mut(|| { + let group_id = 1u32; + let amount = 100 * CFG; + + utils::give_balance::(STAKER.id(), T::ExistentialDeposit::get() + amount); + + assert_ok!(pallet_rewards::Pallet::::attach_currency( + CurrencyId::Native, + group_id, + )); + + assert_ok!(pallet_rewards::Pallet::::deposit_stake( + CurrencyId::Native, + &STAKER.id(), + amount, + )); + + assert_ok!( + pallet_rewards::Pallet::::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() { + RuntimeEnv::::from_parachain_storage( + Genesis::default() + .add(genesis::balances::( + T::ExistentialDeposit::get() + cfg(100), + )) + .add(genesis::invulnerables::(vec![Keyring::Admin])) + .add(genesis::session_keys::()) + .add(genesis::block_rewards::(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::::add( + RawOrigin::Root.into(), + account.id() + )); + } + } + + // SESSION 0 -> 1; + apply_and_check_session::(1, collators_1.clone(), vec![]); + + // SESSION 1 -> 2; + apply_and_check_session::(3, collators_2.clone(), vec![]); + + // SESSION 2 -> 3; + apply_and_check_session::(7, vec![], vec![Keyring::Alice.id()]); + + assert!(collators_1.iter().all(|c| has_reward::(c))); + assert!(collators_2.iter().all(|c| !has_reward::(c))); + + // SESSION 3 -> 4; + apply_and_check_session::(6, vec![], vec![]); + + assert!(collators_2.iter().all(|c| has_reward::(c))); + }); +} + +fn apply_and_check_session( + collator_count: u32, + joining: Vec, + leaving: Vec, +) { + for collator in &joining { + pallet_collator_selection::Pallet::::register_as_candidate( + RawOrigin::Signed(collator.clone()).into(), + ) + .unwrap(); + } + + for collator in &leaving { + pallet_collator_selection::Pallet::::leave_intent( + RawOrigin::Signed(collator.clone()).into(), + ) + .unwrap(); + } + + frame_system::Pallet::::reset_events(); + + pallet_session::Pallet::::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::::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::::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::::GroupRewarded { + group_id: 1, + amount: 2, + }); + + // And I call try_into(), it works. + let re: pallet_rewards::Event = e.try_into().ok().unwrap(); + */ + + /* // Uncomment once fix the above issue + utils::find_event::(|e| match e { + pallet_rewards::Event::<_, BlockRewards>::GroupRewarded { .. } => Some(true), + _ => None, + }) + .unwrap(); + */ + + utils::find_event::(|e| match e { + pallet_block_rewards::Event::NewSession { .. } => Some(true), + _ => None, + }) + .unwrap(); + + // Checks post applying new session: + + assert_eq!( + pallet_block_rewards::Pallet::::active_session_data().collator_count, + collator_count, + ); + + if !joining.is_empty() || !leaving.is_empty() { + assert_eq!( + pallet_block_rewards::Pallet::::next_session_changes().collator_count, + Some(collator_count + joining.len() as u32 - leaving.len() as u32) + ); + } + + let next_collators = pallet_block_rewards::Pallet::::next_session_changes().collators; + assert_eq!(*next_collators.inc, joining); + assert_eq!(*next_collators.out, leaving); + + assert!(joining.iter().all(|c| !is_staked::(c))); + assert!(joining.iter().all(|c| is_candidate::(c))); + assert!(leaving.iter().all(|c| is_staked::(c))); + assert!(leaving.iter().all(|c| !is_candidate::(c))); +} + +fn has_reward(collator: &AccountId) -> bool { + !pallet_rewards::Pallet::::compute_reward(T::StakeCurrencyId::get(), collator) + .unwrap() + .is_zero() +} + +fn is_staked(collator: &AccountId) -> bool { + !pallet_rewards::Pallet::::account_stake(T::StakeCurrencyId::get(), collator) + .is_zero() +} + +fn is_candidate(collator: &AccountId) -> bool { + pallet_collator_selection::Pallet::::candidates() + .into_iter() + .find(|c| c.who == *collator) + .is_some() +} diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 0e99907f03..b84d5cd14b 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -27,7 +27,7 @@ fn transfer_balance() { Genesis::default() .add(pallet_balances::GenesisConfig:: { balances: vec![( - Keyring::Alice.to_account_id(), + Keyring::Alice.id(), T::ExistentialDeposit::get() + FOR_FEES + TRANSFER, )], }) @@ -47,8 +47,8 @@ fn transfer_balance() { // Check for an even occurred in this block env.check_event(pallet_balances::Event::Transfer { - from: Keyring::Alice.to_account_id(), - to: Keyring::Bob.to_account_id(), + from: Keyring::Alice.id(), + to: Keyring::Bob.id(), amount: TRANSFER, }) .unwrap(); @@ -56,11 +56,11 @@ fn transfer_balance() { // Check the state env.parachain_state(|| { assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), + pallet_balances::Pallet::::free_balance(Keyring::Alice.id()), T::ExistentialDeposit::get() + FOR_FEES - fee, ); assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), + pallet_balances::Pallet::::free_balance(Keyring::Bob.id()), TRANSFER ); }); @@ -78,7 +78,7 @@ fn fudge_transfer_balance() { Genesis::default() .add(pallet_balances::GenesisConfig:: { balances: vec![( - Keyring::Alice.to_account_id(), + Keyring::Alice.id(), T::ExistentialDeposit::get() + FOR_FEES + TRANSFER, )], }) @@ -99,8 +99,8 @@ fn fudge_transfer_balance() { // Check for an even occurred in this block env.check_event(pallet_balances::Event::Transfer { - from: Keyring::Alice.to_account_id(), - to: Keyring::Bob.to_account_id(), + from: Keyring::Alice.id(), + to: Keyring::Bob.id(), amount: TRANSFER, }) .unwrap(); @@ -118,11 +118,11 @@ fn fudge_transfer_balance() { // Check the state env.parachain_state(|| { assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), + pallet_balances::Pallet::::free_balance(Keyring::Alice.id()), T::ExistentialDeposit::get() + FOR_FEES - fee, ); assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), + pallet_balances::Pallet::::free_balance(Keyring::Bob.id()), TRANSFER ); }); diff --git a/runtime/integration-tests/src/generic/cases/liquidity_pools.rs b/runtime/integration-tests/src/generic/cases/liquidity_pools.rs index d5d8aa8b74..32ea52b414 100644 --- a/runtime/integration-tests/src/generic/cases/liquidity_pools.rs +++ b/runtime/integration-tests/src/generic/cases/liquidity_pools.rs @@ -1,6 +1,5 @@ use cfg_primitives::{ - currency_decimals, parachains, AccountId, Balance, CouncilCollective, OrderId, PoolId, - TrancheId, + currency_decimals, parachains, AccountId, Balance, OrderId, PoolId, TrancheId, }; use cfg_traits::{ investments::{Investment, OrderManager, TrancheCurrency}, @@ -78,9 +77,17 @@ use crate::{ genesis::Genesis, }, }, - utils::{accounts::Keyring, AUSD_CURRENCY_ID, AUSD_ED, USDT_CURRENCY_ID, USDT_ED}, + utils::accounts::Keyring, }; +/// The AUSD asset id +pub const AUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(3); +/// The USDT asset id +pub const USDT_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); + +pub const AUSD_ED: Balance = 1_000_000_000; +pub const USDT_ED: Balance = 10_000; + pub mod utils { use super::*; @@ -281,7 +288,7 @@ mod development { pub const DEFAULT_DOMAIN_ADDRESS_MOONBEAM: DomainAddress = DomainAddress::EVM(MOONBEAM_EVM_CHAIN_ID, DEFAULT_EVM_ADDRESS_MOONBEAM); pub const DEFAULT_OTHER_DOMAIN_ADDRESS: DomainAddress = - DomainAddress::EVM(crate::utils::MOONBEAM_EVM_CHAIN_ID, [0; 20]); + DomainAddress::EVM(MOONBEAM_EVM_CHAIN_ID, [0; 20]); pub type LiquidityPoolMessage = Message; @@ -1003,7 +1010,7 @@ mod development { // Finally, verify we can call pallet_liquidity_pools::Pallet::::add_tranche // successfully when given a valid pool + tranche id pair. - let new_member = DomainAddress::EVM(crate::utils::MOONBEAM_EVM_CHAIN_ID, [3; 20]); + let new_member = DomainAddress::EVM(MOONBEAM_EVM_CHAIN_ID, [3; 20]); // Make ALICE the MembersListAdmin of this Pool assert_ok!(pallet_permissions::Pallet::::add( @@ -4769,9 +4776,7 @@ mod development { let mut env = FudgeEnv::::from_parachain_storage( Genesis::default() .add(genesis::balances::(cfg(1_000))) - .add(genesis::council_members::( - get_council_members(), - )) + .add(genesis::council_members::(get_council_members())) .storage(), ); @@ -4955,7 +4960,7 @@ mod development { interior: X1(Parachain(T::FudgeHandle::SIBLING_ID)), } .into(), - crate::utils::GLMR_CURRENCY_ID, + GLMR_CURRENCY_ID, ); assert_ok!( @@ -5094,9 +5099,7 @@ mod development { let mut env = FudgeEnv::::from_parachain_storage( Genesis::default() .add(genesis::balances::(cfg(1_000))) - .add(genesis::council_members::( - get_council_members(), - )) + .add(genesis::council_members::(get_council_members())) .storage(), ); @@ -5165,9 +5168,7 @@ mod development { let mut env = FudgeEnv::::from_parachain_storage( Genesis::default() .add(genesis::balances::(cfg(1_000))) - .add(genesis::council_members::( - get_council_members(), - )) + .add(genesis::council_members::(get_council_members())) .storage(), ); @@ -5223,9 +5224,7 @@ mod development { let mut env = FudgeEnv::::from_parachain_storage( Genesis::default() .add(genesis::balances::(cfg(1_000))) - .add(genesis::council_members::( - get_council_members(), - )) + .add(genesis::council_members::(get_council_members())) .storage(), ); @@ -6819,11 +6818,6 @@ mod centrifuge { ); } - #[test] - fn _test() { - restrict_cfg_extrinsic::() - } - fn restrict_cfg_extrinsic() { let mut env = RuntimeEnv::::from_parachain_storage( Genesis::default() @@ -7571,6 +7565,7 @@ mod centrifuge { crate::test_for_runtimes!([centrifuge], restrict_usdc_xcm_transfer); crate::test_for_runtimes!([centrifuge], restrict_dot_transfer); crate::test_for_runtimes!([centrifuge], restrict_dot_xcm_transfer); + crate::test_for_runtimes!([centrifuge], restrict_cfg_extrinsic); crate::test_for_runtimes!([centrifuge], restrict_all); } diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index 1bc33b5d1b..819c14db25 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -44,7 +44,7 @@ use crate::{ POOL_MIN_EPOCH_TIME, }, }, - utils::{accounts::Keyring, tokens::rate_from_percent}, + utils::accounts::Keyring, }; const POOL_ADMIN: Keyring = Keyring::Admin; @@ -171,6 +171,10 @@ mod common { pub fn price_to_usd6(price: Quantity) -> Balance { currency::price_to_currency(price, Usd6) } + + pub fn rate_from_percent(perc: u64) -> Rate { + Rate::saturating_from_rational(perc, 100) + } } /// Predefined loan calls for use cases diff --git a/runtime/integration-tests/src/generic/cases/rewards.rs b/runtime/integration-tests/src/generic/cases/rewards.rs deleted file mode 100644 index 3b7ee83c83..0000000000 --- a/runtime/integration-tests/src/generic/cases/rewards.rs +++ /dev/null @@ -1,51 +0,0 @@ -use cfg_primitives::CFG; -use cfg_traits::rewards::{AccountRewards, CurrencyGroupChange, DistributedRewards}; -use cfg_types::tokens::CurrencyId; -use frame_support::assert_ok; -use runtime_common::apis::{runtime_decl_for_rewards_api::RewardsApiV1, RewardDomain}; -use sp_runtime::traits::Get; - -use crate::{ - generic::{config::Runtime, env::Env, envs::runtime_env::RuntimeEnv, utils}, - utils::accounts::Keyring, -}; - -type BlockRewards = pallet_rewards::Instance1; - -const STAKER: Keyring = Keyring::Alice; - -fn block_rewards_api() { - RuntimeEnv::::default().parachain_state_mut(|| { - let group_id = 1u32; - let amount = 100 * CFG; - - utils::give_balance::(STAKER.id(), T::ExistentialDeposit::get() + amount); - - assert_ok!(pallet_rewards::Pallet::::attach_currency( - CurrencyId::Native, - group_id, - )); - - assert_ok!(pallet_rewards::Pallet::::deposit_stake( - CurrencyId::Native, - &STAKER.id(), - amount, - )); - - assert_ok!( - pallet_rewards::Pallet::::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!(all, block_rewards_api); diff --git a/runtime/integration-tests/src/generic/config.rs b/runtime/integration-tests/src/generic/config.rs index ea973247f8..ffc587c207 100644 --- a/runtime/integration-tests/src/generic/config.rs +++ b/runtime/integration-tests/src/generic/config.rs @@ -27,18 +27,22 @@ use parity_scale_codec::Codec; use runtime_common::{ apis, fees::{DealWithFees, WeightToFee}, + instances, oracle::Feeder, remarks::Remark, rewards::SingleCurrencyMovement, }; -use sp_core::H256; +use sp_core::{sr25519::Public, H256}; use sp_runtime::{ scale_info::TypeInfo, - traits::{AccountIdLookup, Block, Dispatchable, Get, Member}, + traits::{ + AccountIdLookup, Block, Dispatchable, Get, MaybeSerializeDeserialize, Member, OpaqueKeys, + }, FixedI128, }; /// Kind of runtime to check in runtime time +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum RuntimeKind { Development, Altair, @@ -149,12 +153,15 @@ pub trait Runtime: > + pallet_preimage::Config + pallet_collective::Config + pallet_democracy::Config> + + pallet_collator_selection::Config> + + pallet_collator_allowlist::Config + + pallet_session::Config + pallet_evm_chain_id::Config + pallet_evm::Config + pallet_remarks::Config + pallet_utility::Config + pallet_rewards::Config< - pallet_rewards::Instance1, + instances::BlockRewards, GroupId = u32, CurrencyId = CurrencyId, RewardMechanism = pallet_rewards::mechanism::base::Mechanism< @@ -163,8 +170,16 @@ pub trait Runtime: FixedI128, SingleCurrencyMovement, >, + > + pallet_block_rewards::Config< + Rate = Rate, + CurrencyId = CurrencyId, + Balance = Balance, + Rewards = pallet_rewards::Pallet, > + axelar_gateway_precompile::Config { + /// Value to differentiate the runtime in tests. + const KIND: RuntimeKind; + /// Just the RuntimeCall type, but redefined with extra bounds. /// You can add `From` bounds in order to convert pallet calls to /// RuntimeCall in tests. @@ -193,6 +208,7 @@ pub trait Runtime: + From> + From> + From> + + From> + IsSubType> + IsSubType> + IsSubType> @@ -213,6 +229,9 @@ pub trait Runtime: + TryInto> + TryInto> + TryInto + + TryInto> + + TryInto> + + TryInto> + From> + From> + From> @@ -222,6 +241,7 @@ pub trait Runtime: + From> + From> + From> + + From> + From> + From> + From> @@ -229,6 +249,8 @@ pub trait Runtime: + From> + From> + From> + + From> + + From> + From; type RuntimeOriginExt: Into, ::RuntimeOrigin>> @@ -296,6 +318,7 @@ pub trait Runtime: type MaxTranchesExt: Codec + Get + Member + PartialOrd + TypeInfo; - /// Value to differentiate the runtime in tests. - const KIND: RuntimeKind; + type SessionKeysExt: OpaqueKeys + Member + Parameter + MaybeSerializeDeserialize; + + fn initialize_session_keys(public_id: Public) -> Self::SessionKeysExt; } diff --git a/runtime/integration-tests/src/generic/env.rs b/runtime/integration-tests/src/generic/env.rs index 9bc283c084..153d61c658 100644 --- a/runtime/integration-tests/src/generic/env.rs +++ b/runtime/integration-tests/src/generic/env.rs @@ -31,6 +31,13 @@ pub enum Blocks { /// computationally very fast. /// (i.e. years) JumpBySeconds(Seconds), + + /// Jumps to a block in the future. + /// Only one real block is created in the process. + /// This can be used to emulate passing time during long periods + /// computationally very fast. + /// (i.e. years) + JumpByNumber(BlockNumber), } impl Blocks { @@ -53,6 +60,7 @@ impl Blocks { }; (next + blocks.saturating_sub(1), next + blocks) } + Blocks::JumpByNumber(n) => (next + (*n - 1), next + *n), }; from..to } @@ -193,7 +201,6 @@ pub mod utils { mod tests { use super::*; - struct MockEnv; const SLOT_DURATION: Seconds = 12; const EMPTY: [BlockNumber; 0] = []; diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 4fc86e1b28..573cb5bc1b 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -27,7 +27,11 @@ use sp_runtime::{traits::AccountIdLookup, BuildStorage, Storage}; use sp_transaction_pool::runtime_api::TaggedTransactionQueue; use tokio::runtime::Handle; -use crate::{generic::config::Runtime, utils::time::START_DATE}; +use crate::generic::config::Runtime; + +/// Start date used for timestamps in test-enviornments +/// Sat Jan 01 2022 00:00:00 GMT+0000 +pub const START_DATE: u64 = 1640995200u64; type InherentCreator = Box< dyn CreateInherentDataProviders< diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index d8cb7ca0a0..8b5720921b 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -1,7 +1,6 @@ use std::{cell::RefCell, marker::PhantomData, mem, rc::Rc}; use cfg_primitives::{AuraId, Balance, BlockNumber, Header}; -use cfg_types::ParaId; use cumulus_primitives_core::PersistedValidationData; use cumulus_primitives_parachain_inherent::ParachainInherentData; use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; @@ -19,7 +18,7 @@ use sp_core::{sr25519::Public, Get, H256}; use sp_runtime::{ traits::Extrinsic, transaction_validity::{InvalidTransaction, TransactionValidityError}, - BuildStorage, Digest, DigestItem, DispatchError, Storage, + Digest, DigestItem, DispatchError, Storage, }; use sp_timestamp::Timestamp; @@ -37,7 +36,6 @@ pub struct RuntimeEnv { parachain_ext: Rc>, sibling_ext: Rc>, pending_extrinsics: Vec<(Keyring, T::RuntimeCallExt)>, - pending_xcm: Vec<(ParaId, Vec)>, _config: PhantomData, } @@ -53,45 +51,14 @@ impl Env for RuntimeEnv { } fn from_storage( - mut _relay_storage: Storage, - mut parachain_storage: Storage, - mut sibling_storage: Storage, + _relay_storage: Storage, + parachain_storage: Storage, + sibling_storage: Storage, ) -> Self { - // Needed for the aura usage - pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Public([0; 32]))], - } - .assimilate_storage(&mut parachain_storage) - .unwrap(); - - let mut parachain_ext = sp_io::TestExternalities::new(parachain_storage); - - // NOTE: Setting the current on-chain runtime version to the latest one, to - // prevent running migrations - parachain_ext.execute_with(|| { - frame_system::LastRuntimeUpgrade::::put(LastRuntimeUpgradeInfo::from( - ::Version::get(), - )) - }); - - parachain_ext.execute_with(|| Self::prepare_block(1)); - - // Needed for the aura usage - pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Public([0; 32]))], - } - .assimilate_storage(&mut sibling_storage) - .unwrap(); - - let mut sibling_ext = sp_io::TestExternalities::new(sibling_storage); - - sibling_ext.execute_with(|| Self::prepare_block(1)); - Self { - parachain_ext: Rc::new(RefCell::new(parachain_ext)), - sibling_ext: Rc::new(RefCell::new(sibling_ext)), + parachain_ext: Self::build_externality(parachain_storage), + sibling_ext: Self::build_externality(sibling_storage), pending_extrinsics: Vec::default(), - pending_xcm: Vec::default(), _config: PhantomData, } } @@ -200,6 +167,27 @@ impl Env for RuntimeEnv { } impl RuntimeEnv { + fn build_externality(storage: Storage) -> Rc> { + let mut ext = sp_io::TestExternalities::new(storage); + + ext.execute_with(|| { + // NOTE: Setting the current on-chain runtime version to the latest one, to + // prevent running migrations + frame_system::LastRuntimeUpgrade::::put(LastRuntimeUpgradeInfo::from( + ::Version::get(), + )); + + // If no authorities we set a default authority + if pallet_aura::Pallet::::authorities().is_empty() { + pallet_aura::Pallet::::initialize_authorities(&[AuraId::from(Public([0; 32]))]); + } + + Self::prepare_block(1); + }); + + Rc::new(RefCell::new(ext)) + } + fn process_pending_extrinsics(&mut self) { let pending_extrinsics = mem::replace(&mut self.pending_extrinsics, Vec::default()); diff --git a/runtime/integration-tests/src/generic/impls.rs b/runtime/integration-tests/src/generic/impls.rs index 274dc95082..88916f4997 100644 --- a/runtime/integration-tests/src/generic/impls.rs +++ b/runtime/integration-tests/src/generic/impls.rs @@ -2,9 +2,14 @@ use polkadot_primitives::{AssignmentId, AuthorityDiscoveryId, ValidatorId}; use sp_core::ByteArray; /// Implements the `Runtime` trait for a runtime +/// +/// You could add new associated types if you need to use types different for +/// each runtime macro_rules! impl_runtime { ($runtime_path:ident, $kind:ident) => { const _: () = { + use sp_core::sr25519::Public; + use crate::generic::config::{Runtime, RuntimeKind}; impl Runtime for $runtime_path::Runtime { @@ -14,8 +19,16 @@ macro_rules! impl_runtime { type RuntimeCallExt = $runtime_path::RuntimeCall; type RuntimeEventExt = $runtime_path::RuntimeEvent; type RuntimeOriginExt = $runtime_path::RuntimeOrigin; + type SessionKeysExt = $runtime_path::SessionKeys; const KIND: RuntimeKind = RuntimeKind::$kind; + + fn initialize_session_keys(public_id: Public) -> Self::SessionKeysExt { + $runtime_path::SessionKeys { + aura: public_id.into(), + block_rewards: public_id.into(), + } + } } }; }; diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 95cfc67104..478926f9a4 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -1,8 +1,3 @@ -// For generic modules we can reactive the unused warn disabled on lib.rs -#![warn(unused)] -// Allow dead code for utilities not used yet -#![allow(dead_code)] - pub mod env; pub mod envs { pub mod fudge_env; @@ -15,6 +10,7 @@ pub mod utils; // Test cases mod cases { mod account_derivation; + mod block_rewards; mod ethereum_transaction; mod example; mod investments; @@ -24,7 +20,6 @@ mod cases { mod precompile; mod proxy; mod restricted_transfers; - mod rewards; } /// Generate tests for the specified runtimes or all runtimes. diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index 21b912fc16..102f1d7ac1 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -2,10 +2,10 @@ //! considered at this level. use cfg_primitives::Balance; -use cfg_types::tokens::CurrencyId; +use cfg_types::{fixed_point::Rate, tokens::CurrencyId}; use parity_scale_codec::Encode; -use sp_core::crypto::AccountId32; -use sp_runtime::{BuildStorage, Storage}; +use sp_core::Get; +use sp_runtime::{BuildStorage, FixedPointNumber, Storage}; use crate::{ generic::{config::Runtime, utils::currency::CurrencyInfo}, @@ -28,8 +28,6 @@ impl Genesis { } } -// Add BuildStorage functions for pallet initialization. - pub fn balances(balance: Balance) -> impl BuildStorage { pallet_balances::GenesisConfig:: { balances: default_accounts() @@ -65,17 +63,35 @@ pub fn assets(currency_ids: Vec>) -> impl Buil } } -pub fn council_members(members: Vec) -> impl BuildStorage -where - I: 'static, - T: pallet_collective::Config, - T::AccountId: From, -{ - pallet_collective::GenesisConfig:: { +pub fn council_members(members: Vec) -> impl BuildStorage { + pallet_collective::GenesisConfig:: { phantom: Default::default(), - members: members + members: members.into_iter().map(|acc| acc.id()).collect(), + } +} + +pub fn invulnerables(invulnerables: Vec) -> impl BuildStorage { + pallet_collator_selection::GenesisConfig:: { + invulnerables: invulnerables.into_iter().map(|acc| acc.id()).collect(), + candidacy_bond: cfg_primitives::MILLI_CFG, + desired_candidates: T::MaxCandidates::get(), + } +} + +pub fn session_keys() -> impl BuildStorage { + pallet_session::GenesisConfig:: { + keys: default_accounts() .into_iter() - .map(|acc| acc.to_account_id().into()) + .map(|acc| (acc.id(), acc.id(), T::initialize_session_keys(acc.public()))) .collect(), } } + +pub fn block_rewards(collators: Vec) -> impl BuildStorage { + pallet_block_rewards::GenesisConfig:: { + collators: collators.into_iter().map(|acc| acc.id()).collect(), + collator_reward: (1000 * cfg_primitives::CFG).into(), + treasury_inflation_rate: Rate::saturating_from_rational(3, 100).into(), + last_update: Default::default(), + } +} diff --git a/runtime/integration-tests/src/lib.rs b/runtime/integration-tests/src/lib.rs index 5beef9f4af..017b191cb4 100644 --- a/runtime/integration-tests/src/lib.rs +++ b/runtime/integration-tests/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(stmt_expr_attributes)] // Copyright 2021 Centrifuge GmbH (centrifuge.io). // This file is part of Centrifuge chain project. @@ -11,27 +10,11 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. + +// Allow dead code for utilities not used yet +#![allow(dead_code)] +// All code in this crate is test related #![cfg(test)] -#![allow(unused)] mod generic; -mod rewards; mod utils; - -/// Re-exports the correct runtimes that we run the integration tests with -/// This allows all other modules to use the import of `crate::chain::{...}` -/// in order to get the right stuff from the respective runtime. -mod chain { - pub mod centrifuge { - pub use development::*; - - pub mod development { - pub use development_runtime::*; - pub const PARA_ID: u32 = 2000; - } - } - - pub mod relay { - pub use rococo_runtime::*; - } -} diff --git a/runtime/integration-tests/src/rewards/block/env.rs b/runtime/integration-tests/src/rewards/block/env.rs deleted file mode 100644 index ef367bb3c7..0000000000 --- a/runtime/integration-tests/src/rewards/block/env.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -use cfg_primitives::AccountId; -use fudge::primitives::Chain; -use sp_runtime::Storage; -use tokio::runtime::Handle; - -use crate::{ - chain::centrifuge::{CollatorSelection, Runtime, PARA_ID}, - rewards::block::invariants::assert_all_staked, - utils::{ - accounts::Keyring, - env::test_env_with_centrifuge_storage, - genesis::{ - admin_collator, admin_invulnerable, default_native_balances, default_session_keys, - }, - }, -}; - -pub(crate) fn default_collators() -> Vec { - vec![ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, - ] -} - -pub(crate) fn default_genesis_block_rewards(genesis: &mut Storage) { - default_native_balances::(genesis); - admin_invulnerable::(genesis); - default_session_keys::(genesis); - admin_collator::(genesis); -} - -#[tokio::test] -async fn env_works() { - let mut genesis = Storage::default(); - default_genesis_block_rewards(&mut genesis); - let mut env = test_env_with_centrifuge_storage(Handle::current(), genesis); - - let collator_accounts: Vec = default_collators() - .clone() - .iter() - .map(|c| c.to_account_id()) - .collect(); - - // Ensure default collators are neither candidates nor invulnerables - env.with_state(Chain::Para(PARA_ID), || { - let candidates = CollatorSelection::candidates(); - let invulnerables = CollatorSelection::invulnerables(); - assert!(collator_accounts - .iter() - .all(|j| !candidates.iter().any(|candidate| &candidate.who == j) - && !invulnerables.iter().any(|invulnerable| invulnerable == j))); - }); -} - -#[tokio::test] -async fn genesis_collators_are_staked() { - let mut genesis = Storage::default(); - default_genesis_block_rewards(&mut genesis); - let mut env = test_env_with_centrifuge_storage(Handle::current(), genesis); - - // Ensure default collators are neither candidates nor invulnerables - env.with_state(Chain::Para(PARA_ID), || { - assert_all_staked(&[Keyring::Admin.to_account_id()]); - }); -} diff --git a/runtime/integration-tests/src/rewards/block/invariants.rs b/runtime/integration-tests/src/rewards/block/invariants.rs deleted file mode 100644 index 5fcf7326ce..0000000000 --- a/runtime/integration-tests/src/rewards/block/invariants.rs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -use cfg_primitives::AccountId; -use cfg_traits::rewards::AccountRewards; -use cfg_types::tokens::{CurrencyId, StakingCurrency}; -use fudge::primitives::Chain; -use sp_runtime::{traits::Zero, BoundedVec, SaturatedConversion}; - -use crate::{ - chain::centrifuge::{ - BlockRewards, BlockRewardsBase, CollatorSelection, Period, Runtime, RuntimeCall, - RuntimeEvent, Tokens, PARA_ID, - }, - utils::env::{assert_events, EventRange, TestEnv}, -}; - -/// Verify assumptions about joining and leaving collators. -pub(crate) fn assert_session_invariants( - env: &mut TestEnv, - session_index: u32, - collator_count: u32, - joining: Vec, - leaving: Vec, -) { - let inc = - BoundedVec::<_, ::MaxCollators>::truncate_from( - joining.clone(), - ); - let out = - BoundedVec::<_, ::MaxCollators>::truncate_from( - leaving.clone(), - ); - let next_collator_count: u32 = collator_count - .saturating_add(inc.len().saturated_into()) - .saturating_sub(out.len().saturated_into()); - - env.with_state(Chain::Para(PARA_ID), || { - assert_eq!( - inc, - BlockRewards::next_session_changes().collators.inc, - "Joining collators mismatch in session {}", - session_index - ); - assert_eq!( - out, - BlockRewards::next_session_changes().collators.out, - "Leaving collators mismatch in session {}", - session_index - ); - assert_eq!( - collator_count, - BlockRewards::active_session_data().collator_count, - "Active collator count mismatch in session {}", - session_index - ); - assert_eq!( - Some(next_collator_count), - BlockRewards::next_session_changes().collator_count, - "Next collator count mismatch in session {}", - session_index - ); - - // joining should not be staked yet - assert_all_not_staked(&joining[..]); - - // leaving should still be staked - assert_all_staked(&leaving[..]); - - let candidates: Vec = CollatorSelection::candidates() - .into_iter() - .map(|c| c.who) - .collect(); - // joining should already be candidates - assert_all_candidate(&candidates[..], &joining[..]); - - // leaving should not be candidates anymore - assert_all_not_candidate(&candidates[..], &leaving[..]); - }); - - assert_events!( - env, - Chain::Para(PARA_ID), - RuntimeEvent, - EventRange::One(Period::get().saturating_mul(session_index)), - RuntimeEvent::BlockRewardsBase(pallet_rewards::Event::GroupRewarded { .. }) if [count 1], - RuntimeEvent::BlockRewards(pallet_block_rewards::Event::NewSession { .. }) if [count 1], - ); -} - -/// Verifies that each provided account address is staked for block rewards. -pub(crate) fn assert_all_staked(v: &[AccountId]) { - assert!(v.iter().all(|acc| { - !::Rewards::account_stake( - ::StakeCurrencyId::get(), - acc, - ) - .is_zero() - })); -} - -/// Verifies that none of the provided account addresses is staked for block -/// rewards. -fn assert_all_not_staked(v: &[AccountId]) { - assert!(v.iter().all(|acc| { - ::Rewards::account_stake( - ::StakeCurrencyId::get(), - acc, - ) - .is_zero() - })); -} - -/// Verifies that candidates is a superset of the given slice. -fn assert_all_candidate(candidates: &[AccountId], v: &[AccountId]) { - assert!(v - .iter() - .all(|acc| candidates.iter().any(|candidate| acc == candidate))); -} - -/// Verifies that both slices are disjoint. -fn assert_all_not_candidate(candidates: &[AccountId], v: &[AccountId]) { - assert!(v - .iter() - .all(|acc| !candidates.iter().any(|candidate| acc == candidate))); -} diff --git a/runtime/integration-tests/src/rewards/block/mod.rs b/runtime/integration-tests/src/rewards/block/mod.rs deleted file mode 100644 index 63b302dd2c..0000000000 --- a/runtime/integration-tests/src/rewards/block/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -mod env; -mod invariants; -mod session_advances; diff --git a/runtime/integration-tests/src/rewards/block/session_advances.rs b/runtime/integration-tests/src/rewards/block/session_advances.rs deleted file mode 100644 index b66bdbab83..0000000000 --- a/runtime/integration-tests/src/rewards/block/session_advances.rs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -use cfg_primitives::AccountId; -use cfg_traits::rewards::AccountRewards; -use cfg_types::tokens::{CurrencyId, StakingCurrency}; -use fudge::primitives::Chain; -use pallet_collator_selection::Call as CollatorSelectionCall; -use parity_scale_codec::Encode; -use sp_runtime::{traits::Zero, Storage}; -use tokio::runtime::Handle; - -use crate::{ - chain::centrifuge::{ - BlockRewards, BlockRewardsBase, CollatorSelection, Period, Runtime, RuntimeCall, - RuntimeEvent, Tokens, PARA_ID, - }, - rewards::block::{ - env::{default_collators, default_genesis_block_rewards}, - invariants::assert_session_invariants, - }, - utils::{ - accounts::Keyring, - env::{ - assert_events, pass_n, test_env_with_centrifuge_storage, ChainState, EventRange, - TestEnv, - }, - extrinsics::{nonce_centrifuge, xt_centrifuge}, - }, -}; - -/// Execute extrinsic to add the given keyring as a candidate of the -/// CollatorSelection. Upon success, the collator's session key will be included -/// in the next sessions queued keys and thus be added to -/// `NextEpochChanges::.collators.joining.` -pub(crate) fn add_collator(env: &mut TestEnv, who: Keyring) { - let xt = xt_centrifuge( - &env, - who.clone(), - nonce_centrifuge(&env, who), - RuntimeCall::CollatorSelection(CollatorSelectionCall::register_as_candidate {}), - ) - .unwrap(); - env.append_extrinsic(Chain::Para(PARA_ID), xt.encode()) - .unwrap(); -} - -#[cfg(feature = "fast-runtime")] -#[tokio::test] -async fn collator_list_synchronized() { - let mut genesis = Storage::default(); - default_genesis_block_rewards(&mut genesis); - let mut env = test_env_with_centrifuge_storage(Handle::current(), genesis); - - let collators = default_collators(); - let collator_accounts: Vec = collators - .clone() - .iter() - .map(|c| c.to_account_id()) - .collect(); - - add_collator(&mut env, collators[0]); - add_collator(&mut env, collators[1]); - - // SESSION 0 -> 1; - frame_support::assert_ok!(pass_n(&mut env, Period::get().into())); - assert_session_invariants( - &mut env, - 1, - 1, - vec![collator_accounts[0].clone(), collator_accounts[1].clone()], - vec![], - ); - - add_collator(&mut env, collators[2]); - add_collator(&mut env, collators[3]); - add_collator(&mut env, collators[4]); - add_collator(&mut env, collators[5]); - - // SESSION 1 -> 2; - frame_support::assert_ok!(pass_n(&mut env, Period::get().into())); - - // Alice leaves - let xt = xt_centrifuge( - &env, - collators[0].clone(), - nonce_centrifuge(&env, collators[0]), - RuntimeCall::CollatorSelection(CollatorSelectionCall::leave_intent {}), - ) - .unwrap(); - env.append_extrinsic(Chain::Para(PARA_ID), xt.encode()) - .unwrap(); - assert_session_invariants( - &mut env, - 2, - 3, - vec![ - collator_accounts[2].clone(), - collator_accounts[3].clone(), - collator_accounts[4].clone(), - collator_accounts[5].clone(), - ], - vec![], - ); - - // SESSION 2 -> 3; - frame_support::assert_ok!(pass_n(&mut env, Period::get().into())); - - assert_events!( - env, - Chain::Para(PARA_ID), - RuntimeEvent, - EventRange::Range(2 * Period::get(), 3 * Period::get()), - RuntimeEvent::CollatorSelection(pallet_collator_selection::Event::CandidateRemoved { .. }) if [count 1], - ); - assert_session_invariants(&mut env, 3, 7, vec![], vec![collators[0].clone().into()]); - - env.with_state(Chain::Para(PARA_ID), || { - for collator in collator_accounts[0..2].iter() { - assert!( - !::Rewards::compute_reward( - ::StakeCurrencyId::get(), - collator.into(), - ) - .unwrap() - .is_zero() - ); - } - for collator in collator_accounts[2..].iter() { - assert!( - ::Rewards::compute_reward( - ::StakeCurrencyId::get(), - collator.into(), - ) - .unwrap() - .is_zero() - ); - } - }); - - // SESSION 3 -> 4; - frame_support::assert_ok!(pass_n(&mut env, Period::get().into())); - env.with_state(Chain::Para(PARA_ID), || { - for collator in collator_accounts[2..].iter() { - assert!( - !::Rewards::compute_reward( - ::StakeCurrencyId::get(), - collator.into(), - ) - .unwrap() - .is_zero() - ); - } - }); -} diff --git a/runtime/integration-tests/src/rewards/mod.rs b/runtime/integration-tests/src/rewards/mod.rs deleted file mode 100644 index f70913ef94..0000000000 --- a/runtime/integration-tests/src/rewards/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -mod block; diff --git a/runtime/integration-tests/src/utils/accounts.rs b/runtime/integration-tests/src/utils/accounts.rs index 3a0f563486..0b38d5f9de 100644 --- a/runtime/integration-tests/src/utils/accounts.rs +++ b/runtime/integration-tests/src/utils/accounts.rs @@ -10,131 +10,12 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// NOTE: Taken mostly from paritytech-substrate - -use std::collections::HashMap; - -use cfg_primitives::Nonce; -use fudge::primitives::Chain; -use polkadot_core_primitives::{AccountId as RelayAccountId, Nonce as RelayNonce}; -pub use sp_core::sr25519; use sp_core::{ sr25519::{Pair, Public, Signature}, Pair as PairT, }; use sp_runtime::AccountId32; -use crate::{ - chain::{centrifuge, centrifuge::PARA_ID, relay}, - utils::env::TestEnv, -}; - -/// Struct that takes care of handling nonces for accounts -pub struct NonceManager { - nonces: HashMap>, -} - -impl NonceManager { - pub fn new() -> Self { - Self { - nonces: HashMap::new(), - } - } - - /// Retrieves the latest nonce of an account. - /// If the nonce is not already in the map for a given chain-account - /// combination it ensures to fetch the latest nonce and store it in the - /// map. - /// - /// MUST be executed in an externalites provided env. - pub fn nonce(&mut self, chain: Chain, who: Keyring) -> Nonce { - self.nonces - .entry(chain) - .or_insert(HashMap::new()) - .entry(who) - .or_insert(Self::nonce_from_chain(chain, who)) - .clone() - } - - fn nonce_from_chain(chain: Chain, who: Keyring) -> Nonce { - match chain { - Chain::Relay => nonce::( - who.clone().to_account_id().into(), - ), - Chain::Para(id) => match id { - _ if id == PARA_ID => nonce::( - who.clone().to_account_id().into() - ), - _ => unreachable!("Currently no nonces for chains differing from Relay and centrifuge are supported. Para ID {}", id) - } - } - } - - /// Retrieves the latest nonce of an account. Returns latest and increases - /// the nonce by 1. - /// If the nonce is not already in the map for a given chain-account - /// combination it ensures to fetch the latest nonce and store it in the - /// map. - /// - /// MUST be executed in an externalites provided env. - pub fn fetch_add(&mut self, chain: Chain, who: Keyring) -> Nonce { - let curr = self - .nonces - .entry(chain) - .or_insert(HashMap::new()) - .entry(who) - .or_insert(Self::nonce_from_chain(chain, who)); - let next = curr.clone(); - *curr = *curr + 1; - next - } - - /// Increases the nonce by one. If it is not existing fails. - pub fn incr(&mut self, chain: Chain, who: Keyring) -> Result<(), ()> { - let curr = self - .nonces - .get_mut(&chain) - .ok_or(())? - .get_mut(&who) - .ok_or(())?; - *curr = *curr + 1; - Ok(()) - } -} - -/// Retrieves a nonce from the centrifuge state -/// -/// **NOTE: Usually one should use the TestEnv::nonce() api** -fn nonce_centrifuge(env: &TestEnv, who: Keyring) -> Nonce { - env.centrifuge - .with_state(|| { - nonce::( - who.clone().to_account_id().into(), - ) - }) - .expect("ESSENTIAL: Nonce must be retrievable.") -} - -/// Retrieves a nonce from the relay state -/// -/// **NOTE: Usually one should use the TestEnv::nonce() api** -fn nonce_relay(env: &TestEnv, who: Keyring) -> RelayNonce { - env.relay - .with_state(|| { - nonce::(who.clone().to_account_id().into()) - }) - .expect("ESSENTIAL: Nonce must be retrievable.") -} - -fn nonce(who: AccountId) -> Nonce -where - Runtime: frame_system::Config, - AccountId: Into<::AccountId>, - Nonce: From<::Nonce>, -{ - frame_system::Pallet::::account_nonce(who.into()).into() -} - /// Set of test accounts. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Keyring { @@ -249,65 +130,6 @@ impl std::str::FromStr for Keyring { } /// Returns a Vector of default accounts -/// -/// Accounts: -/// * Keyring::Admin -/// * Keyring::Alice -/// * Keyring::Bob -/// * Keyring::Ferdie -/// * Keyring::Charlie -/// * Keyring::Dave -/// * Keyring::Eve -/// * Keyring::TrancheInvestor(1) -/// * Keyring::TrancheInvestor(2) -/// * Keyring::TrancheInvestor(3) -/// * Keyring::TrancheInvestor(4) -/// * Keyring::TrancheInvestor(5) -/// * Keyring::TrancheInvestor(6) -/// * Keyring::TrancheInvestor(7) -/// * Keyring::TrancheInvestor(8) -/// * Keyring::TrancheInvestor(9) -/// * Keyring::TrancheInvestor(10) -/// * Keyring::TrancheInvestor(11) -/// * Keyring::TrancheInvestor(12) -/// * Keyring::TrancheInvestor(13) -/// * Keyring::TrancheInvestor(14) -/// * Keyring::TrancheInvestor(15) -/// * Keyring::TrancheInvestor(16) -/// * Keyring::TrancheInvestor(17) -/// * Keyring::TrancheInvestor(18) -/// * Keyring::TrancheInvestor(19) -/// * Keyring::TrancheInvestor(20) -/// * Keyring::TrancheInvestor(21) -/// * Keyring::TrancheInvestor(22) -/// * Keyring::TrancheInvestor(23) -/// * Keyring::TrancheInvestor(24) -/// * Keyring::TrancheInvestor(25) -/// * Keyring::TrancheInvestor(26) -/// * Keyring::TrancheInvestor(27) -/// * Keyring::TrancheInvestor(28) -/// * Keyring::TrancheInvestor(29) -/// * Keyring::TrancheInvestor(30) -/// * Keyring::TrancheInvestor(31) -/// * Keyring::TrancheInvestor(32) -/// * Keyring::TrancheInvestor(33) -/// * Keyring::TrancheInvestor(34) -/// * Keyring::TrancheInvestor(35) -/// * Keyring::TrancheInvestor(36) -/// * Keyring::TrancheInvestor(37) -/// * Keyring::TrancheInvestor(38) -/// * Keyring::TrancheInvestor(39) -/// * Keyring::TrancheInvestor(40) -/// * Keyring::TrancheInvestor(41) -/// * Keyring::TrancheInvestor(42) -/// * Keyring::TrancheInvestor(43) -/// * Keyring::TrancheInvestor(44) -/// * Keyring::TrancheInvestor(45) -/// * Keyring::TrancheInvestor(46) -/// * Keyring::TrancheInvestor(47) -/// * Keyring::TrancheInvestor(48) -/// * Keyring::TrancheInvestor(49) -/// * Keyring::TrancheInvestor(50) pub fn default_accounts() -> Vec { let mut standard = vec![ Keyring::Admin, @@ -323,111 +145,8 @@ pub fn default_accounts() -> Vec { } /// Returns a Vector of default investor accounts -/// -/// Accounts: -/// * Keyring::TrancheInvestor(1) -/// * Keyring::TrancheInvestor(2) -/// * Keyring::TrancheInvestor(3) -/// * Keyring::TrancheInvestor(4) -/// * Keyring::TrancheInvestor(5) -/// * Keyring::TrancheInvestor(6) -/// * Keyring::TrancheInvestor(7) -/// * Keyring::TrancheInvestor(8) -/// * Keyring::TrancheInvestor(9) -/// * Keyring::TrancheInvestor(10) -/// * Keyring::TrancheInvestor(11) -/// * Keyring::TrancheInvestor(12) -/// * Keyring::TrancheInvestor(13) -/// * Keyring::TrancheInvestor(14) -/// * Keyring::TrancheInvestor(15) -/// * Keyring::TrancheInvestor(16) -/// * Keyring::TrancheInvestor(17) -/// * Keyring::TrancheInvestor(18) -/// * Keyring::TrancheInvestor(19) -/// * Keyring::TrancheInvestor(20) -/// * Keyring::TrancheInvestor(21) -/// * Keyring::TrancheInvestor(22) -/// * Keyring::TrancheInvestor(23) -/// * Keyring::TrancheInvestor(24) -/// * Keyring::TrancheInvestor(25) -/// * Keyring::TrancheInvestor(26) -/// * Keyring::TrancheInvestor(27) -/// * Keyring::TrancheInvestor(28) -/// * Keyring::TrancheInvestor(29) -/// * Keyring::TrancheInvestor(30) -/// * Keyring::TrancheInvestor(31) -/// * Keyring::TrancheInvestor(32) -/// * Keyring::TrancheInvestor(33) -/// * Keyring::TrancheInvestor(34) -/// * Keyring::TrancheInvestor(35) -/// * Keyring::TrancheInvestor(36) -/// * Keyring::TrancheInvestor(37) -/// * Keyring::TrancheInvestor(38) -/// * Keyring::TrancheInvestor(39) -/// * Keyring::TrancheInvestor(40) -/// * Keyring::TrancheInvestor(41) -/// * Keyring::TrancheInvestor(42) -/// * Keyring::TrancheInvestor(43) -/// * Keyring::TrancheInvestor(44) -/// * Keyring::TrancheInvestor(45) -/// * Keyring::TrancheInvestor(46) -/// * Keyring::TrancheInvestor(47) -/// * Keyring::TrancheInvestor(48) -/// * Keyring::TrancheInvestor(49) -/// * Keyring::TrancheInvestor(50) pub fn default_investors() -> Vec { - vec![ - Keyring::TrancheInvestor(1), - Keyring::TrancheInvestor(2), - Keyring::TrancheInvestor(3), - Keyring::TrancheInvestor(4), - Keyring::TrancheInvestor(5), - Keyring::TrancheInvestor(6), - Keyring::TrancheInvestor(7), - Keyring::TrancheInvestor(8), - Keyring::TrancheInvestor(9), - Keyring::TrancheInvestor(10), - Keyring::TrancheInvestor(11), - Keyring::TrancheInvestor(12), - Keyring::TrancheInvestor(13), - Keyring::TrancheInvestor(14), - Keyring::TrancheInvestor(15), - Keyring::TrancheInvestor(16), - Keyring::TrancheInvestor(17), - Keyring::TrancheInvestor(18), - Keyring::TrancheInvestor(19), - Keyring::TrancheInvestor(20), - Keyring::TrancheInvestor(21), - Keyring::TrancheInvestor(22), - Keyring::TrancheInvestor(23), - Keyring::TrancheInvestor(24), - Keyring::TrancheInvestor(25), - Keyring::TrancheInvestor(26), - Keyring::TrancheInvestor(27), - Keyring::TrancheInvestor(28), - Keyring::TrancheInvestor(29), - Keyring::TrancheInvestor(30), - Keyring::TrancheInvestor(31), - Keyring::TrancheInvestor(32), - Keyring::TrancheInvestor(33), - Keyring::TrancheInvestor(34), - Keyring::TrancheInvestor(35), - Keyring::TrancheInvestor(36), - Keyring::TrancheInvestor(37), - Keyring::TrancheInvestor(38), - Keyring::TrancheInvestor(39), - Keyring::TrancheInvestor(40), - Keyring::TrancheInvestor(41), - Keyring::TrancheInvestor(42), - Keyring::TrancheInvestor(43), - Keyring::TrancheInvestor(44), - Keyring::TrancheInvestor(45), - Keyring::TrancheInvestor(46), - Keyring::TrancheInvestor(47), - Keyring::TrancheInvestor(48), - Keyring::TrancheInvestor(49), - Keyring::TrancheInvestor(50), - ] + (0..=50).map(Keyring::TrancheInvestor).collect() } impl From for AccountId32 { @@ -454,18 +173,6 @@ impl From for [u8; 32] { } } -impl From for crate::chain::centrifuge::RuntimeOrigin { - fn from(account: Keyring) -> Self { - crate::chain::centrifuge::RuntimeOrigin::signed(AccountId32::from(account)) - } -} - -impl From for crate::chain::relay::RuntimeOrigin { - fn from(account: Keyring) -> Self { - crate::chain::relay::RuntimeOrigin::signed(AccountId32::from(account)) - } -} - #[cfg(test)] mod tests { use sp_core::{sr25519::Pair, Pair as PairT}; diff --git a/runtime/integration-tests/src/utils/env.rs b/runtime/integration-tests/src/utils/env.rs deleted file mode 100644 index 59f89635dd..0000000000 --- a/runtime/integration-tests/src/utils/env.rs +++ /dev/null @@ -1,1029 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Utilities to create a relay-chain-parachain setup -use std::collections::HashMap; - -use cfg_primitives::{AuraId, BlockNumber, Nonce}; -use frame_system::EventRecord; -use fudge::{ - digest::{DigestCreator, DigestProvider, FudgeAuraDigest, FudgeBabeDigest}, - inherent::{ - CreateInherentDataProviders, FudgeDummyInherentRelayParachain, FudgeInherentParaParachain, - FudgeInherentTimestamp, - }, - primitives::{Chain, PoolState}, - state::StateProvider, - InherentBuilder, ParachainBuilder, RelaychainBuilder, TWasmExecutor, -}; -use lazy_static::lazy_static; -//pub use macros::{assert_events, events, run}; -pub use macros::*; -use parity_scale_codec::{Decode, Encode}; -use polkadot_core_primitives::{Block as RelayBlock, Header as RelayHeader}; -use polkadot_parachain_primitives::primitives::Id as ParaId; -use polkadot_runtime_parachains::{configuration, configuration::HostConfiguration, dmp}; -use sc_executor::{WasmExecutionMethod, WasmExecutor}; -use sc_service::{TFullBackend, TFullClient, TaskManager}; -use sp_consensus_babe::digests::CompatibleDigestItem; -use sp_consensus_slots::SlotDuration; -use sp_core::H256; -use sp_runtime::{ - generic::BlockId, - traits::{BlakeTwo256, Extrinsic}, - BuildStorage, DigestItem, Storage, -}; -use tokio::runtime::Handle; - -use crate::{ - chain::{ - centrifuge, - centrifuge::{ - Block as CentrifugeBlock, Runtime, RuntimeApi as CentrifugeRtApi, RuntimeEvent, - PARA_ID, WASM_BINARY as CentrifugeCode, - }, - relay, - relay::{Runtime as RelayRt, RuntimeApi as RelayRtApi, WASM_BINARY as RelayCode}, - }, - utils::{ - accounts::{Keyring, NonceManager}, - extrinsics::{xt_centrifuge, xt_relay}, - logs, - time::START_DATE, - }, -}; - -pub mod macros { - /// A macro that evolves the chain until the provided event and pattern are - /// encountered. - /// - /// Usage: - /// ```ignore - /// env::evolve_until_event!( - /// env, - /// Chain::Para(PARA_ID), - /// RuntimeEvent, - /// max_blocks, - /// RuntimeEvent::LiquidityPoolsGateway(pallet_liquidity_pools_gateway::Event::DomainRouterSet { - /// domain, - /// router, - /// }) if [*domain == test_domain && *router == test_router], - /// ); - /// ``` - macro_rules! evolve_until_event_is_found { - ($env:expr, $chain:expr, $event:ty, $max_count:expr, $pattern:pat_param $(if $extra:tt)?, ) => {{ - use frame_support::assert_ok; - use frame_system::EventRecord as __hidden_EventRecord; - use sp_core::H256 as __hidden_H256; - use parity_scale_codec::Decode as _; - - use crate::utils::env::macros::{extra_counts, extra_guards}; - - let mut matched: Vec<$event> = Vec::new(); - - for _ in 0..$max_count { - let latest = $env - .centrifuge - .with_state(|| frame_system::Pallet::::block_number()) - .expect("Failed retrieving latest block"); - - if latest == 0 { - $env.evolve().unwrap(); - continue - } - - let scale_events = $env - .events($chain, EventRange::One(latest)) - .expect("Failed fetching events"); - - let events: Vec<$event> = scale_events - .into_iter() - .map(|scale_record| { - __hidden_EventRecord::<$event, __hidden_H256>::decode( - &mut scale_record.as_slice(), - ) - .expect("Decoding from chain data does not fail. qed") - }) - .map(|record| record.event) - .collect(); - - let matches = |event: &RuntimeEvent| { - match event { - $pattern $(if extra_guards!($extra))? => true, - _ => false - } - }; - - matched = events.clone(); - matched.retain(|event| matches(event)); - - if matched.len() > 0 { - break - } - - $env.evolve().unwrap(); - } - - let scale_events = $env.events($chain, EventRange::All).expect("Failed fetching events"); - let events: Vec<$event> = scale_events - .into_iter() - .map(|scale_record| __hidden_EventRecord::<$event, __hidden_H256>::decode(&mut scale_record.as_slice()) - .expect("Decoding from chain data does not fail. qed")) - .map(|record| record.event) - .collect(); - - assert!( - matched.len() == extra_counts!($pattern $(,$extra)?), - "events do not match the provided pattern - '{}'.\nMatched events: {:?}\nTotal events: {:?}\n", - stringify!($pattern $(,$extra)?), - matched, - events, - ); - }}; - } - - /// A macro that helps checking whether a given list of events - /// has been included in the given range of blocks. - /// - /// Usage: - /// ```ignore - /// env::assert_events!( - /// env, //-> The test environment create with fudge::companion - /// Chain::Para(PARA_ID), //-> The chain where we fetch the events from - /// Event, //-> The event-enum type from the runtime - /// EventRange::All, //-> The range of blocks we check for the events - /// RuntimeEvent::System(frame_system::Event::ExtrinsicFailed{..}) - /// if [count 0], // -> Ensures zero occurencies of the given event. Could also ensure n-occurencies - /// RuntimeEvent::PoolSystem(pallet_pool_system::RuntimeEvent::Created(id, ..)) if [id == 0], //-> matches only of the id matches to 0 - /// RuntimeEvent::Loans(pallet_loans::Event::PoolInitialised(id)) if [id == 0], - /// RuntimeEvent::Loans(pallet_loans::Event::Created(id, loan, asset)) - /// if [id == 0 && loan == InstanceId(1) && asset == Asset(4294967296, InstanceId(1))], //-> matches only of the clause matches - /// RuntimeEvent::Loans(pallet_loans::Event::Priced(id, loan)) if [id == 0 && loan == InstanceId(1)], - /// ); - /// ``` - macro_rules! assert_events { - ($env:expr, $chain:expr, $event:ty, $range:expr, $($pattern:pat_param $(if $extra:tt)? ,)+ ) => {{ - use frame_system::EventRecord as __hidden_EventRecord; - use crate::utils::env::macros::{extra_guards, extra_counts}; - use sp_core::H256 as __hidden_H256; - use parity_scale_codec::Decode as _; - - - let scale_events = $env.events($chain, $range).expect("Failed fetching events"); - let events: Vec<$event> = scale_events - .into_iter() - .map(|scale_record| __hidden_EventRecord::<$event, __hidden_H256>::decode(&mut scale_record.as_slice()) - .expect("Decoding from chain data does not fail. qed")) - .map(|record| record.event) - .collect(); - let mut msg = "Failed asserting event clause of: ".to_owned(); - - $( - let matches = |event: &RuntimeEvent| { - match event { - $pattern $(if extra_guards!($extra) )? => true, - _ => false - } - }; - - let mut matched = events.clone(); - matched.retain(|event| matches(event)); - assert!( - matched.len() == extra_counts!($pattern $(,$extra)?), - "events do not match the provided pattern - '{}'.\nMatched events: {:?}\nTotal events: {:?}\n", - stringify!($pattern $(,$extra)?), - matched, - events, - ); - )+ - - }}; - } - - /// DO NOT USE! This macro is solely expected to be used within the macros - /// modules - macro_rules! extra_counts { - ($pattern:pat_param) => { - 1 - }; - ($pattern:pat_param, [$guard:expr]) => { - 1 - }; - ($pattern:pat_param, [$guard:expr, count $count:expr]) => { - $count - }; - ($pattern:pat_param, [count $count:expr]) => { - $count - }; - } - - /// DO NOT USE! This macro is solely expected to be used within the macros - /// modules - macro_rules! extra_guards { - ( [count $count:expr] ) => { - true - }; - ( [$guard:expr] ) => { - $guard - }; - ( [$guard:expr, count $count:expr] ) => { - $guard - }; - } - - /// A macro that helps retrieving specific events with a filter - /// This is useful as the general interface of the TestEnv return - /// scale-encoded events. - /// - /// Returns a vector of the given events. - /// - /// Usage: - /// ```ignore - /// env::events!( - /// env, //-> The test environment create with fudge::companion - /// Chain::Para(PARA_ID), //-> The chain where we fetch the events from - /// Event, //-> The event-enum type from the runtime - /// EventRange::All, //-> The range of blocks we check for the events - /// RuntimeEvent::System(frame_system::Event::ExtrinsicFailed{..}) //-> The list of events that should be matched - /// | RuntimeEvent::PoolSystem(pallet_pool_system::RuntimeEvent::Created(id, ..)) if id == 0 //-> matches only of the id matches to 0 - /// | RuntimeEvent::Loans(..) - /// ); - /// ``` - macro_rules! events { - ($env:expr, $chain:expr, $event:ty, $range:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {{ - use frame_system::EventRecord as __hidden_EventRecord; - use sp_core::H256 as __hidden_H256; - use parity_scale_codec::Decode as _; - - let scale_events = $env.events($chain, $range).expect("Failed fetching events"); - let event_records: Vec<__hidden_EventRecord> = scale_events - .into_iter() - .map(|scale_record| __hidden_EventRecord::<$event, __hidden_H256>::decode(&mut scale_record.as_slice()) - .expect("Decoding from chain data does not fail. qed")) - .collect(); - - let matches = |event: &RuntimeEvent| { - match *event { - $( $pattern )|+ $( if $guard )? => true, - _ => false - } - }; - - let mut searched_events = Vec::new(); - for record in event_records.clone() { - if matches(&record.event) { - searched_events.push(record.event); - } - } - - (searched_events, event_records) - }}; - } - - /// A macro that helps including the given calls into a chain - /// and to progress a chain until all of them are included - /// - /// Usage: - /// ```ignore - /// env::run!( - /// env, //-> The test environment create with fudge::companion - /// Chain::Para(PARA_ID), //-> The chain, where the calls should be submitted - /// Call, //-> The Call-enum of the chains-runtime - /// ChainState::PoolEmpty, //-> The state the chain should evolve to - /// Keyring::Admin => //-> The executing account of the calls below - /// ..., //-> An infinity list of either Call-Variants or Vec - /// ....; // -> End of calls executed by the previously mentioned account - /// Keyring::Alice => ANOTHER_CALL_HERE; - /// ); - /// ``` - macro_rules! run { - // ($env:expr, $chain:expr, $call:ty, $state:expr, $($sender:expr => $($calls:expr),+);*) => {{ - ($env:expr, $chain:expr, $call:ty, $state:expr, $($sender:expr => $($calls:expr$(,)?)+);*) => {{ - use parity_scale_codec::Encode as _; - - trait CallAssimilator { - fn assimilate(self, calls: &mut Vec<$call>); - } - - impl CallAssimilator for Vec<$call> { - fn assimilate(self, calls: &mut Vec<$call>) { - calls.extend(self); - } - } - - impl CallAssimilator for $call { - fn assimilate(self, calls: &mut Vec<$call>) { - calls.push(self) - } - } - - $( - let mut calls = Vec::new(); - $( - $calls.assimilate(&mut calls); - )* - - let sign_and_submit_res = $env.batch_sign_and_submit($chain, $sender, calls.into_iter().map(|call| call.encode()).collect()); - assert!(sign_and_submit_res.is_ok()); - )* - - let evolve_res = $env.evolve_till($chain, $state); - assert!(evolve_res.is_ok()) - } - }; - } - // Need to export after definition. - pub(crate) use assert_events; - pub(crate) use events; - pub(crate) use evolve_until_event_is_found; - pub(crate) use extra_counts; - pub(crate) use extra_guards; - pub(crate) use run; -} - -lazy_static! { - pub static ref INSTANCE_COUNTER: Arc = - Arc::new(sp_std::sync::atomic::AtomicU64::new(0)); -} - -#[derive(Clone, Copy)] -pub enum ChainState { - PoolEmpty, - PoolMax(usize), - EvolvedBy(u64), -} - -#[cfg(not(feature = "runtime-benchmarks"))] -/// HostFunctions that do not include benchmarking specific host functions -type CentrifugeHF = sp_io::SubstrateHostFunctions; -#[cfg(feature = "runtime-benchmarks")] -/// Host functions that include benchmarking specific functionalities -type CentrifugeHF = sc_executor::sp_wasm_interface::ExtendedHostFunctions< - sp_io::SubstrateHostFunctions, - frame_benchmarking::benchmarking::HostFunctions, ->; - -/// Basic supstrate host functions -type HF = sp_io::SubstrateHostFunctions; - -/// The type that CreatesInherentDataProviders for the relay-chain. -/// As a new-type here as otherwise the TestEnv is badly -/// readable. -#[allow(unused)] -type RelayCidp = Box< - dyn CreateInherentDataProviders< - RelayBlock, - (), - InherentDataProviders = ( - FudgeInherentTimestamp, - sp_consensus_babe::inherents::InherentDataProvider, - FudgeDummyInherentRelayParachain, - ), - >, ->; - -/// The type that CreatesInherentDataProviders for the para-chain. -/// As a new-type here as otherwise the TestEnv is badly -/// readable. -#[allow(unused)] -type CentrifugeCidp = Box< - dyn CreateInherentDataProviders< - CentrifugeBlock, - (), - InherentDataProviders = ( - FudgeInherentTimestamp, - sp_consensus_aura::inherents::InherentDataProvider, - FudgeInherentParaParachain, - ), - >, ->; - -/// The type creates digests for the chains. -#[allow(unused)] -type CentrifugeDp = Box + Send + Sync>; - -/// The type creates digests for the chains. -#[allow(unused)] -type RelayDp = Box + Send + Sync>; - -/// A struct that stores all events that have been generated -/// since we are building blocks locally here. -pub struct EventsStorage { - pub centrifuge: HashMap>>, -} - -impl EventsStorage { - pub fn new() -> Self { - Self { - centrifuge: HashMap::new(), - } - } -} - -pub enum EventRange { - All, - One(BlockNumber), - Range(BlockNumber, BlockNumber), - Latest, -} - -pub(crate) const PARA_ID_SIBLING: u32 = 2001; - -#[fudge::companion] -pub struct TestEnv { - #[fudge::relaychain] - pub relay: RelaychainBuilder, - #[fudge::parachain(PARA_ID)] - pub centrifuge: - ParachainBuilder, - #[fudge::parachain(PARA_ID_SIBLING)] - pub sibling: ParachainBuilder, - nonce_manager: Arc>, - pub events: Arc>, -} - -pub type Header = cfg_primitives::Header; -pub type Block = cfg_primitives::Block; -pub type UncheckedExtrinsic = centrifuge::UncheckedExtrinsic; - -type EnvError = Box; - -// NOTE: Nonce management is a known issue when interacting with a chain and -// wanting to submit a lot of extrinsic. This interface eases this issues. -impl TestEnv { - pub fn events(&self, chain: Chain, range: EventRange) -> Result>, EnvError> - where - sp_runtime::generic::Block: sp_runtime::traits::Block, - { - match chain { - Chain::Relay => { - let latest = self - .centrifuge - .with_state(|| frame_system::Pallet::::block_number())?; - - match range { - EventRange::Latest => self.events_relay(latest), - EventRange::All => { - let mut events = Vec::new(); - // We MUST NOT query events at genesis block, as this triggers - // a panic. Hence, start at 1. - for block in 1..latest + 1 { - events.extend(self.events_relay(block)?) - } - - Ok(events) - } - EventRange::Range(from, to) => { - let mut events = Vec::new(); - for block in from..to + 1 { - events.extend(self.events_relay(block)?) - } - - Ok(events) - } - EventRange::One(at) => self.events_relay(at), - } - } - Chain::Para(id) => match id { - _ if id == PARA_ID => { - let latest = self - .centrifuge - .with_state(|| frame_system::Pallet::::block_number())?; - - match range { - EventRange::Latest => self.events_centrifuge(latest), - EventRange::All => { - let mut events = Vec::new(); - // We MUST NOT query events at genesis block, as this triggers - // a panic. Hence, start at 1. - for block in 1..latest + 1 { - events.extend(self.events_centrifuge(block)?) - } - - Ok(events) - } - EventRange::Range(from, to) => { - let mut events = Vec::new(); - for block in from..to + 1 { - events.extend(self.events_centrifuge(block)?) - } - - Ok(events) - } - EventRange::One(at) => self.events_centrifuge(at), - } - } - _ => Err(EnvError::from("parachain not found")), - }, - } - } - - fn events_centrifuge(&self, at: BlockNumber) -> Result>, EnvError> { - self.centrifuge - .with_state_at(BlockId::Number(at), || { - frame_system::Pallet::::events() - }) - .map_err(|e| e.into()) - .map(|records| records.into_iter().map(|record| record.encode()).collect()) - } - - fn events_relay(&self, at: BlockNumber) -> Result>, EnvError> { - self.relay - .with_state_at(BlockId::Number(at), || { - frame_system::Pallet::::events() - }) - .map_err(|e| e.into()) - .map(|records| records.into_iter().map(|record| record.encode()).collect()) - } - - /// Returns the next nonce to be used - /// **WARN: Increases the nonce counter on `NonceManager** - fn fetch_add_nonce(&mut self, chain: Chain, who: Keyring) -> Nonce { - let manager = self.nonce_manager.clone(); - self.with_state(chain, || { - manager - .lock() - .expect("Locking nonce manager must not fail.") - .fetch_add(chain, who) - }) - .expect("Essential: Nonce need to be retrievable and incrementable") - } - - /// Returns the next nonce to be used. Does NOT increase counter in - /// `NonceManager` - fn nonce(&mut self, chain: Chain, who: Keyring) -> Nonce { - let manager = self.nonce_manager.clone(); - self.with_state(chain, || { - manager - .lock() - .expect("Locking nonce manager must not fail.") - .nonce(chain, who) - }) - .expect("Essential: Nonce need to be retrievable") - } - - /// Does increase counter in `NonceManager`. MUST only be called - /// if a previously `nonce` has been called for a given `Keyring` - /// `Chain` combination. - fn incr_nonce(&mut self, chain: Chain, who: Keyring) { - let manager = self.nonce_manager.clone(); - self.with_state(chain, || { - manager - .lock() - .expect("Locking nonce manager must not fail.") - .incr(chain, who) - .expect("Essential: Nonce need to be incrementable") - }) - .expect("Essential: Nonce need to be retrievable") - } - - /// Resets the current nonce-manager - /// - /// General notes on usage of this function: - /// * should be used when an extrinsics fails -> nonces are out of sync - /// * should be used when a signed extrinsic is dropped -> nonces are out of - /// sync - pub fn clear_nonces(&mut self) { - self.nonce_manager = Arc::new(Mutex::new(NonceManager::new())); - } - - /// Signs a given call for the given chain. Should only be used if the - /// extrinsic really should be submitted afterwards. - /// **NOTE: This will increase the stored nonce of an account** - pub fn sign(&mut self, chain: Chain, who: Keyring, call: Vec) -> Result, EnvError> { - let nonce = self.fetch_add_nonce(chain, who); - match chain { - Chain::Relay => { - Ok(xt_relay(self, who, nonce, Decode::decode(&mut call.as_slice())?)?.encode()) - } - Chain::Para(id) => match id { - _ if id == PARA_ID => { - Ok( - xt_centrifuge(self, who, nonce, Decode::decode(&mut call.as_slice())?)? - .encode(), - ) - } - _ => Err(EnvError::from("parachain not found")), - }, - } - } - - /// Submits a previously signed extrinsics to the pool of the respective - /// chain. - pub fn submit(&mut self, chain: Chain, xt: Vec) -> Result<(), EnvError> { - self.append_extrinsic(chain, xt).map_err(|e| e.into()) - } - - /// Signs and submits an extrinsic to the given chain. Will take the nonce - /// for the account from the `NonceManager`. - pub fn sign_and_submit( - &mut self, - chain: Chain, - who: Keyring, - call: Vec, - ) -> Result<(), EnvError> { - let nonce = self.nonce(chain, who); - let xt = match chain { - Chain::Relay => { - xt_relay(self, who, nonce, Decode::decode(&mut call.as_slice())?)?.encode() - } - Chain::Para(id) => match id { - _ if id == PARA_ID => { - xt_centrifuge(self, who, nonce, Decode::decode(&mut call.as_slice())?)?.encode() - } - _ => return Err(EnvError::from("parachain not found")), - }, - }; - - self.append_extrinsic(chain, xt)?; - self.incr_nonce(chain, who); - Ok(()) - } - - /// Signs and submits a batch of extrinsic to the given chain. Will take the - /// nonce for the account from the `NonceManager`. - /// - /// Returns early of an extrinsic fails to be submitted. - pub fn batch_sign_and_submit( - &mut self, - chain: Chain, - who: Keyring, - calls: Vec>, - ) -> Result<(), EnvError> { - for call in calls { - self.sign_and_submit(chain, who, call)?; - } - - Ok(()) - } - - pub fn evolve_till(&mut self, chain: Chain, till_state: ChainState) -> Result<(), EnvError> { - match chain { - Chain::Relay => match till_state { - ChainState::EvolvedBy(blocks) => pass_n(self, blocks / 2), - ChainState::PoolEmpty => self.evolve_till_pool_xts_relay(0), - ChainState::PoolMax(max) => self.evolve_till_pool_xts_relay(max), - }, - Chain::Para(id) => match id { - _ if id == PARA_ID => match till_state { - ChainState::EvolvedBy(blocks) => pass_n(self, blocks), - ChainState::PoolEmpty => self.evolve_till_pool_xts_centrifuge(0), - ChainState::PoolMax(max) => self.evolve_till_pool_xts_centrifuge(max), - }, - _ => unreachable!("No other parachain supported currently."), - }, - } - } - - fn evolve_till_pool_xts_centrifuge(&mut self, xts: usize) -> Result<(), EnvError> { - let state = self.centrifuge.pool_state(); - let mut curr_xts = match state { - PoolState::Empty => return Ok(()), - PoolState::Busy(curr_xts) => curr_xts, - }; - - if curr_xts <= xts { - return Ok(()); - } else { - while curr_xts > xts { - self.evolve()?; - let event_storage = self.events.clone(); - self.centrifuge.with_state(|| { - let mut storage = event_storage - .lock() - .expect("Must not fail getting event-storage"); - let block = frame_system::Pallet::::block_number(); - storage - .centrifuge - .insert(block, frame_system::Pallet::::events()); - }); - - curr_xts = match self.centrifuge.pool_state() { - PoolState::Empty => return Ok(()), - PoolState::Busy(curr_xts) => curr_xts, - }; - } - } - - Ok(()) - } - - fn evolve_till_pool_xts_relay(&mut self, xts: usize) -> Result<(), EnvError> { - let state = self.relay.pool_state(); - let mut curr_xts = match state { - PoolState::Empty => return Ok(()), - PoolState::Busy(curr_xts) => curr_xts, - }; - - if curr_xts <= xts { - return Ok(()); - } else { - while curr_xts > xts { - self.evolve()?; - curr_xts = match self.relay.pool_state() { - PoolState::Empty => return Ok(()), - PoolState::Busy(curr_xts) => curr_xts, - }; - } - } - - Ok(()) - } -} - -#[allow(unused)] -pub fn test_env_default(handle: Handle) -> TestEnv { - test_env(handle, None, None) -} - -#[allow(unused)] -pub fn test_env_with_relay_storage(handle: Handle, storage: Storage) -> TestEnv { - test_env(handle, Some(storage), None) -} - -#[allow(unused)] -pub fn test_env_with_centrifuge_storage(handle: Handle, storage: Storage) -> TestEnv { - test_env(handle, None, Some(storage)) -} - -#[allow(unused)] -pub fn test_env_with_both_storage( - handle: Handle, - relay_storage: Storage, - centrifuge_storage: Storage, -) -> TestEnv { - test_env(handle, Some(relay_storage), Some(centrifuge_storage)) -} - -fn test_env( - handle: Handle, - relay_storage: Option, - centrifuge_storage: Option, -) -> TestEnv { - logs::init_logs(); - - // Build relay-chain builder - let relay = { - sp_tracing::enter_span!(sp_tracing::Level::INFO, "Relay - StartUp"); - - //TODO(cdamian): Use RelayBlock - let mut state = - StateProvider::, centrifuge::Block>::empty_default( - Some(RelayCode.expect("Wasm is build. Qed.")), - ) - .expect("ESSENTIAL: State provider can be created"); - - let mut configuration = configuration::GenesisConfig::::default(); - - let mut host_config = HostConfiguration::::default(); - host_config.max_downward_message_size = 1024; - host_config.hrmp_channel_max_capacity = 100; - host_config.hrmp_channel_max_message_size = 1024; - host_config.hrmp_channel_max_total_size = 1024; - host_config.hrmp_max_parachain_outbound_channels = 10; - host_config.hrmp_max_parachain_inbound_channels = 10; - host_config.hrmp_max_message_num_per_candidate = 100; - - configuration.config = host_config; - - state.insert_storage( - configuration - .build_storage() - .expect("ESSENTIAL: Host Configuration GenesisBuild must not fail at this stage."), - ); - - state.insert_storage( - frame_system::GenesisConfig:: { - code: RelayCode.expect("ESSENTIAL: Relay WASM is some.").to_vec(), - _config: Default::default(), - } - .build_storage() - .expect("ESSENTIAL: Frame System GenesisBuild must not fail at this stage."), - ); - - if let Some(storage) = relay_storage { - state.insert_storage(storage); - } - - let mut init = fudge::initiator::default(handle.clone()); - init.with_genesis(Box::new(state)); - - let cidp: fn(Arc<_>) -> RelayCidp = |clone_client: Arc< - TFullClient, - >| { - let instance_id = FudgeInherentTimestamp::create_instance( - std::time::Duration::from_secs(6), - Some(std::time::Duration::from_millis(START_DATE)), - ) - .expect("ESSENTIAL: Instance ID can be created."); - - Box::new(move |parent: H256, ()| { - let client = clone_client.clone(); - let parent_header = client - .header(parent.clone()) - .expect("ESSENTIAL: Relay CIDP must not fail.") - .expect("ESSENTIAL: Relay CIDP must not fail."); - - async move { - let timestamp = FudgeInherentTimestamp::get_instance(instance_id) - .expect("Instances is initialized"); - - let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - timestamp.current_time(), - SlotDuration::from_millis(std::time::Duration::from_secs(6).as_millis() as u64), - ); - - let relay_para_inherent = FudgeDummyInherentRelayParachain::new(parent_header); - Ok((timestamp, slot, relay_para_inherent)) - } - }) - }; - - let dp: RelayDp = Box::new( - move |parent: sp_runtime::generic::Header, inherents| async move { - let babe = FudgeBabeDigest::::new(); - let digest = babe.build_digest(parent, &inherents).await?; - Ok(digest) - }, - ); - - RelaychainBuilder::<_, _, RelayRt, RelayCidp, RelayDp>::new(init, |client| { - (cidp(client), dp) - }) - .expect("ESSENTIAL: Relay chain builder can be created.") - }; - - let para_inherent_builder = relay.inherent_builder(ParaId::from(PARA_ID)); - let sibling_inherent_builder = relay.inherent_builder(ParaId::from(PARA_ID_SIBLING)); - - let para_builder = get_parachain_builder( - handle.clone(), - para_inherent_builder, - PARA_ID, - centrifuge_storage.clone(), - ); - - let sibling_builder = get_parachain_builder( - handle, - sibling_inherent_builder, - PARA_ID_SIBLING, - centrifuge_storage, - ); - - TestEnv::new( - relay, - para_builder, - sibling_builder, - Arc::new(Mutex::new(NonceManager::new())), - Arc::new(Mutex::new(EventsStorage::new())), - ) - .expect("ESSENTIAL: Creating new TestEnv instance must not fail.") -} - -fn get_parachain_builder( - handle: Handle, - inherent_builder: InherentBuilder< - TFullBackend, - TFullClient, - >, - para_id: u32, - centrifuge_storage: Option, -) -> ParachainBuilder { - sp_tracing::enter_span!(sp_tracing::Level::INFO, "Parachain - StartUp"); - - let mut state = - StateProvider::, centrifuge::Block>::empty_default(Some( - CentrifugeCode.expect("Wasm is build. Qed."), - )) - .expect("ESSENTIAL: State provider can be created."); - - state.insert_storage( - frame_system::GenesisConfig:: { - code: CentrifugeCode - .expect("ESSENTIAL: Centrifuge WASM is some.") - .to_vec(), - _config: Default::default(), - } - .build_storage() - .expect("ESSENTIAL: Frame System GenesisBuild must not fail at this stage."), - ); - state.insert_storage( - pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(sp_core::sr25519::Public([0u8; 32]))], - } - .build_storage() - .expect("ESSENTIAL: Pallet Aura GenesisBuild must not fail at this stage."), - ); - state.insert_storage( - parachain_info::GenesisConfig:: { - _config: Default::default(), - parachain_id: ParaId::from(para_id), - } - .build_storage() - .expect("ESSENTIAL: Parachain Info GenesisBuild must not fail at this stage."), - ); - - if let Some(storage) = centrifuge_storage { - state.insert_storage(storage); - } - - let mut init = fudge::initiator::default(handle); - init.with_genesis(Box::new(state)); - - let para_id = ParaId::from(para_id); - let instance_id = FudgeInherentTimestamp::create_instance( - std::time::Duration::from_secs(12), - Some(std::time::Duration::from_millis(START_DATE)), - ) - .expect("ESSENTIAL: Instance ID can be created."); - - let cidp = Box::new(move |_parent: H256, ()| { - let inherent_builder_clone = inherent_builder.clone(); - async move { - let timestamp = FudgeInherentTimestamp::get_instance(instance_id) - .expect("Instances is initialized"); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - timestamp.current_time(), - SlotDuration::from_millis(std::time::Duration::from_secs(12).as_millis() as u64), - ); - let inherent = inherent_builder_clone.parachain_inherent().await.unwrap(); - let relay_para_inherent = FudgeInherentParaParachain::new(inherent); - Ok((timestamp, slot, relay_para_inherent)) - } - }); - let dp = |clone_client: Arc< - sc_service::TFullClient, - >| { - Box::new(move |parent, inherents| { - let client = clone_client.clone(); - - async move { - let aura = FudgeAuraDigest::< - CentrifugeBlock, - sc_service::TFullClient, - >::new(&*client) - .expect("ESSENTIAL: Aura digest can be created."); - - let digest = aura.build_digest(parent, &inherents).await?; - Ok(digest) - } - }) - }; - - ParachainBuilder::<_, _, CentrifugeCidp, CentrifugeDp>::new(para_id, init, |client| { - (cidp, dp(client)) - }) - .expect("ESSENTIAL: Parachain builder can be created.") -} - -/// Pass n_blocks on the parachain-side! -pub fn pass_n(env: &mut TestEnv, n: u64) -> Result<(), EnvError> { - for _ in 0..n { - env.evolve()?; - } - - Ok(()) -} - -mod tests { - use super::*; - - #[tokio::test] - async fn env_works() { - let mut env = test_env_default(Handle::current()); - - // FIXME: https://github.com/centrifuge/centrifuge-chain/issues/1219 - // Breaks on >= 10 for fast-runtime since session length is 5 blocks - #[cfg(feature = "fast-runtime")] - let num_blocks = 9; - #[cfg(not(feature = "fast-runtime"))] - let num_blocks = 10; - let block_before = env - .with_state(Chain::Para(PARA_ID), || { - frame_system::Pallet::::block_number() - }) - .expect("Cannot create block before"); - - frame_support::assert_ok!(pass_n(&mut env, num_blocks)); - - let block_after = env - .with_state(Chain::Para(PARA_ID), || { - frame_system::Pallet::::block_number() - }) - .expect("Cannot create block after"); - - assert_eq!(block_before + num_blocks as u32, block_after) - } -} diff --git a/runtime/integration-tests/src/utils/evm.rs b/runtime/integration-tests/src/utils/evm.rs deleted file mode 100644 index ec5f7020c5..0000000000 --- a/runtime/integration-tests/src/utils/evm.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -use frame_support::{dispatch::RawOrigin, traits::fungible::Mutate}; -use fudge::primitives::Chain; -use pallet_evm::FeeCalculator; -use runtime_common::account_conversion::AccountConverter; -use sp_core::{Get, H160, U256}; - -use crate::{ - chain::centrifuge::{Balances, Runtime, PARA_ID}, - utils::env::TestEnv, -}; - -pub fn mint_balance_into_derived_account(env: &mut TestEnv, address: H160, balance: u128) { - let chain_id = env - .with_state(Chain::Para(PARA_ID), || { - pallet_evm_chain_id::Pallet::::get() - }) - .unwrap(); - - let derived_account = AccountConverter::convert_evm_address(chain_id, address.to_fixed_bytes()); - - env.with_mut_state(Chain::Para(PARA_ID), || { - Balances::mint_into(&derived_account.into(), balance).unwrap() - }) - .unwrap(); -} - -pub fn deploy_contract(env: &mut TestEnv, address: H160, code: Vec) { - let chain_id = env - .with_state(Chain::Para(PARA_ID), || { - pallet_evm_chain_id::Pallet::::get() - }) - .unwrap(); - - let derived_address = AccountConverter::convert_evm_address(chain_id, address.to_fixed_bytes()); - - let transaction_create_cost = env - .with_state(Chain::Para(PARA_ID), || { - ::config().gas_transaction_create - }) - .unwrap(); - - let base_fee = env - .with_state(Chain::Para(PARA_ID), || { - let (base_fee, _) = ::FeeCalculator::min_gas_price(); - base_fee - }) - .unwrap(); - - env.with_mut_state(Chain::Para(PARA_ID), || { - pallet_evm::Pallet::::create( - RawOrigin::from(Some(derived_address)).into(), - address, - code, - U256::from(0), - transaction_create_cost * 10, - U256::from(base_fee + 10), - None, - None, - Vec::new(), - ) - .unwrap(); - }) - .unwrap(); -} diff --git a/runtime/integration-tests/src/utils/extrinsics.rs b/runtime/integration-tests/src/utils/extrinsics.rs deleted file mode 100644 index 5cf9c6a311..0000000000 --- a/runtime/integration-tests/src/utils/extrinsics.rs +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Utilities for creating extrinsics -#![allow(unused)] - -use cfg_primitives::{ - AccountId as CentrifugeAccountId, Address as CentrifugeAddress, Nonce as CentrifugeNonce, -}; -use parity_scale_codec::Encode; -use polkadot_core_primitives::{ - AccountId as RelayAccountId, BlockId as RelayBlockId, Nonce as RelayNonce, -}; -use sc_client_api::client::BlockBackend; -use sp_core::H256; -use sp_runtime::{ - generic::{Era, SignedPayload}, - MultiSignature, -}; - -use crate::{ - chain::{ - centrifuge, - centrifuge::{ - Runtime as CentrifugeRuntime, RuntimeCall as CentrifugeCall, - SignedExtra as CentrifugeSignedExtra, UncheckedExtrinsic as CentrifugeUnchecked, - }, - relay, - relay::{ - Address as RelayAddress, Runtime as RelayRuntime, RuntimeCall as RelayCall, - SignedExtra as RelaySignedExtra, UncheckedExtrinsic as RelayUnchecked, - }, - }, - utils::{accounts::Keyring, env::TestEnv}, -}; - -/// Generates an signed-extrinisc for centrifuge-chain. -/// -/// **NOTE: Should not be used if the TesteEnv::sign_and_submit() interface is -/// also used with the same `who` as the sender** -pub fn xt_centrifuge( - env: &TestEnv, - who: Keyring, - nonce: cfg_primitives::Nonce, - call: centrifuge::RuntimeCall, -) -> Result> { - let client = env.centrifuge.client(); - - let genesis_hash = client - .block_hash(0) - .expect("ESSENTIAL: Genesis MUST be avilable.") - .unwrap(); - let (spec_version, tx_version) = { - let version = client - .runtime_version_at(client.chain_info().best_hash) - .unwrap(); - (version.spec_version, version.transaction_version) - }; - - env.centrifuge - .with_state(|| sign_centrifuge(who, nonce, call, spec_version, tx_version, genesis_hash)) - .map_err(|e| e.into()) -} - -/// Generates an signed-extrinisc for relay-chain. -/// -/// **NOTE: Should not be used if the TesteEnv::sign_and_submit() interface is -/// also used with the same `who` as the sender** -pub fn xt_relay( - env: &TestEnv, - who: Keyring, - nonce: RelayNonce, - call: relay::RuntimeCall, -) -> Result> { - let client = env.relay.client(); - - let genesis_hash = client - .block_hash(0) - .expect("ESSENTIAL: Genesis MUST be avilable.") - .expect("ESSENTIAL: Genesis MUST be avilable."); - let (spec_version, tx_version) = { - let version = client - .runtime_version_at(client.chain_info().best_hash) - .unwrap(); - (version.spec_version, version.transaction_version) - }; - - env.relay - .with_state(|| sign_relay(who, nonce, call, spec_version, tx_version, genesis_hash)) - .map_err(|e| e.into()) -} - -fn signed_extra_centrifuge(nonce: cfg_primitives::Nonce) -> CentrifugeSignedExtra { - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - runtime_common::transfer_filter::PreBalanceTransferExtension::::new(), - ) -} - -fn sign_centrifuge( - who: Keyring, - nonce: cfg_primitives::Nonce, - call: CentrifugeCall, - spec_version: u32, - tx_version: u32, - genesis_hash: H256, -) -> CentrifugeUnchecked { - let extra = signed_extra_centrifuge(nonce); - let additional = ( - (), - spec_version, - tx_version, - genesis_hash, - genesis_hash.clone(), - (), - (), - (), - (), - ); - let raw_payload = SignedPayload::from_raw(call.clone(), extra.clone(), additional); - let signature = MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - CentrifugeUnchecked::new_signed( - call, - CentrifugeAddress::Id(who.to_account_id()), - signature, - extra, - ) -} - -fn signed_extra_relay(nonce: RelayNonce) -> RelaySignedExtra { - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckMortality::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ) -} - -fn sign_relay( - who: Keyring, - nonce: RelayNonce, - call: RelayCall, - spec_version: u32, - tx_version: u32, - genesis_hash: H256, -) -> RelayUnchecked { - let extra = signed_extra_relay(nonce); - let additional = ( - (), - spec_version, - tx_version, - genesis_hash.clone(), - genesis_hash, - (), - (), - (), - ); - let raw_payload = SignedPayload::from_raw(call.clone(), extra.clone(), additional); - let signature = MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - RelayUnchecked::new_signed( - call, - RelayAddress::Id(who.to_account_id()), - signature, - extra, - ) -} - -/// Retrieves the latest centrifuge nonce for a given account. -/// -/// **NOTE: Should not be used if the TesteEnv::sign_and_submit() interface is -/// also used with the same `who` as the sender** -pub fn nonce_centrifuge(env: &TestEnv, who: Keyring) -> cfg_primitives::Nonce { - env.centrifuge - .with_state(|| { - nonce::( - who.clone().to_account_id().into(), - ) - }) - .expect("ESSENTIAL: Nonce must be retrievable.") -} - -/// Retrieves the latest relay nonce for a given account. -/// -/// **NOTE: Should not be used if the TesteEnv::sign_and_submit() interface is -/// also used with the same `who` as the sender** -pub fn nonce_relay(env: &TestEnv, who: Keyring) -> RelayNonce { - env.relay - .with_state(|| { - nonce::(who.clone().to_account_id().into()) - }) - .expect("ESSENTIAL: Nonce must be retrievable.") -} - -fn nonce(who: AccountId) -> Nonce -where - Runtime: frame_system::Config, - AccountId: Into<::AccountId>, - Nonce: From<::Nonce>, -{ - frame_system::Pallet::::account_nonce(who.into()).into() -} - -mod tests { - use fudge::primitives::Chain; - use pallet_balances::Call as BalancesCall; - use parity_scale_codec::Encode; - use sp_runtime::Storage; - use tokio::runtime::Handle; - - use super::{nonce_centrifuge, xt_centrifuge}; - use crate::{ - chain::{ - centrifuge, - centrifuge::{Runtime, PARA_ID}, - }, - utils::{accounts::Keyring, env, genesis}, - }; - - #[tokio::test] - async fn extrinsics_works() { - let mut genesis = Storage::default(); - genesis::default_balances::(&mut genesis); - let mut env = env::test_env_with_centrifuge_storage(Handle::current(), genesis); - - let to: cfg_primitives::Address = Keyring::Bob.into(); - let xt = xt_centrifuge( - &env, - Keyring::Alice, - nonce_centrifuge(&env, Keyring::Alice), - centrifuge::RuntimeCall::Balances(BalancesCall::transfer { - dest: to, - value: 100 * cfg_primitives::constants::CFG, - }), - ) - .unwrap(); - env.append_extrinsic(Chain::Para(PARA_ID), xt.encode()) - .unwrap(); - - let (alice_before, bob_before) = env - .with_state(Chain::Para(PARA_ID), || { - ( - frame_system::Pallet::::account(Keyring::Alice.to_account_id()), - frame_system::Pallet::::account(Keyring::Bob.to_account_id()), - ) - }) - .unwrap(); - - env.evolve().unwrap(); - - let (alice_after, bob_after) = env - .with_state(Chain::Para(PARA_ID), || { - ( - frame_system::Pallet::::account(Keyring::Alice.to_account_id()), - frame_system::Pallet::::account(Keyring::Bob.to_account_id()), - ) - }) - .unwrap(); - - // Need to account for fees here - assert!( - alice_after.data.free <= alice_before.data.free - 100 * cfg_primitives::constants::CFG - ); - assert_eq!( - bob_after.data.free, - bob_before.data.free + 100 * cfg_primitives::constants::CFG - ); - - env.evolve().unwrap(); - - let (alice_after, bob_after) = env - .with_state(Chain::Para(PARA_ID), || { - ( - frame_system::Pallet::::account(Keyring::Alice.to_account_id()), - frame_system::Pallet::::account(Keyring::Bob.to_account_id()), - ) - }) - .unwrap(); - - // Need to account for fees here - assert!( - alice_after.data.free <= alice_before.data.free - 100 * cfg_primitives::constants::CFG - ); - assert_eq!( - bob_after.data.free, - bob_before.data.free + 100 * cfg_primitives::constants::CFG - ); - } -} diff --git a/runtime/integration-tests/src/utils/genesis.rs b/runtime/integration-tests/src/utils/genesis.rs deleted file mode 100644 index 123268ceb1..0000000000 --- a/runtime/integration-tests/src/utils/genesis.rs +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// TODO: this file must be removed after -// https://github.com/centrifuge/centrifuge-chain/issues/1790 -#![allow(deprecated)] - -//! Utilities around populating a genesis storage -use cfg_types::{ - fixed_point::Rate, - tokens::{CurrencyId, CustomMetadata}, -}; -use frame_support::traits::GenesisBuild; -use serde::{Deserialize, Serialize}; -use sp_runtime::{AccountId32, BoundedVec, BuildStorage, FixedPointNumber, Storage}; - -use crate::utils::{ - accounts::{default_accounts, Keyring}, - tokens::{DECIMAL_BASE_12, DECIMAL_BASE_18}, - AUSD_CURRENCY_ID, AUSD_ED, GLMR_CURRENCY_ID, GLMR_ED, RELAY_ASSET_ID, USDT_CURRENCY_ID, - USDT_ED, -}; - -/// Provides 100_000 * DECIMAL_BASE_18 native tokens to the -/// `accounts::default_accounts()` -pub fn default_native_balances(storage: &mut Storage) -where - Runtime: pallet_balances::Config, - Runtime::Balance: From, - Runtime::AccountId: From, -{ - pallet_balances::GenesisConfig:: { - balances: default_accounts() - .into_iter() - .map(|acc| { - ( - AccountId32::from(acc).into(), - (100_000 * DECIMAL_BASE_18).into(), - ) - }) - .collect(), - } - .assimilate_storage(storage) - .expect("ESSENTIAL: Balances Genesisbuild is not allowed to fail."); -} - -/// Sets the balances for default accounts in the Orml Tokens genesis config -/// with the provided amount for a specific currency. -pub fn default_orml_balances(storage: &mut Storage, currency_id: CurrencyId, amount: u128) -where - Runtime: orml_tokens::Config, - Runtime::Balance: From, - Runtime::AccountId: From, - Runtime::CurrencyId: From, -{ - orml_tokens::GenesisConfig:: { - balances: default_accounts() - .into_iter() - .map(|acc| { - ( - AccountId32::from(acc).into(), - currency_id.into(), - amount.into(), - ) - }) - .collect(), - } - .assimilate_storage(storage) - .expect("ESSENTIAL: Orml Tokens Genesisbuild is not allowed to fail."); -} - -/// Provides 100_000 * DECIMAL_BASE_18 and Provides 100_000 * DECIMAL_BASE_12 -/// AUSD tokens to the `accounts::default_accounts()` -pub fn default_balances(storage: &mut Storage) -where - Runtime: orml_tokens::Config + pallet_balances::Config, - ::Balance: From, - ::Balance: From, - Runtime::AccountId: From, - Runtime::CurrencyId: From, -{ - default_native_balances::(storage); - default_orml_balances::(storage, AUSD_CURRENCY_ID, AUSD_ED); - default_orml_balances::(storage, USDT_CURRENCY_ID, USDT_ED); - default_orml_balances::(storage, GLMR_CURRENCY_ID, GLMR_ED); -} - -/// Register the Relay chain token and AUSD_CURRENCY_ID in the asset registry -pub fn register_default_asset(storage: &mut Storage) -where - Runtime: orml_asset_registry::Config, - ::Balance: From, - ::AssetId: From, - ::CustomMetadata: From, -{ - let genesis = MockGenesisConfigAssetRegistry { - assets: vec![RELAY_ASSET_ID, AUSD_CURRENCY_ID], - }; - - >::assimilate_storage( - &genesis, storage, - ) - .expect("ESSENTIAL: Genesisbuild is not allowed to fail."); -} - -/// Register the given asset in the orml_asset_registry storage from genesis -/// onwards -pub fn register_asset(asset: CurrencyId, storage: &mut Storage) -where - Runtime: orml_asset_registry::Config + Default, - ::AssetId: From, - ::Balance: From, - ::CustomMetadata: From, -{ - let genesis = MockGenesisConfigAssetRegistry { - assets: vec![asset], - }; - - >::assimilate_storage( - &genesis, storage, - ) - .expect("ESSENTIAL: Genesisbuild is not allowed to fail."); -} - -#[derive(Default, Serialize, Deserialize)] -struct MockGenesisConfigAssetRegistry { - pub assets: Vec, -} - -impl GenesisBuild for MockGenesisConfigAssetRegistry -where - Runtime: orml_asset_registry::Config, - ::AssetId: From, - ::Balance: From, - ::CustomMetadata: From, -{ - fn build(&self) { - let assets = self.assets.clone(); - for asset in assets { - orml_asset_registry::Pallet::::do_register_asset( - orml_asset_registry::AssetMetadata { - decimals: 18, - name: BoundedVec::default(), - symbol: BoundedVec::default(), - existential_deposit: 0u128.into(), - location: None, - additional: CustomMetadata { - pool_currency: asset == AUSD_CURRENCY_ID, - ..CustomMetadata::default().into() - } - .into(), - }, - Some(asset.clone().into()), - ) - .expect("ESSENTIAL: Genesisbuild is not allowed to fail."); - } - } -} - -/// Sets up dummy session keys for all `accounts::default_accounts()` by -/// assigning their sr25519 public keys. -pub fn default_session_keys(storage: &mut Storage) -where - Runtime: pallet_session::Config, - Runtime::AccountId: From, - ::ValidatorId: From, - ::Keys: From, /* ::Keys: From, */ -{ - pallet_session::GenesisConfig:: { - keys: default_accounts() - .into_iter() - .map(|acc| { - ( - AccountId32::from(acc.clone()).into(), - AccountId32::from(acc.clone()).into(), - development_runtime::SessionKeys { - aura: acc.public().into(), - block_rewards: acc.public().into(), - } - .into(), - ) - }) - .collect(), - } - .assimilate_storage(storage) - .expect("ESSENTIAL: Genesisbuild is not allowed to fail."); -} - -/// Sets `Keyring::Admin` as the genesis invulnerable of -/// `pallet_collator_selection`. -pub fn admin_invulnerable(storage: &mut Storage) -where - Runtime::AccountId: From, - Runtime: pallet_collator_selection::Config, - <::Currency as frame_support::traits::Currency< - ::AccountId, - >>::Balance: From, -{ - use sp_core::Get; - - pallet_collator_selection::GenesisConfig:: { - invulnerables: vec![Keyring::Admin.to_account_id().into()], - candidacy_bond: cfg_primitives::MILLI_CFG.into(), - desired_candidates: ::MaxCandidates::get(), - } - .assimilate_storage(storage) - .expect("ESSENTIAL: Genesisbuild is not allowed to fail."); -} - -/// Sets `Keyring::Admin` as the genesis staker of `pallet_block_rewards`. -pub fn admin_collator(storage: &mut Storage) -where - Runtime::AccountId: From, - Runtime: pallet_block_rewards::Config, - ::Balance: From, - ::Rate: From, -{ - pallet_block_rewards::GenesisConfig:: { - collators: vec![Keyring::Admin.to_account_id().into()], - collator_reward: (1000 * cfg_primitives::CFG).into(), - treasury_inflation_rate: Rate::saturating_from_rational(3, 100).into(), - last_update: Default::default(), - } - .assimilate_storage(storage) - .expect("ESSENTIAL: Genesisbuild is not allowed to fail."); -} - -/// Sets the `default_accounts` as council members. -pub fn default_council_members(storage: &mut Storage) -where - Instance: 'static, - Runtime: pallet_collective::Config, - Runtime::AccountId: From, -{ - council_members::(default_accounts(), storage) -} - -/// Sets the provided account IDs as council members. -pub fn council_members(members: Vec, storage: &mut Storage) -where - Instance: 'static, - Runtime: pallet_collective::Config, - Runtime::AccountId: From, -{ - pallet_collective::GenesisConfig:: { - phantom: Default::default(), - members: members - .into_iter() - .map(|acc| acc.to_account_id().into()) - .collect(), - } - .assimilate_storage(storage) - .expect("ESSENTIAL: Pallet collective genesis build is not allowed to fail") -} diff --git a/runtime/integration-tests/src/utils/mod.rs b/runtime/integration-tests/src/utils/mod.rs index a390d3dbbc..f4f23fffaa 100644 --- a/runtime/integration-tests/src/utils/mod.rs +++ b/runtime/integration-tests/src/utils/mod.rs @@ -10,29 +10,5 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -use cfg_primitives::Balance; -use cfg_types::tokens::CurrencyId; - pub mod accounts; -pub mod env; -pub mod evm; -pub mod extrinsics; -pub mod genesis; pub mod logs; -pub mod time; -pub mod tokens; - -/// The relay native token's asset id -pub const RELAY_ASSET_ID: CurrencyId = CurrencyId::ForeignAsset(5); -/// The Glimmer asset id -pub const GLMR_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(4); -/// The AUSD asset id -pub const AUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(3); -/// The USDT asset id -pub const USDT_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); -/// The EVM Chain id of Moonbeam -pub const MOONBEAM_EVM_CHAIN_ID: u64 = 1284; - -pub const GLMR_ED: Balance = 1_000_000; -pub const AUSD_ED: Balance = 1_000_000_000; -pub const USDT_ED: Balance = 10_000; diff --git a/runtime/integration-tests/src/utils/time.rs b/runtime/integration-tests/src/utils/time.rs deleted file mode 100644 index c33494f861..0000000000 --- a/runtime/integration-tests/src/utils/time.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Time constants and utlities around time - -/// Start date used for timestamps in test-enviornments -/// Sat Jan 01 2022 00:00:00 GMT+0000 -pub const START_DATE: u64 = 1640995200u64; - -pub mod secs { - pub const SECOND: u64 = 1000u64; - pub const SECONDS_PER_MINUTE: u64 = 60 * SECOND; - pub const SECONDS_PER_HOUR: u64 = 60 * SECONDS_PER_MINUTE; - pub const SECONDS_PER_DAY: u64 = 24 * SECONDS_PER_HOUR; - pub const SECONDS_PER_YEAR: u64 = 365 * SECONDS_PER_DAY; -} - -pub mod blocks { - use super::secs; - - // as u32 calls are all save as none of the secs is about u32::MAX - pub const SECS_PER_BLOCK: u32 = 12u32; - pub const BLOCKS_PER_MINUTE: u32 = secs::SECONDS_PER_MINUTE as u32 / SECS_PER_BLOCK; - pub const BLOCKS_PER_HOUR: u32 = secs::SECONDS_PER_HOUR as u32 / SECS_PER_BLOCK; - pub const BLOCKS_PER_DAY: u32 = secs::SECONDS_PER_DAY as u32 / SECS_PER_BLOCK; - pub const BLOCKS_PER_YEAR: u32 = secs::SECONDS_PER_YEAR as u32 / SECS_PER_BLOCK; -} diff --git a/runtime/integration-tests/src/utils/tokens.rs b/runtime/integration-tests/src/utils/tokens.rs deleted file mode 100644 index 0776426e47..0000000000 --- a/runtime/integration-tests/src/utils/tokens.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2021 Centrifuge Foundation (centrifuge.io). -// -// This file is part of the Centrifuge chain project. -// Centrifuge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version (see http://www.gnu.org/licenses). -// Centrifuge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Time balances and tokens -use cfg_types::fixed_point::Rate; -use sp_runtime::FixedPointNumber; - -use crate::utils::time::secs::SECONDS_PER_YEAR; - -pub const DECIMAL_BASE_12: u128 = 1_000_000_000_000; -pub const DECIMAL_BASE_18: u128 = DECIMAL_BASE_12 * 1_000_000; -pub const DECIMAL_BASE_27: u128 = DECIMAL_BASE_18 * 1_000_000_000; - -lazy_static::lazy_static! { - pub static ref YEAR_RATE: Rate = Rate::saturating_from_integer(SECONDS_PER_YEAR); -} - -pub fn rate_from_percent(perc: u64) -> Rate { - Rate::saturating_from_rational(perc, 100) -}