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
3 changes: 1 addition & 2 deletions pallets/admin-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,8 +1383,7 @@ pub mod pallet {
///
/// # Arguments
/// * `origin` - The origin of the call, which must be the root account.
/// * `precompile_id` - The identifier of the EVM precompile to toggle.
/// * `enabled` - The new enablement state of the precompile.
/// * `alpha` - The new moving alpha value for the SubnetMovingAlpha.
///
/// # Errors
/// * `BadOrigin` - If the caller is not the root account.
Expand Down
25 changes: 25 additions & 0 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1882,5 +1882,30 @@ mod dispatches {
allow_partial,
)
}

/// Attempts to associate a hotkey with a coldkey.
///
/// # Arguments
/// * `origin` - The origin of the transaction, which must be signed by the coldkey that owns the `hotkey`.
/// * `hotkey` - The hotkey to associate with the coldkey.
///
/// # Note
/// Will charge based on the weight even if the hotkey is already associated with a coldkey.
#[pallet::call_index(91)]
#[pallet::weight((
Weight::from_parts(3_000_000, 0).saturating_add(T::DbWeight::get().reads_writes(3, 3)),
DispatchClass::Operational,
Pays::Yes
))]
pub fn try_associate_hotkey(
origin: T::RuntimeOrigin,
hotkey: T::AccountId,
) -> DispatchResult {
let coldkey = ensure_signed(origin)?;

let _ = Self::do_try_associate_hotkey(&coldkey, &hotkey);

Ok(())
}
}
}
13 changes: 13 additions & 0 deletions pallets/subtensor/src/staking/account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use super::*;

impl<T: Config> Pallet<T> {
pub fn do_try_associate_hotkey(
coldkey: &T::AccountId,
hotkey: &T::AccountId,
) -> DispatchResult {
// Ensure the hotkey is not already associated with a coldkey
Self::create_account_if_non_existent(coldkey, hotkey);

Ok(())
}
}
1 change: 1 addition & 0 deletions pallets/subtensor/src/staking/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
pub mod account;
pub mod add_stake;
pub mod decrease_take;
pub mod helpers;
Expand Down
66 changes: 66 additions & 0 deletions pallets/subtensor/src/tests/staking2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use super::mock::*;
use crate::*;
use frame_support::{
assert_ok,
dispatch::{GetDispatchInfo, Pays},
weights::Weight,
};
use sp_core::U256;
use substrate_fixed::types::I96F32;

Expand Down Expand Up @@ -557,3 +562,64 @@ fn test_share_based_staking_stake_inject_stake_new() {
});
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::staking2::test_try_associate_hotkey --exact --show-output --nocapture
#[test]
fn test_try_associate_hotkey() {
new_test_ext(1).execute_with(|| {
let hotkey1 = U256::from(1);
let coldkey1 = U256::from(2);
let coldkey2 = U256::from(3);

// Check initial association
assert!(!SubtensorModule::hotkey_account_exists(&hotkey1));

// Associate hotkey1 with coldkey1
assert_ok!(SubtensorModule::try_associate_hotkey(
RuntimeOrigin::signed(coldkey1),
hotkey1
));

// Check that hotkey1 is associated with coldkey1
assert!(SubtensorModule::hotkey_account_exists(&hotkey1));
assert_eq!(
SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey1),
coldkey1
);
assert_ne!(SubtensorModule::get_owned_hotkeys(&coldkey1).len(), 0);
assert!(SubtensorModule::get_owned_hotkeys(&coldkey1).contains(&hotkey1));

// Verify this tx requires a fee
let call =
RuntimeCall::SubtensorModule(crate::Call::try_associate_hotkey { hotkey: hotkey1 });
let dispatch_info = call.get_dispatch_info();
// Verify tx weight > 0
assert!(dispatch_info.weight.all_gte(Weight::from_all(0)));
// Verify pays Yes is set
assert_eq!(dispatch_info.pays_fee, Pays::Yes);

// Check that coldkey2 is not associated with any hotkey
assert!(!SubtensorModule::get_owned_hotkeys(&coldkey2).contains(&hotkey1));
assert_eq!(SubtensorModule::get_owned_hotkeys(&coldkey2).len(), 0);

// Try to associate hotkey1 with coldkey2
// Should have no effect because coldkey1 is already associated with hotkey1
assert_ok!(SubtensorModule::try_associate_hotkey(
RuntimeOrigin::signed(coldkey2),
hotkey1
));

// Check that hotkey1 is still associated with coldkey1
assert!(SubtensorModule::hotkey_account_exists(&hotkey1));
assert_eq!(
SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey1),
coldkey1
);
assert_ne!(SubtensorModule::get_owned_hotkeys(&coldkey1).len(), 0);
assert!(SubtensorModule::get_owned_hotkeys(&coldkey1).contains(&hotkey1));

// Check that coldkey2 is still not associated with any hotkey
assert!(!SubtensorModule::get_owned_hotkeys(&coldkey2).contains(&hotkey1));
assert_eq!(SubtensorModule::get_owned_hotkeys(&coldkey2).len(), 0);
});
}
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 243,
spec_version: 244,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading