Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
b7253a2
First draft
Krayt78 Mar 18, 2025
da72746
Implement reserved balance tracking for test accounts in the session …
Krayt78 Mar 18, 2025
691e38d
Update inner_set_keys to accept old keys as an argument to reduce red…
Krayt78 Mar 18, 2025
734ffc6
Update session pallet to use NamedReservableCurrency for key reservat…
Krayt78 Mar 18, 2025
5843e53
Refactor session pallet to replace NamedReservableCurrency with hold …
Krayt78 Mar 18, 2025
1d9351e
removed events and reverted some logic according to comments
Krayt78 Apr 22, 2025
851ff35
frogot a let
Krayt78 Apr 22, 2025
ebce494
rewrote mock file to use pallet_balances
Krayt78 Apr 22, 2025
69be552
fmt
Krayt78 Apr 23, 2025
59881ad
fix toml
Krayt78 Apr 23, 2025
f91a083
Merge branch 'master' into add-deposit-for-setting-session-keys
Krayt78 Apr 23, 2025
2141bde
fix merge issue
Krayt78 Apr 23, 2025
c279916
removed useless deps
Krayt78 Apr 23, 2025
783f9f4
Update benchmarking.rs to use fully qualified path for Currency methods
Krayt78 May 6, 2025
1f00943
started fixing runtimes
Krayt78 May 8, 2025
740d3e7
reworked hold reason and reworked on the runtime impls
Krayt78 May 9, 2025
d6d9dc7
fix soem runtime issues
Krayt78 May 9, 2025
a392303
some more runtimes
Krayt78 May 9, 2025
4e61c71
Merge branch 'master' into add-deposit-for-setting-session-keys
Krayt78 May 11, 2025
132a0ad
fmt
Krayt78 May 11, 2025
d3b7ae5
updated almost all runtimes and mocks
Krayt78 May 11, 2025
a5d2a42
converted other mocks
Krayt78 May 11, 2025
702a3bb
fix mock const type
Krayt78 May 11, 2025
bb1894b
fixed some dependecies
Krayt78 May 11, 2025
8366315
fix some cargo that were missing pallet_balances
Krayt78 May 11, 2025
f121b18
cargo update since i changed some deps
Krayt78 May 11, 2025
a67a35e
Revert "cargo update since i changed some deps"
Krayt78 May 13, 2025
8bbb2e2
Merge branch 'master' into add-deposit-for-setting-session-keys
Krayt78 May 13, 2025
a8752f0
updated beefy mmr (need review one test breaks)
Krayt78 May 13, 2025
78cb376
fix imonline
Krayt78 May 13, 2025
5b91dc4
taplo
Krayt78 May 13, 2025
cb4f308
markdown lint the readme
Krayt78 May 13, 2025
070d5c5
authority discovery done
Krayt78 May 13, 2025
bcac4ae
removed unused deps
Krayt78 May 13, 2025
6c8fdf2
fix session typing
Krayt78 May 13, 2025
180ce6c
fix type
Krayt78 May 13, 2025
8198623
fixed the broken test
Krayt78 May 17, 2025
6821b1e
Update cumulus/pallets/collator-selection/src/mock.rs
Krayt78 May 18, 2025
3f2a737
Update cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
Krayt78 May 18, 2025
1303f82
Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/…
Krayt78 May 18, 2025
ef13458
Update cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
Krayt78 May 18, 2025
3b0422e
Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src…
Krayt78 May 18, 2025
995b4df
Update substrate/frame/session/src/lib.rs
Krayt78 May 18, 2025
4317b66
Update substrate/frame/session/src/tests.rs
Krayt78 May 18, 2025
ced83aa
Update substrate/frame/session/src/lib.rs
Krayt78 May 18, 2025
f5af9c2
set all the key deposits to () outside session pallet
Krayt78 May 18, 2025
aae6d13
fmt
Krayt78 May 18, 2025
87439c3
Merge branch 'master' into add-deposit-for-setting-session-keys
Krayt78 May 18, 2025
6768103
removed all the config that was already done with derive_impl
Krayt78 May 18, 2025
18cb873
changed test mock to be key deopsit-1 instead of existencial deposit
Krayt78 May 18, 2025
587db5b
optimized test
Krayt78 May 18, 2025
f848567
went back and removed unused deps and added back comments that were d…
Krayt78 May 18, 2025
33316dd
Merge branch 'master' into add-deposit-for-setting-session-keys
kianenigma May 29, 2025
c2ae469
some cleanup
kianenigma Jun 10, 2025
3b64867
Update from github-actions[bot] running command 'prdoc --bump minor -…
github-actions[bot] Jun 10, 2025
22c6fff
Merge branch 'master' of github.com:paritytech/polkadot-sdk into add-…
kianenigma Jun 10, 2025
370a8d9
Merge branch 'add-deposit-for-setting-session-keys' of https://github…
kianenigma Jun 10, 2025
495a134
update prdoc
kianenigma Jun 10, 2025
7293fe2
update prdoc
kianenigma Jun 10, 2025
a8c94cf
remove alias
kianenigma Jun 10, 2025
db4ffe7
more cleanup
kianenigma Jun 10, 2025
691f0f8
fix toml
kianenigma Jun 10, 2025
9abd148
Update substrate/frame/session/src/lib.rs
Krayt78 Jun 11, 2025
5664b75
Update substrate/frame/session/src/lib.rs
Krayt78 Jun 11, 2025
caa7800
removed unused mock value
Krayt78 Jun 11, 2025
086eee9
Update prdoc/pr_7953.prdoc
kianenigma Jun 11, 2025
aedd820
Merge branch 'master' into add-deposit-for-setting-session-keys
kianenigma Jun 11, 2025
90b58a3
Removed RuntimeHoldReasons
Krayt78 Jun 11, 2025
d6ddabe
Update prdoc/pr_7953.prdoc
Krayt78 Jun 11, 2025
d026a13
fix prdoc
kianenigma Jun 14, 2025
cef9544
Merge branch 'master' into add-deposit-for-setting-session-keys
kianenigma Jun 14, 2025
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
10 changes: 6 additions & 4 deletions substrate/frame/session/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
101 changes: 83 additions & 18 deletions substrate/frame/session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ use frame_support::{
ensure,
traits::{
Defensive, EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get,
OneSessionHandler, ValidatorRegistration, ValidatorSet,
OneSessionHandler, ValidatorRegistration, ValidatorSet, Currency, NamedReservableCurrency,
ReservableCurrency,
},
weights::Weight,
Parameter,
Expand Down Expand Up @@ -397,6 +398,10 @@ pub mod pallet {
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

/// A simple identifier for session keys.
#[derive(codec::Encode, codec::Decode, codec::MaxEncodedLen, scale_info::TypeInfo, Debug, PartialEq, Eq, Clone)]
pub struct SessionKeysReserveId;

#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
Expand Down Expand Up @@ -436,8 +441,21 @@ pub mod pallet {

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;

/// The currency type for reserving when setting keys.
type Currency: NamedReservableCurrency<Self::AccountId>;

/// The reserve identifier type.
type ReserveIdentifier: Get<<Self::Currency as NamedReservableCurrency<Self::AccountId>>::ReserveIdentifier> + TypeInfo + 'static;

/// The amount to be reserved when setting keys.
#[pallet::constant]
type KeyDeposit: Get<BalanceOf<Self>>;
}

// Add a type alias for the balance
type BalanceOf<T> = <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;

#[pallet::genesis_config]
#[derive(frame_support::DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
Expand Down Expand Up @@ -474,7 +492,7 @@ pub mod pallet {
for (account, val, keys) in
self.keys.iter().chain(self.non_authority_keys.iter()).cloned()
{
Pallet::<T>::inner_set_keys(&val, keys)
Pallet::<T>::inner_set_keys(&val, keys, None)
.expect("genesis config must not contain duplicates; qed");
if frame_system::Pallet::<T>::inc_consumers_without_limit(&account).is_err() {
// This will leak a provider reference, however it only happens once (at
Expand Down Expand Up @@ -558,6 +576,10 @@ pub mod pallet {
ValidatorDisabled { validator: T::ValidatorId },
/// Validator has been re-enabled.
ValidatorReenabled { validator: T::ValidatorId },
/// Funds have been reserved for setting keys.
KeysFundsReserved { account: T::AccountId, amount: <<T as Config>::Currency as Currency<T::AccountId>>::Balance },
/// Funds have been unreserved when purging keys.
KeysFundsUnreserved { account: T::AccountId, amount: <<T as Config>::Currency as Currency<T::AccountId>>::Balance },
}

/// Error for the session pallet.
Expand All @@ -573,6 +595,8 @@ pub mod pallet {
NoKeys,
/// Key setting account is not live, so it's impossible to associate keys.
NoAccount,
/// Insufficient funds for setting keys.
InsufficientFunds,
}

#[pallet::hooks]
Expand Down Expand Up @@ -836,10 +860,41 @@ impl<T: Config> Pallet<T> {
.ok_or(Error::<T>::NoAssociatedValidatorId)?;

ensure!(frame_system::Pallet::<T>::can_inc_consumer(account), Error::<T>::NoAccount);
let old_keys = Self::inner_set_keys(&who, keys)?;
if old_keys.is_none() {

// Load keys once to avoid redundant storage reads
let old_keys = Self::load_keys(&who);
let is_new_registration = old_keys.is_none();

// For new registrations, ensure the account has enough funds for the deposit
if is_new_registration {
let deposit = T::KeyDeposit::get();
let _= T::ReserveIdentifier::get();
// Since NamedReservableCurrency doesn't directly expose can_reserve,
// we need to use the normal reserve method for checking
ensure!(
<T::Currency as ReservableCurrency<_>>::can_reserve(account, deposit),
Error::<T>::InsufficientFunds
);
}

// Now that we've checked funds, proceed with setting keys
// Pass old_keys to avoid another storage read
Self::inner_set_keys(&who, keys, old_keys)?;

// Reserve deposit if this is a new registration
if is_new_registration {
let deposit = T::KeyDeposit::get();
let id = T::ReserveIdentifier::get();
T::Currency::reserve_named(&id, account, deposit)?;

let assertion = frame_system::Pallet::<T>::inc_consumers(account).is_ok();
debug_assert!(assertion, "can_inc_consumer() returned true; no change since; qed");

// Emit an event for the reserved funds
Self::deposit_event(Event::<T>::KeysFundsReserved {
account: account.clone(),
amount: deposit,
});
}

Ok(())
Expand All @@ -854,35 +909,33 @@ impl<T: Config> Pallet<T> {
fn inner_set_keys(
who: &T::ValidatorId,
keys: T::Keys,
old_keys_opt: Option<T::Keys>,
) -> Result<Option<T::Keys>, DispatchError> {
let old_keys = Self::load_keys(who);

// First, check for duplicates without modifying storage
for id in T::Keys::key_ids() {
let key = keys.get_raw(*id);

// ensure keys are without duplication.
ensure!(
Self::key_owner(*id, key).map_or(true, |owner| &owner == who),
Error::<T>::DuplicatedKey,
);
}


// After all duplicate checks have passed, update storage
for id in T::Keys::key_ids() {
let key = keys.get_raw(*id);

if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(*id)) {
if key == old {
continue

if let Some(old_key) = old_keys_opt.as_ref().map(|k| k.get_raw(*id)) {
if key != old_key {
Self::clear_key_owner(*id, old_key);
Self::put_key_owner(*id, key, who);
}

Self::clear_key_owner(*id, old);
} else {
Self::put_key_owner(*id, key, who);
}

Self::put_key_owner(*id, key, who);
}

Self::put_keys(who, &keys);
Ok(old_keys)
Ok(old_keys_opt)
}

fn do_purge_keys(account: &T::AccountId) -> DispatchResult {
Expand All @@ -898,6 +951,18 @@ impl<T: Config> Pallet<T> {
let key_data = old_keys.get_raw(*id);
Self::clear_key_owner(*id, key_data);
}

// Unreserve the deposit using the named reserve
let deposit = T::KeyDeposit::get();
let id = T::ReserveIdentifier::get();
let _ = T::Currency::unreserve_named(&id, account, deposit);

// Emit an event for the unreserved funds
Self::deposit_event(Event::<T>::KeysFundsUnreserved {
account: account.clone(),
amount: deposit,
});

frame_system::Pallet::<T>::dec_consumers(account);

Ok(())
Expand Down
Loading
Loading