Skip to content

Commit b179867

Browse files
authored
Merge pull request #2191 from opentensor/hotfix/vune/recycle-root-alpha-if-no-root-sell
Hotfix/vune/recycle root alpha if no root sell
2 parents 6a76ecc + e931123 commit b179867

File tree

15 files changed

+236
-79
lines changed

15 files changed

+236
-79
lines changed

pallets/subtensor/src/benchmarks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,7 @@ mod pallet_benchmarks {
16191619
netuid,
16201620
AlphaCurrency::ZERO,
16211621
pending_root_alpha.into(),
1622+
pending_root_alpha.into(),
16221623
AlphaCurrency::ZERO,
16231624
);
16241625

pallets/subtensor/src/coinbase/root.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ impl<T: Config> Pallet<T> {
314314

315315
// --- 15. Mechanism step / emissions bookkeeping.
316316
FirstEmissionBlockNumber::<T>::remove(netuid);
317-
PendingEmission::<T>::remove(netuid);
317+
PendingValidatorEmission::<T>::remove(netuid);
318+
PendingServerEmission::<T>::remove(netuid);
318319
PendingRootAlphaDivs::<T>::remove(netuid);
319320
PendingOwnerCut::<T>::remove(netuid);
320321
BlocksSinceLastStep::<T>::remove(netuid);

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -195,37 +195,48 @@ impl<T: Config> Pallet<T> {
195195
let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0));
196196
log::debug!("alpha_out_i: {alpha_out_i:?}");
197197

198-
// Get root proportion of alpha_out dividends.
199-
let mut root_alpha: U96F32 = asfloat!(0.0);
198+
// Get ALPHA issuance.
199+
let alpha_issuance: U96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i));
200+
log::debug!("alpha_issuance: {alpha_issuance:?}");
201+
202+
// Get root proportional dividends.
203+
let root_proportion: U96F32 = tao_weight
204+
.checked_div(tao_weight.saturating_add(alpha_issuance))
205+
.unwrap_or(asfloat!(0.0));
206+
log::debug!("root_proportion: {root_proportion:?}");
207+
208+
// Get root alpha from root prop.
209+
let root_alpha: U96F32 = root_proportion
210+
.saturating_mul(alpha_out_i) // Total alpha emission per block remaining.
211+
.saturating_mul(asfloat!(0.5)); // 50% to validators.
212+
log::debug!("root_alpha: {root_alpha:?}");
213+
200214
if root_sell_flag {
201-
// Get ALPHA issuance.
202-
let alpha_issuance: U96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i));
203-
log::debug!("alpha_issuance: {alpha_issuance:?}");
204-
205-
// Get root proportional dividends.
206-
let root_proportion: U96F32 = tao_weight
207-
.checked_div(tao_weight.saturating_add(alpha_issuance))
208-
.unwrap_or(asfloat!(0.0));
209-
log::debug!("root_proportion: {root_proportion:?}");
210-
211-
// Get root alpha from root prop.
212-
root_alpha = root_proportion
213-
.saturating_mul(alpha_out_i) // Total alpha emission per block remaining.
214-
.saturating_mul(asfloat!(0.5)); // 50% to validators.
215+
// Only accumulate root alpha divs if root sell is allowed.
215216
PendingRootAlphaDivs::<T>::mutate(*netuid_i, |total| {
216217
*total = total.saturating_add(tou64!(root_alpha).into());
217218
});
219+
} else {
220+
// If we are not selling the root alpha, we should recycle it.
221+
Self::recycle_subnet_alpha(*netuid_i, AlphaCurrency::from(tou64!(root_alpha)));
218222
}
219-
// Remove root alpha from alpha_out.
220-
log::debug!("root_alpha: {root_alpha:?}");
221223

222-
// Get pending alpha as original alpha_out - root_alpha.
223-
let pending_alpha: U96F32 = alpha_out_i.saturating_sub(root_alpha);
224-
log::debug!("pending_alpha: {pending_alpha:?}");
224+
// Get pending server alpha, which is the miner cut of the alpha out.
225+
// Currently miner cut is 50% of the alpha out.
226+
let pending_server_alpha = alpha_out_i.saturating_mul(asfloat!(0.5));
227+
// The total validator alpha is the remaining alpha out minus the server alpha.
228+
let total_validator_alpha = alpha_out_i.saturating_sub(pending_server_alpha);
225229

226-
// Accumulate alpha emission in pending.
227-
PendingEmission::<T>::mutate(*netuid_i, |total| {
228-
*total = total.saturating_add(tou64!(pending_alpha).into());
230+
// The alpha validators don't get the root alpha.
231+
let pending_validator_alpha = total_validator_alpha.saturating_sub(root_alpha);
232+
233+
// Accumulate the server alpha emission.
234+
PendingServerEmission::<T>::mutate(*netuid_i, |total| {
235+
*total = total.saturating_add(tou64!(pending_server_alpha).into());
236+
});
237+
// Accumulate the validator alpha emission.
238+
PendingValidatorEmission::<T>::mutate(*netuid_i, |total| {
239+
*total = total.saturating_add(tou64!(pending_validator_alpha).into());
229240
});
230241
}
231242

@@ -252,8 +263,11 @@ impl<T: Config> Pallet<T> {
252263
LastMechansimStepBlock::<T>::insert(netuid, current_block);
253264

254265
// Get and drain the subnet pending emission.
255-
let pending_alpha = PendingEmission::<T>::get(netuid);
256-
PendingEmission::<T>::insert(netuid, AlphaCurrency::ZERO);
266+
let pending_server_alpha = PendingServerEmission::<T>::get(netuid);
267+
PendingServerEmission::<T>::insert(netuid, AlphaCurrency::ZERO);
268+
269+
let pending_validator_alpha = PendingValidatorEmission::<T>::get(netuid);
270+
PendingValidatorEmission::<T>::insert(netuid, AlphaCurrency::ZERO);
257271

258272
// Get and drain the subnet pending root alpha divs.
259273
let pending_root_alpha = PendingRootAlphaDivs::<T>::get(netuid);
@@ -264,7 +278,13 @@ impl<T: Config> Pallet<T> {
264278
PendingOwnerCut::<T>::insert(netuid, AlphaCurrency::ZERO);
265279

266280
// Distribute the emission.
267-
Self::distribute_emission(netuid, pending_alpha, pending_root_alpha, owner_cut);
281+
Self::distribute_emission(
282+
netuid,
283+
pending_server_alpha,
284+
pending_validator_alpha,
285+
pending_root_alpha,
286+
owner_cut,
287+
);
268288
} else {
269289
// Increment
270290
BlocksSinceLastStep::<T>::mutate(netuid, |total| *total = total.saturating_add(1));
@@ -633,20 +653,23 @@ impl<T: Config> Pallet<T> {
633653

634654
pub fn distribute_emission(
635655
netuid: NetUid,
636-
pending_alpha: AlphaCurrency,
656+
pending_server_alpha: AlphaCurrency,
657+
pending_validator_alpha: AlphaCurrency,
637658
pending_root_alpha: AlphaCurrency,
638-
owner_cut: AlphaCurrency,
659+
pending_owner_cut: AlphaCurrency,
639660
) {
640661
log::debug!(
641-
"Draining pending alpha emission for netuid {netuid:?}, pending_alpha: {pending_alpha:?}, pending_root_alpha: {pending_root_alpha:?}, owner_cut: {owner_cut:?}"
662+
"Draining pending alpha emission for netuid {netuid:?}, pending_server_alpha: {pending_server_alpha:?}, pending_validator_alpha: {pending_validator_alpha:?}, pending_root_alpha: {pending_root_alpha:?}, pending_owner_cut: {pending_owner_cut:?}"
642663
);
643664

644665
let tao_weight = Self::get_tao_weight();
645-
let total_alpha = pending_alpha.saturating_add(pending_root_alpha);
666+
let total_alpha_minus_owner_cut = pending_server_alpha
667+
.saturating_add(pending_validator_alpha)
668+
.saturating_add(pending_root_alpha);
646669

647-
// Run the epoch.
670+
// Run the epoch, using the alpha going to both the servers and the validators.
648671
let hotkey_emission: Vec<(T::AccountId, AlphaCurrency, AlphaCurrency)> =
649-
Self::epoch_with_mechanisms(netuid, total_alpha);
672+
Self::epoch_with_mechanisms(netuid, total_alpha_minus_owner_cut);
650673
log::debug!("hotkey_emission: {hotkey_emission:?}");
651674

652675
// Compute the pending validator alpha.
@@ -661,20 +684,20 @@ impl<T: Config> Pallet<T> {
661684
});
662685
log::debug!("incentive_sum: {incentive_sum:?}");
663686

664-
let pending_validator_alpha = if !incentive_sum.is_zero() {
665-
total_alpha
666-
.saturating_div(2.into())
667-
.saturating_sub(pending_root_alpha)
687+
let validator_alpha = if !incentive_sum.is_zero() {
688+
pending_validator_alpha
668689
} else {
669-
// If the incentive is 0, then Validators get 100% of the alpha.
670-
pending_alpha
690+
// If the incentive is 0, then Alpha Validators get both the server and validator alpha.
691+
pending_validator_alpha.saturating_add(pending_server_alpha)
671692
};
693+
let root_alpha = pending_root_alpha;
694+
let owner_cut = pending_owner_cut;
672695

673696
let (incentives, (alpha_dividends, root_alpha_dividends)) =
674697
Self::calculate_dividend_and_incentive_distribution(
675698
netuid,
676-
pending_root_alpha,
677-
pending_validator_alpha,
699+
root_alpha,
700+
validator_alpha,
678701
hotkey_emission,
679702
tao_weight,
680703
);

pallets/subtensor/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,9 +1430,13 @@ pub mod pallet {
14301430
pub type NetworkRegisteredAt<T: Config> =
14311431
StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultNetworkRegisteredAt<T>>;
14321432
#[pallet::storage]
1433-
/// --- MAP ( netuid ) --> pending_emission
1434-
pub type PendingEmission<T> =
1435-
StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultPendingEmission<T>>;
1433+
/// --- MAP ( netuid ) --> pending_server_emission
1434+
pub type PendingServerEmission<T> =
1435+
StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha<T>>;
1436+
/// --- MAP ( netuid ) --> pending_validator_emission
1437+
#[pallet::storage]
1438+
pub type PendingValidatorEmission<T> =
1439+
StorageMap<_, Identity, NetUid, AlphaCurrency, ValueQuery, DefaultZeroAlpha<T>>;
14361440
/// --- MAP ( netuid ) --> pending_root_alpha_emission
14371441
#[pallet::storage]
14381442
pub type PendingRootAlphaDivs<T> =

pallets/subtensor/src/macros/hooks.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ mod hooks {
161161
// Remove obsolete map entries
162162
.saturating_add(migrations::migrate_remove_tao_dividends::migrate_remove_tao_dividends::<T>())
163163
// Re-init tao flows
164-
.saturating_add(migrations::migrate_init_tao_flow::migrate_init_tao_flow::<T>());
164+
.saturating_add(migrations::migrate_init_tao_flow::migrate_init_tao_flow::<T>())
165+
// Migrate pending emissions
166+
.saturating_add(migrations::migrate_pending_emissions::migrate_pending_emissions::<T>());
165167
weight
166168
}
167169

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use super::*;
2+
use frame_support::{storage_alias, traits::Get, weights::Weight};
3+
use substrate_fixed::types::U96F32;
4+
5+
pub mod deprecated_pending_emission_format {
6+
use super::*;
7+
8+
#[storage_alias]
9+
pub(super) type PendingEmission<T: Config> =
10+
StorageMap<Pallet<T>, Identity, NetUid, AlphaCurrency, ValueQuery>;
11+
}
12+
13+
pub fn migrate_pending_emissions<T: Config>() -> Weight {
14+
let migration_name = b"migrate_pending_emissions".to_vec();
15+
let mut weight: Weight = T::DbWeight::get().reads(1);
16+
17+
// Skip if already executed
18+
if HasMigrationRun::<T>::get(&migration_name) {
19+
log::info!(
20+
target: "runtime",
21+
"Migration '{}' already run - skipping.",
22+
String::from_utf8_lossy(&migration_name)
23+
);
24+
return weight;
25+
}
26+
log::info!(
27+
"Running migration '{}'",
28+
String::from_utf8_lossy(&migration_name)
29+
);
30+
31+
// Pull from PendingEmission and distribute to PendingValidatorEmission and PendingServerEmission
32+
for (netuid, pending_emission) in
33+
deprecated_pending_emission_format::PendingEmission::<T>::iter()
34+
{
35+
// Split up the pending emission into server and validator emission
36+
// Server emission is pending+root_alpha times the 50% miner cut.
37+
let root_alpha: U96F32 =
38+
U96F32::saturating_from_num(PendingRootAlphaDivs::<T>::get(netuid).to_u64());
39+
let server_emission_float: U96F32 = U96F32::saturating_from_num(pending_emission.to_u64())
40+
.saturating_add(root_alpha)
41+
.saturating_div(U96F32::saturating_from_num(2));
42+
let server_emission: AlphaCurrency =
43+
server_emission_float.saturating_to_num::<u64>().into();
44+
let validator_emission = pending_emission.saturating_sub(server_emission);
45+
46+
PendingValidatorEmission::<T>::mutate(netuid, |total| {
47+
*total = total.saturating_add(validator_emission)
48+
});
49+
PendingServerEmission::<T>::mutate(netuid, |total| {
50+
*total = total.saturating_add(server_emission)
51+
});
52+
53+
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 2));
54+
}
55+
56+
// Kill the map
57+
let removal_result =
58+
deprecated_pending_emission_format::PendingEmission::<T>::clear(u32::MAX, None);
59+
weight = weight.saturating_add(
60+
T::DbWeight::get().reads_writes(removal_result.loops as u64, removal_result.backend as u64),
61+
);
62+
63+
// Mark Migration as Completed
64+
HasMigrationRun::<T>::insert(&migration_name, true);
65+
weight = weight.saturating_add(T::DbWeight::get().writes(1));
66+
67+
log::info!(
68+
"Migration '{:?}' completed successfully.",
69+
String::from_utf8_lossy(&migration_name)
70+
);
71+
72+
weight
73+
}

pallets/subtensor/src/migrations/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub mod migrate_network_immunity_period;
2727
pub mod migrate_network_lock_cost_2500;
2828
pub mod migrate_network_lock_reduction_interval;
2929
pub mod migrate_orphaned_storage_items;
30+
pub mod migrate_pending_emissions;
3031
pub mod migrate_populate_owned_hotkeys;
3132
pub mod migrate_rao;
3233
pub mod migrate_rate_limit_keys;

pallets/subtensor/src/rpc_info/dynamic_info.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ impl<T: Config> Pallet<T> {
6262
alpha_out_emission: SubnetAlphaOutEmission::<T>::get(netuid).into(),
6363
alpha_in_emission: SubnetAlphaInEmission::<T>::get(netuid).into(),
6464
tao_in_emission: SubnetTaoInEmission::<T>::get(netuid).into(),
65-
pending_alpha_emission: PendingEmission::<T>::get(netuid).into(),
65+
pending_alpha_emission: PendingValidatorEmission::<T>::get(netuid)
66+
.saturating_add(PendingServerEmission::<T>::get(netuid))
67+
.into(),
6668
pending_root_emission: TaoCurrency::from(0u64).into(),
6769
subnet_volume: SubnetVolume::<T>::get(netuid).into(),
6870
network_registered_at: NetworkRegisteredAt::<T>::get(netuid).into(),

pallets/subtensor/src/rpc_info/metagraph.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,9 @@ impl<T: Config> Pallet<T> {
694694
alpha_out_emission: SubnetAlphaOutEmission::<T>::get(netuid).into(), // amount injected in alpha reserves per block
695695
alpha_in_emission: SubnetAlphaInEmission::<T>::get(netuid).into(), // amount injected outstanding per block
696696
tao_in_emission: SubnetTaoInEmission::<T>::get(netuid).into(), // amount of tao injected per block
697-
pending_alpha_emission: PendingEmission::<T>::get(netuid).into(), // pending alpha to be distributed
697+
pending_alpha_emission: PendingValidatorEmission::<T>::get(netuid)
698+
.saturating_add(PendingServerEmission::<T>::get(netuid))
699+
.into(), // pending alpha to be distributed
698700
pending_root_emission: TaoCurrency::from(0u64).into(), // panding tao for root divs to be distributed
699701
subnet_volume: subnet_volume.into(),
700702
moving_price: SubnetMovingPrice::<T>::get(netuid),
@@ -1000,7 +1002,11 @@ impl<T: Config> Pallet<T> {
10001002
},
10011003
Some(SelectiveMetagraphIndex::PendingAlphaEmission) => SelectiveMetagraph {
10021004
netuid: netuid.into(),
1003-
pending_alpha_emission: Some(PendingEmission::<T>::get(netuid).into()),
1005+
pending_alpha_emission: Some(
1006+
PendingValidatorEmission::<T>::get(netuid)
1007+
.saturating_add(PendingServerEmission::<T>::get(netuid))
1008+
.into(),
1009+
),
10041010
..Default::default()
10051011
},
10061012
Some(SelectiveMetagraphIndex::PendingRootEmission) => SelectiveMetagraph {

pallets/subtensor/src/tests/children.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3095,7 +3095,8 @@ fn test_parent_child_chain_emission() {
30953095
);
30963096

30973097
// Set pending emission to 0
3098-
PendingEmission::<Test>::insert(netuid, AlphaCurrency::ZERO);
3098+
PendingValidatorEmission::<Test>::insert(netuid, AlphaCurrency::ZERO);
3099+
PendingServerEmission::<Test>::insert(netuid, AlphaCurrency::ZERO);
30993100

31003101
// Run epoch with emission value
31013102
SubtensorModule::run_coinbase(emission);

0 commit comments

Comments
 (0)