Skip to content

Commit dc9400a

Browse files
committed
session/staking/westend AH and RC: allow to set/purge session keys via AH
- Allow setting or purging keys via AH -> XCM -> RC. - Maintain the option to set or purge keys via RC for backward compatibility. - We do not yet enforce or handle deposits on AH; this will be addressed once RC extrinsics are fully deprecated. - Updated Westend RC to set the deposit to 0, aligning it with the current Polkadot/Kusama RC, and modified Westend AH to support setting or purging keys. TODO: - Tests - Benchmarking
1 parent 4581cab commit dc9400a

File tree

12 files changed

+386
-10
lines changed

12 files changed

+386
-10
lines changed

Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,12 @@ pallet-vesting = { workspace = true }
7777
pallet-whitelist = { workspace = true }
7878
sp-api = { workspace = true }
7979
sp-arithmetic = { workspace = true }
80+
sp-authority-discovery = { workspace = true }
8081
sp-block-builder = { workspace = true }
8182
sp-consensus-aura = { workspace = true }
83+
sp-consensus-babe = { workspace = true }
84+
sp-consensus-beefy = { workspace = true }
85+
sp-consensus-grandpa = { workspace = true }
8286
sp-core = { workspace = true }
8387
sp-genesis-builder = { workspace = true }
8488
sp-inherents = { workspace = true }
@@ -102,6 +106,7 @@ pallet-xcm = { workspace = true }
102106
pallet-xcm-benchmarks = { optional = true, workspace = true }
103107
pallet-xcm-precompiles = { workspace = true }
104108
polkadot-parachain-primitives = { workspace = true }
109+
polkadot-primitives = { workspace = true }
105110
polkadot-runtime-common = { workspace = true }
106111
westend-runtime-constants = { workspace = true }
107112
xcm = { workspace = true }
@@ -209,6 +214,7 @@ runtime-benchmarks = [
209214
"pallet-xcm/runtime-benchmarks",
210215
"parachains-common/runtime-benchmarks",
211216
"polkadot-parachain-primitives/runtime-benchmarks",
217+
"polkadot-primitives/runtime-benchmarks",
212218
"polkadot-runtime-common/runtime-benchmarks",
213219
"snowbridge-pallet-system-frontend/runtime-benchmarks",
214220
"snowbridge-runtime-common/runtime-benchmarks",
@@ -369,6 +375,7 @@ std = [
369375
"parachain-info/std",
370376
"parachains-common/std",
371377
"polkadot-parachain-primitives/std",
378+
"polkadot-primitives/std",
372379
"polkadot-runtime-common/std",
373380
"primitive-types/std",
374381
"scale-info/std",
@@ -378,8 +385,12 @@ std = [
378385
"snowbridge-runtime-common/std",
379386
"sp-api/std",
380387
"sp-arithmetic/std",
388+
"sp-authority-discovery/std",
381389
"sp-block-builder/std",
382390
"sp-consensus-aura/std",
391+
"sp-consensus-babe/std",
392+
"sp-consensus-beefy/std",
393+
"sp-consensus-grandpa/std",
383394
"sp-core/std",
384395
"sp-genesis-builder/std",
385396
"sp-inherents/std",

cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,20 @@ impl_opaque_keys! {
139139
}
140140
}
141141

142+
// Relay chain validator session keys (forwarded to RC).
143+
// IMPORTANT: This MUST match the SessionKeys definition in the corresponding Relay Chain runtime
144+
// (polkadot/runtime/westend/src/lib.rs). If the RC keys change, this must be updated too.
145+
impl_opaque_keys! {
146+
pub struct RCSessionKeys {
147+
pub grandpa: sp_consensus_grandpa::AuthorityId,
148+
pub babe: sp_consensus_babe::AuthorityId,
149+
pub para_validator: polkadot_primitives::ValidatorId,
150+
pub para_assignment: polkadot_primitives::AssignmentId,
151+
pub authority_discovery: sp_authority_discovery::AuthorityId,
152+
pub beefy: sp_consensus_beefy::ecdsa_crypto::AuthorityId,
153+
}
154+
}
155+
142156
#[sp_version::runtime_version]
143157
pub const VERSION: RuntimeVersion = RuntimeVersion {
144158
// Note: "westmint" is the legacy name for this chain. It has been renamed to

cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ impl pallet_staking_async_rc_client::Config for Runtime {
309309
type MaxValidatorSetRetries = ConstU32<64>;
310310
// export validator session at end of session 4 within an era.
311311
type ValidatorSetExportSession = ConstU32<4>;
312+
type Keys = RCSessionKeys;
312313
}
313314

314315
#[derive(Encode, Decode)]
@@ -321,9 +322,15 @@ pub enum RelayChainRuntimePallets {
321322

322323
#[derive(Encode, Decode)]
323324
pub enum AhClientCalls {
324-
// index of `fn validator_set` in `staking-async-ah-client`. It has only one call.
325+
// index of `fn validator_set` in `staking-async-ah-client`.
325326
#[codec(index = 0)]
326327
ValidatorSet(rc_client::ValidatorSetReport<AccountId>),
328+
// index of `fn set_keys_from_ah` in `staking-async-ah-client`.
329+
#[codec(index = 3)]
330+
SetKeys { stash: AccountId, keys: Vec<u8>, proof: Vec<u8> },
331+
// index of `fn purge_keys_from_ah` in `staking-async-ah-client`.
332+
#[codec(index = 4)]
333+
PurgeKeys { stash: AccountId },
327334
}
328335

329336
pub struct ValidatorSetToXcm;
@@ -347,6 +354,64 @@ impl sp_runtime::traits::Convert<rc_client::ValidatorSetReport<AccountId>, Xcm<(
347354
}
348355
}
349356

357+
/// Message to set session keys on the Relay Chain.
358+
#[derive(Encode, Decode, Clone)]
359+
pub struct SetKeysMessage {
360+
pub stash: AccountId,
361+
pub keys: Vec<u8>,
362+
pub proof: Vec<u8>,
363+
}
364+
365+
pub struct SetKeysToXcm;
366+
impl sp_runtime::traits::Convert<SetKeysMessage, Xcm<()>> for SetKeysToXcm {
367+
fn convert(msg: SetKeysMessage) -> Xcm<()> {
368+
Xcm(vec![
369+
Instruction::UnpaidExecution {
370+
weight_limit: WeightLimit::Unlimited,
371+
check_origin: None,
372+
},
373+
Instruction::Transact {
374+
origin_kind: OriginKind::Native,
375+
fallback_max_weight: None,
376+
call: RelayChainRuntimePallets::AhClient(AhClientCalls::SetKeys {
377+
stash: msg.stash,
378+
keys: msg.keys,
379+
proof: msg.proof,
380+
})
381+
.encode()
382+
.into(),
383+
},
384+
])
385+
}
386+
}
387+
388+
/// Message to purge session keys on the Relay Chain.
389+
#[derive(Encode, Decode, Clone)]
390+
pub struct PurgeKeysMessage {
391+
pub stash: AccountId,
392+
}
393+
394+
pub struct PurgeKeysToXcm;
395+
impl sp_runtime::traits::Convert<PurgeKeysMessage, Xcm<()>> for PurgeKeysToXcm {
396+
fn convert(msg: PurgeKeysMessage) -> Xcm<()> {
397+
Xcm(vec![
398+
Instruction::UnpaidExecution {
399+
weight_limit: WeightLimit::Unlimited,
400+
check_origin: None,
401+
},
402+
Instruction::Transact {
403+
origin_kind: OriginKind::Native,
404+
fallback_max_weight: None,
405+
call: RelayChainRuntimePallets::AhClient(AhClientCalls::PurgeKeys {
406+
stash: msg.stash,
407+
})
408+
.encode()
409+
.into(),
410+
},
411+
])
412+
}
413+
}
414+
350415
parameter_types! {
351416
pub RelayLocation: Location = Location::parent();
352417
}
@@ -363,6 +428,24 @@ impl rc_client::SendToRelayChain for StakingXcmToRelayChain {
363428
ValidatorSetToXcm,
364429
>::send(report)
365430
}
431+
432+
fn set_keys(stash: Self::AccountId, keys: Vec<u8>, proof: Vec<u8>) -> Result<(), ()> {
433+
rc_client::XCMSender::<
434+
xcm_config::XcmRouter,
435+
RelayLocation,
436+
SetKeysMessage,
437+
SetKeysToXcm,
438+
>::send(SetKeysMessage { stash, keys, proof })
439+
}
440+
441+
fn purge_keys(stash: Self::AccountId) -> Result<(), ()> {
442+
rc_client::XCMSender::<
443+
xcm_config::XcmRouter,
444+
RelayLocation,
445+
PurgeKeysMessage,
446+
PurgeKeysToXcm,
447+
>::send(PurgeKeysMessage { stash })
448+
}
366449
}
367450

368451
parameter_types! {

polkadot/runtime/westend/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,6 @@ impl pallet_authorship::Config for Runtime {
509509
parameter_types! {
510510
pub const Period: BlockNumber = 10 * MINUTES;
511511
pub const Offset: BlockNumber = 0;
512-
pub const KeyDeposit: Balance = deposit(1, 5 * 32 + 33);
513512
}
514513

515514
impl_opaque_keys! {
@@ -535,7 +534,7 @@ impl pallet_session::Config for Runtime {
535534
type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy;
536535
type WeightInfo = weights::pallet_session::WeightInfo<Runtime>;
537536
type Currency = Balances;
538-
type KeyDeposit = KeyDeposit;
537+
type KeyDeposit = ();
539538
}
540539

541540
impl pallet_session::historical::Config for Runtime {

prdoc/pr_10666.prdoc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
title: 'staking-async: allow session keys handling on AssetHub'
2+
doc:
3+
- audience: Runtime Dev
4+
description: |-
5+
- Added session keys handling on AssetHub for staking-async: validators can now call set_keys and purge_keys on AssetHub, which forwards the request to the RelayChain via XCM.
6+
- Validators are still allowed to call `set_keys` and `purge_keys` via relay-chain pallet-session's related extrinsics. This option will be deprecated in the future.
7+
- Until then, no key deposit is set on AssetHub yet
8+
crates:
9+
- name: asset-hub-westend-runtime
10+
bump: major
11+
- name: westend-runtime
12+
bump: major
13+
- name: pallet-session
14+
bump: major
15+
- name: pallet-staking-async-ah-client
16+
bump: major
17+
- name: pallet-staking-async-rc-client
18+
bump: major

substrate/frame/session/src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,10 @@ impl<T: Config> Pallet<T> {
860860
///
861861
/// This ensures that the reference counter in system is incremented appropriately and as such
862862
/// must accept an account ID, rather than a validator ID.
863-
fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> DispatchResult {
863+
///
864+
/// This function is public to allow cross-chain session key management (e.g., from AssetHub
865+
/// via `pallet-staking-async-ah-client`).
866+
pub fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> DispatchResult {
864867
let who = T::ValidatorIdOf::convert(account.clone())
865868
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
866869

@@ -923,7 +926,11 @@ impl<T: Config> Pallet<T> {
923926
Ok(old_keys)
924927
}
925928

926-
fn do_purge_keys(account: &T::AccountId) -> DispatchResult {
929+
/// Purge session keys for an account.
930+
///
931+
/// This function is public to allow cross-chain session key management (e.g., from AssetHub
932+
/// via `pallet-staking-async-ah-client`).
933+
pub fn do_purge_keys(account: &T::AccountId) -> DispatchResult {
927934
let who = T::ValidatorIdOf::convert(account.clone())
928935
// `purge_keys` may not have a controller-stash pair any more. If so then we expect the
929936
// stash account to be passed in directly and convert that to a `ValidatorId` using the

0 commit comments

Comments
 (0)