Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 7 additions & 2 deletions pallets/subtensor/src/coinbase/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ impl<T: Config> Pallet<T> {

// --- 5. Remove various network-related storages.
NetworkRegisteredAt::<T>::remove(netuid);
let _ = Self::remove_subnet_from_deregistration_priority_queue(netuid);

// --- 6. Remove incentive mechanism memory.
let _ = Uids::<T>::clear_prefix(netuid, u32::MAX, None);
Expand Down Expand Up @@ -592,6 +593,10 @@ impl<T: Config> Pallet<T> {
pub fn get_network_to_prune() -> Option<NetUid> {
let current_block: u64 = Self::get_current_block_as_u64();

if let Some(priority_netuid) = Self::pop_ready_subnet_deregistration_priority() {
return Some(priority_netuid);
}

let mut candidate_netuid: Option<NetUid> = None;
let mut candidate_price: U96F32 = U96F32::saturating_from_num(u128::MAX);
let mut candidate_timestamp: u64 = u64::MAX;
Expand All @@ -610,8 +615,8 @@ impl<T: Config> Pallet<T> {

let price: U96F32 = Self::get_moving_alpha_price(netuid);

// If tie on price, earliest registration wins.
if price < candidate_price
if candidate_netuid.is_none()
|| price < candidate_price
|| (price == candidate_price && registered_at < candidate_timestamp)
{
candidate_netuid = Some(netuid);
Expand Down
15 changes: 15 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1605,11 +1605,26 @@ pub mod pallet {
pub type NetworkRegisteredAt<T: Config> =
StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultNetworkRegisteredAt<T>>;

/// --- FIFO queue of netuids pending deregistration
#[pallet::storage]
pub type SubnetDeregistrationPriorityQueue<T: Config> =
StorageValue<_, sp_std::vec::Vec<NetUid>, ValueQuery>;

/// --- MAP ( netuid ) --> scheduled block for enqueuing deregistration priority
#[pallet::storage]
pub type SubnetDeregistrationPrioritySchedule<T: Config> =
StorageMap<_, Identity, NetUid, BlockNumberFor<T>, OptionQuery>;

/// --- MAP ( netuid ) --> pending_server_emission
#[pallet::storage]
pub type PendingServerEmission<T> =
StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha<T>>;

/// --- MAP ( netuid ) --> pending_emission
#[pallet::storage]
pub type PendingEmission<T> =
StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultPendingEmission<T>>;

/// --- MAP ( netuid ) --> pending_validator_emission
#[pallet::storage]
pub type PendingValidatorEmission<T> =
Expand Down
110 changes: 110 additions & 0 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,7 @@ mod dispatches {
.map_err(|_| Error::<T>::FailedToSchedule)?;

ColdkeySwapScheduled::<T>::insert(&who, (when, new_coldkey.clone()));
Self::cancel_deregistration_priority_schedule_for_owner(&who);
// Emit the SwapScheduled event
Self::deposit_event(Event::ColdkeySwapScheduled {
old_coldkey: who.clone(),
Expand Down Expand Up @@ -2152,6 +2153,115 @@ mod dispatches {
Ok(())
}

/// Manages the deregistration priority queue for a subnet.
///
/// When `schedule_set` is `true`, the subnet is scheduled to be appended to the
/// deregistration queue after approximately five days using the scheduler pallet.
/// When `schedule_set` is `false`, any pending schedule is cleared. Only the root origin
/// may remove the subnet from the queue itself.
///
/// Accessible by the subnet owner (for scheduling or canceling a pending schedule) or root
/// origin (full control).
///
/// # Errors
/// * [`Error::SubnetNotExists`] if the subnet does not exist.
/// * [`Error::SubnetDeregistrationPriorityAlreadyScheduled`] if a set operation is already
/// scheduled.
#[pallet::call_index(125)]
#[pallet::weight((
Weight::from_parts(40_000_000, 0)
.saturating_add(T::DbWeight::get().reads_writes(4, 2)),
DispatchClass::Normal,
Pays::Yes
))]
pub fn manage_deregistration_priority(
origin: OriginFor<T>,
netuid: NetUid,
schedule_set: bool,
) -> DispatchResult {
ensure!(Self::if_subnet_exist(netuid), Error::<T>::SubnetNotExists);
let maybe_owner = Self::ensure_subnet_owner_or_root(origin, netuid)?;

if schedule_set {
ensure!(
SubnetDeregistrationPrioritySchedule::<T>::get(netuid).is_none(),
Error::<T>::SubnetDeregistrationPriorityAlreadyScheduled
);

let current_block: BlockNumberFor<T> = <frame_system::Pallet<T>>::block_number();
let delay: BlockNumberFor<T> = ColdkeySwapScheduleDuration::<T>::get();
let when: BlockNumberFor<T> = current_block.saturating_add(delay);

let call = Call::<T>::force_set_deregistration_priority { netuid };
let bound_call = <T as Config>::Preimages::bound(LocalCallOf::<T>::from(call))
.map_err(|_| Error::<T>::FailedToSchedule)?;

T::Scheduler::schedule(
DispatchTime::At(when),
None,
63,
frame_system::RawOrigin::Root.into(),
bound_call,
)
.map_err(|_| Error::<T>::FailedToSchedule)?;

SubnetDeregistrationPrioritySchedule::<T>::insert(netuid, when);

Self::deposit_event(Event::SubnetDeregistrationPriorityScheduled(netuid, when));
} else {
if maybe_owner.is_some() {
if SubnetDeregistrationPrioritySchedule::<T>::take(netuid).is_some() {
Self::deposit_event(Event::SubnetDeregistrationPriorityScheduleCleared(
netuid,
));
}
} else {
let was_queued = Self::remove_subnet_from_deregistration_priority_queue(netuid);
let had_schedule =
SubnetDeregistrationPrioritySchedule::<T>::take(netuid).is_some();

if was_queued {
Self::deposit_event(Event::SubnetDeregistrationPriorityCleared(netuid));
}
if had_schedule {
Self::deposit_event(Event::SubnetDeregistrationPriorityScheduleCleared(
netuid,
));
}
}
}

Ok(())
}

/// Enqueues the subnet for deregistration immediately.
///
/// This call is intended to be used by the scheduler and requires root origin.
#[pallet::call_index(126)]
#[pallet::weight((
Weight::from_parts(15_000_000, 0)
.saturating_add(T::DbWeight::get().reads_writes(3, 2)),
DispatchClass::Operational,
Pays::No
))]
pub fn force_set_deregistration_priority(
origin: OriginFor<T>,
netuid: NetUid,
) -> DispatchResult {
ensure_root(origin)?;
ensure!(Self::if_subnet_exist(netuid), Error::<T>::SubnetNotExists);

if SubnetDeregistrationPrioritySchedule::<T>::take(netuid).is_none() {
// Schedule was clear already, nothing to do.
return Ok(());
}

let _ = Self::enqueue_subnet_deregistration_priority(netuid);
Self::deposit_event(Event::SubnetDeregistrationPrioritySet(netuid));

Ok(())
}

/// ---- Used to commit timelock encrypted commit-reveal weight values to later be revealed.
///
/// # Args:
Expand Down
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ mod errors {
TxRateLimitExceeded,
/// Swap already scheduled.
SwapAlreadyScheduled,
/// Deregistration priority already scheduled.
SubnetDeregistrationPriorityAlreadyScheduled,
/// failed to swap coldkey
FailedToSchedule,
/// New coldkey is hotkey
Expand Down
8 changes: 8 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ mod events {
NetworkAdded(NetUid, u16),
/// a network is removed.
NetworkRemoved(NetUid),
/// a subnet's deregistration queue entry was scheduled.
SubnetDeregistrationPriorityScheduled(NetUid, BlockNumberFor<T>),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SubnetDeregistrationPriorityScheduled(NetUid, BlockNumberFor<T>),
SubnetDeregistrationPriorityScheduled(NetUid, BlockNumberForEnqueueing<T>),

I'd be more explicit on the arg name as you cannot quickly infer from the context what this block number is for exactly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a type, not an argument name

/// a subnet was enqueued for deregistration.
SubnetDeregistrationPrioritySet(NetUid),
/// network deregistration queue entry cleared or canceled.
SubnetDeregistrationPriorityCleared(NetUid),
/// pending deregistration schedule cleared or canceled.
SubnetDeregistrationPriorityScheduleCleared(NetUid),
/// stake has been transferred from the a coldkey account onto the hotkey staking account.
StakeAdded(
T::AccountId,
Expand Down
Loading
Loading