Skip to content

Commit 0efeaf3

Browse files
Merge pull request #620 from opentensor/arbitrage_coldkeys
Schedule Coldkey Swap
2 parents 2a48be8 + 9de2afb commit 0efeaf3

File tree

20 files changed

+2767
-475
lines changed

20 files changed

+2767
-475
lines changed

node/src/rpc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ where
6060
C::Api: subtensor_custom_rpc_runtime_api::NeuronInfoRuntimeApi<Block>,
6161
C::Api: subtensor_custom_rpc_runtime_api::SubnetInfoRuntimeApi<Block>,
6262
C::Api: subtensor_custom_rpc_runtime_api::SubnetRegistrationRuntimeApi<Block>,
63+
C::Api: subtensor_custom_rpc_runtime_api::ColdkeySwapRuntimeApi<Block>,
6364
B: sc_client_api::Backend<Block> + Send + Sync + 'static,
6465
P: TransactionPool + 'static,
6566
{

pallets/admin-utils/tests/mock.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ parameter_types! {
114114
pub const InitialAlphaHigh: u16 = 58982; // Represents 0.9 as per the production default
115115
pub const InitialAlphaLow: u16 = 45875; // Represents 0.7 as per the production default
116116
pub const InitialLiquidAlphaOn: bool = false; // Default value for LiquidAlphaOn
117+
pub const InitialBaseDifficulty: u64 = 10_000; // Base difficulty
117118
}
118119

119120
impl pallet_subtensor::Config for Test {
@@ -169,6 +170,7 @@ impl pallet_subtensor::Config for Test {
169170
type AlphaHigh = InitialAlphaHigh;
170171
type AlphaLow = InitialAlphaLow;
171172
type LiquidAlphaOn = InitialLiquidAlphaOn;
173+
type InitialBaseDifficulty = InitialBaseDifficulty;
172174
}
173175

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

pallets/subtensor/rpc/src/lib.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::sync::Arc;
1212
use sp_api::ProvideRuntimeApi;
1313

1414
pub use subtensor_custom_rpc_runtime_api::{
15-
DelegateInfoRuntimeApi, NeuronInfoRuntimeApi, SubnetInfoRuntimeApi,
15+
ColdkeySwapRuntimeApi, DelegateInfoRuntimeApi, NeuronInfoRuntimeApi, SubnetInfoRuntimeApi,
1616
SubnetRegistrationRuntimeApi,
1717
};
1818

@@ -51,6 +51,24 @@ pub trait SubtensorCustomApi<BlockHash> {
5151

5252
#[method(name = "subnetInfo_getLockCost")]
5353
fn get_network_lock_cost(&self, at: Option<BlockHash>) -> RpcResult<u64>;
54+
#[method(name = "coldkeySwap_getScheduledColdkeySwap")]
55+
fn get_scheduled_coldkey_swap(
56+
&self,
57+
coldkey_account_vec: Vec<u8>,
58+
at: Option<BlockHash>,
59+
) -> RpcResult<Vec<u8>>;
60+
#[method(name = "coldkeySwap_getRemainingArbitrationPeriod")]
61+
fn get_remaining_arbitration_period(
62+
&self,
63+
coldkey_account_vec: Vec<u8>,
64+
at: Option<BlockHash>,
65+
) -> RpcResult<Vec<u8>>;
66+
#[method(name = "coldkeySwap_getColdkeySwapDestinations")]
67+
fn get_coldkey_swap_destinations(
68+
&self,
69+
coldkey_account_vec: Vec<u8>,
70+
at: Option<BlockHash>,
71+
) -> RpcResult<Vec<u8>>;
5472
}
5573

5674
pub struct SubtensorCustom<C, P> {
@@ -99,6 +117,7 @@ where
99117
C::Api: NeuronInfoRuntimeApi<Block>,
100118
C::Api: SubnetInfoRuntimeApi<Block>,
101119
C::Api: SubnetRegistrationRuntimeApi<Block>,
120+
C::Api: ColdkeySwapRuntimeApi<Block>,
102121
{
103122
fn get_delegates(&self, at: Option<<Block as BlockT>::Hash>) -> RpcResult<Vec<u8>> {
104123
let api = self.client.runtime_api();
@@ -223,4 +242,51 @@ where
223242
Error::RuntimeError(format!("Unable to get subnet lock cost: {:?}", e)).into()
224243
})
225244
}
245+
246+
fn get_scheduled_coldkey_swap(
247+
&self,
248+
coldkey_account_vec: Vec<u8>,
249+
at: Option<<Block as BlockT>::Hash>,
250+
) -> RpcResult<Vec<u8>> {
251+
let api = self.client.runtime_api();
252+
let at = at.unwrap_or_else(|| self.client.info().best_hash);
253+
254+
api.get_scheduled_coldkey_swap(at, coldkey_account_vec)
255+
.map_err(|e| {
256+
Error::RuntimeError(format!("Unable to get scheduled coldkey swap: {:?}", e)).into()
257+
})
258+
}
259+
260+
fn get_remaining_arbitration_period(
261+
&self,
262+
coldkey_account_vec: Vec<u8>,
263+
at: Option<<Block as BlockT>::Hash>,
264+
) -> RpcResult<Vec<u8>> {
265+
let api = self.client.runtime_api();
266+
let at = at.unwrap_or_else(|| self.client.info().best_hash);
267+
268+
api.get_remaining_arbitration_period(at, coldkey_account_vec)
269+
.map_err(|e| {
270+
Error::RuntimeError(format!(
271+
"Unable to get remaining arbitration period: {:?}",
272+
e
273+
))
274+
.into()
275+
})
276+
}
277+
278+
fn get_coldkey_swap_destinations(
279+
&self,
280+
coldkey_account_vec: Vec<u8>,
281+
at: Option<<Block as BlockT>::Hash>,
282+
) -> RpcResult<Vec<u8>> {
283+
let api = self.client.runtime_api();
284+
let at = at.unwrap_or_else(|| self.client.info().best_hash);
285+
286+
api.get_coldkey_swap_destinations(at, coldkey_account_vec)
287+
.map_err(|e| {
288+
Error::RuntimeError(format!("Unable to get coldkey swap destinations: {:?}", e))
289+
.into()
290+
})
291+
}
226292
}

pallets/subtensor/runtime-api/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ sp_api::decl_runtime_apis! {
3232
pub trait SubnetRegistrationRuntimeApi {
3333
fn get_network_registration_cost() -> u64;
3434
}
35+
36+
pub trait ColdkeySwapRuntimeApi {
37+
fn get_scheduled_coldkey_swap( coldkey_account_vec: Vec<u8> ) -> Vec<u8>;
38+
fn get_remaining_arbitration_period( coldkey_account_vec: Vec<u8> ) -> Vec<u8>;
39+
fn get_coldkey_swap_destinations( coldkey_account_vec: Vec<u8> ) -> Vec<u8>;
40+
}
3541
}

pallets/subtensor/src/benchmarks.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,31 @@ reveal_weights {
428428
let _ = Subtensor::<T>::commit_weights(<T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(hotkey.clone())), netuid, commit_hash);
429429

430430
}: reveal_weights(RawOrigin::Signed(hotkey.clone()), netuid, uids, weight_values, salt, version_key)
431+
432+
schedule_coldkey_swap {
433+
let seed: u32 = 1;
434+
let old_coldkey: T::AccountId = account("OldColdkey", 0, seed);
435+
let new_coldkey: T::AccountId = account("NewColdkey", 0, seed + 1);
436+
let hotkey: T::AccountId = account("Hotkey", 0, seed);
437+
438+
let netuid = 1u16;
439+
let tempo = 1u16;
440+
let block_number: u64 = Subtensor::<T>::get_current_block_as_u64();
441+
let nonce = 0;
442+
443+
// Initialize the network
444+
Subtensor::<T>::init_new_network(netuid, tempo);
445+
Subtensor::<T>::set_network_registration_allowed(netuid, true);
446+
447+
// Add balance to the old coldkey account
448+
let amount_to_be_staked: u64 = 1000000u32.into();
449+
Subtensor::<T>::add_balance_to_coldkey_account(&old_coldkey.clone(), amount_to_be_staked+1000000000);
450+
// Burned register the hotkey with the old coldkey
451+
assert_ok!(Subtensor::<T>::burned_register(
452+
RawOrigin::Signed(old_coldkey.clone()).into(),
453+
netuid,
454+
hotkey.clone()
455+
));
456+
457+
}: schedule_coldkey_swap(RawOrigin::Signed(old_coldkey.clone()), new_coldkey.clone(), vec![], block_number, nonce)
431458
}

pallets/subtensor/src/delegate_info.rs

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,19 @@ impl<T: Config> Pallet<T> {
4141
let mut emissions_per_day: U64F64 = U64F64::from_num(0);
4242

4343
for netuid in registrations.iter() {
44-
let _uid = Self::get_uid_for_net_and_hotkey(*netuid, &delegate.clone());
45-
if _uid.is_err() {
46-
continue; // this should never happen
47-
} else {
48-
let uid = _uid.expect("Delegate's UID should be ok");
44+
if let Ok(uid) = Self::get_uid_for_net_and_hotkey(*netuid, &delegate.clone()) {
4945
let validator_permit = Self::get_validator_permit_for_uid(*netuid, uid);
5046
if validator_permit {
5147
validator_permits.push((*netuid).into());
5248
}
5349

5450
let emission: U64F64 = Self::get_emission_for_uid(*netuid, uid).into();
5551
let tempo: U64F64 = Self::get_tempo(*netuid).into();
56-
let epochs_per_day: U64F64 = U64F64::from_num(7200).saturating_div(tempo);
57-
emissions_per_day =
58-
emissions_per_day.saturating_add(emission.saturating_mul(epochs_per_day));
52+
if tempo > U64F64::from_num(0) {
53+
let epochs_per_day: U64F64 = U64F64::from_num(7200).saturating_div(tempo);
54+
emissions_per_day =
55+
emissions_per_day.saturating_add(emission.saturating_mul(epochs_per_day));
56+
}
5957
}
6058
}
6159

@@ -64,15 +62,15 @@ impl<T: Config> Pallet<T> {
6462

6563
let total_stake: U64F64 = Self::get_total_stake_for_hotkey(&delegate.clone()).into();
6664

67-
let mut return_per_1000: U64F64 = U64F64::from_num(0);
68-
69-
if total_stake > U64F64::from_num(0) {
70-
return_per_1000 = emissions_per_day
65+
let return_per_1000: U64F64 = if total_stake > U64F64::from_num(0) {
66+
emissions_per_day
7167
.saturating_mul(U64F64::from_num(0.82))
72-
.saturating_div(total_stake.saturating_div(U64F64::from_num(1000)));
73-
}
68+
.saturating_div(total_stake.saturating_div(U64F64::from_num(1000)))
69+
} else {
70+
U64F64::from_num(0)
71+
};
7472

75-
return DelegateInfo {
73+
DelegateInfo {
7674
delegate_ss58: delegate.clone(),
7775
take,
7876
nominators,
@@ -81,7 +79,7 @@ impl<T: Config> Pallet<T> {
8179
validator_permits,
8280
return_per_1000: U64F64::to_num::<u64>(return_per_1000).into(),
8381
total_daily_return: U64F64::to_num::<u64>(emissions_per_day).into(),
84-
};
82+
}
8583
}
8684

8785
pub fn get_delegate(delegate_account_vec: Vec<u8>) -> Option<DelegateInfo<T>> {
@@ -133,4 +131,47 @@ impl<T: Config> Pallet<T> {
133131

134132
delegates
135133
}
134+
135+
pub fn get_total_delegated_stake(coldkey: &T::AccountId) -> u64 {
136+
let mut total_delegated = 0u64;
137+
138+
// Get all hotkeys associated with this coldkey
139+
let hotkeys = StakingHotkeys::<T>::get(coldkey);
140+
141+
for hotkey in hotkeys {
142+
let owner = Owner::<T>::get(&hotkey);
143+
144+
for (delegator, stake) in Stake::<T>::iter_prefix(&hotkey) {
145+
if delegator != owner {
146+
total_delegated = total_delegated.saturating_add(stake);
147+
}
148+
}
149+
}
150+
151+
log::info!(
152+
"Total delegated stake for coldkey {:?}: {}",
153+
coldkey,
154+
total_delegated
155+
);
156+
total_delegated
157+
}
158+
159+
// Helper function to get total delegated stake for a hotkey
160+
pub fn get_total_hotkey_delegated_stake(hotkey: &T::AccountId) -> u64 {
161+
let mut total_delegated = 0u64;
162+
163+
// Iterate through all delegators for this hotkey
164+
for (delegator, stake) in Stake::<T>::iter_prefix(hotkey) {
165+
if delegator != Self::get_coldkey_for_hotkey(hotkey) {
166+
total_delegated = total_delegated.saturating_add(stake);
167+
}
168+
}
169+
170+
total_delegated
171+
}
172+
173+
// Helper function to get the coldkey associated with a hotkey
174+
pub fn get_coldkey_for_hotkey(hotkey: &T::AccountId) -> T::AccountId {
175+
Owner::<T>::get(hotkey)
176+
}
136177
}

pallets/subtensor/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,15 @@ mod errors {
146146
NoBalanceToTransfer,
147147
/// Same coldkey
148148
SameColdkey,
149+
/// The coldkey is in arbitration
150+
ColdkeyIsInArbitration,
151+
/// The new coldkey is already registered for the drain
152+
DuplicateColdkey,
153+
/// Error thrown on a coldkey swap.
154+
ColdkeySwapError,
155+
/// Insufficient Balance to Schedule coldkey swap
156+
InsufficientBalanceToPerformColdkeySwap,
157+
/// The maximum number of coldkey destinations has been reached
158+
MaxColdkeyDestinationsReached,
149159
}
150160
}

pallets/subtensor/src/events.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,19 @@ mod events {
150150
<T as frame_system::Config>::AccountId,
151151
>>::Balance,
152152
},
153+
/// A coldkey swap has been scheduled
154+
ColdkeySwapScheduled {
155+
/// The account ID of the old coldkey
156+
old_coldkey: T::AccountId,
157+
/// The account ID of the new coldkey
158+
new_coldkey: T::AccountId,
159+
/// The arbitration block for the coldkey swap
160+
arbitration_block: u64,
161+
},
162+
/// The arbitration period has been extended
163+
ArbitrationPeriodExtended {
164+
/// The account ID of the coldkey
165+
coldkey: T::AccountId,
166+
},
153167
}
154168
}

0 commit comments

Comments
 (0)