Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap ids #712

Closed
wants to merge 10 commits into from
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

**/*.lock

*.ipynb

# Generated by code coverage
*.profraw
*.profdata
Expand Down
7 changes: 7 additions & 0 deletions docs/delegate-info.json
Original file line number Diff line number Diff line change
Expand Up @@ -390,5 +390,12 @@
"url": "https://cortex.foundation/",
"description": "Cortex Foundation is committed to advancing the integration of decentralized AI. Our validator is designed for transparency, reliability, and community engagement.",
"signature": "7a6274ff6b0f7ddca97e37ef4a9b90781012ff3cf7baa3159f6feaafc43c557975aad324ea608d6b8abeb21f8f3ca2595e54b81a7564574d0242b803d969618a"
},
{
"address":"5F27Eqz2PhyMtGMEce898x31DokNqRVxkm5AhDDe6rDGNvoY",
"name": "Love",
"url": "https://love.cosimo.fund",
"description": "Love validator exists to accelerate open source AI and be good stewards of the Bittensorr network",
"signature": "c221a3de3be031c149a7be912b3b75e0355605f041dc975153302b23b4d93e45e9cc7453532491e92076ccd333a4c1f95f4a2229aae8f4fcfb88e5dec3f14c87"
}
]
57 changes: 57 additions & 0 deletions pallets/subtensor/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,4 +429,61 @@ reveal_weights {

}: reveal_weights(RawOrigin::Signed(hotkey.clone()), netuid, uids, weight_values, salt, version_key)

swap_coldkey {
// Set up initial state
let old_coldkey: T::AccountId = account("old_coldkey", 0, 0);
let new_coldkey: T::AccountId = account("new_coldkey", 0, 0);
let hotkey1: T::AccountId = account("hotkey1", 0, 0);
let netuid = 1u16;
let stake_amount1 = 1000u64;
let stake_amount2 = 2000u64;
let swap_cost = Subtensor::<T>::get_key_swap_cost();
let free_balance_old = 12345u64 + swap_cost;
let tempo: u16 = 1;

// Setup initial state
Subtensor::<T>::init_new_network(netuid, tempo);
Subtensor::<T>::set_network_registration_allowed(netuid, true);
Subtensor::<T>::set_network_pow_registration_allowed(netuid, true);

let block_number: u64 = Subtensor::<T>::get_current_block_as_u64();
let (nonce, work): (u64, Vec<u8>) = Subtensor::<T>::create_work_for_block_number(
netuid,
block_number,
3,
&hotkey1,
);

let _ = Subtensor::<T>::register(
<T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(old_coldkey.clone())),
netuid,
block_number,
nonce,
work.clone(),
hotkey1.clone(),
old_coldkey.clone(),
);

// Add balance to old coldkey
Subtensor::<T>::add_balance_to_coldkey_account(
&old_coldkey,
stake_amount1 + stake_amount2 + free_balance_old,
);

// Insert an Identity
let name: Vec<u8> = b"The fourth Coolest Identity".to_vec();
let identity: ChainIdentity = ChainIdentity {
name: name.clone(),
url: vec![],
image: vec![],
discord: vec![],
description: vec![],
additional: vec![],
};

Identities::<T>::insert(&old_coldkey, identity);

// Benchmark setup complete, now execute the extrinsic
}: swap_coldkey(RawOrigin::Signed(old_coldkey.clone()), new_coldkey.clone())

}
7 changes: 4 additions & 3 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,9 +668,10 @@ mod dispatches {
///
/// Weight is calculated based on the number of database reads and writes.
#[pallet::call_index(71)]
#[pallet::weight((Weight::from_parts(1_940_000_000, 0)
.saturating_add(T::DbWeight::get().reads(272))
.saturating_add(T::DbWeight::get().writes(527)), DispatchClass::Operational, Pays::No))]
#[pallet::weight((Weight::from_parts(127_713_000, 0)
.saturating_add(Weight::from_parts(0, 11645))
.saturating_add(T::DbWeight::get().reads(18))
.saturating_add(T::DbWeight::get().writes(12)), DispatchClass::Operational, Pays::No))]
pub fn swap_coldkey(
origin: OriginFor<T>,
new_coldkey: T::AccountId,
Expand Down
19 changes: 12 additions & 7 deletions pallets/subtensor/src/swap/swap_coldkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,36 +51,41 @@ impl<T: Config> Pallet<T> {
Error::<T>::ColdKeyAlreadyAssociated
);

// 5. Calculate the swap cost and ensure sufficient balance
// 5. Swap the identity if the old coldkey has one
if let Some(identity) = Identities::<T>::take(&old_coldkey) {
Identities::<T>::insert(new_coldkey, identity);
}

// 6. Calculate the swap cost and ensure sufficient balance
let swap_cost = Self::get_key_swap_cost();
log::debug!("Coldkey swap cost: {:?}", swap_cost);
ensure!(
Self::can_remove_balance_from_coldkey_account(&old_coldkey, swap_cost),
Error::<T>::NotEnoughBalanceToPaySwapColdKey
);

// 6. Remove and burn the swap cost from the old coldkey's account
// 7. Remove and burn the swap cost from the old coldkey's account
let actual_burn_amount =
Self::remove_balance_from_coldkey_account(&old_coldkey, swap_cost)?;
Self::burn_tokens(actual_burn_amount);

// 7. Update the weight for the balance operations
// 8. Update the weight for the balance operations
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));

// 8. Perform the actual coldkey swap
// 9. Perform the actual coldkey swap
let _ = Self::perform_swap_coldkey(&old_coldkey, new_coldkey, &mut weight);

// 9. Update the last transaction block for the new coldkey
// 10. Update the last transaction block for the new coldkey
Self::set_last_tx_block(new_coldkey, Self::get_current_block_as_u64());
weight.saturating_accrue(T::DbWeight::get().writes(1));

// 10. Emit the ColdkeySwapped event
// 11. Emit the ColdkeySwapped event
Self::deposit_event(Event::ColdkeySwapped {
old_coldkey: old_coldkey.clone(),
new_coldkey: new_coldkey.clone(),
});

// 11. Return the result with the updated weight
// 12. Return the result with the updated weight
Ok(Some(weight).into())
}

Expand Down
157 changes: 157 additions & 0 deletions pallets/subtensor/tests/swap_coldkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,22 @@ fn test_do_swap_coldkey_success() {
stake_amount2
));

// Insert an Identity
let name: Vec<u8> = b"The fourth Coolest Identity".to_vec();
let identity: ChainIdentity = ChainIdentity {
name: name.clone(),
url: vec![],
image: vec![],
discord: vec![],
description: vec![],
additional: vec![],
};

Identities::<Test>::insert(old_coldkey, identity.clone());

assert!(Identities::<Test>::get(old_coldkey).is_some());
assert!(Identities::<Test>::get(new_coldkey).is_none());

// Log state after adding stake
log::info!(
"Total stake after adding: {}",
Expand Down Expand Up @@ -594,6 +610,14 @@ fn test_do_swap_coldkey_success() {
"Total stake changed unexpectedly"
);

// Verify identities were swapped
assert!(Identities::<Test>::get(old_coldkey).is_none());
assert!(Identities::<Test>::get(new_coldkey).is_some());
assert_eq!(
Identities::<Test>::get(new_coldkey).expect("Expected an Identity"),
identity
);

// Verify event emission
System::assert_last_event(
Event::ColdkeySwapped {
Expand Down Expand Up @@ -1286,3 +1310,136 @@ fn test_coldkey_delegations() {
assert_eq!(Stake::<Test>::get(delegate, coldkey), 0);
});
}

#[test]
fn test_coldkey_swap_delegate_identity_updated() {
new_test_ext(1).execute_with(|| {
let old_coldkey = U256::from(1);
let new_coldkey = U256::from(2);

let netuid = 1;
let burn_cost = 10;
let tempo = 1;

SubtensorModule::set_burn(netuid, burn_cost);
add_network(netuid, tempo, 0);

SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 100_000_000_000);

assert_ok!(SubtensorModule::burned_register(
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
netuid,
old_coldkey
));

let name: Vec<u8> = b"The Third Coolest Identity".to_vec();
let identity: ChainIdentity = ChainIdentity {
name: name.clone(),
url: vec![],
image: vec![],
discord: vec![],
description: vec![],
additional: vec![],
};

Identities::<Test>::insert(old_coldkey, identity.clone());

assert!(Identities::<Test>::get(old_coldkey).is_some());
assert!(Identities::<Test>::get(new_coldkey).is_none());

assert_ok!(SubtensorModule::do_swap_coldkey(
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
&new_coldkey
));

assert!(Identities::<Test>::get(old_coldkey).is_none());
assert!(Identities::<Test>::get(new_coldkey).is_some());
assert_eq!(
Identities::<Test>::get(new_coldkey).expect("Expected an Identity"),
identity
);
});
}

#[test]
fn test_coldkey_swap_no_identity_no_changes() {
new_test_ext(1).execute_with(|| {
let old_coldkey = U256::from(1);
let new_coldkey = U256::from(2);

let netuid = 1;
let burn_cost = 10;
let tempo = 1;

SubtensorModule::set_burn(netuid, burn_cost);
add_network(netuid, tempo, 0);

SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, 100_000_000_000);

assert_ok!(SubtensorModule::burned_register(
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
netuid,
old_coldkey
));

// Ensure the old coldkey does not have an identity before the swap
assert!(Identities::<Test>::get(old_coldkey).is_none());

// Perform the coldkey swap
assert_ok!(SubtensorModule::do_swap_coldkey(
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey),
&new_coldkey,
));

// Ensure no identities have been changed
assert!(Identities::<Test>::get(old_coldkey).is_none());
assert!(Identities::<Test>::get(new_coldkey).is_none());
});
}

#[test]
fn test_coldkey_swap_no_identity_no_changes_newcoldkey_exists() {
new_test_ext(1).execute_with(|| {
let old_coldkey_2 = U256::from(3);
let new_coldkey_2 = U256::from(4);

let netuid = 1;
let burn_cost = 10;
let tempo = 1;

SubtensorModule::set_burn(netuid, burn_cost);
add_network(netuid, tempo, 0);
SubtensorModule::add_balance_to_coldkey_account(&old_coldkey_2, 100_000_000_000);

assert_ok!(SubtensorModule::burned_register(
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey_2),
netuid,
old_coldkey_2
));

let name: Vec<u8> = b"The Coolest Identity".to_vec();
let identity: ChainIdentity = ChainIdentity {
name: name.clone(),
url: vec![],
image: vec![],
discord: vec![],
description: vec![],
additional: vec![],
};

Identities::<Test>::insert(new_coldkey_2, identity.clone());
// Ensure the new coldkey does have an identity before the swap
assert!(Identities::<Test>::get(new_coldkey_2).is_some());
assert!(Identities::<Test>::get(old_coldkey_2).is_none());

// Perform the coldkey swap
assert_ok!(SubtensorModule::do_swap_coldkey(
<<Test as Config>::RuntimeOrigin>::signed(old_coldkey_2),
&new_coldkey_2,
));

// Ensure no identities have been changed
assert!(Identities::<Test>::get(old_coldkey_2).is_none());
assert!(Identities::<Test>::get(new_coldkey_2).is_some());
});
}
Loading