diff --git a/Cargo.lock b/Cargo.lock index 56385f0214663..3fe7bb2f3f251 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11437,6 +11437,7 @@ version = "28.0.0" dependencies = [ "frame-support", "frame-system", + "pallet-balances", "pallet-session", "parity-scale-codec", "scale-info", @@ -11589,6 +11590,7 @@ dependencies = [ "frame-support", "frame-system", "log", + "pallet-balances", "pallet-beefy", "pallet-mmr", "pallet-session", @@ -12431,6 +12433,7 @@ dependencies = [ "frame-system", "log", "pallet-authorship", + "pallet-balances", "pallet-session", "parity-scale-codec", "scale-info", @@ -13215,6 +13218,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log", + "pallet-balances", "pallet-timestamp", "parity-scale-codec", "scale-info", diff --git a/cumulus/pallets/collator-selection/src/benchmarking.rs b/cumulus/pallets/collator-selection/src/benchmarking.rs index 24823661383b5..706695106ba69 100644 --- a/cumulus/pallets/collator-selection/src/benchmarking.rs +++ b/cumulus/pallets/collator-selection/src/benchmarking.rs @@ -49,8 +49,8 @@ fn create_funded_user( balance_factor: u32, ) -> T::AccountId { let user = account(string, n, SEED); - let balance = T::Currency::minimum_balance() * balance_factor.into(); - let _ = T::Currency::make_free_balance_be(&user, balance); + let balance = ::Currency::minimum_balance() * balance_factor.into(); + let _ = ::Currency::make_free_balance_be(&user, balance); user } @@ -90,7 +90,10 @@ fn register_candidates(count: u32) { assert!(CandidacyBond::::get() > 0u32.into(), "Bond cannot be zero!"); for who in candidates { - T::Currency::make_free_balance_be(&who, CandidacyBond::::get() * 3u32.into()); + ::Currency::make_free_balance_be( + &who, + CandidacyBond::::get() * 3u32.into(), + ); >::register_as_candidate(RawOrigin::Signed(who).into()).unwrap(); } } @@ -144,7 +147,7 @@ mod benchmarks { T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; // need to fill up candidates - CandidacyBond::::put(T::Currency::minimum_balance()); + CandidacyBond::::put(::Currency::minimum_balance()); DesiredCandidates::::put(c); // get accounts and keys for the `c` candidates let mut candidates = (0..c).map(|cc| validator::(cc)).collect::>(); @@ -161,13 +164,13 @@ mod benchmarks { // ... and register them. for (who, _) in candidates.iter() { let deposit = CandidacyBond::::get(); - T::Currency::make_free_balance_be(who, deposit * 1000_u32.into()); + ::Currency::make_free_balance_be(who, deposit * 1000_u32.into()); CandidateList::::try_mutate(|list| { list.try_push(CandidateInfo { who: who.clone(), deposit }).unwrap(); Ok::<(), BenchmarkError>(()) }) .unwrap(); - T::Currency::reserve(who, deposit)?; + ::Currency::reserve(who, deposit)?; LastAuthoredBlock::::insert( who.clone(), frame_system::Pallet::::block_number() + T::KickThreshold::get(), @@ -226,7 +229,8 @@ mod benchmarks { c: Linear<0, { T::MaxCandidates::get() }>, k: Linear<0, { T::MaxCandidates::get() }>, ) -> Result<(), BenchmarkError> { - let initial_bond_amount: BalanceOf = T::Currency::minimum_balance() * 2u32.into(); + let initial_bond_amount: BalanceOf = + ::Currency::minimum_balance() * 2u32.into(); CandidacyBond::::put(initial_bond_amount); register_validators::(c); register_candidates::(c); @@ -236,12 +240,12 @@ mod benchmarks { let bond_amount = if k > 0 { CandidateList::::mutate(|candidates| { for info in candidates.iter_mut().skip(kicked as usize) { - info.deposit = T::Currency::minimum_balance() * 3u32.into(); + info.deposit = ::Currency::minimum_balance() * 3u32.into(); } }); - T::Currency::minimum_balance() * 3u32.into() + ::Currency::minimum_balance() * 3u32.into() } else { - T::Currency::minimum_balance() + ::Currency::minimum_balance() }; #[extrinsic_call] @@ -255,7 +259,7 @@ mod benchmarks { fn update_bond( c: Linear<{ min_candidates::() + 1 }, { T::MaxCandidates::get() }>, ) -> Result<(), BenchmarkError> { - CandidacyBond::::put(T::Currency::minimum_balance()); + CandidacyBond::::put(::Currency::minimum_balance()); DesiredCandidates::::put(c); register_validators::(c); @@ -264,8 +268,8 @@ mod benchmarks { let caller = CandidateList::::get()[0].who.clone(); v2::whitelist!(caller); - let bond_amount: BalanceOf = - T::Currency::minimum_balance() + T::Currency::minimum_balance(); + let bond_amount: BalanceOf = ::Currency::minimum_balance() + + ::Currency::minimum_balance(); #[extrinsic_call] _(RawOrigin::Signed(caller.clone()), bond_amount); @@ -275,7 +279,7 @@ mod benchmarks { ); assert!( CandidateList::::get().iter().last().unwrap().deposit == - T::Currency::minimum_balance() * 2u32.into() + ::Currency::minimum_balance() * 2u32.into() ); Ok(()) } @@ -284,15 +288,15 @@ mod benchmarks { // one. #[benchmark] fn register_as_candidate(c: Linear<1, { T::MaxCandidates::get() - 1 }>) { - CandidacyBond::::put(T::Currency::minimum_balance()); + CandidacyBond::::put(::Currency::minimum_balance()); DesiredCandidates::::put(c + 1); register_validators::(c); register_candidates::(c); let caller: T::AccountId = whitelisted_caller(); - let bond: BalanceOf = T::Currency::minimum_balance() * 2u32.into(); - T::Currency::make_free_balance_be(&caller, bond); + let bond: BalanceOf = ::Currency::minimum_balance() * 2u32.into(); + ::Currency::make_free_balance_be(&caller, bond); >::set_keys( RawOrigin::Signed(caller.clone()).into(), @@ -311,15 +315,15 @@ mod benchmarks { #[benchmark] fn take_candidate_slot(c: Linear<{ min_candidates::() + 1 }, { T::MaxCandidates::get() }>) { - CandidacyBond::::put(T::Currency::minimum_balance()); + CandidacyBond::::put(::Currency::minimum_balance()); DesiredCandidates::::put(1); register_validators::(c); register_candidates::(c); let caller: T::AccountId = whitelisted_caller(); - let bond: BalanceOf = T::Currency::minimum_balance() * 10u32.into(); - T::Currency::make_free_balance_be(&caller, bond); + let bond: BalanceOf = ::Currency::minimum_balance() * 10u32.into(); + ::Currency::make_free_balance_be(&caller, bond); >::set_keys( RawOrigin::Signed(caller.clone()).into(), @@ -342,7 +346,7 @@ mod benchmarks { // worse case is the last candidate leaving. #[benchmark] fn leave_intent(c: Linear<{ min_candidates::() + 1 }, { T::MaxCandidates::get() }>) { - CandidacyBond::::put(T::Currency::minimum_balance()); + CandidacyBond::::put(::Currency::minimum_balance()); DesiredCandidates::::put(c); register_validators::(c); @@ -360,23 +364,23 @@ mod benchmarks { // worse case is paying a non-existing candidate account. #[benchmark] fn note_author() { - CandidacyBond::::put(T::Currency::minimum_balance()); - T::Currency::make_free_balance_be( + CandidacyBond::::put(::Currency::minimum_balance()); + ::Currency::make_free_balance_be( &>::account_id(), - T::Currency::minimum_balance() * 4u32.into(), + ::Currency::minimum_balance() * 4u32.into(), ); let author = account("author", 0, SEED); let new_block: BlockNumberFor = 10u32.into(); frame_system::Pallet::::set_block_number(new_block); - assert!(T::Currency::free_balance(&author) == 0u32.into()); + assert!(::Currency::free_balance(&author) == 0u32.into()); #[block] { as EventHandler<_, _>>::note_author(author.clone()) } - assert!(T::Currency::free_balance(&author) > 0u32.into()); + assert!(::Currency::free_balance(&author) > 0u32.into()); assert_eq!(frame_system::Pallet::::block_number(), new_block); } @@ -386,7 +390,7 @@ mod benchmarks { r: Linear<1, { T::MaxCandidates::get() }>, c: Linear<1, { T::MaxCandidates::get() }>, ) { - CandidacyBond::::put(T::Currency::minimum_balance()); + CandidacyBond::::put(::Currency::minimum_balance()); DesiredCandidates::::put(c); frame_system::Pallet::::set_block_number(0u32.into()); diff --git a/cumulus/pallets/collator-selection/src/mock.rs b/cumulus/pallets/collator-selection/src/mock.rs index 664ba56459ae9..034ef2189deab 100644 --- a/cumulus/pallets/collator-selection/src/mock.rs +++ b/cumulus/pallets/collator-selection/src/mock.rs @@ -140,6 +140,8 @@ impl pallet_session::Config for Test { type Keys = MockSessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } ord_parameter_types! { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index acc6bf63ff454..800607f5512f6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -837,6 +837,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 6825711df38da..98e1f1518f309 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -890,6 +890,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index c8b41e1cb40e5..25e0d3f51b925 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -507,6 +507,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 0021a5191f755..2ee35714b3107 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -493,6 +493,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 2f3ad0e1ffefe..9bf926a6f4933 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -506,6 +506,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 82e9683b6f4b5..3c9c368a5fbdf 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -406,6 +406,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 0c102108dfe2a..7b7e80f6cdbb0 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -407,6 +407,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 42b5a0b11dd4e..01f5f61e4c092 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -368,6 +368,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 14a29430f2799..a2d6e942421f4 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -367,6 +367,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 6a37590ce7cd2..06c09a196c1ee 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -751,7 +751,6 @@ parameter_types! { pub const Period: u32 = 6 * HOURS; pub const Offset: u32 = 0; } - impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; @@ -765,6 +764,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 6f26c3962eebc..58593ff606082 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -484,6 +484,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } pub struct FullIdentificationOf; diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index c3071c48985fc..8392bac8795d8 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -51,7 +51,6 @@ use frame_election_provider_support::{ use frame_support::{ construct_runtime, derive_impl, genesis_builder_helper::{build_state, get_preset}, - pallet_prelude::Get, parameter_types, traits::{KeyOwnerProofSystem, WithdrawReasons}, PalletId, @@ -79,7 +78,7 @@ use polkadot_runtime_common::{ use polkadot_runtime_parachains::reward_points::RewardValidatorsWithEraPoints; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_beefy::ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature}; -use sp_core::{ConstBool, ConstU32, ConstUint, OpaqueMetadata}; +use sp_core::{ConstBool, ConstU32, ConstUint, Get, OpaqueMetadata}; use sp_mmr_primitives as mmr; use sp_runtime::{ curve::PiecewiseLinear, @@ -340,6 +339,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy; type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Runtime { diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 810033ffdc27b..9c0db32e9cf30 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -538,6 +538,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy; type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Runtime { diff --git a/prdoc/pr_7953.prdoc b/prdoc/pr_7953.prdoc new file mode 100644 index 0000000000000..305a6659bdf09 --- /dev/null +++ b/prdoc/pr_7953.prdoc @@ -0,0 +1,64 @@ +title: Add deposit for setting session keys +doc: +- audience: [Runtime Dev, Runtime User] + description: |- + Setting session keys might put some funds on hold in the future, depending on how runtimes use this feature. + + Requires `pallet_session::Config` to specify: + * `type Currency`, assigned to an instance of `pallet_balances`. + * `type KeyDeposit`, the amount of deposit. Set to `()` to assert no deposit amount is needed. +crates: +- name: pallet-session + bump: major +- name: pallet-collator-selection + bump: patch +- name: penpal-runtime + bump: major +- name: rococo-runtime + bump: major +- name: westend-runtime + bump: major +- name: bridge-hub-westend-runtime + bump: major +- name: asset-hub-westend-runtime + bump: major +- name: bridge-hub-rococo-runtime + bump: major +- name: people-westend-runtime + bump: major +- name: asset-hub-rococo-runtime + bump: major +- name: collectives-westend-runtime + bump: major +- name: coretime-rococo-runtime + bump: major +- name: coretime-westend-runtime + bump: major +- name: people-rococo-runtime + bump: major +- name: pallet-im-online + bump: patch +- name: pallet-staking-async-parachain-runtime + bump: major +- name: pallet-staking-async-rc-runtime + bump: major +- name: pallet-authority-discovery + bump: patch +- name: pallet-babe + bump: patch +- name: pallet-beefy-mmr + bump: patch +- name: pallet-beefy + bump: patch +- name: pallet-grandpa + bump: patch +- name: pallet-offences-benchmarking + bump: patch +- name: pallet-root-offences + bump: patch +- name: pallet-session-benchmarking + bump: patch +- name: pallet-staking + bump: patch +- name: yet-another-parachain-runtime + bump: major diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 3a26fc78df3d4..d19c3159f4e19 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -687,8 +687,9 @@ impl pallet_session::Config for Runtime { type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy; - type WeightInfo = pallet_session::weights::SubstrateWeight; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Runtime { diff --git a/substrate/frame/authority-discovery/Cargo.toml b/substrate/frame/authority-discovery/Cargo.toml index 8b48835d07597..095bcfe9449e7 100644 --- a/substrate/frame/authority-discovery/Cargo.toml +++ b/substrate/frame/authority-discovery/Cargo.toml @@ -26,6 +26,7 @@ sp-authority-discovery = { workspace = true } sp-runtime = { workspace = true } [dev-dependencies] +pallet-balances = { workspace = true } sp-core = { workspace = true, default-features = true } sp-io = { workspace = true, default-features = true } @@ -35,6 +36,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "pallet-session/std", "scale-info/std", "sp-application-crypto/std", @@ -46,6 +48,7 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-balances/try-runtime", "pallet-session/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/frame/authority-discovery/src/lib.rs b/substrate/frame/authority-discovery/src/lib.rs index 1914ae4cf9ad2..5d3a0d490544d 100644 --- a/substrate/frame/authority-discovery/src/lib.rs +++ b/substrate/frame/authority-discovery/src/lib.rs @@ -189,6 +189,7 @@ mod tests { { System: frame_system, Session: pallet_session, + Balances: pallet_balances, AuthorityDiscovery: pallet_authority_discovery, } ); @@ -212,6 +213,8 @@ mod tests { type NextSessionRotation = pallet_session::PeriodicSessions; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } pub type BlockNumber = u64; @@ -226,6 +229,12 @@ mod tests { type AccountId = AuthorityId; type Lookup = IdentityLookup; type Block = Block; + type AccountData = pallet_balances::AccountData; + } + + #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] + impl pallet_balances::Config for Test { + type AccountStore = System; } pub struct TestSessionHandler; diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs index c620c3eb62fef..961c3bb06c4cf 100644 --- a/substrate/frame/babe/src/mock.rs +++ b/substrate/frame/babe/src/mock.rs @@ -102,6 +102,8 @@ impl pallet_session::Config for Test { type Keys = MockSessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Test { diff --git a/substrate/frame/beefy-mmr/Cargo.toml b/substrate/frame/beefy-mmr/Cargo.toml index 54343bb9ce51a..6adf5bcd871f5 100644 --- a/substrate/frame/beefy-mmr/Cargo.toml +++ b/substrate/frame/beefy-mmr/Cargo.toml @@ -33,6 +33,7 @@ sp-state-machine = { workspace = true } [dev-dependencies] array-bytes = { workspace = true, default-features = true } +pallet-balances = { workspace = true } sp-staking = { workspace = true, default-features = true } [features] @@ -45,6 +46,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "pallet-beefy/std", "pallet-mmr/std", "pallet-session/std", @@ -61,6 +63,7 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-balances/try-runtime", "pallet-beefy/try-runtime", "pallet-mmr/try-runtime", "pallet-session/try-runtime", @@ -70,6 +73,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "pallet-mmr/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "sp-staking/runtime-benchmarks", diff --git a/substrate/frame/beefy-mmr/src/mock.rs b/substrate/frame/beefy-mmr/src/mock.rs index aa6905306cd6a..7ef8cc4e90ace 100644 --- a/substrate/frame/beefy-mmr/src/mock.rs +++ b/substrate/frame/beefy-mmr/src/mock.rs @@ -52,17 +52,23 @@ construct_runtime!( { System: frame_system, Session: pallet_session, + Balances: pallet_balances, Mmr: pallet_mmr, Beefy: pallet_beefy, BeefyMmr: pallet_beefy_mmr, } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; type Block = Block; } +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] +impl pallet_balances::Config for Test { + type AccountStore = System; +} + impl pallet_session::Config for Test { type RuntimeEvent = RuntimeEvent; type ValidatorId = u64; @@ -74,6 +80,8 @@ impl pallet_session::Config for Test { type Keys = MockSessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } pub type MmrLeaf = sp_consensus_beefy::mmr::MmrLeaf< diff --git a/substrate/frame/beefy-mmr/src/tests.rs b/substrate/frame/beefy-mmr/src/tests.rs index fb61dc1879415..dd305f1c4e95b 100644 --- a/substrate/frame/beefy-mmr/src/tests.rs +++ b/substrate/frame/beefy-mmr/src/tests.rs @@ -202,6 +202,10 @@ fn should_update_authorities() { }); } +// If you need to modify the test because you added a new event or something to the block or block +// header you need to update the test by replacing the expected_mmr_root with the new one +// you can get the new one by running the test while commenting out the first assert +// and then copy pasting the new mmr root from the log of the second assert #[test] fn extract_validation_context_should_work_correctly() { let mut ext = new_test_ext(vec![1, 2]); @@ -214,8 +218,9 @@ fn extract_validation_context_should_work_correctly() { // Check the MMR root log let expected_mmr_root: [u8; 32] = array_bytes::hex_n_into_unchecked( - "d4f38bcfa95e1f03a06f7545aa95f24f5e10cc0bbd54cf97fbbff66d5be4769f", + "322c6a46ac00d3455c87bd9af42ebafb388f589a1b562f5e39b1d0d71bcbe8e0", ); + assert_eq!( System::digest().logs, vec![beefy_log(ConsensusLog::MmrRoot(H256::from_slice(&expected_mmr_root)))] diff --git a/substrate/frame/beefy/src/mock.rs b/substrate/frame/beefy/src/mock.rs index a7d717e0b1b00..85a44254aa528 100644 --- a/substrate/frame/beefy/src/mock.rs +++ b/substrate/frame/beefy/src/mock.rs @@ -186,6 +186,8 @@ impl pallet_session::Config for Test { type Keys = MockSessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Test { diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index 292ade8b3f8c3..84c291d518a2f 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -145,6 +145,8 @@ impl pallet_session::Config for Runtime { SLASHING_DISABLING_FACTOR, >; type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Runtime { type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/grandpa/src/mock.rs b/substrate/frame/grandpa/src/mock.rs index bf1b05ec11c36..6203f0e952349 100644 --- a/substrate/frame/grandpa/src/mock.rs +++ b/substrate/frame/grandpa/src/mock.rs @@ -106,6 +106,8 @@ impl pallet_session::Config for Test { type Keys = TestSessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Test { diff --git a/substrate/frame/im-online/Cargo.toml b/substrate/frame/im-online/Cargo.toml index 179c4c3ce3b18..f00260feac914 100644 --- a/substrate/frame/im-online/Cargo.toml +++ b/substrate/frame/im-online/Cargo.toml @@ -30,6 +30,7 @@ sp-runtime = { features = ["serde"], workspace = true } sp-staking = { features = ["serde"], workspace = true } [dev-dependencies] +pallet-balances = { workspace = true } pallet-session = { workspace = true, default-features = true } [features] @@ -41,6 +42,7 @@ std = [ "frame-system/std", "log/std", "pallet-authorship/std", + "pallet-balances/std", "pallet-session/std", "scale-info/std", "sp-application-crypto/std", @@ -53,6 +55,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "sp-staking/runtime-benchmarks", ] @@ -60,6 +63,7 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", "pallet-session/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/frame/im-online/src/mock.rs b/substrate/frame/im-online/src/mock.rs index 80834c68a216b..06446cbac1439 100644 --- a/substrate/frame/im-online/src/mock.rs +++ b/substrate/frame/im-online/src/mock.rs @@ -40,6 +40,7 @@ frame_support::construct_runtime!( pub enum Runtime { System: frame_system, Session: pallet_session, + Balances: pallet_balances, ImOnline: imonline, Historical: pallet_session_historical, } @@ -109,9 +110,15 @@ pub fn new_test_ext() -> sp_io::TestExternalities { #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { + type AccountData = pallet_balances::AccountData; type Block = Block; } +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] +impl pallet_balances::Config for Runtime { + type AccountStore = System; +} + parameter_types! { pub const Period: u64 = 1; pub const Offset: u64 = 0; @@ -129,6 +136,8 @@ impl pallet_session::Config for Runtime { type NextSessionRotation = pallet_session::PeriodicSessions; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Runtime { diff --git a/substrate/frame/offences/benchmarking/src/mock.rs b/substrate/frame/offences/benchmarking/src/mock.rs index 61a8cf53533a9..7b2ddf26228a3 100644 --- a/substrate/frame/offences/benchmarking/src/mock.rs +++ b/substrate/frame/offences/benchmarking/src/mock.rs @@ -97,6 +97,8 @@ impl pallet_session::Config for Test { type ValidatorIdOf = sp_runtime::traits::ConvertInto; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } pallet_staking_reward_curve::build! { diff --git a/substrate/frame/root-offences/src/mock.rs b/substrate/frame/root-offences/src/mock.rs index ffe4367e8b810..1a3627fca7b38 100644 --- a/substrate/frame/root-offences/src/mock.rs +++ b/substrate/frame/root-offences/src/mock.rs @@ -168,6 +168,8 @@ impl pallet_session::Config for Test { type NextSessionRotation = pallet_session::PeriodicSessions; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_timestamp::Config for Test { diff --git a/substrate/frame/session/Cargo.toml b/substrate/frame/session/Cargo.toml index 737678bea8a3b..18905d6a56a2d 100644 --- a/substrate/frame/session/Cargo.toml +++ b/substrate/frame/session/Cargo.toml @@ -21,6 +21,7 @@ frame-support = { workspace = true } frame-system = { workspace = true } impl-trait-for-tuples = { workspace = true } log = { workspace = true } +pallet-balances = { workspace = true } pallet-timestamp = { workspace = true } scale-info = { features = ["derive", "serde"], workspace = true } sp-core = { features = ["serde"], workspace = true } @@ -39,6 +40,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "pallet-timestamp/std", "scale-info/std", "sp-core/std", @@ -52,6 +54,7 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-balances/try-runtime", "pallet-timestamp/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/frame/session/README.md b/substrate/frame/session/README.md index 5a063bffee0b1..6d1d4611f67e9 100644 --- a/substrate/frame/session/README.md +++ b/substrate/frame/session/README.md @@ -23,10 +23,12 @@ same as the account ID. For staking systems using a stash/controller model, the ID of the controller. - **Session key configuration process:** Session keys are set using `set_keys` for use not in the next session, but the session after next. They are stored in `NextKeys`, a mapping between the caller's `ValidatorId` and the session keys -provided. `set_keys` allows users to set their session key prior to being selected as validator. It is a public call -since it uses `ensure_signed`, which checks that the origin is a signed account. As such, the account ID of the origin -stored in `NextKeys` may not necessarily be associated with a block author or a validator. The session keys of accounts -are removed once their account balance is zero. +provided. `set_keys` allows users to set their session key prior to being selected as validator. When setting keys, a deposit +is required and reserved from the account. The account must have sufficient funds available for this deposit, or the +operation will fail. This deposit is returned when the keys are purged. `set_keys` is a public call since it uses +`ensure_signed`, which checks that the origin is a signed account. As such, the account ID of the origin stored in +`NextKeys` may not necessarily be associated with a block author or a validator. The session keys of accounts are removed +once their account balance is zero. - **Session length:** This pallet does not assume anything about the length of each session. Rather, it relies on an implementation of `ShouldEndSession` to dictate a new session's start. This pallet provides the `PeriodicSessions` struct for simple periodic sessions. @@ -70,7 +72,7 @@ set. use pallet_session as session; fn validators() -> Vec<::ValidatorId> { - pallet_session::Validators::::get() + pallet_session::Validators::::get() } ``` diff --git a/substrate/frame/session/benchmarking/src/mock.rs b/substrate/frame/session/benchmarking/src/mock.rs index d4003004628e5..288bf56ad25ee 100644 --- a/substrate/frame/session/benchmarking/src/mock.rs +++ b/substrate/frame/session/benchmarking/src/mock.rs @@ -106,6 +106,8 @@ impl pallet_session::Config for Test { type ValidatorIdOf = sp_runtime::traits::ConvertInto; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } pallet_staking_reward_curve::build! { const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!( diff --git a/substrate/frame/session/src/lib.rs b/substrate/frame/session/src/lib.rs index 45ef1ac4f100c..bfa7540132293 100644 --- a/substrate/frame/session/src/lib.rs +++ b/substrate/frame/session/src/lib.rs @@ -129,6 +129,7 @@ use frame_support::{ dispatch::DispatchResult, ensure, traits::{ + fungible::{hold::Mutate as HoldMutate, Inspect}, Defensive, EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get, OneSessionHandler, ValidatorRegistration, ValidatorSet, }, @@ -415,6 +416,10 @@ pub mod pallet { /// A conversion from account ID to validator ID. /// + /// It is also a means to check that an account id is eligible to set session keys, through + /// being associated with a validator id. To disable this check, use + /// [`sp_runtime::traits::ConvertInto`]. + /// /// Its cost must be at most one storage read. type ValidatorIdOf: Convert>; @@ -440,6 +445,16 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; + + /// The currency type for placing holds when setting keys. + type Currency: Inspect + + HoldMutate>; + + /// The amount to be held when setting keys. + #[pallet::constant] + type KeyDeposit: Get< + <::Currency as Inspect<::AccountId>>::Balance, + >; } #[pallet::genesis_config] @@ -516,6 +531,14 @@ pub mod pallet { } } + /// A reason for the pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + // Funds are held when settings keys + #[codec(index = 0)] + Keys, + } + /// The current set of validators. #[pallet::storage] pub type Validators = StorageValue<_, Vec, ValueQuery>; @@ -823,8 +846,17 @@ impl Pallet { .ok_or(Error::::NoAssociatedValidatorId)?; ensure!(frame_system::Pallet::::can_inc_consumer(account), Error::::NoAccount); + let old_keys = Self::inner_set_keys(&who, keys)?; + + // Place deposit on hold if this is a new registration (i.e. old_keys is None). + // The hold call itself will return an error if funds are insufficient. if old_keys.is_none() { + let deposit = T::KeyDeposit::get(); + if !deposit.is_zero() { + T::Currency::hold(&HoldReason::Keys.into(), account, deposit)?; + } + let assertion = frame_system::Pallet::::inc_consumers(account).is_ok(); debug_assert!(assertion, "can_inc_consumer() returned true; no change since; qed"); } @@ -885,6 +917,14 @@ impl Pallet { let key_data = old_keys.get_raw(*id); Self::clear_key_owner(*id, key_data); } + + // Use release_all to handle the case where the exact amount might not be available + let _ = T::Currency::release_all( + &HoldReason::Keys.into(), + account, + frame_support::traits::tokens::Precision::BestEffort, + ); + frame_system::Pallet::::dec_consumers(account); Ok(()) diff --git a/substrate/frame/session/src/mock.rs b/substrate/frame/session/src/mock.rs index 1a5fcdc9b6579..ff85c4e2f2730 100644 --- a/substrate/frame/session/src/mock.rs +++ b/substrate/frame/session/src/mock.rs @@ -21,15 +21,17 @@ use super::*; use crate as pallet_session; #[cfg(feature = "historical")] use crate::historical as pallet_session_historical; - -use std::collections::BTreeMap; - +use frame_support::{derive_impl, parameter_types, traits::ConstU64}; +use pallet_balances::{self, AccountData}; use sp_core::crypto::key_types::DUMMY; -use sp_runtime::{impl_opaque_keys, testing::UintAuthorityId, BuildStorage}; +use sp_runtime::{ + impl_opaque_keys, + testing::UintAuthorityId, + traits::{Convert, OpaqueKeys}, + BuildStorage, +}; use sp_staking::SessionIndex; -use sp_state_machine::BasicExternalities; - -use frame_support::{derive_impl, parameter_types, traits::ConstU64}; +use std::collections::BTreeMap; impl_opaque_keys! { pub struct MockSessionKeys { @@ -76,6 +78,7 @@ frame_support::construct_runtime!( { System: frame_system, Session: pallet_session, + Balances: pallet_balances, Historical: pallet_session_historical, } ); @@ -86,6 +89,7 @@ frame_support::construct_runtime!( { System: frame_system, Session: pallet_session, + Balances: pallet_balances, } ); @@ -102,6 +106,7 @@ parameter_types! { // Stores if `on_before_session_end` was called pub static BeforeSessionEndCalled: bool = false; pub static ValidatorAccounts: BTreeMap = BTreeMap::new(); + pub static KeyDeposit: u64 = 10; } pub struct TestShouldEndSession; @@ -200,21 +205,48 @@ pub fn reset_before_session_end_called() { BeforeSessionEndCalled::mutate(|b| *b = false); } +parameter_types! { + pub static LastSessionEventIndex: usize = 0; +} + +pub fn session_events_since_last_call() -> Vec> { + let events = System::read_events_for_pallet::>(); + let already_seen = LastSessionEventIndex::get(); + LastSessionEventIndex::set(events.len()); + events.into_iter().skip(already_seen).collect() +} + +pub fn session_hold(who: u64) -> u64 { + >::balance_on_hold( + &crate::HoldReason::Keys.into(), + &who, + ) +} + pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let ed = ::ExistentialDeposit::get(); + pallet_balances::GenesisConfig:: { + balances: vec![ + (1, (KeyDeposit::get() * 10).max(ed)), + (2, (KeyDeposit::get() * 10).max(ed)), + (3, (KeyDeposit::get() * 10).max(ed)), + (4, (KeyDeposit::get() * 10).max(ed)), + (69, (KeyDeposit::get() * 10).max(ed)), + // one account who does not have enough balance to pay the key deposit + (999, (KeyDeposit::get().saturating_sub(1)).max(ed)), + (1000, (KeyDeposit::get() * 10).max(ed)), + ], + dev_accounts: None, + } + .assimilate_storage(&mut t) + .unwrap(); + let keys: Vec<_> = NextValidators::get() .iter() .cloned() .map(|i| (i, i, UintAuthorityId(i).into())) .collect(); - BasicExternalities::execute_with_storage(&mut t, || { - for (ref k, ..) in &keys { - frame_system::Pallet::::inc_providers(k); - } - frame_system::Pallet::::inc_providers(&4); - // An additional identity that we use. - frame_system::Pallet::::inc_providers(&69); - }); pallet_session::GenesisConfig:: { keys, ..Default::default() } .assimilate_storage(&mut t) .unwrap(); @@ -227,6 +259,8 @@ pub fn new_test_ext() -> sp_io::TestExternalities { #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; + type AccountData = AccountData; + type RuntimeEvent = RuntimeEvent; } impl pallet_timestamp::Config for Test { @@ -267,6 +301,8 @@ impl Config for Test { type DisablingStrategy = disabling::UpToLimitWithReEnablingDisablingStrategy; type WeightInfo = (); + type Currency = pallet_balances::Pallet; + type KeyDeposit = KeyDeposit; } #[cfg(feature = "historical")] @@ -275,3 +311,9 @@ impl crate::historical::Config for Test { type FullIdentification = u64; type FullIdentificationOf = sp_runtime::traits::ConvertInto; } + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Test { + type AccountStore = System; + type RuntimeEvent = RuntimeEvent; +} diff --git a/substrate/frame/session/src/tests.rs b/substrate/frame/session/src/tests.rs index 245524a2e5989..4a749b0a7817a 100644 --- a/substrate/frame/session/src/tests.rs +++ b/substrate/frame/session/src/tests.rs @@ -20,9 +20,10 @@ use super::*; use crate::mock::{ authorities, before_session_end_called, force_new_session, new_test_ext, - reset_before_session_end_called, session_changed, set_next_validators, set_session_length, + reset_before_session_end_called, session_changed, session_events_since_last_call, session_hold, + set_next_validators, set_session_length, Balances, KeyDeposit, MockSessionKeys, PreUpgradeMockSessionKeys, RuntimeOrigin, Session, SessionChanged, System, Test, - TestSessionChanged, TestValidatorIdOf, + TestSessionChanged, TestValidatorIdOf, ValidatorAccounts, }; use codec::Decode; @@ -30,7 +31,7 @@ use sp_core::crypto::key_types::DUMMY; use sp_runtime::{testing::UintAuthorityId, Perbill}; use frame_support::{ - assert_noop, assert_ok, + assert_err, assert_noop, assert_ok, traits::{ConstU64, OnInitialize}, }; @@ -187,27 +188,42 @@ fn session_change_should_work() { // Block 1: No change initialize_block(1); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!(session_events_since_last_call(), vec![]); // Block 2: Session rollover, but no change. initialize_block(2); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!( + session_events_since_last_call(), + vec![Event::NewQueued, Event::NewSession { session_index: 1 }] + ); // Block 3: Set new key for validator 2; no visible change. initialize_block(3); assert_ok!(Session::set_keys(RuntimeOrigin::signed(2), UintAuthorityId(5).into(), vec![])); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!(session_events_since_last_call(), vec![]); // Block 4: Session rollover; no visible change. initialize_block(4); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!( + session_events_since_last_call(), + vec![Event::NewQueued, Event::NewSession { session_index: 2 }] + ); // Block 5: No change. initialize_block(5); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!(session_events_since_last_call(), vec![]); // Block 6: Session rollover; authority 2 changes. initialize_block(6); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]); + assert_eq!( + session_events_since_last_call(), + vec![Event::NewQueued, Event::NewSession { session_index: 3 }] + ); }); } @@ -467,6 +483,113 @@ fn test_migration_v1() { }); } +#[test] +fn set_keys_should_fail_with_insufficient_funds() { + new_test_ext().execute_with(|| { + // Account 999 is mocked to have KeyDeposit -1 + let account_id = 999; + let keys = MockSessionKeys { dummy: UintAuthorityId(account_id).into() }; + frame_system::Pallet::::inc_providers(&account_id); + // Make sure we have a validator ID + ValidatorAccounts::mutate(|m| { + m.insert(account_id, account_id); + }); + + // Attempt to set keys with an account that has insufficient funds + // Should fail with Err(Token(FundsUnavailable)) from `pallet-balances` + assert_err!( + Session::set_keys(RuntimeOrigin::signed(account_id), keys, vec![]), + sp_runtime::TokenError::FundsUnavailable + ); + }); +} + +#[test] +fn set_keys_should_hold_funds() { + new_test_ext().execute_with(|| { + // Account 1000 is mocked to have sufficient funds + let account_id = 1000; + let keys = MockSessionKeys { dummy: UintAuthorityId(account_id).into() }; + let deposit = KeyDeposit::get(); + + // Make sure we have a validator ID + ValidatorAccounts::mutate(|m| { + m.insert(account_id, account_id); + }); + + // Set keys and check the operation succeeds + let res = Session::set_keys(RuntimeOrigin::signed(account_id), keys, vec![]); + assert_ok!(res); + + // Check that the funds are held + assert_eq!(session_hold(account_id), deposit); + }); +} + +#[test] +fn purge_keys_should_unhold_funds() { + new_test_ext().execute_with(|| { + // Account 1000 is mocked to have sufficient funds + let account_id = 1000; + let keys = MockSessionKeys { dummy: UintAuthorityId(account_id).into() }; + let deposit = KeyDeposit::get(); + + // Make sure we have a validator ID + ValidatorAccounts::mutate(|m| { + m.insert(account_id, account_id); + }); + + // Ensure system providers are properly set for the test account + frame_system::Pallet::::inc_providers(&account_id); + + // First set the keys to reserve the deposit + let res = Session::set_keys(RuntimeOrigin::signed(account_id), keys, vec![]); + assert_ok!(res); + + // Check the reserved balance after setting keys + let reserved_balance_before_purge = Balances::reserved_balance(&account_id); + assert!( + reserved_balance_before_purge >= deposit, + "Deposit should be reserved after setting keys" + ); + + // Now purge the keys + let res = Session::purge_keys(RuntimeOrigin::signed(account_id)); + assert_ok!(res); + + // Check that the funds were unreserved + let reserved_balance_after_purge = Balances::reserved_balance(&account_id); + assert_eq!(reserved_balance_after_purge, reserved_balance_before_purge - deposit); + }); +} + +#[test] +fn existing_validators_without_hold_are_except() { + // upon addition of `SessionDeposit`, a runtime may have some old validators without any held + // amount. They can freely still update their session keys. They can also purge them. + + // disable key deposit for initial validators + KeyDeposit::set(0); + new_test_ext().execute_with(|| { + // reset back to the first value. + KeyDeposit::set(10); + // 1 is an initial validator + assert_eq!(session_hold(1), 0); + + // upgrade 1's keys + assert_ok!(Session::set_keys( + RuntimeOrigin::signed(1), + UintAuthorityId(7).into(), + Default::default() + )); + assert_eq!(session_hold(1), 0); + + // purge 1's keys + assert_ok!(Session::purge_keys(RuntimeOrigin::signed(1))); + assert_eq!(session_hold(1), 0); + }); +} + mod disabling_byzantine_threshold { use super::*; use crate::disabling::{DisablingStrategy, UpToLimitDisablingStrategy}; diff --git a/substrate/frame/staking-async/ahm-test/src/rc/mock.rs b/substrate/frame/staking-async/ahm-test/src/rc/mock.rs index 128d0a1150e12..1386debdd3c8f 100644 --- a/substrate/frame/staking-async/ahm-test/src/rc/mock.rs +++ b/substrate/frame/staking-async/ahm-test/src/rc/mock.rs @@ -179,6 +179,8 @@ impl pallet_session::Config for Runtime { type SessionManager = pallet_session::historical::NoteHistoricalRoot; type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } parameter_types! { diff --git a/substrate/frame/staking-async/runtimes/parachain/src/lib.rs b/substrate/frame/staking-async/runtimes/parachain/src/lib.rs index e069e032f3c9a..b595910c52dfa 100644 --- a/substrate/frame/staking-async/runtimes/parachain/src/lib.rs +++ b/substrate/frame/staking-async/runtimes/parachain/src/lib.rs @@ -908,6 +908,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_aura::Config for Runtime { diff --git a/substrate/frame/staking-async/runtimes/rc/src/lib.rs b/substrate/frame/staking-async/runtimes/rc/src/lib.rs index c02c7ebaa8e7e..8ca28426fbf31 100644 --- a/substrate/frame/staking-async/runtimes/rc/src/lib.rs +++ b/substrate/frame/staking-async/runtimes/rc/src/lib.rs @@ -565,6 +565,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy; type WeightInfo = weights::pallet_session::WeightInfo; + type Currency = Balances; + type KeyDeposit = (); } impl session_historical::Config for Runtime { diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs index 732c23562300c..aaec1d15c7416 100644 --- a/substrate/frame/staking/src/mock.rs +++ b/substrate/frame/staking/src/mock.rs @@ -151,6 +151,8 @@ impl pallet_session::Config for Test { type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy; type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session::historical::Config for Test { diff --git a/templates/parachain/runtime/src/configs/mod.rs b/templates/parachain/runtime/src/configs/mod.rs index 70f343a23f458..a15a2c6d8bc4b 100644 --- a/templates/parachain/runtime/src/configs/mod.rs +++ b/templates/parachain/runtime/src/configs/mod.rs @@ -277,6 +277,8 @@ impl pallet_session::Config for Runtime { type Keys = SessionKeys; type DisablingStrategy = (); type WeightInfo = (); + type Currency = Balances; + type KeyDeposit = (); } #[docify::export(aura_config)]