Skip to content
Merged
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
4 changes: 4 additions & 0 deletions pallets/admin-utils/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ parameter_types! {
pub const InitialTaoWeight: u64 = u64::MAX/10; // 10% global weight.
pub const InitialEmaPriceHalvingPeriod: u64 = 201_600_u64; // 4 weeks
pub const DurationOfStartCall: u64 = 7 * 24 * 60 * 60 / 12; // 7 days
pub const InitialKeySwapOnSubnetCost: u64 = 10_000_000;
pub const HotkeySwapOnSubnetInterval: u64 = 7 * 24 * 60 * 60 / 12; // 7 days
}

impl pallet_subtensor::Config for Test {
Expand Down Expand Up @@ -209,6 +211,8 @@ impl pallet_subtensor::Config for Test {
type InitialTaoWeight = InitialTaoWeight;
type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod;
type DurationOfStartCall = DurationOfStartCall;
type KeySwapOnSubnetCost = InitialKeySwapOnSubnetCost;
type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval;
}

#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
Expand Down
7 changes: 6 additions & 1 deletion pallets/subtensor/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,12 @@ mod pallet_benchmarks {
Subtensor::<T>::add_balance_to_coldkey_account(&coldkey, cost);

#[extrinsic_call]
_(RawOrigin::Signed(coldkey.clone()), old.clone(), new.clone());
_(
RawOrigin::Signed(coldkey.clone()),
old.clone(),
new.clone(),
None,
);
}

#[benchmark]
Expand Down
13 changes: 13 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,19 @@ pub mod pallet {
OptionQuery,
>;

#[pallet::storage]
/// --- DMap ( netuid, coldkey ) --> blocknumber | last hotkey swap on network.
pub type LastHotkeySwapOnNetuid<T: Config> = StorageDoubleMap<
_,
Identity,
u16,
Blake2_128Concat,
T::AccountId,
u64,
ValueQuery,
DefaultZeroU64<T>,
>;

#[pallet::storage]
/// Ensures unique IDs for StakeJobs storage map
pub type NextStakeJobId<T> = StorageValue<_, u64, ValueQuery, DefaultZeroU64<T>>;
Expand Down
6 changes: 6 additions & 0 deletions pallets/subtensor/src/macros/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,5 +224,11 @@ mod config {
/// Block number after a new subnet accept the start call extrinsic.
#[pallet::constant]
type DurationOfStartCall: Get<u64>;
/// Cost of swapping a hotkey in a subnet.
#[pallet::constant]
type KeySwapOnSubnetCost: Get<u64>;
/// Block number for a coldkey swap the hotkey in specific subnet.
#[pallet::constant]
type HotkeySwapOnSubnetInterval: Get<u64>;
}
}
11 changes: 6 additions & 5 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -935,17 +935,18 @@ mod dispatches {
Self::do_burned_registration(origin, netuid, hotkey)
}

/// The extrinsic for user to change its hotkey
/// The extrinsic for user to change its hotkey in subnet or all subnets.
#[pallet::call_index(70)]
#[pallet::weight((Weight::from_parts(240_600_000, 0)
.saturating_add(T::DbWeight::get().reads(31))
.saturating_add(T::DbWeight::get().writes(23)), DispatchClass::Operational, Pays::No))]
#[pallet::weight((Weight::from_parts(285_900_000, 0)
.saturating_add(T::DbWeight::get().reads(47))
.saturating_add(T::DbWeight::get().writes(37)), DispatchClass::Operational, Pays::No))]
pub fn swap_hotkey(
origin: OriginFor<T>,
hotkey: T::AccountId,
new_hotkey: T::AccountId,
netuid: Option<u16>,
) -> DispatchResultWithPostInfo {
Self::do_swap_hotkey(origin, &hotkey, &new_hotkey)
Self::do_swap_hotkey(origin, &hotkey, &new_hotkey, netuid)
}

/// The extrinsic for user to change the coldkey associated with their account.
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 @@ -210,6 +210,8 @@ mod errors {
InvalidRecoveredPublicKey,
/// SubToken disabled now
SubtokenDisabled,
/// Too frequent hotkey swap on subnet
HotKeySwapOnSubnetIntervalNotPassed,
/// Zero max stake amount
ZeroMaxStakeAmount,
/// Invalid netuid duplication
Expand Down
12 changes: 12 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,5 +351,17 @@ mod events {
/// - **netuid**: The network identifier.
/// - **Enabled**: Is Commit-Reveal enabled.
CommitRevealEnabled(u16, bool),

/// the hotkey is swapped
HotkeySwappedOnSubnet {
/// the account ID of coldkey
coldkey: T::AccountId,
/// the account ID of old hotkey
old_hotkey: T::AccountId,
/// the account ID of new hotkey
new_hotkey: T::AccountId,
/// the subnet ID
netuid: u16,
},
}
}
44 changes: 43 additions & 1 deletion pallets/subtensor/src/macros/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ mod hooks {
// # Args:
// * 'n': (BlockNumberFor<T>):
// - The number of the block we are initializing.
fn on_initialize(_block_number: BlockNumberFor<T>) -> Weight {
fn on_initialize(block_number: BlockNumberFor<T>) -> Weight {
let hotkey_swap_clean_up_weight = Self::clean_up_hotkey_swap_records(block_number);

let block_step_result = Self::block_step();
match block_step_result {
Ok(_) => {
Expand All @@ -23,13 +25,15 @@ mod hooks {
Weight::from_parts(110_634_229_000_u64, 0)
.saturating_add(T::DbWeight::get().reads(8304_u64))
.saturating_add(T::DbWeight::get().writes(110_u64))
.saturating_add(hotkey_swap_clean_up_weight)
}
Err(e) => {
// --- If the block step was unsuccessful, return the weight anyway.
log::error!("Error while stepping block: {:?}", e);
Weight::from_parts(110_634_229_000_u64, 0)
.saturating_add(T::DbWeight::get().reads(8304_u64))
.saturating_add(T::DbWeight::get().writes(110_u64))
.saturating_add(hotkey_swap_clean_up_weight)
}
}
}
Expand Down Expand Up @@ -127,4 +131,42 @@ mod hooks {
Ok(())
}
}

impl<T: Config> Pallet<T> {
// This function is to clean up the old hotkey swap records
// It just clean up for one subnet at a time, according to the block number
fn clean_up_hotkey_swap_records(block_number: BlockNumberFor<T>) -> Weight {
let mut weight = Weight::from_parts(0, 0);
let hotkey_swap_on_subnet_interval = T::HotkeySwapOnSubnetInterval::get();
let block_number: u64 = TryInto::try_into(block_number)
.ok()
.expect("blockchain will not exceed 2^64 blocks; QED.");
weight.saturating_accrue(T::DbWeight::get().reads(2_u64));

let netuids = Self::get_all_subnet_netuids();
weight.saturating_accrue(T::DbWeight::get().reads(netuids.len() as u64));

if let Some(slot) = block_number.checked_rem(hotkey_swap_on_subnet_interval) {
// only handle the subnet with the same residue as current block number by HotkeySwapOnSubnetInterval
for netuid in netuids.iter().filter(|netuid| {
(**netuid as u64).checked_rem(hotkey_swap_on_subnet_interval) == Some(slot)
}) {
// Iterate over all the coldkeys in the subnet
for (coldkey, swap_block_number) in
LastHotkeySwapOnNetuid::<T>::iter_prefix(netuid)
{
// Clean up out of date swap records
if swap_block_number.saturating_add(hotkey_swap_on_subnet_interval)
< block_number
{
LastHotkeySwapOnNetuid::<T>::remove(netuid, coldkey);
weight.saturating_accrue(T::DbWeight::get().writes(1_u64));
}
weight.saturating_accrue(T::DbWeight::get().reads(1_u64));
}
}
}
weight
}
}
}
6 changes: 6 additions & 0 deletions pallets/subtensor/src/subnets/uids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,10 @@ impl<T: Config> Pallet<T> {
}
false
}

/// Return true if a hotkey is registered on specific network.
///
pub fn is_hotkey_registered_on_specific_network(hotkey: &T::AccountId, netuid: u16) -> bool {
IsNetworkMember::<T>::contains_key(hotkey, netuid)
}
}
Loading
Loading