Skip to content

Commit 2ff00c3

Browse files
authored
Merge pull request #1109 from opentensor/fix/pending-childkeys
Fix/pending childkeys
2 parents 85fa7dd + ff7d88b commit 2ff00c3

File tree

3 files changed

+122
-15
lines changed

3 files changed

+122
-15
lines changed

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl<T: Config> Pallet<T> {
6565
// --- 3. Drain the subnet block emission and accumulate it as subnet emission, which increases until the tempo is reached in #4.
6666
// subnet_blockwise_emission -> subnet_pending_emission
6767
for netuid in subnets.clone().iter() {
68-
if *netuid == 0 || !Self::is_registration_allowed(*netuid) {
68+
if *netuid == 0 || !Self::get_network_registration_allowed(*netuid) {
6969
continue;
7070
}
7171
// --- 3.1 Get the network's block-wise emission amount.
@@ -105,7 +105,10 @@ impl<T: Config> Pallet<T> {
105105
};
106106
}
107107

108-
// --- 4.3 Drain the subnet emission.
108+
// 4.3 Apply pending childkeys of this subnet for the next epoch
109+
Self::do_set_pending_children(*netuid);
110+
111+
// --- 4.4 Drain the subnet emission.
109112
let mut subnet_emission: u64 = PendingEmission::<T>::get(*netuid);
110113
PendingEmission::<T>::insert(*netuid, 0);
111114
log::debug!(
@@ -114,39 +117,39 @@ impl<T: Config> Pallet<T> {
114117
subnet_emission
115118
);
116119

117-
// --- 4.4 Set last step counter.
120+
// --- 4.5 Set last step counter.
118121
Self::set_blocks_since_last_step(*netuid, 0);
119122
Self::set_last_mechanism_step_block(*netuid, current_block);
120123

121-
if *netuid == 0 || !Self::is_registration_allowed(*netuid) {
124+
if *netuid == 0 || !Self::get_network_registration_allowed(*netuid) {
122125
// Skip netuid 0 payouts
123126
continue;
124127
}
125128

126-
// --- 4.5 Distribute owner take.
129+
// --- 4.6 Distribute owner take.
127130
if SubnetOwner::<T>::contains_key(netuid) {
128131
// Does the subnet have an owner?
129132

130-
// --- 4.5.1 Compute the subnet owner cut.
133+
// --- 4.6.1 Compute the subnet owner cut.
131134
let owner_cut: I96F32 = I96F32::from_num(subnet_emission).saturating_mul(
132135
I96F32::from_num(Self::get_subnet_owner_cut())
133136
.saturating_div(I96F32::from_num(u16::MAX)),
134137
);
135138

136-
// --- 4.5.2 Remove the cut from the subnet emission
139+
// --- 4.6.2 Remove the cut from the subnet emission
137140
subnet_emission = subnet_emission.saturating_sub(owner_cut.to_num::<u64>());
138141

139-
// --- 4.5.3 Add the cut to the balance of the owner
142+
// --- 4.6.3 Add the cut to the balance of the owner
140143
Self::add_balance_to_coldkey_account(
141144
&Self::get_subnet_owner(*netuid),
142145
owner_cut.to_num::<u64>(),
143146
);
144147

145-
// --- 4.5.4 Increase total issuance on the chain.
148+
// --- 4.6.4 Increase total issuance on the chain.
146149
Self::coinbase(owner_cut.to_num::<u64>());
147150
}
148151

149-
// 4.6 Pass emission through epoch() --> hotkey emission.
152+
// 4.7 Pass emission through epoch() --> hotkey emission.
150153
let hotkey_emission: Vec<(T::AccountId, u64, u64)> =
151154
Self::epoch(*netuid, subnet_emission);
152155
log::debug!(
@@ -155,7 +158,7 @@ impl<T: Config> Pallet<T> {
155158
hotkey_emission
156159
);
157160

158-
// 4.7 Accumulate the tuples on hotkeys:
161+
// 4.8 Accumulate the tuples on hotkeys:
159162
for (hotkey, mining_emission, validator_emission) in hotkey_emission {
160163
// 4.8 Accumulate the emission on the hotkey and parent hotkeys.
161164
Self::accumulate_hotkey_emission(
@@ -166,9 +169,6 @@ impl<T: Config> Pallet<T> {
166169
);
167170
log::debug!("Accumulated emissions on hotkey {:?} for netuid {:?}: mining {:?}, validator {:?}", hotkey, *netuid, mining_emission, validator_emission);
168171
}
169-
170-
// 4.5 Apply pending childkeys of this subnet for the next epoch
171-
Self::do_set_pending_children(*netuid);
172172
} else {
173173
// No epoch, increase blocks since last step and continue
174174
Self::set_blocks_since_last_step(

pallets/subtensor/src/staking/set_children.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,12 @@ impl<T: Config> Pallet<T> {
110110
}
111111

112112
// Check that the parent key has at least the minimum own stake
113+
// if children vector is not empty
113114
// (checking with check_weights_min_stake wouldn't work because it considers
114115
// grandparent stake in this case)
115116
ensure!(
116-
Self::get_total_stake_for_hotkey(&hotkey) >= StakeThreshold::<T>::get(),
117+
children.is_empty()
118+
|| Self::get_total_stake_for_hotkey(&hotkey) >= StakeThreshold::<T>::get(),
117119
Error::<T>::NotEnoughStakeToSetChildkeys
118120
);
119121

pallets/subtensor/src/tests/children.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3747,3 +3747,108 @@ fn test_do_set_child_cooldown_period() {
37473747
assert_eq!(children_after, vec![(proportion, child)]);
37483748
});
37493749
}
3750+
3751+
// Test that revoking childkeys does not require minimum stake
3752+
#[test]
3753+
fn test_revoke_child_no_min_stake_check() {
3754+
new_test_ext(1).execute_with(|| {
3755+
let coldkey = U256::from(1);
3756+
let parent = U256::from(2);
3757+
let child = U256::from(3);
3758+
let netuid: u16 = 1;
3759+
let proportion: u64 = 1000;
3760+
3761+
// Add network and register hotkey
3762+
add_network(netuid, 13, 0);
3763+
register_ok_neuron(netuid, parent, coldkey, 0);
3764+
3765+
// Set minimum stake for setting children
3766+
let parent_total_stake_original = TotalHotkeyStake::<Test>::get(parent);
3767+
StakeThreshold::<Test>::put(1_000_000_000_000);
3768+
TotalHotkeyStake::<Test>::insert(parent, StakeThreshold::<Test>::get());
3769+
3770+
// Schedule parent-child relationship
3771+
assert_ok!(SubtensorModule::do_schedule_children(
3772+
RuntimeOrigin::signed(coldkey),
3773+
parent,
3774+
netuid,
3775+
vec![(proportion, child)],
3776+
));
3777+
3778+
// Ensure the childkeys are not yet applied
3779+
let children_before = SubtensorModule::get_children(&parent, netuid);
3780+
assert_eq!(children_before, vec![]);
3781+
3782+
wait_and_set_pending_children(netuid);
3783+
TotalHotkeyStake::<Test>::insert(parent, parent_total_stake_original);
3784+
3785+
// Ensure the childkeys are applied
3786+
let children_after = SubtensorModule::get_children(&parent, netuid);
3787+
assert_eq!(children_after, vec![(proportion, child)]);
3788+
3789+
// Reduce the stake below required threshold
3790+
TotalHotkeyStake::<Test>::insert(parent, StakeThreshold::<Test>::get() - 1);
3791+
3792+
// Bypass tx rate limit
3793+
SubtensorModule::set_last_transaction_block_on_subnet(
3794+
&parent,
3795+
netuid,
3796+
&TransactionType::SetChildren,
3797+
0,
3798+
);
3799+
3800+
// Schedule parent-child relationship revokation
3801+
assert_ok!(SubtensorModule::do_schedule_children(
3802+
RuntimeOrigin::signed(coldkey),
3803+
parent,
3804+
netuid,
3805+
vec![],
3806+
));
3807+
3808+
wait_and_set_pending_children(netuid);
3809+
TotalHotkeyStake::<Test>::insert(parent, parent_total_stake_original);
3810+
3811+
// Ensure the childkeys are revoked
3812+
let children_after = SubtensorModule::get_children(&parent, netuid);
3813+
assert_eq!(children_after, vec![]);
3814+
});
3815+
}
3816+
3817+
// Test that setting childkeys works even if subnet registration is disabled
3818+
#[test]
3819+
fn test_do_set_child_registration_disabled() {
3820+
new_test_ext(1).execute_with(|| {
3821+
let coldkey = U256::from(1);
3822+
let parent = U256::from(2);
3823+
let child = U256::from(3);
3824+
let netuid: u16 = 1;
3825+
let proportion: u64 = 1000;
3826+
3827+
// Add network and register hotkey
3828+
add_network(netuid, 13, 0);
3829+
register_ok_neuron(netuid, parent, coldkey, 0);
3830+
3831+
// Set minimum stake for setting children
3832+
let parent_total_stake_original = TotalHotkeyStake::<Test>::get(parent);
3833+
StakeThreshold::<Test>::put(1_000_000_000_000);
3834+
TotalHotkeyStake::<Test>::insert(parent, StakeThreshold::<Test>::get());
3835+
3836+
// Disable subnet registrations
3837+
NetworkRegistrationAllowed::<Test>::insert(netuid, false);
3838+
3839+
// Schedule parent-child relationship
3840+
assert_ok!(SubtensorModule::do_schedule_children(
3841+
RuntimeOrigin::signed(coldkey),
3842+
parent,
3843+
netuid,
3844+
vec![(proportion, child)],
3845+
));
3846+
3847+
wait_and_set_pending_children(netuid);
3848+
TotalHotkeyStake::<Test>::insert(parent, parent_total_stake_original);
3849+
3850+
// Ensure the childkeys are applied
3851+
let children_after = SubtensorModule::get_children(&parent, netuid);
3852+
assert_eq!(children_after, vec![(proportion, child)]);
3853+
});
3854+
}

0 commit comments

Comments
 (0)