Skip to content

Commit 795bc77

Browse files
Ank4nbkchrgemini132muracaliamaharon
authored
[Pools] Refactors and runtime apis for DelegateStake (#4537)
## Runtime Apis Introduces the following runtime apis to facilitate dapps and wallets in integrating with the `DelegateStake` functionalities of the pools (related: #3905). These apis are meant to support pool and member migration, as well as lazy application of pending slashes of pool members. ```rust fn pool_pending_slash(pool_id: PoolId) -> Balance; fn member_pending_slash(member: AccountId) -> Balance; fn pool_needs_delegate_migration(pool_id: PoolId) -> bool; fn member_needs_delegate_migration(member: AccountId) -> bool; ``` ## Refactors - Introduces newtypes for `Agent`, `Delegator`, `Pool` and `[Pool]Member`. And refactors `StakeAdapter` and `DelegationInterface` to accept the above types. This will help make these apis typesafe against using wrong account type. - Fixing `DelegationInterface` apis to return optional (instead of default value if key does not exist). - Rename struct `Agent` that wraps `AgentLedger` to `AgentOuterLedger` which is clearer (naming wise) and different from the newtype `Agent`. - Cleaning up new Pool events (related to `Delegation` feature of pool). --------- Signed-off-by: Matteo Muraca <[email protected]> Signed-off-by: Alexandru Gheorghe <[email protected]> Signed-off-by: Andrei Sandu <[email protected]> Signed-off-by: Adrian Catangiu <[email protected]> Signed-off-by: Alexandru Vasile <[email protected]> Signed-off-by: Oliver Tale-Yazdi <[email protected]> Signed-off-by: divdeploy <[email protected]> Signed-off-by: dependabot[bot] <[email protected]> Signed-off-by: hongkuang <[email protected]> Co-authored-by: Bastian Köcher <[email protected]> Co-authored-by: gemini132 <[email protected]> Co-authored-by: Matteo Muraca <[email protected]> Co-authored-by: Liam Aharon <[email protected]> Co-authored-by: Kian Paimani <[email protected]> Co-authored-by: Alexandru Gheorghe <[email protected]> Co-authored-by: Alessandro Siniscalchi <[email protected]> Co-authored-by: Andrei Sandu <[email protected]> Co-authored-by: Ross Bulat <[email protected]> Co-authored-by: Serban Iorga <[email protected]> Co-authored-by: s0me0ne-unkn0wn <[email protected]> Co-authored-by: Sam Johnson <[email protected]> Co-authored-by: Adrian Catangiu <[email protected]> Co-authored-by: Javier Viola <[email protected]> Co-authored-by: Alexandru Vasile <[email protected]> Co-authored-by: Niklas Adolfsson <[email protected]> Co-authored-by: Dastan <[email protected]> Co-authored-by: Clara van Staden <[email protected]> Co-authored-by: Ron <[email protected]> Co-authored-by: Vincent Geddes <[email protected]> Co-authored-by: Svyatoslav Nikolsky <[email protected]> Co-authored-by: Michal Kucharczyk <[email protected]> Co-authored-by: Dino Pačandi <[email protected]> Co-authored-by: Andrei Eres <[email protected]> Co-authored-by: Alin Dima <[email protected]> Co-authored-by: Andrei Sandu <[email protected]> Co-authored-by: Oliver Tale-Yazdi <[email protected]> Co-authored-by: Bastian Köcher <[email protected]> Co-authored-by: Branislav Kontur <[email protected]> Co-authored-by: Sebastian Kunert <[email protected]> Co-authored-by: gupnik <[email protected]> Co-authored-by: Vladimir Istyufeev <[email protected]> Co-authored-by: Lulu <[email protected]> Co-authored-by: Juan Girini <[email protected]> Co-authored-by: Francisco Aguirre <[email protected]> Co-authored-by: Dónal Murray <[email protected]> Co-authored-by: Shawn Tabrizi <[email protected]> Co-authored-by: Kutsal Kaan Bilgin <[email protected]> Co-authored-by: Ermal Kaleci <[email protected]> Co-authored-by: ordian <[email protected]> Co-authored-by: divdeploy <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sergej Sakac <[email protected]> Co-authored-by: Squirrel <[email protected]> Co-authored-by: HongKuang <[email protected]> Co-authored-by: Tsvetomir Dimitrov <[email protected]> Co-authored-by: Egor_P <[email protected]> Co-authored-by: Aaro Altonen <[email protected]> Co-authored-by: Dmitry Markin <[email protected]> Co-authored-by: Alexandru Vasile <[email protected]> Co-authored-by: Léa Narzis <[email protected]> Co-authored-by: Gonçalo Pestana <[email protected]> Co-authored-by: georgepisaltu <[email protected]> Co-authored-by: command-bot <> Co-authored-by: PG Herveou <[email protected]> Co-authored-by: jimwfs <[email protected]> Co-authored-by: jimwfs <[email protected]> Co-authored-by: polka.dom <[email protected]>
1 parent 5779ec5 commit 795bc77

17 files changed

Lines changed: 800 additions & 431 deletions

File tree

polkadot/runtime/westend/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2287,6 +2287,22 @@ sp_api::impl_runtime_apis! {
22872287
fn balance_to_points(pool_id: pallet_nomination_pools::PoolId, new_funds: Balance) -> Balance {
22882288
NominationPools::api_balance_to_points(pool_id, new_funds)
22892289
}
2290+
2291+
fn pool_pending_slash(pool_id: pallet_nomination_pools::PoolId) -> Balance {
2292+
NominationPools::api_pool_pending_slash(pool_id)
2293+
}
2294+
2295+
fn member_pending_slash(member: AccountId) -> Balance {
2296+
NominationPools::api_member_pending_slash(member)
2297+
}
2298+
2299+
fn pool_needs_delegate_migration(pool_id: pallet_nomination_pools::PoolId) -> bool {
2300+
NominationPools::api_pool_needs_delegate_migration(pool_id)
2301+
}
2302+
2303+
fn member_needs_delegate_migration(member: AccountId) -> bool {
2304+
NominationPools::api_member_needs_delegate_migration(member)
2305+
}
22902306
}
22912307

22922308
impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime {

prdoc/pr_4537.prdoc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
2+
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
3+
4+
title: Runtime apis to help with delegate-stake based Nomination Pools.
5+
6+
doc:
7+
- audience: Runtime User
8+
description: |
9+
Introduces a new set of runtime apis to facilitate dapps and wallets to integrate with delegate-stake
10+
functionalities of Nomination Pools. These apis support pool and member migration, as well as lazy application of
11+
pending slashes of the pool members.
12+
13+
crates:
14+
- name: pallet-nomination-pools
15+
bump: minor
16+
- name: westend-runtime
17+
bump: minor
18+
- name: kitchensink-runtime
19+
bump: minor
20+
- name: pallet-delegated-staking
21+
bump: minor
22+
- name: sp-staking
23+
bump: minor
24+
- name: pallet-nomination-pools-benchmarking
25+
bump: patch
26+
- name: pallet-nomination-pools-runtime-api
27+
bump: minor

substrate/bin/node/runtime/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,6 +2774,22 @@ impl_runtime_apis! {
27742774
fn balance_to_points(pool_id: pallet_nomination_pools::PoolId, new_funds: Balance) -> Balance {
27752775
NominationPools::api_balance_to_points(pool_id, new_funds)
27762776
}
2777+
2778+
fn pool_pending_slash(pool_id: pallet_nomination_pools::PoolId) -> Balance {
2779+
NominationPools::api_pool_pending_slash(pool_id)
2780+
}
2781+
2782+
fn member_pending_slash(member: AccountId) -> Balance {
2783+
NominationPools::api_member_pending_slash(member)
2784+
}
2785+
2786+
fn pool_needs_delegate_migration(pool_id: pallet_nomination_pools::PoolId) -> bool {
2787+
NominationPools::api_pool_needs_delegate_migration(pool_id)
2788+
}
2789+
2790+
fn member_needs_delegate_migration(member: AccountId) -> bool {
2791+
NominationPools::api_member_needs_delegate_migration(member)
2792+
}
27772793
}
27782794

27792795
impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime {

substrate/frame/delegated-staking/src/impls.rs

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,80 +19,78 @@
1919
//! Implementations of public traits, namely [`DelegationInterface`] and [`OnStakingUpdate`].
2020
2121
use super::*;
22-
use sp_staking::{DelegationInterface, DelegationMigrator, OnStakingUpdate};
22+
use sp_staking::{Agent, DelegationInterface, DelegationMigrator, Delegator, OnStakingUpdate};
2323

2424
impl<T: Config> DelegationInterface for Pallet<T> {
2525
type Balance = BalanceOf<T>;
2626
type AccountId = T::AccountId;
2727

2828
/// Effective balance of the `Agent` account.
29-
fn agent_balance(who: &Self::AccountId) -> Self::Balance {
30-
Agent::<T>::get(who)
31-
.map(|agent| agent.ledger.effective_balance())
32-
.unwrap_or_default()
29+
fn agent_balance(agent: Agent<Self::AccountId>) -> Option<Self::Balance> {
30+
AgentLedgerOuter::<T>::get(&agent.get())
31+
.map(|a| a.ledger.effective_balance())
32+
.ok()
3333
}
3434

35-
fn delegator_balance(delegator: &Self::AccountId) -> Self::Balance {
36-
Delegation::<T>::get(delegator).map(|d| d.amount).unwrap_or_default()
35+
fn delegator_balance(delegator: Delegator<Self::AccountId>) -> Option<Self::Balance> {
36+
Delegation::<T>::get(&delegator.get()).map(|d| d.amount)
3737
}
3838

3939
/// Delegate funds to an `Agent`.
4040
fn delegate(
41-
who: &Self::AccountId,
42-
agent: &Self::AccountId,
41+
who: Delegator<Self::AccountId>,
42+
agent: Agent<Self::AccountId>,
4343
reward_account: &Self::AccountId,
4444
amount: Self::Balance,
4545
) -> DispatchResult {
4646
Pallet::<T>::register_agent(
47-
RawOrigin::Signed(agent.clone()).into(),
47+
RawOrigin::Signed(agent.clone().get()).into(),
4848
reward_account.clone(),
4949
)?;
5050

5151
// Delegate the funds from who to the `Agent` account.
52-
Pallet::<T>::delegate_to_agent(RawOrigin::Signed(who.clone()).into(), agent.clone(), amount)
52+
Pallet::<T>::delegate_to_agent(RawOrigin::Signed(who.get()).into(), agent.get(), amount)
5353
}
5454

5555
/// Add more delegation to the `Agent` account.
5656
fn delegate_extra(
57-
who: &Self::AccountId,
58-
agent: &Self::AccountId,
57+
who: Delegator<Self::AccountId>,
58+
agent: Agent<Self::AccountId>,
5959
amount: Self::Balance,
6060
) -> DispatchResult {
61-
Pallet::<T>::delegate_to_agent(RawOrigin::Signed(who.clone()).into(), agent.clone(), amount)
61+
Pallet::<T>::delegate_to_agent(RawOrigin::Signed(who.get()).into(), agent.get(), amount)
6262
}
6363

6464
/// Withdraw delegation of `delegator` to `Agent`.
6565
///
6666
/// If there are funds in `Agent` account that can be withdrawn, then those funds would be
6767
/// unlocked/released in the delegator's account.
6868
fn withdraw_delegation(
69-
delegator: &Self::AccountId,
70-
agent: &Self::AccountId,
69+
delegator: Delegator<Self::AccountId>,
70+
agent: Agent<Self::AccountId>,
7171
amount: Self::Balance,
7272
num_slashing_spans: u32,
7373
) -> DispatchResult {
7474
Pallet::<T>::release_delegation(
75-
RawOrigin::Signed(agent.clone()).into(),
76-
delegator.clone(),
75+
RawOrigin::Signed(agent.get()).into(),
76+
delegator.get(),
7777
amount,
7878
num_slashing_spans,
7979
)
8080
}
8181

82-
/// Returns true if the `Agent` have any slash pending to be applied.
83-
fn has_pending_slash(agent: &Self::AccountId) -> bool {
84-
Agent::<T>::get(agent)
85-
.map(|d| !d.ledger.pending_slash.is_zero())
86-
.unwrap_or(false)
82+
/// Returns pending slash of the `agent`.
83+
fn pending_slash(agent: Agent<Self::AccountId>) -> Option<Self::Balance> {
84+
AgentLedgerOuter::<T>::get(&agent.get()).map(|d| d.ledger.pending_slash).ok()
8785
}
8886

8987
fn delegator_slash(
90-
agent: &Self::AccountId,
91-
delegator: &Self::AccountId,
88+
agent: Agent<Self::AccountId>,
89+
delegator: Delegator<Self::AccountId>,
9290
value: Self::Balance,
9391
maybe_reporter: Option<Self::AccountId>,
9492
) -> sp_runtime::DispatchResult {
95-
Pallet::<T>::do_slash(agent.clone(), delegator.clone(), value, maybe_reporter)
93+
Pallet::<T>::do_slash(agent, delegator, value, maybe_reporter)
9694
}
9795
}
9896

@@ -101,32 +99,29 @@ impl<T: Config> DelegationMigrator for Pallet<T> {
10199
type AccountId = T::AccountId;
102100

103101
fn migrate_nominator_to_agent(
104-
agent: &Self::AccountId,
102+
agent: Agent<Self::AccountId>,
105103
reward_account: &Self::AccountId,
106104
) -> DispatchResult {
107-
Pallet::<T>::migrate_to_agent(
108-
RawOrigin::Signed(agent.clone()).into(),
109-
reward_account.clone(),
110-
)
105+
Pallet::<T>::migrate_to_agent(RawOrigin::Signed(agent.get()).into(), reward_account.clone())
111106
}
112107
fn migrate_delegation(
113-
agent: &Self::AccountId,
114-
delegator: &Self::AccountId,
108+
agent: Agent<Self::AccountId>,
109+
delegator: Delegator<Self::AccountId>,
115110
value: Self::Balance,
116111
) -> DispatchResult {
117112
Pallet::<T>::migrate_delegation(
118-
RawOrigin::Signed(agent.clone()).into(),
119-
delegator.clone(),
113+
RawOrigin::Signed(agent.get()).into(),
114+
delegator.get(),
120115
value,
121116
)
122117
}
123118

124119
/// Only used for testing.
125120
#[cfg(feature = "runtime-benchmarks")]
126-
fn drop_agent(agent: &T::AccountId) {
127-
<Agents<T>>::remove(agent);
121+
fn drop_agent(agent: Agent<Self::AccountId>) {
122+
<Agents<T>>::remove(agent.clone().get());
128123
<Delegators<T>>::iter()
129-
.filter(|(_, delegation)| delegation.agent == *agent)
124+
.filter(|(_, delegation)| delegation.agent == agent.clone().get())
130125
.for_each(|(delegator, _)| {
131126
let _ = T::Currency::release_all(
132127
&HoldReason::StakingDelegation.into(),
@@ -136,7 +131,7 @@ impl<T: Config> DelegationMigrator for Pallet<T> {
136131
<Delegators<T>>::remove(&delegator);
137132
});
138133

139-
T::CoreStaking::migrate_to_direct_staker(agent);
134+
T::CoreStaking::migrate_to_direct_staker(&agent.get());
140135
}
141136
}
142137

@@ -158,7 +153,7 @@ impl<T: Config> OnStakingUpdate<T::AccountId, BalanceOf<T>> for Pallet<T> {
158153

159154
fn on_withdraw(stash: &T::AccountId, amount: BalanceOf<T>) {
160155
// if there is a withdraw to the agent, then add it to the unclaimed withdrawals.
161-
let _ = Agent::<T>::get(stash)
156+
let _ = AgentLedgerOuter::<T>::get(stash)
162157
// can't do anything if there is an overflow error. Just raise a defensive error.
163158
.and_then(|agent| agent.add_unclaimed_withdraw(amount).defensive())
164159
.map(|agent| agent.save());

0 commit comments

Comments
 (0)