Skip to content

Commit 948afbb

Browse files
authored
Merge pull request #1198 from opentensor/chore/safer-math
Ban saturating_div, to_num, and from_num
2 parents 1f27c9f + ffa8a6e commit 948afbb

File tree

27 files changed

+603
-416
lines changed

27 files changed

+603
-416
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/collective/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,8 @@ pub mod pallet {
549549
);
550550

551551
let threshold = T::GetVotingMembers::get_count()
552-
.saturating_div(2)
552+
.checked_div(2)
553+
.unwrap_or(0)
553554
.saturating_add(1);
554555

555556
let members = Self::members();

pallets/subtensor/Cargo.toml

Lines changed: 2 additions & 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" }
@@ -104,6 +105,7 @@ std = [
104105
"ark-serialize/std",
105106
"w3f-bls/std",
106107
"rand_chacha/std",
108+
"safe-math/std",
107109
"sha2/std",
108110
"share-pool/std"
109111
]

pallets/subtensor/src/coinbase/block_emission.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::*;
22
use frame_support::traits::Get;
3+
use safe_math::*;
34
use substrate_fixed::{transcendental::log2, types::I96F32};
45

56
impl<T: Config> Pallet<T> {
@@ -30,15 +31,15 @@ impl<T: Config> Pallet<T> {
3031
alpha_block_emission: u64,
3132
) -> (u64, u64, u64) {
3233
// Init terms.
33-
let mut tao_in_emission: I96F32 = I96F32::from_num(tao_emission);
34-
let float_alpha_block_emission: I96F32 = I96F32::from_num(alpha_block_emission);
34+
let mut tao_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission);
35+
let float_alpha_block_emission: I96F32 = I96F32::saturating_from_num(alpha_block_emission);
3536

3637
// Get alpha price for subnet.
3738
let alpha_price: I96F32 = Self::get_alpha_price(netuid);
3839
log::debug!("{:?} - alpha_price: {:?}", netuid, alpha_price);
3940

4041
// Get initial alpha_in
41-
let mut alpha_in_emission: I96F32 = I96F32::from_num(tao_emission)
42+
let mut alpha_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission)
4243
.checked_div(alpha_price)
4344
.unwrap_or(float_alpha_block_emission);
4445

@@ -59,9 +60,11 @@ impl<T: Config> Pallet<T> {
5960
}
6061

6162
// Avoid rounding errors.
62-
if tao_in_emission < I96F32::from_num(1) || alpha_in_emission < I96F32::from_num(1) {
63-
alpha_in_emission = I96F32::from_num(0);
64-
tao_in_emission = I96F32::from_num(0);
63+
if tao_in_emission < I96F32::saturating_from_num(1)
64+
|| alpha_in_emission < I96F32::saturating_from_num(1)
65+
{
66+
alpha_in_emission = I96F32::saturating_from_num(0);
67+
tao_in_emission = I96F32::saturating_from_num(0);
6568
}
6669

6770
// Set Alpha in emission.
@@ -78,9 +81,9 @@ impl<T: Config> Pallet<T> {
7881

7982
// Return result.
8083
(
81-
tao_in_emission.to_num::<u64>(),
82-
alpha_in_emission.to_num::<u64>(),
83-
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>(),
8487
)
8588
}
8689

@@ -103,23 +106,22 @@ impl<T: Config> Pallet<T> {
103106
/// Returns the block emission for an issuance value.
104107
pub fn get_block_emission_for_issuance(issuance: u64) -> Result<u64, &'static str> {
105108
// Convert issuance to a float for calculations below.
106-
let total_issuance: I96F32 = I96F32::from_num(issuance);
109+
let total_issuance: I96F32 = I96F32::saturating_from_num(issuance);
107110
// Check to prevent division by zero when the total supply is reached
108111
// and creating an issuance greater than the total supply.
109-
if total_issuance >= I96F32::from_num(TotalSupply::<T>::get()) {
112+
if total_issuance >= I96F32::saturating_from_num(TotalSupply::<T>::get()) {
110113
return Ok(0);
111114
}
112115
// Calculate the logarithmic residual of the issuance against half the total supply.
113116
let residual: I96F32 = log2(
114-
I96F32::from_num(1.0)
117+
I96F32::saturating_from_num(1.0)
115118
.checked_div(
116-
I96F32::from_num(1.0)
119+
I96F32::saturating_from_num(1.0)
117120
.checked_sub(
118121
total_issuance
119-
.checked_div(
120-
I96F32::from_num(2.0)
121-
.saturating_mul(I96F32::from_num(10_500_000_000_000_000.0)),
122-
)
122+
.checked_div(I96F32::saturating_from_num(2.0).saturating_mul(
123+
I96F32::saturating_from_num(10_500_000_000_000_000.0),
124+
))
123125
.ok_or("Logarithm calculation failed")?,
124126
)
125127
.ok_or("Logarithm calculation failed")?,
@@ -131,18 +133,19 @@ impl<T: Config> Pallet<T> {
131133
let floored_residual: I96F32 = residual.floor();
132134
// Calculate the final emission rate using the floored residual.
133135
// Convert floored_residual to an integer
134-
let floored_residual_int: u64 = floored_residual.to_num::<u64>();
136+
let floored_residual_int: u64 = floored_residual.saturating_to_num::<u64>();
135137
// Multiply 2.0 by itself floored_residual times to calculate the power of 2.
136-
let mut multiplier: I96F32 = I96F32::from_num(1.0);
138+
let mut multiplier: I96F32 = I96F32::saturating_from_num(1.0);
137139
for _ in 0..floored_residual_int {
138-
multiplier = multiplier.saturating_mul(I96F32::from_num(2.0));
140+
multiplier = multiplier.saturating_mul(I96F32::saturating_from_num(2.0));
139141
}
140-
let block_emission_percentage: I96F32 = I96F32::from_num(1.0).saturating_div(multiplier);
142+
let block_emission_percentage: I96F32 =
143+
I96F32::saturating_from_num(1.0).safe_div(multiplier);
141144
// Calculate the actual emission based on the emission rate
142145
let block_emission: I96F32 = block_emission_percentage
143-
.saturating_mul(I96F32::from_num(DefaultBlockEmission::<T>::get()));
146+
.saturating_mul(I96F32::saturating_from_num(DefaultBlockEmission::<T>::get()));
144147
// Convert to u64
145-
let block_emission_u64: u64 = block_emission.to_num::<u64>();
148+
let block_emission_u64: u64 = block_emission.saturating_to_num::<u64>();
146149
if BlockEmission::<T>::get() != block_emission_u64 {
147150
BlockEmission::<T>::put(block_emission_u64);
148151
}

pallets/subtensor/src/coinbase/block_step.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::*;
22
use frame_support::storage::IterableStorageMap;
3+
use safe_math::*;
34
use substrate_fixed::types::{I110F18, I96F32};
45

56
impl<T: Config + pallet_drand::Config> Pallet<T> {
@@ -10,7 +11,8 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {
1011
// --- 1. Adjust difficulties.
1112
Self::adjust_registration_terms_for_networks();
1213
// --- 2. Get the current coinbase emission.
13-
let block_emission: I96F32 = I96F32::from_num(Self::get_block_emission().unwrap_or(0));
14+
let block_emission: I96F32 =
15+
I96F32::saturating_from_num(Self::get_block_emission().unwrap_or(0));
1416
log::debug!("Block emission: {:?}", block_emission);
1517
// --- 3. Run emission through network.
1618
Self::run_coinbase(block_emission);
@@ -198,28 +200,28 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {
198200
registrations_this_interval: u16,
199201
target_registrations_per_interval: u16,
200202
) -> u64 {
201-
let updated_difficulty: I110F18 = I110F18::from_num(current_difficulty)
202-
.saturating_mul(I110F18::from_num(
203+
let updated_difficulty: I110F18 = I110F18::saturating_from_num(current_difficulty)
204+
.saturating_mul(I110F18::saturating_from_num(
203205
registrations_this_interval.saturating_add(target_registrations_per_interval),
204206
))
205-
.saturating_div(I110F18::from_num(
207+
.safe_div(I110F18::saturating_from_num(
206208
target_registrations_per_interval.saturating_add(target_registrations_per_interval),
207209
));
208-
let alpha: I110F18 = I110F18::from_num(Self::get_adjustment_alpha(netuid))
209-
.saturating_div(I110F18::from_num(u64::MAX));
210+
let alpha: I110F18 = I110F18::saturating_from_num(Self::get_adjustment_alpha(netuid))
211+
.safe_div(I110F18::saturating_from_num(u64::MAX));
210212
let next_value: I110F18 = alpha
211-
.saturating_mul(I110F18::from_num(current_difficulty))
213+
.saturating_mul(I110F18::saturating_from_num(current_difficulty))
212214
.saturating_add(
213-
I110F18::from_num(1.0)
215+
I110F18::saturating_from_num(1.0)
214216
.saturating_sub(alpha)
215217
.saturating_mul(updated_difficulty),
216218
);
217-
if next_value >= I110F18::from_num(Self::get_max_difficulty(netuid)) {
219+
if next_value >= I110F18::saturating_from_num(Self::get_max_difficulty(netuid)) {
218220
Self::get_max_difficulty(netuid)
219-
} else if next_value <= I110F18::from_num(Self::get_min_difficulty(netuid)) {
221+
} else if next_value <= I110F18::saturating_from_num(Self::get_min_difficulty(netuid)) {
220222
return Self::get_min_difficulty(netuid);
221223
} else {
222-
return next_value.to_num::<u64>();
224+
return next_value.saturating_to_num::<u64>();
223225
}
224226
}
225227

@@ -232,28 +234,28 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {
232234
registrations_this_interval: u16,
233235
target_registrations_per_interval: u16,
234236
) -> u64 {
235-
let updated_burn: I110F18 = I110F18::from_num(current_burn)
236-
.saturating_mul(I110F18::from_num(
237+
let updated_burn: I110F18 = I110F18::saturating_from_num(current_burn)
238+
.saturating_mul(I110F18::saturating_from_num(
237239
registrations_this_interval.saturating_add(target_registrations_per_interval),
238240
))
239-
.saturating_div(I110F18::from_num(
241+
.safe_div(I110F18::saturating_from_num(
240242
target_registrations_per_interval.saturating_add(target_registrations_per_interval),
241243
));
242-
let alpha: I110F18 = I110F18::from_num(Self::get_adjustment_alpha(netuid))
243-
.saturating_div(I110F18::from_num(u64::MAX));
244+
let alpha: I110F18 = I110F18::saturating_from_num(Self::get_adjustment_alpha(netuid))
245+
.safe_div(I110F18::saturating_from_num(u64::MAX));
244246
let next_value: I110F18 = alpha
245-
.saturating_mul(I110F18::from_num(current_burn))
247+
.saturating_mul(I110F18::saturating_from_num(current_burn))
246248
.saturating_add(
247-
I110F18::from_num(1.0)
249+
I110F18::saturating_from_num(1.0)
248250
.saturating_sub(alpha)
249251
.saturating_mul(updated_burn),
250252
);
251-
if next_value >= I110F18::from_num(Self::get_max_burn_as_u64(netuid)) {
253+
if next_value >= I110F18::saturating_from_num(Self::get_max_burn_as_u64(netuid)) {
252254
Self::get_max_burn_as_u64(netuid)
253-
} else if next_value <= I110F18::from_num(Self::get_min_burn_as_u64(netuid)) {
255+
} else if next_value <= I110F18::saturating_from_num(Self::get_min_burn_as_u64(netuid)) {
254256
return Self::get_min_burn_as_u64(netuid);
255257
} else {
256-
return next_value.to_num::<u64>();
258+
return next_value.saturating_to_num::<u64>();
257259
}
258260
}
259261
}

pallets/subtensor/src/coinbase/root.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use super::*;
1919
use frame_support::dispatch::Pays;
2020
use frame_support::storage::IterableStorageDoubleMap;
2121
use frame_support::weights::Weight;
22+
use safe_math::*;
2223
use sp_core::Get;
2324
use sp_std::vec;
2425
use substrate_fixed::types::I64F64;
@@ -112,7 +113,7 @@ impl<T: Config> Pallet<T> {
112113

113114
// --- 2. Initialize a 2D vector with zeros to store the weights. The dimensions are determined
114115
// by `n` (number of validators) and `k` (total number of subnets).
115-
let mut weights: Vec<Vec<I64F64>> = vec![vec![I64F64::from_num(0.0); k]; n];
116+
let mut weights: Vec<Vec<I64F64>> = vec![vec![I64F64::saturating_from_num(0.0); k]; n];
116117
log::debug!("weights:\n{:?}\n", weights);
117118

118119
let subnet_list = Self::get_all_subnet_netuids();
@@ -134,7 +135,7 @@ impl<T: Config> Pallet<T> {
134135
.zip(&subnet_list)
135136
.find(|(_, subnet)| *subnet == netuid)
136137
{
137-
*w = I64F64::from_num(*weight_ij);
138+
*w = I64F64::saturating_from_num(*weight_ij);
138139
}
139140
}
140141
}
@@ -624,7 +625,7 @@ impl<T: Config> Pallet<T> {
624625

625626
let mut lock_cost = last_lock.saturating_mul(mult).saturating_sub(
626627
last_lock
627-
.saturating_div(lock_reduction_interval)
628+
.safe_div(lock_reduction_interval)
628629
.saturating_mul(current_block.saturating_sub(last_lock_block)),
629630
);
630631

0 commit comments

Comments
 (0)