Skip to content

Commit 259a0ec

Browse files
authored
Merge pull request #1465 from opentensor/devnet-ready
devnet deploy 3/25/2025
2 parents 1047a72 + eb9549f commit 259a0ec

File tree

6 files changed

+293
-35
lines changed

6 files changed

+293
-35
lines changed

pallets/admin-utils/src/tests/mock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ parameter_types! {
8686
pub const InitialImmunityPeriod: u16 = 2;
8787
pub const InitialMaxAllowedUids: u16 = 2;
8888
pub const InitialBondsMovingAverage: u64 = 900_000;
89-
pub const InitialBondsPenalty: u16 = 0;
89+
pub const InitialBondsPenalty: u16 = u16::MAX;
9090
pub const InitialStakePruningMin: u16 = 0;
9191
pub const InitialFoundationDistribution: u64 = 0;
9292
pub const InitialDefaultDelegateTake: u16 = 11_796; // 18% honest number.

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,24 @@ impl<T: Config> Pallet<T> {
3737
let current_block: u64 = Self::get_current_block_as_u64();
3838
log::debug!("Current block: {:?}", current_block);
3939

40-
// --- 1. Get all netuids (filter out root and new subnet without first emission block)
40+
// --- 1. Get all netuids (filter out root)
4141
let subnets: Vec<u16> = Self::get_all_subnet_netuids()
4242
.into_iter()
4343
.filter(|netuid| *netuid != 0)
44-
.filter(|netuid| FirstEmissionBlockNumber::<T>::get(*netuid).is_some())
4544
.collect();
4645
log::debug!("All subnet netuids: {:?}", subnets);
46+
// Filter out subnets with no first emission block number.
47+
let subnets_to_emit_to: Vec<u16> = subnets
48+
.clone()
49+
.into_iter()
50+
.filter(|netuid| FirstEmissionBlockNumber::<T>::get(*netuid).is_some())
51+
.collect();
52+
log::debug!("Subnets to emit to: {:?}", subnets_to_emit_to);
4753

4854
// --- 2. Get sum of tao reserves ( in a later version we will switch to prices. )
4955
let mut total_moving_prices: I96F32 = I96F32::saturating_from_num(0.0);
50-
for netuid_i in subnets.iter() {
56+
// Only get price EMA for subnets that we emit to.
57+
for netuid_i in subnets_to_emit_to.iter() {
5158
// Get and update the moving price of each subnet adding the total together.
5259
total_moving_prices =
5360
total_moving_prices.saturating_add(Self::get_moving_alpha_price(*netuid_i));
@@ -59,7 +66,8 @@ impl<T: Config> Pallet<T> {
5966
let mut tao_in: BTreeMap<u16, I96F32> = BTreeMap::new();
6067
let mut alpha_in: BTreeMap<u16, I96F32> = BTreeMap::new();
6168
let mut alpha_out: BTreeMap<u16, I96F32> = BTreeMap::new();
62-
for netuid_i in subnets.iter() {
69+
// Only calculate for subnets that we are emitting to.
70+
for netuid_i in subnets_to_emit_to.iter() {
6371
// Get subnet price.
6472
let price_i: I96F32 = Self::get_alpha_price(*netuid_i);
6573
log::debug!("price_i: {:?}", price_i);
@@ -104,7 +112,7 @@ impl<T: Config> Pallet<T> {
104112
// --- 4. Injection.
105113
// Actually perform the injection of alpha_in, alpha_out and tao_in into the subnet pool.
106114
// This operation changes the pool liquidity each block.
107-
for netuid_i in subnets.iter() {
115+
for netuid_i in subnets_to_emit_to.iter() {
108116
// Inject Alpha in.
109117
let alpha_in_i: u64 = tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0)));
110118
SubnetAlphaInEmission::<T>::insert(*netuid_i, alpha_in_i);
@@ -136,7 +144,7 @@ impl<T: Config> Pallet<T> {
136144
// Owner cuts are accumulated and then fed to the drain at the end of this func.
137145
let cut_percent: I96F32 = Self::get_float_subnet_owner_cut();
138146
let mut owner_cuts: BTreeMap<u16, I96F32> = BTreeMap::new();
139-
for netuid_i in subnets.iter() {
147+
for netuid_i in subnets_to_emit_to.iter() {
140148
// Get alpha out.
141149
let alpha_out_i: I96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0));
142150
log::debug!("alpha_out_i: {:?}", alpha_out_i);
@@ -155,7 +163,7 @@ impl<T: Config> Pallet<T> {
155163

156164
// --- 6. Seperate out root dividends in alpha and sell them into tao.
157165
// Then accumulate those dividends for later.
158-
for netuid_i in subnets.iter() {
166+
for netuid_i in subnets_to_emit_to.iter() {
159167
// Get remaining alpha out.
160168
let alpha_out_i: I96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0));
161169
log::debug!("alpha_out_i: {:?}", alpha_out_i);
@@ -200,12 +208,14 @@ impl<T: Config> Pallet<T> {
200208
}
201209

202210
// --- 7 Update moving prices after using them in the emission calculation.
203-
for netuid_i in subnets.iter() {
211+
// Only update price EMA for subnets that we emit to.
212+
for netuid_i in subnets_to_emit_to.iter() {
204213
// Update moving prices after using them above.
205214
Self::update_moving_price(*netuid_i);
206215
}
207216

208217
// --- 7. Drain pending emission through the subnet based on tempo.
218+
// Run the epoch for *all* subnets, even if we don't emit anything.
209219
for &netuid in subnets.iter() {
210220
// Pass on subnets that have not reached their tempo.
211221
if Self::should_run_epoch(netuid, current_block) {

pallets/subtensor/src/tests/coinbase.rs

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,3 +1889,245 @@ fn test_drain_pending_emission_no_miners_all_drained() {
18891889
assert_abs_diff_eq!(new_stake, emission.saturating_add(init_stake), epsilon = 1);
18901890
});
18911891
}
1892+
1893+
#[test]
1894+
fn test_drain_pending_emission_zero_emission() {
1895+
new_test_ext(1).execute_with(|| {
1896+
let netuid = add_dynamic_network(&U256::from(1), &U256::from(2));
1897+
let hotkey = U256::from(3);
1898+
let coldkey = U256::from(4);
1899+
let miner_hk = U256::from(5);
1900+
let miner_ck = U256::from(6);
1901+
let init_stake: u64 = 100_000_000_000_000;
1902+
let tempo = 2;
1903+
SubtensorModule::set_tempo(netuid, tempo);
1904+
// Set weight-set limit to 0.
1905+
SubtensorModule::set_weights_set_rate_limit(netuid, 0);
1906+
1907+
register_ok_neuron(netuid, hotkey, coldkey, 0);
1908+
register_ok_neuron(netuid, miner_hk, miner_ck, 0);
1909+
// Give non-zero stake
1910+
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
1911+
&hotkey, &coldkey, netuid, init_stake,
1912+
);
1913+
assert_eq!(
1914+
SubtensorModule::get_total_stake_for_hotkey(&hotkey),
1915+
init_stake
1916+
);
1917+
1918+
// Set the weight of root TAO to be 0%, so only alpha is effective.
1919+
SubtensorModule::set_tao_weight(0);
1920+
1921+
run_to_block_no_epoch(netuid, 50);
1922+
1923+
// Run epoch for initial setup.
1924+
SubtensorModule::epoch(netuid, 0);
1925+
1926+
// Set weights on miner
1927+
assert_ok!(SubtensorModule::set_weights(
1928+
RuntimeOrigin::signed(hotkey),
1929+
netuid,
1930+
vec![0, 1, 2],
1931+
vec![0, 0, 1],
1932+
0,
1933+
));
1934+
1935+
run_to_block_no_epoch(netuid, 50);
1936+
1937+
// Clear incentive and dividends.
1938+
Incentive::<Test>::remove(netuid);
1939+
Dividends::<Test>::remove(netuid);
1940+
1941+
// Set the emission to be ZERO.
1942+
SubtensorModule::drain_pending_emission(netuid, 0, 0, 0, 0);
1943+
1944+
// Get the new stake of the hotkey.
1945+
let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey);
1946+
// We expect the stake to remain unchanged.
1947+
assert_eq!(new_stake, init_stake);
1948+
1949+
// Check that the incentive and dividends are set by epoch.
1950+
assert!(Incentive::<Test>::get(netuid).iter().sum::<u16>() > 0);
1951+
assert!(Dividends::<Test>::get(netuid).iter().sum::<u16>() > 0);
1952+
});
1953+
}
1954+
1955+
#[test]
1956+
fn test_run_coinbase_not_started() {
1957+
new_test_ext(1).execute_with(|| {
1958+
let netuid = 1;
1959+
let tempo = 2;
1960+
1961+
let sn_owner_hk = U256::from(7);
1962+
let sn_owner_ck = U256::from(8);
1963+
1964+
add_network_without_emission_block(netuid, tempo, 0);
1965+
assert_eq!(FirstEmissionBlockNumber::<Test>::get(netuid), None);
1966+
1967+
SubnetOwner::<Test>::insert(netuid, sn_owner_ck);
1968+
SubnetOwnerHotkey::<Test>::insert(netuid, sn_owner_hk);
1969+
1970+
let hotkey = U256::from(3);
1971+
let coldkey = U256::from(4);
1972+
let miner_hk = U256::from(5);
1973+
let miner_ck = U256::from(6);
1974+
let init_stake: u64 = 100_000_000_000_000;
1975+
let tempo = 2;
1976+
SubtensorModule::set_tempo(netuid, tempo);
1977+
// Set weight-set limit to 0.
1978+
SubtensorModule::set_weights_set_rate_limit(netuid, 0);
1979+
1980+
register_ok_neuron(netuid, hotkey, coldkey, 0);
1981+
register_ok_neuron(netuid, miner_hk, miner_ck, 0);
1982+
register_ok_neuron(netuid, sn_owner_hk, sn_owner_ck, 0);
1983+
// Give non-zero stake
1984+
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
1985+
&hotkey, &coldkey, netuid, init_stake,
1986+
);
1987+
assert_eq!(
1988+
SubtensorModule::get_total_stake_for_hotkey(&hotkey),
1989+
init_stake
1990+
);
1991+
1992+
// Set the weight of root TAO to be 0%, so only alpha is effective.
1993+
SubtensorModule::set_tao_weight(0);
1994+
1995+
run_to_block_no_epoch(netuid, 30);
1996+
1997+
// Run epoch for initial setup.
1998+
SubtensorModule::epoch(netuid, 0);
1999+
2000+
// Set weights on miner
2001+
assert_ok!(SubtensorModule::set_weights(
2002+
RuntimeOrigin::signed(hotkey),
2003+
netuid,
2004+
vec![0, 1, 2],
2005+
vec![0, 0, 1],
2006+
0,
2007+
));
2008+
2009+
// Clear incentive and dividends.
2010+
Incentive::<Test>::remove(netuid);
2011+
Dividends::<Test>::remove(netuid);
2012+
2013+
// Step so tempo should run.
2014+
next_block_no_epoch(netuid);
2015+
next_block_no_epoch(netuid);
2016+
next_block_no_epoch(netuid);
2017+
let current_block = System::block_number();
2018+
assert!(SubtensorModule::should_run_epoch(netuid, current_block));
2019+
2020+
// Run coinbase with emission.
2021+
SubtensorModule::run_coinbase(I96F32::saturating_from_num(100_000_000));
2022+
2023+
// We expect that the epoch ran.
2024+
assert_eq!(BlocksSinceLastStep::<Test>::get(netuid), 0);
2025+
2026+
// Get the new stake of the hotkey. We expect no emissions.
2027+
let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey);
2028+
// We expect the stake to remain unchanged.
2029+
assert_eq!(new_stake, init_stake);
2030+
2031+
// Check that the incentive and dividends are set.
2032+
assert!(Incentive::<Test>::get(netuid).iter().sum::<u16>() > 0);
2033+
assert!(Dividends::<Test>::get(netuid).iter().sum::<u16>() > 0);
2034+
});
2035+
}
2036+
2037+
#[test]
2038+
fn test_run_coinbase_not_started_start_after() {
2039+
new_test_ext(1).execute_with(|| {
2040+
let netuid = 1;
2041+
let tempo = 2;
2042+
2043+
let sn_owner_hk = U256::from(7);
2044+
let sn_owner_ck = U256::from(8);
2045+
2046+
add_network_without_emission_block(netuid, tempo, 0);
2047+
assert_eq!(FirstEmissionBlockNumber::<Test>::get(netuid), None);
2048+
2049+
SubnetOwner::<Test>::insert(netuid, sn_owner_ck);
2050+
SubnetOwnerHotkey::<Test>::insert(netuid, sn_owner_hk);
2051+
2052+
let hotkey = U256::from(3);
2053+
let coldkey = U256::from(4);
2054+
let miner_hk = U256::from(5);
2055+
let miner_ck = U256::from(6);
2056+
let init_stake: u64 = 100_000_000_000_000;
2057+
let tempo = 2;
2058+
SubtensorModule::set_tempo(netuid, tempo);
2059+
// Set weight-set limit to 0.
2060+
SubtensorModule::set_weights_set_rate_limit(netuid, 0);
2061+
2062+
register_ok_neuron(netuid, hotkey, coldkey, 0);
2063+
register_ok_neuron(netuid, miner_hk, miner_ck, 0);
2064+
register_ok_neuron(netuid, sn_owner_hk, sn_owner_ck, 0);
2065+
// Give non-zero stake
2066+
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
2067+
&hotkey, &coldkey, netuid, init_stake,
2068+
);
2069+
assert_eq!(
2070+
SubtensorModule::get_total_stake_for_hotkey(&hotkey),
2071+
init_stake
2072+
);
2073+
2074+
// Set the weight of root TAO to be 0%, so only alpha is effective.
2075+
SubtensorModule::set_tao_weight(0);
2076+
2077+
run_to_block_no_epoch(netuid, 30);
2078+
2079+
// Run epoch for initial setup.
2080+
SubtensorModule::epoch(netuid, 0);
2081+
2082+
// Set weights on miner
2083+
assert_ok!(SubtensorModule::set_weights(
2084+
RuntimeOrigin::signed(hotkey),
2085+
netuid,
2086+
vec![0, 1, 2],
2087+
vec![0, 0, 1],
2088+
0,
2089+
));
2090+
2091+
// Clear incentive and dividends.
2092+
Incentive::<Test>::remove(netuid);
2093+
Dividends::<Test>::remove(netuid);
2094+
2095+
// Step so tempo should run.
2096+
next_block_no_epoch(netuid);
2097+
next_block_no_epoch(netuid);
2098+
next_block_no_epoch(netuid);
2099+
let current_block = System::block_number();
2100+
assert!(SubtensorModule::should_run_epoch(netuid, current_block));
2101+
2102+
// Run coinbase with emission.
2103+
SubtensorModule::run_coinbase(I96F32::saturating_from_num(100_000_000));
2104+
// We expect that the epoch ran.
2105+
assert_eq!(BlocksSinceLastStep::<Test>::get(netuid), 0);
2106+
2107+
let block_number = DurationOfStartCall::get();
2108+
run_to_block_no_epoch(netuid, block_number);
2109+
2110+
let current_block = System::block_number();
2111+
2112+
// Run start call.
2113+
assert_ok!(SubtensorModule::start_call(
2114+
RuntimeOrigin::signed(sn_owner_ck),
2115+
netuid
2116+
));
2117+
assert_eq!(
2118+
FirstEmissionBlockNumber::<Test>::get(netuid),
2119+
Some(current_block + 1)
2120+
);
2121+
2122+
// Run coinbase with emission.
2123+
SubtensorModule::run_coinbase(I96F32::saturating_from_num(100_000_000));
2124+
// We expect that the epoch ran.
2125+
assert_eq!(BlocksSinceLastStep::<Test>::get(netuid), 0);
2126+
2127+
// Get the new stake of the hotkey. We expect no emissions.
2128+
let new_stake = SubtensorModule::get_total_stake_for_hotkey(&hotkey);
2129+
// We expect the stake to remain unchanged.
2130+
assert!(new_stake > init_stake);
2131+
log::info!("new_stake: {}", new_stake);
2132+
});
2133+
}

pallets/subtensor/src/tests/epoch.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -983,28 +983,6 @@ fn test_512_graph_random_weights() {
983983
// });
984984
// }
985985

986-
fn next_block_no_epoch(netuid: u16) -> u64 {
987-
// high tempo to skip automatic epochs in on_initialize
988-
let high_tempo: u16 = u16::MAX - 1;
989-
let old_tempo: u16 = SubtensorModule::get_tempo(netuid);
990-
991-
SubtensorModule::set_tempo(netuid, high_tempo);
992-
let new_block = next_block();
993-
SubtensorModule::set_tempo(netuid, old_tempo);
994-
995-
new_block
996-
}
997-
998-
fn run_to_block_no_epoch(netuid: u16, n: u64) {
999-
// high tempo to skip automatic epochs in on_initialize
1000-
let high_tempo: u16 = u16::MAX - 1;
1001-
let old_tempo: u16 = SubtensorModule::get_tempo(netuid);
1002-
1003-
SubtensorModule::set_tempo(netuid, high_tempo);
1004-
run_to_block(n);
1005-
SubtensorModule::set_tempo(netuid, old_tempo);
1006-
}
1007-
1008986
// Test bonds exponential moving average over a sequence of epochs.
1009987
#[test]
1010988
fn test_bonds() {

0 commit comments

Comments
 (0)