Skip to content

Commit 548f984

Browse files
authored
Merge pull request #1559 from opentensor/hotkey-splitting
Hotkey splitting
2 parents 4234b95 + ff01f9e commit 548f984

File tree

15 files changed

+2145
-395
lines changed

15 files changed

+2145
-395
lines changed

pallets/admin-utils/src/tests/mock.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ parameter_types! {
140140
pub const InitialTaoWeight: u64 = u64::MAX/10; // 10% global weight.
141141
pub const InitialEmaPriceHalvingPeriod: u64 = 201_600_u64; // 4 weeks
142142
pub const DurationOfStartCall: u64 = 7 * 24 * 60 * 60 / 12; // 7 days
143+
pub const InitialKeySwapOnSubnetCost: u64 = 10_000_000;
144+
pub const HotkeySwapOnSubnetInterval: u64 = 7 * 24 * 60 * 60 / 12; // 7 days
143145
}
144146

145147
impl pallet_subtensor::Config for Test {
@@ -209,6 +211,8 @@ impl pallet_subtensor::Config for Test {
209211
type InitialTaoWeight = InitialTaoWeight;
210212
type InitialEmaPriceHalvingPeriod = InitialEmaPriceHalvingPeriod;
211213
type DurationOfStartCall = DurationOfStartCall;
214+
type KeySwapOnSubnetCost = InitialKeySwapOnSubnetCost;
215+
type HotkeySwapOnSubnetInterval = HotkeySwapOnSubnetInterval;
212216
}
213217

214218
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]

pallets/subtensor/src/benchmarks.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,12 @@ mod pallet_benchmarks {
14541454
Subtensor::<T>::add_balance_to_coldkey_account(&coldkey, cost);
14551455

14561456
#[extrinsic_call]
1457-
_(RawOrigin::Signed(coldkey.clone()), old.clone(), new.clone());
1457+
_(
1458+
RawOrigin::Signed(coldkey.clone()),
1459+
old.clone(),
1460+
new.clone(),
1461+
None,
1462+
);
14581463
}
14591464

14601465
#[benchmark]

pallets/subtensor/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,19 @@ pub mod pallet {
940940
OptionQuery,
941941
>;
942942

943+
#[pallet::storage]
944+
/// --- DMap ( netuid, coldkey ) --> blocknumber | last hotkey swap on network.
945+
pub type LastHotkeySwapOnNetuid<T: Config> = StorageDoubleMap<
946+
_,
947+
Identity,
948+
u16,
949+
Blake2_128Concat,
950+
T::AccountId,
951+
u64,
952+
ValueQuery,
953+
DefaultZeroU64<T>,
954+
>;
955+
943956
#[pallet::storage]
944957
/// Ensures unique IDs for StakeJobs storage map
945958
pub type NextStakeJobId<T> = StorageValue<_, u64, ValueQuery, DefaultZeroU64<T>>;

pallets/subtensor/src/macros/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,11 @@ mod config {
224224
/// Block number after a new subnet accept the start call extrinsic.
225225
#[pallet::constant]
226226
type DurationOfStartCall: Get<u64>;
227+
/// Cost of swapping a hotkey in a subnet.
228+
#[pallet::constant]
229+
type KeySwapOnSubnetCost: Get<u64>;
230+
/// Block number for a coldkey swap the hotkey in specific subnet.
231+
#[pallet::constant]
232+
type HotkeySwapOnSubnetInterval: Get<u64>;
227233
}
228234
}

pallets/subtensor/src/macros/dispatches.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -935,17 +935,18 @@ mod dispatches {
935935
Self::do_burned_registration(origin, netuid, hotkey)
936936
}
937937

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

951952
/// The extrinsic for user to change the coldkey associated with their account.

pallets/subtensor/src/macros/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ mod errors {
210210
InvalidRecoveredPublicKey,
211211
/// SubToken disabled now
212212
SubtokenDisabled,
213+
/// Too frequent hotkey swap on subnet
214+
HotKeySwapOnSubnetIntervalNotPassed,
213215
/// Zero max stake amount
214216
ZeroMaxStakeAmount,
215217
/// Invalid netuid duplication

pallets/subtensor/src/macros/events.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,5 +351,17 @@ mod events {
351351
/// - **netuid**: The network identifier.
352352
/// - **Enabled**: Is Commit-Reveal enabled.
353353
CommitRevealEnabled(u16, bool),
354+
355+
/// the hotkey is swapped
356+
HotkeySwappedOnSubnet {
357+
/// the account ID of coldkey
358+
coldkey: T::AccountId,
359+
/// the account ID of old hotkey
360+
old_hotkey: T::AccountId,
361+
/// the account ID of new hotkey
362+
new_hotkey: T::AccountId,
363+
/// the subnet ID
364+
netuid: u16,
365+
},
354366
}
355367
}

pallets/subtensor/src/macros/hooks.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ mod hooks {
1414
// # Args:
1515
// * 'n': (BlockNumberFor<T>):
1616
// - The number of the block we are initializing.
17-
fn on_initialize(_block_number: BlockNumberFor<T>) -> Weight {
17+
fn on_initialize(block_number: BlockNumberFor<T>) -> Weight {
18+
let hotkey_swap_clean_up_weight = Self::clean_up_hotkey_swap_records(block_number);
19+
1820
let block_step_result = Self::block_step();
1921
match block_step_result {
2022
Ok(_) => {
@@ -23,13 +25,15 @@ mod hooks {
2325
Weight::from_parts(110_634_229_000_u64, 0)
2426
.saturating_add(T::DbWeight::get().reads(8304_u64))
2527
.saturating_add(T::DbWeight::get().writes(110_u64))
28+
.saturating_add(hotkey_swap_clean_up_weight)
2629
}
2730
Err(e) => {
2831
// --- If the block step was unsuccessful, return the weight anyway.
2932
log::error!("Error while stepping block: {:?}", e);
3033
Weight::from_parts(110_634_229_000_u64, 0)
3134
.saturating_add(T::DbWeight::get().reads(8304_u64))
3235
.saturating_add(T::DbWeight::get().writes(110_u64))
36+
.saturating_add(hotkey_swap_clean_up_weight)
3337
}
3438
}
3539
}
@@ -125,4 +129,42 @@ mod hooks {
125129
Ok(())
126130
}
127131
}
132+
133+
impl<T: Config> Pallet<T> {
134+
// This function is to clean up the old hotkey swap records
135+
// It just clean up for one subnet at a time, according to the block number
136+
fn clean_up_hotkey_swap_records(block_number: BlockNumberFor<T>) -> Weight {
137+
let mut weight = Weight::from_parts(0, 0);
138+
let hotkey_swap_on_subnet_interval = T::HotkeySwapOnSubnetInterval::get();
139+
let block_number: u64 = TryInto::try_into(block_number)
140+
.ok()
141+
.expect("blockchain will not exceed 2^64 blocks; QED.");
142+
weight.saturating_accrue(T::DbWeight::get().reads(2_u64));
143+
144+
let netuids = Self::get_all_subnet_netuids();
145+
weight.saturating_accrue(T::DbWeight::get().reads(netuids.len() as u64));
146+
147+
if let Some(slot) = block_number.checked_rem(hotkey_swap_on_subnet_interval) {
148+
// only handle the subnet with the same residue as current block number by HotkeySwapOnSubnetInterval
149+
for netuid in netuids.iter().filter(|netuid| {
150+
(**netuid as u64).checked_rem(hotkey_swap_on_subnet_interval) == Some(slot)
151+
}) {
152+
// Iterate over all the coldkeys in the subnet
153+
for (coldkey, swap_block_number) in
154+
LastHotkeySwapOnNetuid::<T>::iter_prefix(netuid)
155+
{
156+
// Clean up out of date swap records
157+
if swap_block_number.saturating_add(hotkey_swap_on_subnet_interval)
158+
< block_number
159+
{
160+
LastHotkeySwapOnNetuid::<T>::remove(netuid, coldkey);
161+
weight.saturating_accrue(T::DbWeight::get().writes(1_u64));
162+
}
163+
weight.saturating_accrue(T::DbWeight::get().reads(1_u64));
164+
}
165+
}
166+
}
167+
weight
168+
}
169+
}
128170
}

pallets/subtensor/src/subnets/uids.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,10 @@ impl<T: Config> Pallet<T> {
187187
}
188188
false
189189
}
190+
191+
/// Return true if a hotkey is registered on specific network.
192+
///
193+
pub fn is_hotkey_registered_on_specific_network(hotkey: &T::AccountId, netuid: u16) -> bool {
194+
IsNetworkMember::<T>::contains_key(hotkey, netuid)
195+
}
190196
}

0 commit comments

Comments
 (0)