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

Make devnet mergable with main #883

Closed
wants to merge 1 commit 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
64 changes: 37 additions & 27 deletions pallets/subtensor/src/coinbase/run_coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,69 +265,65 @@ impl<T: Config> Pallet<T> {
// --- 1.0 Drain the hotkey emission.
PendingdHotkeyEmission::<T>::insert(hotkey, 0);

// --- 2 Retrieve the last time this hotkey's emissions were drained.
let last_emission_drain: u64 = LastHotkeyEmissionDrain::<T>::get(hotkey);

// --- 3 Update the block value to the current block number.
// --- 2 Update the block value to the current block number.
LastHotkeyEmissionDrain::<T>::insert(hotkey, block_number);

// --- 4 Retrieve the total stake for the hotkey from all nominations.
// --- 3 Retrieve the total stake for the hotkey from all nominations.
let total_hotkey_stake: u64 = Self::get_total_stake_for_hotkey(hotkey);

// --- 5 Calculate the emission take for the hotkey.
// --- 4 Calculate the emission take for the hotkey.
let take_proportion: I64F64 = I64F64::from_num(Delegates::<T>::get(hotkey))
.saturating_div(I64F64::from_num(u16::MAX));
let hotkey_take: u64 =
(take_proportion.saturating_mul(I64F64::from_num(emission))).to_num::<u64>();

// --- 6 Compute the remaining emission after deducting the hotkey's take.
// --- 5 Compute the remaining emission after deducting the hotkey's take.
let emission_minus_take: u64 = emission.saturating_sub(hotkey_take);

// --- 7 Calculate the remaining emission after the hotkey's take.
// --- 6 Calculate the remaining emission after the hotkey's take.
let mut remainder: u64 = emission_minus_take;

// --- 8 Iterate over each nominator and get all viable stake.
// --- 7 Iterate over each nominator and get all viable stake.
let mut total_viable_nominator_stake: u64 = total_hotkey_stake;
for (nominator, nominator_stake) in Stake::<T>::iter_prefix(hotkey) {
if LastAddStakeIncrease::<T>::get(hotkey, nominator) > last_emission_drain {
total_viable_nominator_stake =
total_viable_nominator_stake.saturating_sub(nominator_stake);
}
for (nominator, _) in Stake::<T>::iter_prefix(hotkey) {
let nonviable_nomintaor_stake = Self::get_nonviable_stake(hotkey, &nominator);

total_viable_nominator_stake =
total_viable_nominator_stake.saturating_sub(nonviable_nomintaor_stake);
}

// --- 9 Iterate over each nominator.
// --- 8 Iterate over each nominator.
if total_viable_nominator_stake != 0 {
for (nominator, nominator_stake) in Stake::<T>::iter_prefix(hotkey) {
// --- 10 Check if the stake was manually increased by the user since the last emission drain for this hotkey.
// --- 9 Check if the stake was manually increased by the user since the last emission drain for this hotkey.
// If it was, skip this nominator as they will not receive their proportion of the emission.
if LastAddStakeIncrease::<T>::get(hotkey, nominator.clone()) > last_emission_drain {
continue;
}
let viable_nominator_stake =
nominator_stake.saturating_sub(Self::get_nonviable_stake(hotkey, &nominator));

// --- 11 Calculate this nominator's share of the emission.
let nominator_emission: I64F64 = I64F64::from_num(emission_minus_take)
.saturating_mul(I64F64::from_num(nominator_stake))
// --- 10 Calculate this nominator's share of the emission.
let nominator_emission: I64F64 = I64F64::from_num(viable_nominator_stake)
.checked_div(I64F64::from_num(total_viable_nominator_stake))
.unwrap_or(I64F64::from_num(0));
.unwrap_or(I64F64::from_num(0))
.saturating_mul(I64F64::from_num(emission_minus_take));

// --- 12 Increase the stake for the nominator.
// --- 11 Increase the stake for the nominator.
Self::increase_stake_on_coldkey_hotkey_account(
&nominator,
hotkey,
nominator_emission.to_num::<u64>(),
);

// --- 13* Record event and Subtract the nominator's emission from the remainder.
// --- 12* Record event and Subtract the nominator's emission from the remainder.
total_new_tao = total_new_tao.saturating_add(nominator_emission.to_num::<u64>());
remainder = remainder.saturating_sub(nominator_emission.to_num::<u64>());
}
}

// --- 14 Finally, add the stake to the hotkey itself, including its take and the remaining emission.
// --- 13 Finally, add the stake to the hotkey itself, including its take and the remaining emission.
let hotkey_new_tao: u64 = hotkey_take.saturating_add(remainder);
Self::increase_stake_on_hotkey_account(hotkey, hotkey_new_tao);

// --- 15 Record new tao creation event and return the amount created.
// --- 14 Record new tao creation event and return the amount created.
total_new_tao = total_new_tao.saturating_add(hotkey_new_tao);
total_new_tao
}
Expand Down Expand Up @@ -382,4 +378,18 @@ impl<T: Config> Pallet<T> {
let remainder = block_plus_netuid.rem_euclid(tempo_plus_one);
(tempo as u64).saturating_sub(remainder)
}

/// Calculates the nonviable stake for a nominator.
/// The nonviable stake is the stake that was added by the nominator since the last emission drain.
/// This stake will not receive emission until the next emission drain.
/// Note: if the stake delta is below zero, we return zero. We don't allow more stake than the nominator has.
pub fn get_nonviable_stake(hotkey: &T::AccountId, nominator: &T::AccountId) -> u64 {
let stake_delta = StakeDeltaSinceLastEmissionDrain::<T>::get(hotkey, nominator);
if stake_delta.is_negative() {
0
} else {
// Should never fail the into, but we handle it anyway.
stake_delta.try_into().unwrap_or(u64::MAX)
}
}
}
13 changes: 9 additions & 4 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ pub mod pallet {
0
}
#[pallet::type_value]
/// Default stake delta.
pub fn DefaultStakeDelta<T: Config>() -> i128 {
0
}
#[pallet::type_value]
/// Default stakes per interval.
pub fn DefaultStakesPerInterval<T: Config>() -> (u64, u64) {
(0, 0)
Expand Down Expand Up @@ -791,16 +796,16 @@ pub mod pallet {
DefaultAccumulatedEmission<T>,
>;
#[pallet::storage]
/// Map ( hot, cold ) --> block_number | Last add stake increase.
pub type LastAddStakeIncrease<T: Config> = StorageDoubleMap<
/// Map ( hot, cold ) --> stake: i128 | Stake added/removed since last emission drain.
pub type StakeDeltaSinceLastEmissionDrain<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::AccountId,
Identity,
T::AccountId,
u64,
i128,
ValueQuery,
DefaultAccountTake<T>,
DefaultStakeDelta<T>,
>;
#[pallet::storage]
/// DMAP ( parent, netuid ) --> Vec<(proportion,child)>
Expand Down
6 changes: 4 additions & 2 deletions pallets/subtensor/src/staking/add_stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ impl<T: Config> Pallet<T> {
Error::<T>::StakeRateLimitExceeded
);

// Set the last time the stake increased for nominator drain protection.
LastAddStakeIncrease::<T>::insert(&hotkey, &coldkey, Self::get_current_block_as_u64());
// Track this addition in the stake delta.
StakeDeltaSinceLastEmissionDrain::<T>::mutate(&hotkey, &coldkey, |stake_delta| {
*stake_delta = stake_delta.saturating_add_unsigned(stake_to_be_added as u128);
});

// If coldkey is not owner of the hotkey, it's a nomination stake.
if !Self::coldkey_owns_hotkey(&coldkey, &hotkey) {
Expand Down
48 changes: 35 additions & 13 deletions pallets/subtensor/src/swap/swap_hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,33 +206,42 @@ impl<T: Config> Pallet<T> {
Delegates::<T>::insert(new_hotkey, old_delegate_take);
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
}
// 9. Swap all subnet specific info.

// 9. swap PendingdHotkeyEmission
if PendingdHotkeyEmission::<T>::contains_key(old_hotkey) {
let old_pending_hotkey_emission = PendingdHotkeyEmission::<T>::get(old_hotkey);
PendingdHotkeyEmission::<T>::remove(old_hotkey);
PendingdHotkeyEmission::<T>::insert(new_hotkey, old_pending_hotkey_emission);
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
}

// 10. Swap all subnet specific info.
let all_netuids: Vec<u16> = Self::get_all_subnet_netuids();
for netuid in all_netuids {
// 9.1 Remove the previous hotkey and insert the new hotkey from membership.
// 10.1 Remove the previous hotkey and insert the new hotkey from membership.
// IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member.
let is_network_member: bool = IsNetworkMember::<T>::get(old_hotkey, netuid);
IsNetworkMember::<T>::remove(old_hotkey, netuid);
IsNetworkMember::<T>::insert(new_hotkey, netuid, is_network_member);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));

// 9.2 Swap Uids + Keys.
// 10.2 Swap Uids + Keys.
// Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member.
// Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has.
if is_network_member {
// 9.2.1 Swap the UIDS
// 10.2.1 Swap the UIDS
if let Ok(old_uid) = Uids::<T>::try_get(netuid, old_hotkey) {
Uids::<T>::remove(netuid, old_hotkey);
Uids::<T>::insert(netuid, new_hotkey, old_uid);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));

// 9.2.2 Swap the keys.
// 10.2.2 Swap the keys.
Keys::<T>::insert(netuid, old_uid, new_hotkey.clone());
weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1));
}
}

// 9.3 Swap Prometheus.
// 10.3 Swap Prometheus.
// Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network.
if is_network_member {
if let Ok(old_prometheus_info) = Prometheus::<T>::try_get(netuid, old_hotkey) {
Expand All @@ -242,7 +251,7 @@ impl<T: Config> Pallet<T> {
}
}

// 9.4. Swap axons.
// 10.4. Swap axons.
// Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has.
if is_network_member {
if let Ok(old_axon_info) = Axons::<T>::try_get(netuid, old_hotkey) {
Expand All @@ -252,7 +261,7 @@ impl<T: Config> Pallet<T> {
}
}

// 9.5 Swap WeightCommits
// 10.5 Swap WeightCommits
// WeightCommits( hotkey ) --> Vec<u64> -- the weight commits for the hotkey.
if is_network_member {
if let Ok(old_weight_commits) = WeightCommits::<T>::try_get(netuid, old_hotkey) {
Expand All @@ -262,7 +271,7 @@ impl<T: Config> Pallet<T> {
}
}

// 9.6. Swap the subnet loaded emission.
// 10.6. Swap the subnet loaded emission.
// LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet.
if is_network_member {
if let Some(mut old_loaded_emission) = LoadedEmission::<T>::get(netuid) {
Expand All @@ -277,7 +286,7 @@ impl<T: Config> Pallet<T> {
}
}

// 9.7. Swap neuron TLS certificates.
// 10.7. Swap neuron TLS certificates.
// NeuronCertificates( netuid, hotkey ) -> Vec<u8> -- the neuron certificate for the hotkey.
if is_network_member {
if let Ok(old_neuron_certificates) =
Expand All @@ -290,7 +299,7 @@ impl<T: Config> Pallet<T> {
}
}

// 10. Swap Stake.
// 11. Swap Stake.
// Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey.
let stakes: Vec<(T::AccountId, u64)> = Stake::<T>::iter_prefix(old_hotkey).collect();
// Clear the entire old prefix here.
Expand Down Expand Up @@ -320,7 +329,7 @@ impl<T: Config> Pallet<T> {
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
}

// 11. Swap ChildKeys.
// 12. Swap ChildKeys.
// ChildKeys( parent, netuid ) --> Vec<(proportion,child)> -- the child keys of the parent.
for netuid in Self::get_all_subnet_netuids() {
// Get the children of the old hotkey for this subnet
Expand All @@ -331,7 +340,7 @@ impl<T: Config> Pallet<T> {
ChildKeys::<T>::insert(new_hotkey, netuid, my_children);
}

// 12. Swap ParentKeys.
// 13. Swap ParentKeys.
// ParentKeys( child, netuid ) --> Vec<(proportion,parent)> -- the parent keys of the child.
for netuid in Self::get_all_subnet_netuids() {
// Get the parents of the old hotkey for this subnet
Expand All @@ -355,6 +364,19 @@ impl<T: Config> Pallet<T> {
}
}

// 14. Swap Stake Delta for all coldkeys.
for (coldkey, stake_delta) in StakeDeltaSinceLastEmissionDrain::<T>::iter_prefix(old_hotkey)
{
let new_stake_delta = StakeDeltaSinceLastEmissionDrain::<T>::get(new_hotkey, &coldkey);
StakeDeltaSinceLastEmissionDrain::<T>::insert(
new_hotkey,
&coldkey,
new_stake_delta.saturating_add(stake_delta),
);
StakeDeltaSinceLastEmissionDrain::<T>::remove(old_hotkey, &coldkey);
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
}

// Return successful after swapping all the relevant terms.
Ok(())
}
Expand Down
Loading