Skip to content

Commit 33c6af0

Browse files
committed
Ban to_num, organize safe math into a crate
1 parent b0a6a78 commit 33c6af0

File tree

21 files changed

+193
-121
lines changed

21 files changed

+193
-121
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pallets/subtensor/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pallet-utility = { workspace = true }
4141
ndarray = { workspace = true }
4242
hex = { workspace = true }
4343
share-pool = { default-features = false, path = "../../primitives/share-pool" }
44+
safe-math = { default-features = false, path = "../../primitives/safe-math" }
4445
approx = { workspace = true }
4546

4647
pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../collective" }

pallets/subtensor/src/coinbase/block_emission.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::*;
2-
use crate::epoch::math::*;
32
use frame_support::traits::Get;
3+
use safe_math::*;
44
use substrate_fixed::{transcendental::log2, types::I96F32};
55

66
impl<T: Config> Pallet<T> {
@@ -81,9 +81,9 @@ impl<T: Config> Pallet<T> {
8181

8282
// Return result.
8383
(
84-
tao_in_emission.to_num::<u64>(),
85-
alpha_in_emission.to_num::<u64>(),
86-
alpha_out_emission.to_num::<u64>(),
84+
tao_in_emission.saturating_to_num::<u64>(),
85+
alpha_in_emission.saturating_to_num::<u64>(),
86+
alpha_out_emission.saturating_to_num::<u64>(),
8787
)
8888
}
8989

@@ -134,7 +134,7 @@ impl<T: Config> Pallet<T> {
134134
let floored_residual: I96F32 = residual.floor();
135135
// Calculate the final emission rate using the floored residual.
136136
// Convert floored_residual to an integer
137-
let floored_residual_int: u64 = floored_residual.to_num::<u64>();
137+
let floored_residual_int: u64 = floored_residual.saturating_to_num::<u64>();
138138
// Multiply 2.0 by itself floored_residual times to calculate the power of 2.
139139
let mut multiplier: I96F32 = I96F32::from_num(1.0);
140140
for _ in 0..floored_residual_int {
@@ -145,7 +145,7 @@ impl<T: Config> Pallet<T> {
145145
let block_emission: I96F32 = block_emission_percentage
146146
.saturating_mul(I96F32::from_num(DefaultBlockEmission::<T>::get()));
147147
// Convert to u64
148-
let block_emission_u64: u64 = block_emission.to_num::<u64>();
148+
let block_emission_u64: u64 = block_emission.saturating_to_num::<u64>();
149149
if BlockEmission::<T>::get() != block_emission_u64 {
150150
BlockEmission::<T>::put(block_emission_u64);
151151
}

pallets/subtensor/src/coinbase/block_step.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::*;
2-
use crate::epoch::math::*;
32
use frame_support::storage::IterableStorageMap;
3+
use safe_math::*;
44
use substrate_fixed::types::{I110F18, I96F32};
55

66
impl<T: Config + pallet_drand::Config> Pallet<T> {
@@ -220,7 +220,7 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {
220220
} else if next_value <= I110F18::from_num(Self::get_min_difficulty(netuid)) {
221221
return Self::get_min_difficulty(netuid);
222222
} else {
223-
return next_value.to_num::<u64>();
223+
return next_value.saturating_to_num::<u64>();
224224
}
225225
}
226226

@@ -254,7 +254,7 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {
254254
} else if next_value <= I110F18::from_num(Self::get_min_burn_as_u64(netuid)) {
255255
return Self::get_min_burn_as_u64(netuid);
256256
} else {
257-
return next_value.to_num::<u64>();
257+
return next_value.saturating_to_num::<u64>();
258258
}
259259
}
260260
}

pallets/subtensor/src/coinbase/root.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
// DEALINGS IN THE SOFTWARE.
1717

1818
use super::*;
19-
use crate::epoch::math::*;
2019
use frame_support::dispatch::Pays;
2120
use frame_support::storage::IterableStorageDoubleMap;
2221
use frame_support::weights::Weight;
22+
use safe_math::*;
2323
use sp_core::Get;
2424
use sp_std::vec;
2525
use substrate_fixed::types::I64F64;

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::*;
2-
use crate::epoch::math::*;
32
use alloc::collections::BTreeMap;
3+
use safe_math::*;
44
use substrate_fixed::types::I96F32;
55
use tle::stream_ciphers::AESGCMStreamCipherProvider;
66
use tle::tlock::tld;
@@ -118,7 +118,7 @@ impl<T: Config> Pallet<T> {
118118
let tao_in: u64 = mech_emission
119119
.checked_mul(subnet_proportion)
120120
.unwrap_or(I96F32::from_num(0))
121-
.to_num::<u64>();
121+
.saturating_to_num::<u64>();
122122
log::debug!(
123123
"Subnet TAO emission (E_s) for netuid {:?}: {:?}",
124124
netuid,
@@ -201,7 +201,7 @@ impl<T: Config> Pallet<T> {
201201
// Calculate the owner cut.
202202
let owner_cut: u64 = I96F32::from_num(alpha_out_emission)
203203
.saturating_mul(Self::get_float_subnet_owner_cut())
204-
.to_num::<u64>();
204+
.saturating_to_num::<u64>();
205205
log::debug!("Owner cut for netuid {:?}: {:?}", netuid, owner_cut);
206206
// Store the owner cut for this subnet.
207207
*owner_cuts.entry(*netuid).or_insert(0) = owner_cut;
@@ -225,20 +225,25 @@ impl<T: Config> Pallet<T> {
225225
let pending_alpha_emission: I96F32 =
226226
I96F32::from_num(remaining_emission).saturating_sub(root_emission_in_alpha);
227227
// Sell root emission through the pool.
228-
let root_emission_in_tao: u64 =
229-
Self::swap_alpha_for_tao(*netuid, root_emission_in_alpha.to_num::<u64>());
230-
SubnetAlphaEmissionSell::<T>::insert(*netuid, root_emission_in_alpha.to_num::<u64>());
228+
let root_emission_in_tao: u64 = Self::swap_alpha_for_tao(
229+
*netuid,
230+
root_emission_in_alpha.saturating_to_num::<u64>(),
231+
);
232+
SubnetAlphaEmissionSell::<T>::insert(
233+
*netuid,
234+
root_emission_in_alpha.saturating_to_num::<u64>(),
235+
);
231236
// Accumulate root divs for subnet.
232237
PendingRootDivs::<T>::mutate(*netuid, |total| {
233238
*total = total.saturating_add(root_emission_in_tao);
234239
});
235240
// Accumulate alpha that was swapped for the pending root divs.
236241
PendingAlphaSwapped::<T>::mutate(*netuid, |total| {
237-
*total = total.saturating_add(root_emission_in_alpha.to_num::<u64>());
242+
*total = total.saturating_add(root_emission_in_alpha.saturating_to_num::<u64>());
238243
});
239244
// Accumulate alpha emission in pending.
240245
PendingEmission::<T>::mutate(*netuid, |total| {
241-
*total = total.saturating_add(pending_alpha_emission.to_num::<u64>());
246+
*total = total.saturating_add(pending_alpha_emission.saturating_to_num::<u64>());
242247
});
243248
// Accumulate the owner cut in pending.
244249
PendingOwnerCut::<T>::mutate(*netuid, |total| {
@@ -413,14 +418,14 @@ impl<T: Config> Pallet<T> {
413418
// Store the root-alpha divs under hotkey_j
414419
root_alpha_divs
415420
.entry(hotkey_j.clone())
416-
.and_modify(|e| *e = e.saturating_add(root_divs.to_num::<u64>()))
417-
.or_insert(root_divs.to_num::<u64>());
421+
.and_modify(|e| *e = e.saturating_add(root_divs.saturating_to_num::<u64>()))
422+
.or_insert(root_divs.saturating_to_num::<u64>());
418423
total_root_alpha_divs =
419-
total_root_alpha_divs.saturating_add(root_divs.to_num::<u64>());
424+
total_root_alpha_divs.saturating_add(root_divs.saturating_to_num::<u64>());
420425
log::debug!(
421426
"Stored root alpha dividends for hotkey {:?}: {:?}",
422427
hotkey_j,
423-
root_divs.to_num::<u64>()
428+
root_divs.saturating_to_num::<u64>()
424429
);
425430
}
426431
}
@@ -478,26 +483,26 @@ impl<T: Config> Pallet<T> {
478483
hotkey_j,
479484
&Owner::<T>::get(hotkey_j.clone()),
480485
netuid,
481-
validator_take.to_num::<u64>(),
486+
validator_take.saturating_to_num::<u64>(),
482487
);
483488
log::debug!(
484489
"Distributed validator take for hotkey {:?} on netuid {:?}: {:?}",
485490
hotkey_j,
486491
netuid,
487-
validator_take.to_num::<u64>()
492+
validator_take.saturating_to_num::<u64>()
488493
);
489494

490495
// Distribute the alpha divs to the hotkey.
491496
Self::increase_stake_for_hotkey_on_subnet(
492497
hotkey_j,
493498
netuid,
494-
rem_divs_j.to_num::<u64>(),
499+
rem_divs_j.saturating_to_num::<u64>(),
495500
);
496501
log::debug!(
497502
"Distributed alpha dividends for hotkey {:?} on netuid {:?}: {:?}",
498503
hotkey_j,
499504
netuid,
500-
rem_divs_j.to_num::<u64>()
505+
rem_divs_j.saturating_to_num::<u64>()
501506
);
502507

503508
// Record dividends for this hotkey on this subnet.
@@ -522,7 +527,7 @@ impl<T: Config> Pallet<T> {
522527
.unwrap_or(I96F32::from_num(0));
523528
let root_divs_to_pay: u64 = proportion
524529
.saturating_mul(I96F32::from_num(pending_root_divs))
525-
.to_num::<u64>();
530+
.saturating_to_num::<u64>();
526531
log::debug!(
527532
"Proportion for hotkey {:?}: {:?}, root_divs_to_pay: {:?}",
528533
hotkey_j,
@@ -581,7 +586,7 @@ impl<T: Config> Pallet<T> {
581586
let combined_contribution: I96F32 = alpha_contribution.saturating_add(root_contribution);
582587

583588
// Return the combined contribution as a u64
584-
combined_contribution.to_num::<u64>()
589+
combined_contribution.saturating_to_num::<u64>()
585590
}
586591

587592
/// Returns a list of tuples for each parent associated with this hotkey including self
@@ -695,7 +700,7 @@ impl<T: Config> Pallet<T> {
695700
.checked_div(total_contribution)
696701
.unwrap_or(I96F32::from_num(0));
697702
let parent_emission: u64 =
698-
(remaining_emission.saturating_mul(emission_factor)).to_num::<u64>();
703+
(remaining_emission.saturating_mul(emission_factor)).saturating_to_num::<u64>();
699704

700705
// Add the parent's emission to the distribution list
701706
dividend_tuples.push((parent, parent_emission));
@@ -707,7 +712,7 @@ impl<T: Config> Pallet<T> {
707712
// This includes the take left from the parents and the self contribution.
708713
let child_emission = remaining_emission
709714
.saturating_add(child_emission_take)
710-
.to_num::<u64>()
715+
.saturating_to_num::<u64>()
711716
.saturating_sub(to_parents);
712717

713718
// Add the hotkey's own emission to the distribution list

pallets/subtensor/src/epoch/math.rs

Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
use crate::alloc::borrow::ToOwned;
44
#[allow(unused)]
55
use num_traits::float::Float;
6+
use safe_math::*;
67
use sp_runtime::traits::{CheckedAdd, Saturating};
78
use sp_std::cmp::Ordering;
89

910
use sp_std::vec;
1011
use substrate_fixed::transcendental::{exp, ln};
11-
use substrate_fixed::types::{I110F18, I32F32, I64F64, I96F32, U64F64};
12+
use substrate_fixed::types::{I32F32, I64F64};
1213

1314
// TODO: figure out what cfg gate this needs to not be a warning in rustc
1415
#[allow(unused)]
@@ -21,17 +22,17 @@ pub fn fixed(val: f32) -> I32F32 {
2122

2223
#[allow(dead_code)]
2324
pub fn fixed_to_u16(x: I32F32) -> u16 {
24-
x.to_num::<u16>()
25+
x.saturating_to_num::<u16>()
2526
}
2627

2728
#[allow(dead_code)]
2829
pub fn fixed_to_u64(x: I32F32) -> u64 {
29-
x.to_num::<u64>()
30+
x.saturating_to_num::<u64>()
3031
}
3132

3233
#[allow(dead_code)]
3334
pub fn fixed64_to_u64(x: I64F64) -> u64 {
34-
x.to_num::<u64>()
35+
x.saturating_to_num::<u64>()
3536
}
3637

3738
#[allow(dead_code)]
@@ -100,7 +101,7 @@ pub fn vec_max_upscale_to_u16(vec: &[I32F32]) -> Vec<u16> {
100101
if *val == I32F32::from_num(0) {
101102
return vec
102103
.iter()
103-
.map(|e: &I32F32| e.saturating_mul(u16_max).to_num::<u16>())
104+
.map(|e: &I32F32| e.saturating_mul(u16_max).saturating_to_num::<u16>())
104105
.collect();
105106
}
106107
if *val > threshold {
@@ -109,7 +110,7 @@ pub fn vec_max_upscale_to_u16(vec: &[I32F32]) -> Vec<u16> {
109110
.map(|e: &I32F32| {
110111
e.saturating_mul(u16_max.safe_div(*val))
111112
.round()
112-
.to_num::<u16>()
113+
.saturating_to_num::<u16>()
113114
})
114115
.collect();
115116
}
@@ -118,14 +119,18 @@ pub fn vec_max_upscale_to_u16(vec: &[I32F32]) -> Vec<u16> {
118119
e.saturating_mul(u16_max)
119120
.safe_div(*val)
120121
.round()
121-
.to_num::<u16>()
122+
.saturating_to_num::<u16>()
122123
})
123124
.collect()
124125
}
125126
None => {
126127
let sum: I32F32 = vec.iter().sum();
127128
vec.iter()
128-
.map(|e: &I32F32| e.saturating_mul(u16_max).safe_div(sum).to_num::<u16>())
129+
.map(|e: &I32F32| {
130+
e.saturating_mul(u16_max)
131+
.safe_div(sum)
132+
.saturating_to_num::<u16>()
133+
})
129134
.collect()
130135
}
131136
}
@@ -1406,48 +1411,3 @@ pub fn safe_ln(value: I32F32) -> I32F32 {
14061411
pub fn safe_exp(value: I32F32) -> I32F32 {
14071412
exp(value).unwrap_or(I32F32::from_num(0.0))
14081413
}
1409-
1410-
/// Safe division trait
1411-
pub trait SafeDiv {
1412-
/// Safe division that returns supplied default value for division by zero
1413-
fn safe_div_or(self, rhs: Self, def: Self) -> Self;
1414-
/// Safe division that returns default value for division by zero
1415-
fn safe_div(self, rhs: Self) -> Self;
1416-
}
1417-
1418-
/// Implementation of safe division trait for primitive types
1419-
macro_rules! impl_safe_div_for_primitive {
1420-
($($t:ty),*) => {
1421-
$(
1422-
impl SafeDiv for $t {
1423-
fn safe_div_or(self, rhs: Self, def: Self) -> Self {
1424-
self.checked_div(rhs).unwrap_or(def)
1425-
}
1426-
1427-
fn safe_div(self, rhs: Self) -> Self {
1428-
self.checked_div(rhs).unwrap_or_default()
1429-
}
1430-
}
1431-
)*
1432-
};
1433-
}
1434-
impl_safe_div_for_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, usize);
1435-
1436-
/// Implementation of safe division trait for substrate fixed types
1437-
macro_rules! impl_safe_div_for_fixed {
1438-
($($t:ty),*) => {
1439-
$(
1440-
impl SafeDiv for $t {
1441-
fn safe_div_or(self, rhs: Self, def: Self) -> Self {
1442-
self.checked_div(rhs).unwrap_or(def)
1443-
}
1444-
1445-
fn safe_div(self, rhs: Self) -> Self {
1446-
self.checked_div(rhs).unwrap_or_default()
1447-
}
1448-
}
1449-
)*
1450-
};
1451-
}
1452-
1453-
impl_safe_div_for_fixed!(I96F32, I32F32, I64F64, I110F18, U64F64);

0 commit comments

Comments
 (0)