Skip to content

Commit

Permalink
Merge branch 'manta' into release-v4.7.3-1
Browse files Browse the repository at this point in the history
  • Loading branch information
Dengjianping authored Feb 14, 2025
2 parents 128e880 + 67e9473 commit 9062df1
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 1 deletion.
1 change: 1 addition & 0 deletions pallets/pallet-lottery/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ impl pallet_parachain_staking::Config for Test {
type Currency = Balances;
type BlockAuthor = BlockAuthor;
type MonetaryGovernanceOrigin = EnsureRoot<AccountId>;
type RemoveCollatorOrigin = frame_system::EnsureRoot<AccountId>;
/// Minimum round length is 2 minutes (10 * 12 second block times)
type MinBlocksPerRound = ConstU32<10>;
/// Blocks per round
Expand Down
84 changes: 84 additions & 0 deletions pallets/parachain-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ pub mod pallet {
+ Inspect<Self::AccountId>;
/// The origin for monetary governance
type MonetaryGovernanceOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// The origin for removing collators
type RemoveCollatorOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// Minimum number of blocks per round
#[pallet::constant]
type MinBlocksPerRound: Get<u32>;
Expand Down Expand Up @@ -1399,6 +1401,88 @@ pub mod pallet {
frame_system::ensure_root(origin)?;
Self::delegation_execute_scheduled_request(candidate, delegator)
}

#[pallet::call_index(29)]
#[pallet::weight(<T as Config>::WeightInfo::go_offline())]
/// Temporarily leave the set of collator candidates without unbonding
pub fn force_go_offline_collators(
origin: OriginFor<T>,
candidates: Vec<T::AccountId>,
) -> DispatchResultWithPostInfo {
T::RemoveCollatorOrigin::ensure_origin(origin)?;

let mut collators = <CandidatePool<T>>::get();
for candidate in candidates {
let state = <CandidateInfo<T>>::get(&candidate).ok_or(Error::<T>::CandidateDNE)?;
// ensure!(
// state.delegation_count <= candidate_delegation_count,
// Error::<T>::TooLowCandidateDelegationCountToLeaveCandidates
// );
// state.can_leave::<T>()?;
let return_stake = |bond: Bond<T::AccountId, BalanceOf<T>>| -> DispatchResult {
// remove delegation from delegator state
let mut delegator =
DelegatorState::<T>::get(&bond.owner).ok_or(Error::<T>::InvalidState)?;

if let Some(remaining) = delegator.rm_delegation::<T>(&candidate) {
Self::delegation_remove_request_with_state(
&candidate,
&bond.owner,
&mut delegator,
);

if remaining.is_zero() {
// we do not remove the scheduled delegation requests from other collators
// since it is assumed that they were removed incrementally before only the
// last delegation was left.
<DelegatorState<T>>::remove(&bond.owner);
<T as Config>::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner);
} else {
<DelegatorState<T>>::insert(&bond.owner, delegator);
}
} else {
// TODO: review. we assume here that this delegator has no remaining staked
// balance, so we ensure the lock is cleared
<T as Config>::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner);
}
Ok(())
};
// total backing stake is at least the candidate self bond
let mut total_backing = state.bond;
// return all top delegations
let top_delegations =
<TopDelegations<T>>::take(&candidate).ok_or(Error::<T>::InvalidState)?;
for bond in top_delegations.delegations {
return_stake(bond)?;
}
total_backing = total_backing.saturating_add(top_delegations.total);
// return all bottom delegations
let bottom_delegations =
<BottomDelegations<T>>::take(&candidate).ok_or(Error::<T>::InvalidState)?;
for bond in bottom_delegations.delegations {
return_stake(bond)?;
}
total_backing = total_backing.saturating_add(bottom_delegations.total);
// return stake to collator
<T as Config>::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate);
<CandidateInfo<T>>::remove(&candidate);
<DelegationScheduledRequests<T>>::remove(&candidate);
<TopDelegations<T>>::remove(&candidate);
<BottomDelegations<T>>::remove(&candidate);
let new_total_staked = <Total<T>>::get().saturating_sub(total_backing);
<Total<T>>::put(new_total_staked);

collators.remove(&Bond::from_owner(candidate.clone()));

Self::deposit_event(Event::CandidateLeft {
ex_candidate: candidate,
unlocked_amount: total_backing,
new_total_amt_locked: new_total_staked,
});
}
<CandidatePool<T>>::put(collators);
Ok(().into())
}
}

impl<T: Config> Pallet<T> {
Expand Down
9 changes: 8 additions & 1 deletion pallets/parachain-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
};
use frame_support::{
construct_runtime, derive_impl, parameter_types,
traits::{Everything, LockIdentifier, OnFinalize, OnInitialize},
traits::{EitherOfDiverse, Everything, LockIdentifier, OnFinalize, OnInitialize},
};
use manta_primitives::types::BlockNumber;
use sp_core::H256;
Expand Down Expand Up @@ -125,10 +125,17 @@ parameter_types! {
pub const MinDelegatorStk: u128 = 5;
pub const MinDelegation: u128 = 3;
}

ord_parameter_types! {
pub const One: AccountId = 1;
}

impl Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type MonetaryGovernanceOrigin = frame_system::EnsureRoot<AccountId>;
type RemoveCollatorOrigin =
EitherOfDiverse<frame_system::EnsureRoot<AccountId>, EnsureSignedBy<One, AccountId>>;
type MinBlocksPerRound = MinBlocksPerRound;
type DefaultBlocksPerRound = DefaultBlocksPerRound;
type LeaveCandidatesDelay = LeaveCandidatesDelay;
Expand Down
25 changes: 25 additions & 0 deletions pallets/parachain-staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,31 @@ fn cannot_go_offline_if_already_offline() {
});
}

// Force go offline
#[test]
fn force_go_offline_event_emits_correctly() {
let collator = 1;
ExtBuilder::default()
.with_balances(vec![(collator, 20), (2, 40)])
.with_candidates(vec![(collator, 20), (2, 20)])
.build()
.execute_with(|| {
assert_ok!(ParachainStaking::schedule_leave_candidates(
RuntimeOrigin::signed(1),
100,
));
assert_ok!(ParachainStaking::force_go_offline_collators(
RuntimeOrigin::root(),
vec![collator]
));
assert_last_event!(MetaEvent::ParachainStaking(Event::CandidateLeft {
ex_candidate: collator,
unlocked_amount: 20,
new_total_amt_locked: 20,
}));
});
}

// GO ONLINE

#[test]
Expand Down
5 changes: 5 additions & 0 deletions runtime/calamari/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ impl Contains<RuntimeCall> for BaseFilter {
| pallet_parachain_staking::Call::schedule_candidate_bond_less{..}
| pallet_parachain_staking::Call::execute_candidate_bond_less{..}
| pallet_parachain_staking::Call::cancel_candidate_bond_less{..}
| pallet_parachain_staking::Call::force_go_offline_collators{..}
// Delegator extrinsics
| pallet_parachain_staking::Call::delegate{..}
| pallet_parachain_staking::Call::schedule_leave_delegators{..}
Expand Down Expand Up @@ -741,6 +742,10 @@ impl pallet_parachain_staking::Config for Runtime {
type Currency = Balances;
type BlockAuthor = AuthorInherent;
type MonetaryGovernanceOrigin = EnsureRoot<AccountId>;
type RemoveCollatorOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<AccountId, TechnicalCollective, 2, 3>,
>;
/// Minimum round length is 2 minutes (10 * 12 second block times)
type MinBlocksPerRound = ConstU32<10>;
/// Blocks per round
Expand Down
1 change: 1 addition & 0 deletions runtime/manta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ impl pallet_parachain_staking::Config for Runtime {
type Currency = Balances;
type BlockAuthor = AuthorInherent;
type MonetaryGovernanceOrigin = EnsureRoot<AccountId>;
type RemoveCollatorOrigin = EnsureRoot<AccountId>;
/// Minimum round length is 2 minutes (10 * 12 second block times)
type MinBlocksPerRound = ConstU32<10>;
/// Blocks per round
Expand Down

0 comments on commit 9062df1

Please sign in to comment.