Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
960e322
cap era duration, needs more tests.
Ank4n May 29, 2025
5d3d02a
impl min bond
Ank4n May 29, 2025
8cc3d3b
Merge branch 'master' into ankn/bounded-era-reward
Ank4n May 29, 2025
c47f127
doc fix
Ank4n May 29, 2025
873333a
fix min bond chec
Ank4n May 29, 2025
1381a78
fmt
Ank4n May 29, 2025
80479ff
Merge branch 'master' into ankn/bounded-era-reward
Ank4n Jun 2, 2025
fc8f315
Merge branch 'master' into ankn/bounded-era-reward
Ank4n Jun 3, 2025
3455016
use AHStakingInterface to rotate session
Ank4n Jun 3, 2025
35bd423
fmt
Ank4n Jun 3, 2025
b1e5247
wip: failing test missing events
Ank4n Jun 3, 2025
971de13
cap era duration test
Ank4n Jun 3, 2025
5f0aed8
refactor to handle incorrect activation stamp
Ank4n Jun 3, 2025
36448f9
fix force always era rotation issue
Ank4n Jun 3, 2025
2d7e2a2
fmt
Ank4n Jun 3, 2025
44d6164
minor
Ank4n Jun 3, 2025
d377884
no full unbond needed yet
Ank4n Jun 3, 2025
6650ad1
Merge branch 'master' into ankn/bounded-era-reward
Ank4n Jun 3, 2025
31c5c85
fmt
Ank4n Jun 3, 2025
8c7c840
add era duration in non default runtimes
Ank4n Jun 3, 2025
84ec94b
Update from github-actions[bot] running command 'prdoc --audience run…
github-actions[bot] Jun 4, 2025
77615b5
Merge branch 'master' into ankn/bounded-era-reward
Ank4n Jun 9, 2025
0a3723f
Update from github-actions[bot] running command 'fmt'
github-actions[bot] Jun 9, 2025
81ee0ae
PR feedback
Ank4n Jun 9, 2025
422d7b3
compiles
Ank4n Jun 10, 2025
277fc16
make planned_era private
Ank4n Jun 10, 2025
f3a6d23
don't use CurrentEra outside rotator
Ank4n Jun 10, 2025
158f9ff
some more removals
Ank4n Jun 10, 2025
821167a
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jun 10, 2025
f16859d
fmt
Ank4n Jun 10, 2025
3c80523
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jun 10, 2025
971b25d
rename set current era to set active era
Ank4n Jun 10, 2025
18f0bed
staking async looks good
Ank4n Jun 10, 2025
406b35b
fmt
Ank4n Jun 10, 2025
7d4a70a
use active era in pools
Ank4n Jun 10, 2025
5a46b99
hunting and killing more CurrentEras
Ank4n Jun 10, 2025
83ad245
fix tests
Ank4n Jun 10, 2025
a532171
fmt
Ank4n Jun 10, 2025
1fc30ff
fix try state
Ank4n Jun 11, 2025
57b41ad
fix ahm test
Ank4n Jun 11, 2025
91486cc
fix missing fn
Ank4n Jun 11, 2025
e002b13
fix fast unstake
Ank4n Jun 11, 2025
89e08ec
fmt
Ank4n Jun 11, 2025
329ca65
fix pools
Ank4n Jun 11, 2025
cdb3050
fix test delegate stake
Ank4n Jun 11, 2025
a4f1cd2
fmt
Ank4n Jun 11, 2025
e400b1f
fix rustdoc
Ank4n Jun 11, 2025
34f97d3
Merge branch 'master' into ankn/current-era-refactor
nkpar Jun 11, 2025
7d13bca
Merge branch 'master' into ankn/current-era-refactor
sigurpol Jun 13, 2025
f2235a0
Merge branch 'master' into ankn/current-era-refactor
sigurpol Jun 18, 2025
ea83e16
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jun 23, 2025
44b1fab
Merge branch 'master' into ankn/current-era-refactor
sigurpol Jun 26, 2025
a5a05b1
Merge branch 'master' into ankn/current-era-refactor
sigurpol Jun 27, 2025
7bd882d
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jul 4, 2025
44e0520
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jul 6, 2025
57da741
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jul 29, 2025
dfe935e
Merge branch 'master' into ankn/current-era-refactor
Ank4n Jul 31, 2025
43afe7d
Merge branch 'master' into ankn/current-era-refactor
Ank4n Aug 7, 2025
e0c8134
fixes
Ank4n Aug 7, 2025
21eb4e9
def fix
Ank4n Aug 7, 2025
abc1645
Merge branch 'master' into ankn/current-era-refactor
Ank4n Nov 26, 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
5 changes: 4 additions & 1 deletion substrate/frame/fast-unstake/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ mod benchmarks {
#[benchmark]
fn on_idle_unstake(b: Linear<1, { T::BatchSize::get() }>) {
ErasToCheckPerBlock::<T>::put(1);
// initialise the era.
T::Staking::set_active_era(0, Some(0));

for who in create_unexposed_batch::<T>(b).into_iter() {
assert_ok!(Pallet::<T>::register_fast_unstake(RawOrigin::Signed(who.clone()).into(),));
}
Expand Down Expand Up @@ -134,7 +137,7 @@ mod benchmarks {
let u = T::MaxErasToCheckPerBlock::get().min(T::Staking::bonding_duration());

ErasToCheckPerBlock::<T>::put(u);
T::Staking::set_current_era(u);
T::Staking::set_active_era(u, Some(0));

// setup staking with v validators and u eras of data (0..=u+1)
setup_staking::<T>(v, u);
Expand Down
7 changes: 3 additions & 4 deletions substrate/frame/fast-unstake/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,18 +520,17 @@ pub mod pallet {
);

// the range that we're allowed to check in this round.
let current_era = T::Staking::current_era();
let active_era = T::Staking::active_era();
let bonding_duration = T::Staking::bonding_duration();

// prune all the old eras that we don't care about. This will help us keep the bound
// of `checked`.
checked.retain(|e| *e >= current_era.saturating_sub(bonding_duration));
checked.retain(|e| *e >= active_era.saturating_sub(bonding_duration));

let unchecked_eras_to_check = {
// get the last available `bonding_duration` eras up to current era in reverse
// order.
let total_check_range = (current_era.saturating_sub(bonding_duration)..=
current_era)
let total_check_range = (active_era.saturating_sub(bonding_duration)..=active_era)
.rev()
.collect::<Vec<_>>();
debug_assert!(
Expand Down
8 changes: 8 additions & 0 deletions substrate/frame/fast-unstake/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,11 @@ pub fn create_exposed_nominator(exposed: AccountId, era: u32) {
// register the exposed one.
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(exposed)));
}

pub fn set_active_era(era: sp_staking::EraIndex) {
pallet_staking::CurrentEra::<T>::put(era);
pallet_staking::ActiveEra::<T>::put(pallet_staking::ActiveEraInfo {
index: era,
start: Some(0),
});
}
36 changes: 18 additions & 18 deletions substrate/frame/fast-unstake/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ mod on_idle {
fn early_exit() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// set up Queue item
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand All @@ -249,7 +249,7 @@ mod on_idle {
fn if_head_not_set_one_random_fetched_from_queue() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// given
// reserved balance prior to registering for fast unstake.
Expand Down Expand Up @@ -324,7 +324,7 @@ mod on_idle {
fn successful_multi_queue() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register multi accounts for fast unstake
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand Down Expand Up @@ -378,7 +378,7 @@ mod on_idle {
fn successful_unstake() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register for fast unstake
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand Down Expand Up @@ -418,7 +418,7 @@ mod on_idle {
fn successful_unstake_all_eras_per_block() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

Balances::make_free_balance_be(&2, 100);

Expand Down Expand Up @@ -461,7 +461,7 @@ mod on_idle {
ExtBuilder::default().build_and_execute(|| {
// put 1 era per block
ErasToCheckPerBlock::<T>::put(1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register for fast unstake
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand Down Expand Up @@ -539,7 +539,7 @@ mod on_idle {
ExtBuilder::default().build_and_execute(|| {
// given
ErasToCheckPerBlock::<T>::put(1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register for fast unstake
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand Down Expand Up @@ -582,7 +582,7 @@ mod on_idle {
);

// when: a new era happens right before one is free.
CurrentEra::<T>::put(CurrentEra::<T>::get().unwrap() + 1);
set_active_era(<Staking as StakingInterface>::active_era() + 1);
ExtBuilder::register_stakers_for_era(CurrentEra::<T>::get().unwrap());

// then
Expand Down Expand Up @@ -620,7 +620,7 @@ mod on_idle {
ExtBuilder::default().build_and_execute(|| {
// give: put 1 era per block
ErasToCheckPerBlock::<T>::put(1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register for fast unstake
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand Down Expand Up @@ -668,7 +668,7 @@ mod on_idle {

// then we register a new era.
Ongoing::set(false);
CurrentEra::<T>::put(CurrentEra::<T>::get().unwrap() + 1);
set_active_era(<Staking as StakingInterface>::active_era() + 1);
ExtBuilder::register_stakers_for_era(CurrentEra::<T>::get().unwrap());

// then we can progress again, but notice that the new era that had to be checked.
Expand Down Expand Up @@ -716,7 +716,7 @@ mod on_idle {
fn exposed_nominator_cannot_unstake() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// create an exposed nominator in era 1
let exposed = 666;
Expand Down Expand Up @@ -760,7 +760,7 @@ mod on_idle {
// same as the previous check, but we check 2 eras per block, and we make the exposed be
// exposed in era 0, so that it is detected halfway in a check era.
ErasToCheckPerBlock::<T>::put(2);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// create an exposed nominator in era 0
let exposed = 666;
Expand Down Expand Up @@ -794,7 +794,7 @@ mod on_idle {
fn validators_cannot_bail() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// a validator switches role and register...
assert_ok!(Staking::nominate(
Expand Down Expand Up @@ -831,7 +831,7 @@ mod on_idle {
fn unexposed_validator_can_fast_unstake() {
ExtBuilder::default().build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// create a new validator that 100% not exposed.
Balances::make_free_balance_be(&42, 100 + Deposit::get());
Expand Down Expand Up @@ -872,7 +872,7 @@ mod batched {
fn single_block_batched_successful() {
ExtBuilder::default().batch(3).build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(BondingDuration::get() + 1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(3)));
Expand Down Expand Up @@ -923,7 +923,7 @@ mod batched {
fn multi_block_batched_successful() {
ExtBuilder::default().batch(3).build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(2);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(3)));
Expand Down Expand Up @@ -989,7 +989,7 @@ mod batched {
fn multi_block_batched_some_fail() {
ExtBuilder::default().batch(4).build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(2);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register two good ones.
assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
Expand Down Expand Up @@ -1054,7 +1054,7 @@ mod batched {
fn multi_block_batched_all_fail_early_exit() {
ExtBuilder::default().batch(2).build_and_execute(|| {
ErasToCheckPerBlock::<T>::put(1);
CurrentEra::<T>::put(BondingDuration::get());
set_active_era(BondingDuration::get());

// register two bad ones.
create_exposed_nominator(666, 3);
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/nomination-pools/fuzzer/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ fn main() {

// trigger an era change, and check the status of the reward agent.
if iteration % ERA == 0 {
CurrentEra::mutate(|c| *c += 1);
ActiveEra::mutate(|c| *c += 1);
BondedPools::<T>::iter().for_each(|(id, _)| {
let amount = random_ed_multiple(&mut rng);
let _ =
Expand Down
6 changes: 3 additions & 3 deletions substrate/frame/nomination-pools/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ pub trait StakeStrategy {
Self::CoreStaking::bonding_duration()
}

/// See [`StakingInterface::current_era`].
fn current_era() -> EraIndex {
Self::CoreStaking::current_era()
/// See [`StakingInterface::active_era`].
fn active_era() -> EraIndex {
Self::CoreStaking::active_era()
}

/// See [`StakingInterface::minimum_nominator_bond`].
Expand Down
26 changes: 13 additions & 13 deletions substrate/frame/nomination-pools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@
//! ```
//!
//! For scalability, a bound is maintained on the number of unbonding sub pools (see
//! [`TotalUnbondingPools`]). An unbonding pool is removed once its older than `current_era -
//! [`TotalUnbondingPools`]). An unbonding pool is removed once its older than `active_era -
//! TotalUnbondingPools`. An unbonding pool is merged into the unbonded pool with
//!
//! ```text
Expand All @@ -312,9 +312,9 @@
//!
//! This scheme "averages" out the points value in the unbonded pool.
//!
//! Once a members `unbonding_era` is older than `current_era -
//! Once a members `unbonding_era` is older than `active_era -
//! [sp_staking::StakingInterface::bonding_duration]`, it can can cash it's points out of the
//! corresponding unbonding pool. If it's `unbonding_era` is older than `current_era -
//! corresponding unbonding pool. If it's `unbonding_era` is older than `active_era -
//! TotalUnbondingPools`, it can cash it's points from the unbonded pool.
//!
//! **Relevant extrinsics:**
Expand Down Expand Up @@ -672,13 +672,13 @@ impl<T: Config> PoolMember<T> {
/// Infallible, noop if no unbonding eras exist.
fn withdraw_unlocked(
&mut self,
current_era: EraIndex,
active_era: EraIndex,
) -> BoundedBTreeMap<EraIndex, BalanceOf<T>, T::MaxUnbonding> {
// NOTE: if only drain-filter was stable..
let mut removed_points =
BoundedBTreeMap::<EraIndex, BalanceOf<T>, T::MaxUnbonding>::default();
self.unbonding_eras.retain(|e, p| {
if *e > current_era {
if *e > active_era {
true
} else {
removed_points
Expand Down Expand Up @@ -1593,7 +1593,7 @@ impl<T: Config> UnbondPool<T> {
pub struct SubPools<T: Config> {
/// A general, era agnostic pool of funds that have fully unbonded. The pools
/// of `Self::with_era` will lazily be merged into into this pool if they are
/// older then `current_era - TotalUnbondingPools`.
/// older then `active_era - TotalUnbondingPools`.
pub no_era: UnbondPool<T>,
/// Map of era in which a pool becomes unbonded in => unbond pools.
pub with_era: BoundedBTreeMap<EraIndex, UnbondPool<T>, TotalUnbondingPools<T>>,
Expand All @@ -1604,12 +1604,12 @@ impl<T: Config> SubPools<T> {
///
/// This is often used whilst getting the sub-pool from storage, thus it consumes and returns
/// `Self` for ergonomic purposes.
fn maybe_merge_pools(mut self, current_era: EraIndex) -> Self {
fn maybe_merge_pools(mut self, active_era: EraIndex) -> Self {
// Ex: if `TotalUnbondingPools` is 5 and current era is 10, we only want to retain pools
// 6..=10. Note that in the first few eras where `checked_sub` is `None`, we don't remove
// anything.
if let Some(newest_era_to_remove) =
current_era.checked_sub(T::PostUnbondingPoolsWindow::get())
active_era.checked_sub(T::PostUnbondingPoolsWindow::get())
{
self.with_era.retain(|k, v| {
if *k > newest_era_to_remove {
Expand Down Expand Up @@ -2300,8 +2300,8 @@ pub mod pallet {
&mut reward_pool,
)?;

let current_era = T::StakeAdapter::current_era();
let unbond_era = T::StakeAdapter::bonding_duration().saturating_add(current_era);
let active_era = T::StakeAdapter::active_era();
let unbond_era = T::StakeAdapter::bonding_duration().saturating_add(active_era);

// Unbond in the actual underlying nominator.
let unbonding_balance = bonded_pool.dissolve(unbonding_points);
Expand All @@ -2310,7 +2310,7 @@ pub mod pallet {
// Note that we lazily create the unbonding pools here if they don't already exist
let mut sub_pools = SubPoolsStorage::<T>::get(member.pool_id)
.unwrap_or_default()
.maybe_merge_pools(current_era);
.maybe_merge_pools(active_era);

// Update the unbond pool associated with the current era with the unbonded funds. Note
// that we lazily create the unbond pool if it does not yet exist.
Expand Down Expand Up @@ -2420,7 +2420,7 @@ pub mod pallet {

let mut member =
PoolMembers::<T>::get(&member_account).ok_or(Error::<T>::PoolMemberNotFound)?;
let current_era = T::StakeAdapter::current_era();
let active_era = T::StakeAdapter::active_era();

let bonded_pool = BondedPool::<T>::get(member.pool_id)
.defensive_ok_or::<Error<T>>(DefensiveError::PoolNotFound.into())?;
Expand Down Expand Up @@ -2448,7 +2448,7 @@ pub mod pallet {
let pool_account = bonded_pool.bonded_account();

// NOTE: must do this after we have done the `ok_to_withdraw_unbonded_other_with` check.
let withdrawn_points = member.withdraw_unlocked(current_era);
let withdrawn_points = member.withdraw_unlocked(active_era);
ensure!(!withdrawn_points.is_empty(), Error::<T>::CannotWithdrawAny);

// Before calculating the `balance_to_unbond`, we call withdraw unbonded to ensure the
Expand Down
22 changes: 15 additions & 7 deletions substrate/frame/nomination-pools/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub fn default_reward_account() -> AccountId {

parameter_types! {
pub static MinJoinBondConfig: Balance = 2;
pub static CurrentEra: EraIndex = 0;
pub static ActiveEra: EraIndex = 0;
pub static BondingDuration: EraIndex = 3;
pub storage BondedBalanceMap: BTreeMap<AccountId, Balance> = Default::default();
// map from a user to a vec of eras and amounts being unlocked in each era.
Expand Down Expand Up @@ -100,8 +100,8 @@ impl sp_staking::StakingInterface for StakingMock {
unimplemented!("method currently not used in testing")
}

fn current_era() -> EraIndex {
CurrentEra::get()
fn active_era() -> EraIndex {
ActiveEra::get()
}

fn bonding_duration() -> EraIndex {
Expand Down Expand Up @@ -132,7 +132,7 @@ impl sp_staking::StakingInterface for StakingMock {
*x.get_mut(who).unwrap() = x.get_mut(who).unwrap().saturating_sub(amount);
BondedBalanceMap::set(&x);

let era = Self::current_era();
let era = Self::active_era();
let unlocking_at = era + Self::bonding_duration();
let mut y = UnbondingBalanceMap::get();
y.entry(*who).or_insert(Default::default()).push((unlocking_at, amount));
Expand Down Expand Up @@ -161,9 +161,9 @@ impl sp_staking::StakingInterface for StakingMock {
let staker_map = unbonding_map.get_mut(&who).ok_or("Nothing to unbond")?;
let unlocking_before = unlocking(&staker_map);

let current_era = Self::current_era();
let active_era = Self::active_era();

staker_map.retain(|(unlocking_at, _amount)| *unlocking_at > current_era);
staker_map.retain(|(unlocking_at, _amount)| *unlocking_at > active_era);

// if there was a withdrawal, notify the pallet.
let withdraw_amount = unlocking_before.saturating_sub(unlocking(&staker_map));
Expand Down Expand Up @@ -231,7 +231,15 @@ impl sp_staking::StakingInterface for StakingMock {
}

#[cfg(feature = "runtime-benchmarks")]
fn set_current_era(_era: EraIndex) {
fn set_active_era(_era: EraIndex, _start: Option<u64>) {
unimplemented!("method currently not used in testing")
}

#[cfg(feature = "runtime-benchmarks")]
fn activate_next_era(
_era_duration_in_session: sp_staking::SessionIndex,
_era_duration_in_millis: u64,
) {
unimplemented!("method currently not used in testing")
}

Expand Down
Loading
Loading