Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pallet_pooled_staking to Dancelight #774

Merged
merged 16 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions runtime/dancebox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1569,11 +1569,11 @@ parameter_types! {
pub const StakingSessionDelay: u32 = 2;
}

pub struct SessionTimer<G>(PhantomData<G>);
pub struct SessionTimer<Delay>(PhantomData<Delay>);

impl<G> Timer for SessionTimer<G>
impl<Delay> Timer for SessionTimer<Delay>
where
G: Get<u32>,
Delay: Get<u32>,
{
type Instant = u32;

Expand All @@ -1582,7 +1582,7 @@ where
}

fn is_elapsed(instant: &Self::Instant) -> bool {
let delay = G::get();
let delay = Delay::get();
let Some(end) = instant.checked_add(delay) else {
return false;
};
Expand All @@ -1591,7 +1591,7 @@ where

#[cfg(feature = "runtime-benchmarks")]
fn elapsed_instant() -> Self::Instant {
let delay = G::get();
let delay = Delay::get();
Self::now()
.checked_add(delay)
.expect("overflow when computing valid elapsed instant")
Expand Down
4 changes: 4 additions & 0 deletions solo-chains/runtime/dancelight/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ pallet-author-noting-runtime-api = { workspace = true }
pallet-configuration = { workspace = true }
pallet-data-preservers = { workspace = true }
pallet-inflation-rewards = { workspace = true }
pallet-pooled-staking = { workspace = true }
pallet-registrar = { workspace = true }
pallet-registrar-runtime-api = { workspace = true }
pallet-services-payment = { workspace = true }
Expand Down Expand Up @@ -237,6 +238,7 @@ std = [
"pallet-multisig/std",
"pallet-offences/std",
"pallet-parameters/std",
"pallet-pooled-staking/std",
"pallet-preimage/std",
"pallet-proxy/std",
"pallet-ranked-collective/std",
Expand Down Expand Up @@ -347,6 +349,7 @@ runtime-benchmarks = [
"pallet-multisig/runtime-benchmarks",
"pallet-offences/runtime-benchmarks",
"pallet-parameters/runtime-benchmarks",
"pallet-pooled-staking/runtime-benchmarks",
"pallet-preimage/runtime-benchmarks",
"pallet-proxy/runtime-benchmarks",
"pallet-ranked-collective/runtime-benchmarks",
Expand Down Expand Up @@ -425,6 +428,7 @@ try-runtime = [
"pallet-multisig/try-runtime",
"pallet-offences/try-runtime",
"pallet-parameters/try-runtime",
"pallet-pooled-staking/try-runtime",
"pallet-preimage/try-runtime",
"pallet-proxy/try-runtime",
"pallet-ranked-collective/try-runtime",
Expand Down
17 changes: 16 additions & 1 deletion solo-chains/runtime/dancelight/src/genesis_config_presets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,25 @@ fn dancelight_testnet_genesis(
let next_free_para_id = max_para_id
.map(|x| ParaId::from(u32::from(*x) + 1))
.unwrap_or(primitives::LOWEST_PUBLIC_ID);
let accounts_with_ed = [
crate::StakingAccount::get(),
crate::DancelightBondAccount::get(),
crate::PendingRewardsAccount::get(),
];

serde_json::json!({
"balances": {
"balances": endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect::<Vec<_>>(),
"balances": endowed_accounts
.iter()
.cloned()
.map(|k| (k, ENDOWMENT))
.chain(
accounts_with_ed
.iter()
.cloned()
.map(|k| (k, crate::EXISTENTIAL_DEPOSIT)),
)
.collect::<Vec<_>>(),
},
"session": {
"keys": initial_authorities
Expand Down
129 changes: 125 additions & 4 deletions solo-chains/runtime/dancelight/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,9 @@ pub struct TreasuryBenchmarkHelper<T>(PhantomData<T>);

#[cfg(feature = "runtime-benchmarks")]
use frame_support::traits::Currency;
use frame_support::traits::{ExistenceRequirement, OnUnbalanced, WithdrawReasons};
use frame_support::traits::{
ExistenceRequirement, OnUnbalanced, ValidatorRegistration, WithdrawReasons,
};
use pallet_services_payment::BalanceOf;
#[cfg(feature = "runtime-benchmarks")]
use pallet_treasury::ArgumentsFactory;
Expand Down Expand Up @@ -1307,7 +1309,9 @@ impl pallet_beefy_mmr::Config for Runtime {

impl paras_sudo_wrapper::Config for Runtime {}

use pallet_pooled_staking::traits::{IsCandidateEligible, Timer};
use pallet_staking::SessionInterface;

pub struct DancelightSessionInterface;
impl SessionInterface<AccountId> for DancelightSessionInterface {
fn disable_validator(validator_index: u32) -> bool {
Expand Down Expand Up @@ -1654,10 +1658,106 @@ impl pallet_inflation_rewards::Config for Runtime {
type InflationRate = InflationRate;
type OnUnbalanced = OnUnbalancedInflation;
type PendingRewardsAccount = PendingRewardsAccount;
type StakingRewardsDistributor = InvulnerableRewardDistribution<Self, Balances, ()>;
type StakingRewardsDistributor = InvulnerableRewardDistribution<Self, Balances, PooledStaking>;
type RewardsPortion = RewardsPortion;
}

parameter_types! {
pub StakingAccount: AccountId32 = PalletId(*b"POOLSTAK").into_account_truncating();
pub const InitialManualClaimShareValue: u128 = MILLIUNITS;
pub const InitialAutoCompoundingShareValue: u128 = MILLIUNITS;
pub const MinimumSelfDelegation: u128 = 10_000 * UNITS;
pub const RewardsCollatorCommission: Perbill = Perbill::from_percent(20);
// Need to wait 2 sessions before being able to join or leave staking pools
pub const StakingSessionDelay: u32 = 2;
}

pub struct SessionTimer<Delay>(PhantomData<Delay>);

impl<Delay> Timer for SessionTimer<Delay>
where
Delay: Get<u32>,
{
type Instant = u32;

fn now() -> Self::Instant {
Session::current_index()
}

fn is_elapsed(instant: &Self::Instant) -> bool {
let delay = Delay::get();
let Some(end) = instant.checked_add(delay) else {
return false;
};
end <= Self::now()
}

#[cfg(feature = "runtime-benchmarks")]
fn elapsed_instant() -> Self::Instant {
let delay = Delay::get();
Self::now()
.checked_add(delay)
.expect("overflow when computing valid elapsed instant")
}

#[cfg(feature = "runtime-benchmarks")]
fn skip_to_elapsed() {
let session_to_reach = Self::elapsed_instant();
while Self::now() < session_to_reach {
Session::rotate_session();
}
}
}

pub struct CandidateHasRegisteredKeys;
impl IsCandidateEligible<AccountId> for CandidateHasRegisteredKeys {
fn is_candidate_eligible(a: &AccountId) -> bool {
<Session as ValidatorRegistration<AccountId>>::is_registered(a)
}
#[cfg(feature = "runtime-benchmarks")]
fn make_candidate_eligible(a: &AccountId, eligible: bool) {
use crate::genesis_config_presets::get_authority_keys_from_seed;

if eligible {
let a_u8: &[u8] = a.as_ref();
let seed = sp_runtime::format!("{:?}", a_u8);
let authority_keys = get_authority_keys_from_seed(&seed, None);
let _ = Session::set_keys(
RuntimeOrigin::signed(a.clone()),
SessionKeys {
grandpa: authority_keys.grandpa,
babe: authority_keys.babe,
para_validator: authority_keys.para_validator,
para_assignment: authority_keys.para_assignment,
authority_discovery: authority_keys.authority_discovery,
beefy: authority_keys.beefy,
nimbus: authority_keys.nimbus,
},
vec![],
);
} else {
let _ = Session::purge_keys(RuntimeOrigin::signed(a.clone()));
}
}
}

impl pallet_pooled_staking::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type Balance = Balance;
type StakingAccount = StakingAccount;
type InitialManualClaimShareValue = InitialManualClaimShareValue;
type InitialAutoCompoundingShareValue = InitialAutoCompoundingShareValue;
type MinimumSelfDelegation = MinimumSelfDelegation;
type RuntimeHoldReason = RuntimeHoldReason;
type RewardsCollatorCommission = RewardsCollatorCommission;
type JoiningRequestTimer = SessionTimer<StakingSessionDelay>;
type LeavingRequestTimer = SessionTimer<StakingSessionDelay>;
type EligibleCandidatesBufferSize = ConstU32<100>;
type EligibleCandidatesFilter = CandidateHasRegisteredKeys;
type WeightInfo = weights::pallet_pooled_staking::SubstrateWeight<Runtime>;
}

construct_runtime! {
pub enum Runtime
{
Expand Down Expand Up @@ -1703,6 +1803,7 @@ construct_runtime! {

// InflationRewards must be after Session
InflationRewards: pallet_inflation_rewards = 33,
PooledStaking: pallet_pooled_staking = 34,

// Governance stuff; uncallable initially.
Treasury: pallet_treasury = 40,
Expand Down Expand Up @@ -2101,6 +2202,7 @@ mod benches {
[pallet_external_validators_rewards, ExternalValidatorsRewards]
[pallet_external_validator_slashes, ExternalValidatorSlashes]
[pallet_invulnerables, TanssiInvulnerables]
[pallet_pooled_staking, PooledStaking]
// XCM
[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
[pallet_xcm_benchmarks::fungible, pallet_xcm_benchmarks::fungible::Pallet::<Runtime>]
Expand Down Expand Up @@ -3041,8 +3143,27 @@ impl tanssi_initializer::ApplyNewSession<Runtime> for OwnApplySession {
ContainerRegistrar::initializer_on_new_session(&session_index);

let invulnerables = TanssiInvulnerables::invulnerables().to_vec();

let next_collators = invulnerables;
let candidates_staking =
pallet_pooled_staking::SortedEligibleCandidates::<Runtime>::get().to_vec();
// Max number of collators is set in pallet_configuration
let target_session_index = session_index.saturating_add(1);
let max_collators = <CollatorConfiguration as GetHostConfiguration<u32>>::max_collators(
target_session_index,
);
let next_collators: Vec<_> = invulnerables
.iter()
.cloned()
.chain(candidates_staking.into_iter().filter_map(|elig| {
let cand = elig.candidate;
if invulnerables.contains(&cand) {
tmpolaczyk marked this conversation as resolved.
Show resolved Hide resolved
// If a candidate is both in pallet_invulnerables and pallet_staking, do not count it twice
None
} else {
Some(cand)
}
}))
.take(max_collators as usize)
.collect();

// Queue next session keys.
let queued_amalgamated = next_collators
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,27 +185,33 @@ fn test_author_collation_aura_change_of_authorities_on_session() {
DAVE.into()
));

assert!(
authorities_for_container(1000u32.into())
== Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
assert_eq!(
authorities_for_container(1000u32.into()),
Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
);

// SESSION CHANGE. First session. it takes 2 sessions to see the change
run_to_session(1u32);

assert!(babe_authorities() == vec![alice_keys.babe.clone(), bob_keys.babe.clone()]);
assert!(
authorities_for_container(1000u32.into())
== Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
assert_eq!(
babe_authorities(),
vec![alice_keys.babe.clone(), bob_keys.babe.clone()]
);
assert_eq!(
authorities_for_container(1000u32.into()),
Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
);

// Invulnerables should have triggered on new session authorities change
run_to_session(2u32);

assert!(babe_authorities() == vec![alice_keys.babe.clone(), bob_keys.babe.clone()]);
assert!(
authorities_for_container(1000u32.into())
== Some(vec![charlie_keys.nimbus.clone(), dave_keys.nimbus.clone()])
assert_eq!(
babe_authorities(),
vec![alice_keys.babe.clone(), bob_keys.babe.clone()]
);
assert_eq!(
authorities_for_container(1000u32.into()),
Some(vec![charlie_keys.nimbus.clone(), dave_keys.nimbus.clone()])
);
});
}
Expand All @@ -225,7 +231,7 @@ fn test_collators_per_container() {
(AccountId::from(BOB), 100 * UNIT),
])
.with_config(pallet_configuration::HostConfiguration {
max_collators: 2,
max_collators: 100,
min_orchestrator_collators: 0,
max_orchestrator_collators: 0,
collators_per_container: 2,
Expand Down Expand Up @@ -261,9 +267,9 @@ fn test_collators_per_container() {
));

// Initial assignment: Alice & Bob collating for container 1000
assert!(
authorities_for_container(1000u32.into())
== Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
assert_eq!(
authorities_for_container(1000u32.into()),
Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
);

// Change the collators_per_container param to 3.
Expand All @@ -275,20 +281,20 @@ fn test_collators_per_container() {

// SESSION CHANGE. First session. it takes 2 sessions to see the change
run_to_session(1u32);
assert!(
authorities_for_container(1000u32.into())
== Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
assert_eq!(
authorities_for_container(1000u32.into()),
Some(vec![alice_keys.nimbus.clone(), bob_keys.nimbus.clone()])
);

// We should see Charlie included in the authorities now
run_to_session(2u32);
assert!(
authorities_for_container(1000u32.into())
== Some(vec![
alice_keys.nimbus.clone(),
bob_keys.nimbus.clone(),
charlie_keys.nimbus.clone()
])
assert_eq!(
authorities_for_container(1000u32.into()),
Some(vec![
alice_keys.nimbus.clone(),
bob_keys.nimbus.clone(),
charlie_keys.nimbus.clone()
])
);
});
}
Expand Down
1 change: 1 addition & 0 deletions solo-chains/runtime/dancelight/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mod relay_registrar;
mod services_payment;
mod session_keys;
mod slashes;
mod staking;
mod sudo;

#[test]
Expand Down
Loading
Loading