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 #747

Merged
merged 15 commits into from
Aug 23, 2024
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
14 changes: 14 additions & 0 deletions docs/delegate-info.json
Original file line number Diff line number Diff line change
Expand Up @@ -390,5 +390,19 @@
"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"
},
{
"address": "5Hb63SvXBXqZ8zw6mwW1A39fHdqUrJvohXgepyhp2jgWedSB",
"name": "TAO Miner's Union",
"url": "https://minersunion.ai",
"description": "The first Bittensor validator that empowers you to choose which subnets to incentivize. Committed to transparency and integrity, we ensure fair and honest validation processes that contribute to the growth and strength of the network.",
"signature": "e8c68bc766a06f36c633e1f68d5aca4c4090a26e394372f64d5b00cc13621f361ec9df85fc9f0d247dbc1fe452bd53ffc0224dee2bc85c9d82cb250e4ac10984"
}
]
60 changes: 59 additions & 1 deletion pallets/subtensor/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ reveal_weights {
let new_rate_limit: u64 = 100;
}: sudo_set_tx_childkey_take_rate_limit(RawOrigin::Root, new_rate_limit)

benchmark_set_childkey_take {
benchmark_set_childkey_take {
// Setup
let netuid: u16 = 1;
let tempo: u16 = 1;
Expand All @@ -462,4 +462,62 @@ benchmark_set_childkey_take {
Subtensor::<T>::add_balance_to_coldkey_account(&coldkey, amount_to_be_staked);
assert_ok!(Subtensor::<T>::do_burned_registration(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone()));
}: set_childkey_take(RawOrigin::Signed(coldkey), hotkey, netuid, take)

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()), 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 @@ -672,9 +672,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>,
old_coldkey: T::AccountId,
Expand Down
21 changes: 13 additions & 8 deletions pallets/subtensor/src/swap/swap_coldkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,37 +49,42 @@ impl<T: Config> Pallet<T> {
);
weight = weight.saturating_add(T::DbWeight::get().reads(1));

// 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();
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. Remove the coldkey swap scheduled record
// 11. Remove the coldkey swap scheduled record
ColdkeySwapScheduled::<T>::remove(old_coldkey);

// 11. Emit the ColdkeySwapped event
// 12. 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
148 changes: 148 additions & 0 deletions pallets/subtensor/tests/swap_coldkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,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 @@ -601,6 +617,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 @@ -1480,3 +1504,127 @@ fn test_schedule_swap_coldkey_with_pending_swap() {
);
});
}

#[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(&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(&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 = U256::from(3);
let new_coldkey = 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, 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 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, identity.clone());
// Ensure the new coldkey does have an identity before the swap
assert!(Identities::<Test>::get(new_coldkey).is_some());
assert!(Identities::<Test>::get(old_coldkey).is_none());

// Perform the coldkey swap
assert_ok!(SubtensorModule::do_swap_coldkey(&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_some());
});
}
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,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: 193,
spec_version: 194,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading