11use super :: * ;
2- use frame_support:: weights:: Weight ;
3- use sp_core:: Get ;
42use substrate_fixed:: types:: U64F64 ;
53
64impl < T : Config > Pallet < T > {
7- /// Swaps the coldkey associated with a set of hotkeys from an old coldkey to a new coldkey.
8- ///
9- /// # Arguments
10- ///
11- /// * `origin` - The origin of the call, which must be signed by the old coldkey.
12- /// * `new_coldkey` - The account ID of the new coldkey.
13- ///
14- /// # Returns
15- ///
16- /// Returns a `DispatchResultWithPostInfo` indicating success or failure, along with the weight consumed.
17- ///
18- /// # Errors
19- ///
20- /// This function will return an error if:
21- /// - The caller is not a valid signed origin.
22- /// - The old coldkey (caller) is in arbitration.
23- /// - The new coldkey is already associated with other hotkeys or is a hotkey itself.
24- /// - There's not enough balance to pay for the swap.
25- ///
26- /// # Events
27- ///
28- /// Emits a `ColdkeySwapped` event when successful.
29- ///
30- /// # Weight
31- ///
32- /// Weight is tracked and updated throughout the function execution.
5+ /// Logic for the coldkey swap operation. Checks for collisions, balances, and cooldowns
6+ /// before executing the swap.
337 pub fn do_swap_coldkey (
348 old_coldkey : & T :: AccountId ,
359 new_coldkey : & T :: AccountId ,
3610 swap_cost : TaoCurrency ,
37- ) -> DispatchResultWithPostInfo {
38- // 2. Initialize the weight for this operation
39- let mut weight: Weight = T :: DbWeight :: get ( ) . reads ( 2 ) ;
40- // 3. Ensure the new coldkey is not associated with any hotkeys
11+ ) -> DispatchResult {
4112 ensure ! (
4213 StakingHotkeys :: <T >:: get( new_coldkey) . is_empty( ) ,
4314 Error :: <T >:: ColdKeyAlreadyAssociated
4415 ) ;
45- weight = weight. saturating_add ( T :: DbWeight :: get ( ) . reads ( 1 ) ) ;
46-
47- // 4. Ensure the new coldkey is not a hotkey
4816 ensure ! (
4917 !Self :: hotkey_account_exists( new_coldkey) ,
5018 Error :: <T >:: NewColdKeyIsHotkey
5119 ) ;
52- weight = weight. saturating_add ( T :: DbWeight :: get ( ) . reads ( 1 ) ) ;
53-
54- // 5. Swap the identity if the old coldkey has one
55- if let Some ( identity) = IdentitiesV2 :: < T > :: take ( old_coldkey) {
56- IdentitiesV2 :: < T > :: insert ( new_coldkey, identity) ;
57- }
58-
59- // 6. Ensure sufficient balance for the swap cost
6020 ensure ! (
6121 Self :: can_remove_balance_from_coldkey_account( old_coldkey, swap_cost. into( ) ) ,
6222 Error :: <T >:: NotEnoughBalanceToPaySwapColdKey
6323 ) ;
6424
65- // 7. Remove and recycle the swap cost from the old coldkey's account
66- let actual_burn_amount =
67- Self :: remove_balance_from_coldkey_account ( old_coldkey , swap_cost . into ( ) ) ? ;
68- Self :: recycle_tao ( actual_burn_amount ) ;
25+ // Swap the identity if the old coldkey has one
26+ if let Some ( identity ) = IdentitiesV2 :: < T > :: take ( old_coldkey ) {
27+ IdentitiesV2 :: < T > :: insert ( new_coldkey , identity ) ;
28+ }
6929
70- // 8. Update the weight for the balance operations
71- weight. saturating_accrue ( T :: DbWeight :: get ( ) . reads_writes ( 1 , 1 ) ) ;
30+ // Remove and recycle the swap cost from the old coldkey's account
31+ let burn_amount = Self :: remove_balance_from_coldkey_account ( old_coldkey, swap_cost. into ( ) ) ?;
32+ Self :: recycle_tao ( burn_amount) ;
7233
73- // 9. Perform the actual coldkey swap
74- let _ = Self :: perform_swap_coldkey ( old_coldkey, new_coldkey, & mut weight) ;
34+ Self :: perform_swap_coldkey ( old_coldkey, new_coldkey) ?;
7535
76- // 10. Update the last transaction block for the new coldkey
7736 Self :: set_last_tx_block ( new_coldkey, Self :: get_current_block_as_u64 ( ) ) ;
78- weight. saturating_accrue ( T :: DbWeight :: get ( ) . writes ( 1 ) ) ;
7937
80- // 11. Remove the coldkey swap scheduled record
8138 ColdkeySwapScheduled :: < T > :: remove ( old_coldkey) ;
8239
83- // 12. Emit the ColdkeySwapped event
8440 Self :: deposit_event ( Event :: ColdkeySwapped {
8541 old_coldkey : old_coldkey. clone ( ) ,
8642 new_coldkey : new_coldkey. clone ( ) ,
8743 swap_cost,
8844 } ) ;
89-
90- // 12. Return the result with the updated weight
91- Ok ( Some ( weight) . into ( ) )
45+ Ok ( ( ) )
9246 }
9347
94- /// Performs the actual coldkey swap operation, transferring all associated data and balances from the old coldkey to the new coldkey.
95- ///
96- /// # Arguments
97- ///
98- /// * `old_coldkey` - The account ID of the old coldkey.
99- /// * `new_coldkey` - The account ID of the new coldkey.
100- /// * `weight` - A mutable reference to the current transaction weight.
101- ///
102- /// # Returns
103- ///
104- /// Returns a `DispatchResult` indicating success or failure of the operation.
105- ///
106- /// # Steps
107- ///
108- /// 1. Swap TotalHotkeyColdkeyStakesThisInterval:
109- /// - For each hotkey owned by the old coldkey, transfer its stake and block data to the new coldkey.
110- ///
111- /// 2. Swap subnet ownership:
112- /// - For each subnet, if the old coldkey is the owner, transfer ownership to the new coldkey.
113- ///
114- /// 3. Swap Stakes:
115- /// - For each hotkey staking for the old coldkey, transfer its stake to the new coldkey.
48+ /// Transfer all assets, stakes, subnet ownerships, and hotkey associations from `old_coldkey` to `new_coldkey`.
11649 ///
117- /// 4. Swap total coldkey stake:
118- /// - Transfer the total stake from the old coldkey to the new coldkey.
119- ///
120- /// 5. Swap StakingHotkeys:
121- /// - Transfer the list of staking hotkeys from the old coldkey to the new coldkey.
122- ///
123- /// 6. Swap hotkey owners:
124- /// - For each hotkey owned by the old coldkey, transfer ownership to the new coldkey.
125- /// - Update the list of owned hotkeys for both old and new coldkeys.
126- ///
127- /// 7. Transfer remaining balance:
128- /// - Transfer any remaining balance from the old coldkey to the new coldkey.
129- ///
130- /// Throughout the process, the function updates the transaction weight to reflect the operations performed.
131- ///
132- /// # Notes
133- ///
134- /// This function is a critical part of the coldkey swap process and should be called only after all necessary checks and validations have been performed.
50+ /// # Warning
51+ /// This function performs NO validation checks. It assumes the caller has done all the checks before calling it.
13552 pub fn perform_swap_coldkey (
13653 old_coldkey : & T :: AccountId ,
13754 new_coldkey : & T :: AccountId ,
138- weight : & mut Weight ,
13955 ) -> DispatchResult {
140- // 1. Swap TotalHotkeyColdkeyStakesThisInterval
141- // TotalHotkeyColdkeyStakesThisInterval: MAP ( hotkey, coldkey ) --> ( stake, block ) | Stake of the hotkey for the coldkey.
142- // for hotkey in OwnedHotkeys::<T>::get(old_coldkey).iter() {
143- // let (stake, block) =
144- // TotalHotkeyColdkeyStakesThisInterval::<T>::get(&hotkey, old_coldkey);
145- // TotalHotkeyColdkeyStakesThisInterval::<T>::remove(&hotkey, old_coldkey);
146- // TotalHotkeyColdkeyStakesThisInterval::<T>::insert(&hotkey, new_coldkey, (stake, block));
147- // weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
148- // } (DEPRECATED)
149-
150- // 2. Swap subnet owner.
151- // SubnetOwner: MAP ( netuid ) --> (coldkey) | Owner of the subnet.
15256 for netuid in Self :: get_all_subnet_netuids ( ) {
153- let subnet_owner = SubnetOwner :: < T > :: get ( netuid) ;
154- if subnet_owner == * old_coldkey {
155- SubnetOwner :: < T > :: insert ( netuid, new_coldkey. clone ( ) ) ;
156- }
157- weight. saturating_accrue ( T :: DbWeight :: get ( ) . reads_writes ( 1 , 1 ) ) ;
57+ Self :: transfer_subnet_ownership ( netuid, old_coldkey, new_coldkey) ;
58+ Self :: transfer_coldkey_stake ( netuid, old_coldkey, new_coldkey) ;
59+ }
15860
159- if let Some ( old_auto_stake_hotkey) = AutoStakeDestination :: < T > :: get ( old_coldkey, netuid)
160- {
161- AutoStakeDestination :: < T > :: remove ( old_coldkey, netuid) ;
162- AutoStakeDestination :: < T > :: insert (
163- new_coldkey,
164- netuid,
165- old_auto_stake_hotkey. clone ( ) ,
166- ) ;
167- AutoStakeDestinationColdkeys :: < T > :: mutate ( old_auto_stake_hotkey, netuid, |v| {
168- // Remove old/new coldkeys (avoid duplicates), then add the new one.
169- v. retain ( |c| * c != * old_coldkey && * c != * new_coldkey) ;
170- v. push ( new_coldkey. clone ( ) ) ;
171- } ) ;
172- }
61+ Self :: transfer_staking_hotkeys ( old_coldkey, new_coldkey) ;
62+ Self :: transfer_hotkeys_ownership ( old_coldkey, new_coldkey) ;
63+
64+ // Transfer any remaining balance from old_coldkey to new_coldkey
65+ let remaining_balance = Self :: get_coldkey_balance ( old_coldkey) ;
66+ if remaining_balance > 0 {
67+ Self :: kill_coldkey_account ( old_coldkey, remaining_balance) ?;
68+ Self :: add_balance_to_coldkey_account ( new_coldkey, remaining_balance) ;
69+ }
70+
71+ Ok ( ( ) )
72+ }
73+
74+ /// Transfer the ownership of the subnet to the new coldkey if it is owned by the old coldkey.
75+ fn transfer_subnet_ownership (
76+ netuid : NetUid ,
77+ old_coldkey : & T :: AccountId ,
78+ new_coldkey : & T :: AccountId ,
79+ ) {
80+ let subnet_owner = SubnetOwner :: < T > :: get ( netuid) ;
81+ if subnet_owner == * old_coldkey {
82+ SubnetOwner :: < T > :: insert ( netuid, new_coldkey. clone ( ) ) ;
83+ }
84+
85+ if let Some ( old_auto_stake_hotkey) = AutoStakeDestination :: < T > :: get ( old_coldkey, netuid) {
86+ AutoStakeDestination :: < T > :: remove ( old_coldkey, netuid) ;
87+ AutoStakeDestination :: < T > :: insert ( new_coldkey, netuid, old_auto_stake_hotkey. clone ( ) ) ;
88+ AutoStakeDestinationColdkeys :: < T > :: mutate ( old_auto_stake_hotkey, netuid, |v| {
89+ // Remove old/new coldkeys (avoid duplicates), then add the new one.
90+ v. retain ( |c| * c != * old_coldkey && * c != * new_coldkey) ;
91+ v. push ( new_coldkey. clone ( ) ) ;
92+ } ) ;
17393 }
94+ }
17495
175- // 3. Swap Stake.
176- // StakingHotkeys: MAP ( coldkey ) --> Vec( hotkey )
96+ /// Transfer the stake of all staking hotkeys linked to the old coldkey to the new coldkey.
97+ fn transfer_coldkey_stake (
98+ netuid : NetUid ,
99+ old_coldkey : & T :: AccountId ,
100+ new_coldkey : & T :: AccountId ,
101+ ) {
177102 for hotkey in StakingHotkeys :: < T > :: get ( old_coldkey) {
178- // 3.1 Swap Alpha
179- for netuid in Self :: get_all_subnet_netuids ( ) {
180- // Get the stake on the old (hot,coldkey) account.
181- let old_alpha: U64F64 = Alpha :: < T > :: get ( ( & hotkey, old_coldkey, netuid) ) ;
182- // Get the stake on the new (hot,coldkey) account.
183- let new_alpha: U64F64 = Alpha :: < T > :: get ( ( & hotkey, new_coldkey, netuid) ) ;
184- // Add the stake to new account.
185- Alpha :: < T > :: insert (
186- ( & hotkey, new_coldkey, netuid) ,
187- new_alpha. saturating_add ( old_alpha) ,
103+ // Get the stake on the old (hot,coldkey) account.
104+ let old_alpha: U64F64 = Alpha :: < T > :: get ( ( & hotkey, old_coldkey, netuid) ) ;
105+ // Get the stake on the new (hot,coldkey) account.
106+ let new_alpha: U64F64 = Alpha :: < T > :: get ( ( & hotkey, new_coldkey, netuid) ) ;
107+ // Add the stake to new account.
108+ Alpha :: < T > :: insert (
109+ ( & hotkey, new_coldkey, netuid) ,
110+ new_alpha. saturating_add ( old_alpha) ,
111+ ) ;
112+ // Remove the value from the old account.
113+ Alpha :: < T > :: remove ( ( & hotkey, old_coldkey, netuid) ) ;
114+
115+ if new_alpha. saturating_add ( old_alpha) > U64F64 :: from ( 0u64 ) {
116+ Self :: transfer_root_claimed_for_new_keys (
117+ netuid,
118+ & hotkey,
119+ & hotkey,
120+ old_coldkey,
121+ new_coldkey,
188122 ) ;
189- // Remove the value from the old account.
190- Alpha :: < T > :: remove ( ( & hotkey, old_coldkey, netuid) ) ;
191123
192- if new_alpha. saturating_add ( old_alpha) > U64F64 :: from ( 0u64 ) {
193- Self :: transfer_root_claimed_for_new_keys (
194- netuid,
195- & hotkey,
196- & hotkey,
197- old_coldkey,
198- new_coldkey,
199- ) ;
200-
201- if netuid == NetUid :: ROOT {
202- // Register new coldkey with root stake
203- Self :: maybe_add_coldkey_index ( new_coldkey) ;
204- }
124+ if netuid == NetUid :: ROOT {
125+ // Register new coldkey with root stake
126+ Self :: maybe_add_coldkey_index ( new_coldkey) ;
205127 }
206128 }
207- // Add the weight for the read and write.
208- weight. saturating_accrue ( T :: DbWeight :: get ( ) . reads_writes ( 2 , 2 ) ) ;
209129 }
130+ }
210131
211- // 4. Swap TotalColdkeyAlpha (DEPRECATED)
212- // for netuid in Self::get_all_subnet_netuids() {
213- // let old_alpha_stake: u64 = TotalColdkeyAlpha::<T>::get(old_coldkey, netuid);
214- // let new_alpha_stake: u64 = TotalColdkeyAlpha::<T>::get(new_coldkey, netuid);
215- // TotalColdkeyAlpha::<T>::insert(
216- // new_coldkey,
217- // netuid,
218- // new_alpha_stake.saturating_add(old_alpha_stake),
219- // );
220- // TotalColdkeyAlpha::<T>::remove(old_coldkey, netuid);
221- // }
222- // weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
223-
224- // 5. Swap StakingHotkeys.
225- // StakingHotkeys: MAP ( coldkey ) --> Vec<hotkeys> | Hotkeys staking for the coldkey.
132+ /// Transfer staking hotkeys from the old coldkey to the new coldkey.
133+ fn transfer_staking_hotkeys ( old_coldkey : & T :: AccountId , new_coldkey : & T :: AccountId ) {
226134 let old_staking_hotkeys: Vec < T :: AccountId > = StakingHotkeys :: < T > :: get ( old_coldkey) ;
227135 let mut new_staking_hotkeys: Vec < T :: AccountId > = StakingHotkeys :: < T > :: get ( new_coldkey) ;
228136 for hotkey in old_staking_hotkeys {
@@ -231,13 +139,13 @@ impl<T: Config> Pallet<T> {
231139 new_staking_hotkeys. push ( hotkey) ;
232140 }
233141 }
142+
234143 StakingHotkeys :: < T > :: remove ( old_coldkey) ;
235144 StakingHotkeys :: < T > :: insert ( new_coldkey, new_staking_hotkeys) ;
236- weight . saturating_accrue ( T :: DbWeight :: get ( ) . reads_writes ( 2 , 2 ) ) ;
145+ }
237146
238- // 6. Swap hotkey owners.
239- // Owner: MAP ( hotkey ) --> coldkey | Owner of the hotkey.
240- // OwnedHotkeys: MAP ( coldkey ) --> Vec<hotkeys> | Hotkeys owned by the coldkey.
147+ /// Transfer the ownership of the hotkeys owned by the old coldkey to the new coldkey.
148+ fn transfer_hotkeys_ownership ( old_coldkey : & T :: AccountId , new_coldkey : & T :: AccountId ) {
241149 let old_owned_hotkeys: Vec < T :: AccountId > = OwnedHotkeys :: < T > :: get ( old_coldkey) ;
242150 let mut new_owned_hotkeys: Vec < T :: AccountId > = OwnedHotkeys :: < T > :: get ( new_coldkey) ;
243151 for owned_hotkey in old_owned_hotkeys. iter ( ) {
@@ -252,19 +160,5 @@ impl<T: Config> Pallet<T> {
252160 }
253161 OwnedHotkeys :: < T > :: remove ( old_coldkey) ;
254162 OwnedHotkeys :: < T > :: insert ( new_coldkey, new_owned_hotkeys) ;
255- weight. saturating_accrue ( T :: DbWeight :: get ( ) . reads_writes ( 2 , 2 ) ) ;
256-
257- // 7. Transfer remaining balance.
258- // Balance: MAP ( coldkey ) --> u64 | Balance of the coldkey.
259- // Transfer any remaining balance from old_coldkey to new_coldkey
260- let remaining_balance = Self :: get_coldkey_balance ( old_coldkey) ;
261- if remaining_balance > 0 {
262- Self :: kill_coldkey_account ( old_coldkey, remaining_balance) ?;
263- Self :: add_balance_to_coldkey_account ( new_coldkey, remaining_balance) ;
264- }
265- weight. saturating_accrue ( T :: DbWeight :: get ( ) . reads_writes ( 2 , 2 ) ) ;
266-
267- // Return ok.
268- Ok ( ( ) )
269163 }
270164}
0 commit comments