Skip to content

Commit 2b4610e

Browse files
authored
Merge pull request #885 from opentensor/devnet-ready
bring hotfix into devnet
2 parents 6f846a1 + 69b7ac8 commit 2b4610e

File tree

6 files changed

+90
-60
lines changed

6 files changed

+90
-60
lines changed

.github/workflows/check-rust.yml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,7 @@ jobs:
212212
cargo-audit:
213213
name: cargo audit
214214
runs-on: SubtensorCI
215-
strategy:
216-
matrix:
217-
rust-branch:
218-
- stable
219-
rust-target:
220-
- x86_64-unknown-linux-gnu
221-
# - x86_64-apple-darwin
222-
os:
223-
- ubuntu-latest
224-
# - macos-latest
215+
if: ${{ github.event_name != 'push' && !contains(github.event.pull_request.labels.*.name, 'skip-cargo-audit') }}
225216
steps:
226217
- name: Check-out repositoroy under $GITHUB_WORKSPACE
227218
uses: actions/checkout@v4
@@ -231,17 +222,17 @@ jobs:
231222
sudo apt-get update &&
232223
sudo apt-get install -y clang curl libssl-dev llvm libudev-dev protobuf-compiler
233224
234-
- name: Install Rust ${{ matrix.rust-branch }}
225+
- name: Install Rust Stable
235226
uses: actions-rs/[email protected]
236227
with:
237-
toolchain: ${{ matrix.rust-branch }}
228+
toolchain: stable
238229
components: rustfmt, clippy
239230
profile: minimal
240231

241232
- name: Utilize Shared Rust Cache
242233
uses: Swatinem/[email protected]
243234
with:
244-
key: ${{ matrix.os }}-${{ env.RUST_BIN_DIR }}
235+
key: ubuntu-latest-${{ env.RUST_BIN_DIR }}
245236

246237
- name: Install cargo-audit
247238
run: cargo install cargo-audit

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -265,69 +265,65 @@ impl<T: Config> Pallet<T> {
265265
// --- 1.0 Drain the hotkey emission.
266266
PendingdHotkeyEmission::<T>::insert(hotkey, 0);
267267

268-
// --- 2 Retrieve the last time this hotkey's emissions were drained.
269-
let last_emission_drain: u64 = LastHotkeyEmissionDrain::<T>::get(hotkey);
270-
271-
// --- 3 Update the block value to the current block number.
268+
// --- 2 Update the block value to the current block number.
272269
LastHotkeyEmissionDrain::<T>::insert(hotkey, block_number);
273270

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

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

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

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

289-
// --- 8 Iterate over each nominator and get all viable stake.
286+
// --- 7 Iterate over each nominator and get all viable stake.
290287
let mut total_viable_nominator_stake: u64 = total_hotkey_stake;
291-
for (nominator, nominator_stake) in Stake::<T>::iter_prefix(hotkey) {
292-
if LastAddStakeIncrease::<T>::get(hotkey, nominator) > last_emission_drain {
293-
total_viable_nominator_stake =
294-
total_viable_nominator_stake.saturating_sub(nominator_stake);
295-
}
288+
for (nominator, _) in Stake::<T>::iter_prefix(hotkey) {
289+
let nonviable_nomintaor_stake = Self::get_nonviable_stake(hotkey, &nominator);
290+
291+
total_viable_nominator_stake =
292+
total_viable_nominator_stake.saturating_sub(nonviable_nomintaor_stake);
296293
}
297294

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

307-
// --- 11 Calculate this nominator's share of the emission.
308-
let nominator_emission: I64F64 = I64F64::from_num(emission_minus_take)
309-
.saturating_mul(I64F64::from_num(nominator_stake))
303+
// --- 10 Calculate this nominator's share of the emission.
304+
let nominator_emission: I64F64 = I64F64::from_num(viable_nominator_stake)
310305
.checked_div(I64F64::from_num(total_viable_nominator_stake))
311-
.unwrap_or(I64F64::from_num(0));
306+
.unwrap_or(I64F64::from_num(0))
307+
.saturating_mul(I64F64::from_num(emission_minus_take));
312308

313-
// --- 12 Increase the stake for the nominator.
309+
// --- 11 Increase the stake for the nominator.
314310
Self::increase_stake_on_coldkey_hotkey_account(
315311
&nominator,
316312
hotkey,
317313
nominator_emission.to_num::<u64>(),
318314
);
319315

320-
// --- 13* Record event and Subtract the nominator's emission from the remainder.
316+
// --- 12* Record event and Subtract the nominator's emission from the remainder.
321317
total_new_tao = total_new_tao.saturating_add(nominator_emission.to_num::<u64>());
322318
remainder = remainder.saturating_sub(nominator_emission.to_num::<u64>());
323319
}
324320
}
325321

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

330-
// --- 15 Record new tao creation event and return the amount created.
326+
// --- 14 Record new tao creation event and return the amount created.
331327
total_new_tao = total_new_tao.saturating_add(hotkey_new_tao);
332328
total_new_tao
333329
}
@@ -382,4 +378,18 @@ impl<T: Config> Pallet<T> {
382378
let remainder = block_plus_netuid.rem_euclid(tempo_plus_one);
383379
(tempo as u64).saturating_sub(remainder)
384380
}
381+
382+
/// Calculates the nonviable stake for a nominator.
383+
/// The nonviable stake is the stake that was added by the nominator since the last emission drain.
384+
/// This stake will not receive emission until the next emission drain.
385+
/// Note: if the stake delta is below zero, we return zero. We don't allow more stake than the nominator has.
386+
pub fn get_nonviable_stake(hotkey: &T::AccountId, nominator: &T::AccountId) -> u64 {
387+
let stake_delta = StakeDeltaSinceLastEmissionDrain::<T>::get(hotkey, nominator);
388+
if stake_delta.is_negative() {
389+
0
390+
} else {
391+
// Should never fail the into, but we handle it anyway.
392+
stake_delta.try_into().unwrap_or(u64::MAX)
393+
}
394+
}
385395
}

pallets/subtensor/src/lib.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ pub mod pallet {
259259
0
260260
}
261261
#[pallet::type_value]
262+
/// Default stake delta.
263+
pub fn DefaultStakeDelta<T: Config>() -> i128 {
264+
0
265+
}
266+
#[pallet::type_value]
262267
/// Default stakes per interval.
263268
pub fn DefaultStakesPerInterval<T: Config>() -> (u64, u64) {
264269
(0, 0)
@@ -791,16 +796,16 @@ pub mod pallet {
791796
DefaultAccumulatedEmission<T>,
792797
>;
793798
#[pallet::storage]
794-
/// Map ( hot, cold ) --> block_number | Last add stake increase.
795-
pub type LastAddStakeIncrease<T: Config> = StorageDoubleMap<
799+
/// Map ( hot, cold ) --> stake: i128 | Stake added/removed since last emission drain.
800+
pub type StakeDeltaSinceLastEmissionDrain<T: Config> = StorageDoubleMap<
796801
_,
797802
Blake2_128Concat,
798803
T::AccountId,
799804
Identity,
800805
T::AccountId,
801-
u64,
806+
i128,
802807
ValueQuery,
803-
DefaultAccountTake<T>,
808+
DefaultStakeDelta<T>,
804809
>;
805810
#[pallet::storage]
806811
/// DMAP ( parent, netuid ) --> Vec<(proportion,child)>

pallets/subtensor/src/staking/add_stake.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ impl<T: Config> Pallet<T> {
7070
Error::<T>::StakeRateLimitExceeded
7171
);
7272

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

7678
// If coldkey is not owner of the hotkey, it's a nomination stake.
7779
if !Self::coldkey_owns_hotkey(&coldkey, &hotkey) {

pallets/subtensor/src/swap/swap_hotkey.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -206,33 +206,42 @@ impl<T: Config> Pallet<T> {
206206
Delegates::<T>::insert(new_hotkey, old_delegate_take);
207207
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
208208
}
209-
// 9. Swap all subnet specific info.
209+
210+
// 9. swap PendingdHotkeyEmission
211+
if PendingdHotkeyEmission::<T>::contains_key(old_hotkey) {
212+
let old_pending_hotkey_emission = PendingdHotkeyEmission::<T>::get(old_hotkey);
213+
PendingdHotkeyEmission::<T>::remove(old_hotkey);
214+
PendingdHotkeyEmission::<T>::insert(new_hotkey, old_pending_hotkey_emission);
215+
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
216+
}
217+
218+
// 10. Swap all subnet specific info.
210219
let all_netuids: Vec<u16> = Self::get_all_subnet_netuids();
211220
for netuid in all_netuids {
212-
// 9.1 Remove the previous hotkey and insert the new hotkey from membership.
221+
// 10.1 Remove the previous hotkey and insert the new hotkey from membership.
213222
// IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member.
214223
let is_network_member: bool = IsNetworkMember::<T>::get(old_hotkey, netuid);
215224
IsNetworkMember::<T>::remove(old_hotkey, netuid);
216225
IsNetworkMember::<T>::insert(new_hotkey, netuid, is_network_member);
217226
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
218227

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

229-
// 9.2.2 Swap the keys.
238+
// 10.2.2 Swap the keys.
230239
Keys::<T>::insert(netuid, old_uid, new_hotkey.clone());
231240
weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1));
232241
}
233242
}
234243

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

245-
// 9.4. Swap axons.
254+
// 10.4. Swap axons.
246255
// Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has.
247256
if is_network_member {
248257
if let Ok(old_axon_info) = Axons::<T>::try_get(netuid, old_hotkey) {
@@ -252,7 +261,7 @@ impl<T: Config> Pallet<T> {
252261
}
253262
}
254263

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

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

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

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

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

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

367+
// 14. Swap Stake Delta for all coldkeys.
368+
for (coldkey, stake_delta) in StakeDeltaSinceLastEmissionDrain::<T>::iter_prefix(old_hotkey)
369+
{
370+
let new_stake_delta = StakeDeltaSinceLastEmissionDrain::<T>::get(new_hotkey, &coldkey);
371+
StakeDeltaSinceLastEmissionDrain::<T>::insert(
372+
new_hotkey,
373+
&coldkey,
374+
new_stake_delta.saturating_add(stake_delta),
375+
);
376+
StakeDeltaSinceLastEmissionDrain::<T>::remove(old_hotkey, &coldkey);
377+
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));
378+
}
379+
358380
// Return successful after swapping all the relevant terms.
359381
Ok(())
360382
}

runtime/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
146146
// `spec_version`, and `authoring_version` are the same between Wasm and native.
147147
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
148148
// the compatible custom types.
149-
spec_version: 197,
149+
spec_version: 203,
150150
impl_version: 1,
151151
apis: RUNTIME_API_VERSIONS,
152152
transaction_version: 1,

0 commit comments

Comments
 (0)