diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 2b41539816..fcd0570d23 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -177,7 +177,7 @@ pub mod pallet { #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_tx_rate_limit(origin: OriginFor, tx_rate_limit: u64) -> DispatchResult { ensure_root(origin)?; - pallet_subtensor::Pallet::::set_tx_rate_limit(tx_rate_limit); + pallet_subtensor::Pallet::::set_tx_rate_limit(tx_rate_limit, false); log::debug!("TxRateLimitSet( tx_rate_limit: {:?} ) ", tx_rate_limit); Ok(()) } @@ -196,7 +196,11 @@ pub mod pallet { ) -> DispatchResult { pallet_subtensor::Pallet::::ensure_subnet_owner_or_root(origin, netuid)?; - pallet_subtensor::Pallet::::set_serving_rate_limit(netuid, serving_rate_limit); + pallet_subtensor::Pallet::::set_serving_rate_limit( + netuid, + serving_rate_limit, + false, + ); log::debug!( "ServingRateLimitSet( serving_rate_limit: {:?} ) ", serving_rate_limit @@ -329,6 +333,7 @@ pub mod pallet { pallet_subtensor::Pallet::::set_weights_set_rate_limit( netuid, weights_set_rate_limit, + false, ); log::debug!( "WeightsSetRateLimitSet( netuid: {:?} weights_set_rate_limit: {:?} ) ", @@ -908,7 +913,7 @@ pub mod pallet { rate_limit: u64, ) -> DispatchResult { ensure_root(origin)?; - pallet_subtensor::Pallet::::set_network_rate_limit(rate_limit); + pallet_subtensor::Pallet::::set_network_rate_limit(rate_limit, false); log::debug!("NetworkRateLimit( rate_limit: {:?} ) ", rate_limit); Ok(()) } @@ -1093,7 +1098,7 @@ pub mod pallet { tx_rate_limit: u64, ) -> DispatchResult { ensure_root(origin)?; - pallet_subtensor::Pallet::::set_tx_delegate_take_rate_limit(tx_rate_limit); + pallet_subtensor::Pallet::::set_tx_delegate_take_rate_limit(tx_rate_limit, false); log::debug!( "TxRateLimitDelegateTakeSet( tx_delegate_take_rate_limit: {:?} ) ", tx_rate_limit diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index a7cd03e652..056e57c740 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -349,7 +349,7 @@ mod pallet_benchmarks { netuid, caller.clone() )); - Subtensor::::set_serving_rate_limit(netuid, 0); + Subtensor::::set_serving_rate_limit(netuid, 0, false); #[extrinsic_call] _( @@ -387,7 +387,7 @@ mod pallet_benchmarks { netuid, caller.clone() )); - Subtensor::::set_serving_rate_limit(netuid, 0); + Subtensor::::set_serving_rate_limit(netuid, 0, false); #[extrinsic_call] _( @@ -451,7 +451,7 @@ mod pallet_benchmarks { let coldkey: T::AccountId = account("Test", 0, seed); let hotkey: T::AccountId = account("TestHotkey", 0, seed); - Subtensor::::set_network_rate_limit(1); + Subtensor::::set_network_rate_limit(1, false); let amount: u64 = 100_000_000_000_000u64.saturating_mul(2); Subtensor::::add_balance_to_coldkey_account(&coldkey, amount); @@ -670,7 +670,7 @@ mod pallet_benchmarks { Subtensor::::set_network_registration_allowed(netuid, true); Subtensor::::set_network_pow_registration_allowed(netuid, true); Subtensor::::set_commit_reveal_weights_enabled(netuid, true); - Subtensor::::set_weights_set_rate_limit(netuid, 0); + Subtensor::::set_weights_set_rate_limit(netuid, 0, false); let block_number: u64 = Subtensor::::get_current_block_as_u64(); let (nonce, work) = @@ -1303,7 +1303,7 @@ mod pallet_benchmarks { let identity: Option = None; Subtensor::::set_network_registration_allowed(1, true); - Subtensor::::set_network_rate_limit(1); + Subtensor::::set_network_rate_limit(1, false); let amount: u64 = 9_999_999_999_999; Subtensor::::add_balance_to_coldkey_account(&coldkey, amount); diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 197cd5f8f7..48b792d278 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -581,14 +581,6 @@ pub mod pallet { T::InitialSubnetOwnerCut::get() } #[pallet::type_value] - /// Default value for network rate limit. - pub fn DefaultNetworkRateLimit() -> u64 { - if cfg!(feature = "pow-faucet") { - return 0; - } - T::InitialNetworkRateLimit::get() - } - #[pallet::type_value] /// Default value for weights version key rate limit. /// In units of tempos. pub fn DefaultWeightsVersionKeyRateLimit() -> u64 { @@ -626,11 +618,6 @@ pub mod pallet { T::InitialTempo::get() } #[pallet::type_value] - /// Default value for weights set rate limit. - pub fn DefaultWeightsSetRateLimit() -> u64 { - 100 - } - #[pallet::type_value] /// Default block number at registration. pub fn DefaultBlockAtRegistration() -> u64 { 0 @@ -770,31 +757,11 @@ pub mod pallet { // T::InitialHotkeyEmissionTempo::get() // } (DEPRECATED) #[pallet::type_value] - /// Default value for rate limiting - pub fn DefaultTxRateLimit() -> u64 { - T::InitialTxRateLimit::get() - } - #[pallet::type_value] - /// Default value for delegate take rate limiting - pub fn DefaultTxDelegateTakeRateLimit() -> u64 { - T::InitialTxDelegateTakeRateLimit::get() - } - #[pallet::type_value] - /// Default value for chidlkey take rate limiting - pub fn DefaultTxChildKeyTakeRateLimit() -> u64 { - T::InitialTxChildKeyTakeRateLimit::get() - } - #[pallet::type_value] /// Default value for last extrinsic block. pub fn DefaultLastTxBlock() -> u64 { 0 } #[pallet::type_value] - /// Default value for serving rate limit. - pub fn DefaultServingRateLimit() -> u64 { - T::InitialServingRateLimit::get() - } - #[pallet::type_value] /// Default value for weight commit/reveal enabled. pub fn DefaultCommitRevealWeightsEnabled() -> bool { false @@ -1211,9 +1178,6 @@ pub mod pallet { #[pallet::storage] /// ITEM( subnet_owner_cut ) pub type SubnetOwnerCut = StorageValue<_, u16, ValueQuery, DefaultSubnetOwnerCut>; - #[pallet::storage] - /// ITEM( network_rate_limit ) - pub type NetworkRateLimit = StorageValue<_, u64, ValueQuery, DefaultNetworkRateLimit>; #[pallet::storage] // --- ITEM( nominator_min_required_stake ) pub type NominatorMinRequiredStake = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] @@ -1323,10 +1287,7 @@ pub mod pallet { /// --- MAP ( netuid ) --> subnet_owner_hotkey pub type SubnetOwnerHotkey = StorageMap<_, Identity, u16, T::AccountId, ValueQuery, DefaultSubnetOwner>; - #[pallet::storage] - /// --- MAP ( netuid ) --> serving_rate_limit - pub type ServingRateLimit = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultServingRateLimit>; + #[pallet::storage] /// --- MAP ( netuid ) --> Rho pub type Rho = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultRho>; @@ -1392,10 +1353,6 @@ pub mod pallet { /// --- MAP ( netuid ) --> bonds_reset pub type BondsResetOn = StorageMap<_, Identity, u16, bool, ValueQuery, DefaultBondsResetOn>; - /// --- MAP ( netuid ) --> weights_set_rate_limit - #[pallet::storage] - pub type WeightsSetRateLimit = - StorageMap<_, Identity, u16, u64, ValueQuery, DefaultWeightsSetRateLimit>; #[pallet::storage] /// --- MAP ( netuid ) --> validator_prune_len pub type ValidatorPruneLen = @@ -1453,17 +1410,6 @@ pub mod pallet { pub type RAORecycledForRegistration = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultRAORecycledForRegistration>; #[pallet::storage] - /// --- ITEM ( tx_rate_limit ) - pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; - #[pallet::storage] - /// --- ITEM ( tx_delegate_take_rate_limit ) - pub type TxDelegateTakeRateLimit = - StorageValue<_, u64, ValueQuery, DefaultTxDelegateTakeRateLimit>; - #[pallet::storage] - /// --- ITEM ( tx_childkey_take_rate_limit ) - pub type TxChildkeyTakeRateLimit = - StorageValue<_, u64, ValueQuery, DefaultTxChildKeyTakeRateLimit>; - #[pallet::storage] /// --- MAP ( netuid ) --> Whether or not Liquid Alpha is enabled pub type LiquidAlphaOn = StorageMap<_, Blake2_128Concat, u16, bool, ValueQuery, DefaultLiquidAlpha>; @@ -2699,4 +2645,16 @@ impl CollectiveInterface for () { pub enum RateLimitKey { // The setting sn owner hotkey operation is rate limited per netuid SetSNOwnerHotkey(u16), + // An axon or prometheus serving rate limit for a registered neuron. + ServingRateLimit(u16), + // Limits transaction number + TxRateLimit, + // Limits set_weights operation + SetWeightsRateLimit(u16), + // Network rate limits + NetworkRateLimit, + // Rate limit for delegate take transactions + TxDelegateRateLimit, + // Rate limit for delegate childkey take transactions + TxChildkeyTakeRateLimit, } diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 650fb50451..b8e79f183d 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1045,17 +1045,17 @@ mod dispatches { #[pallet::call_index(69)] #[pallet::weight(( Weight::from_parts(6_873_000, 0) - .saturating_add(T::DbWeight::get().reads(0)) - .saturating_add(T::DbWeight::get().writes(1)), - DispatchClass::Operational, - Pays::No -))] + .saturating_add(T::DbWeight::get().reads(0)) + .saturating_add(T::DbWeight::get().writes(1)), + DispatchClass::Operational, + Pays::No + ))] pub fn sudo_set_tx_childkey_take_rate_limit( origin: OriginFor, tx_rate_limit: u64, ) -> DispatchResult { ensure_root(origin)?; - Self::set_tx_childkey_take_rate_limit(tx_rate_limit); + Self::set_tx_childkey_take_rate_limit(tx_rate_limit, false); Ok(()) } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index a0e2fc6e72..950f29fe11 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -115,7 +115,9 @@ mod hooks { // Reset max burn .saturating_add(migrations::migrate_reset_max_burn::migrate_reset_max_burn::()) // Migrate ColdkeySwapScheduled structure to new format - .saturating_add(migrations::migrate_coldkey_swap_scheduled::migrate_coldkey_swap_scheduled::()); + .saturating_add(migrations::migrate_coldkey_swap_scheduled::migrate_coldkey_swap_scheduled::()) + // Migrate rate limit maps to new format + .saturating_add(migrations::migrate_obsolete_rate_limiting_maps::migrate_obsolete_rate_limiting_maps::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_obsolete_rate_limiting_maps.rs b/pallets/subtensor/src/migrations/migrate_obsolete_rate_limiting_maps.rs new file mode 100644 index 0000000000..8302ac2ed9 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_obsolete_rate_limiting_maps.rs @@ -0,0 +1,209 @@ +use crate::Vec; +use crate::{Config, HasMigrationRun, NetworksAdded, Pallet}; +use alloc::string::String; +use codec::{Decode, Encode}; +use frame_support::IterableStorageMap; +use frame_support::traits::Get; +use frame_support::weights::Weight; +use sp_io::hashing::twox_128; +use sp_io::storage::{clear, get}; + +pub fn migrate_obsolete_rate_limiting_maps() -> Weight { + migrate_serving_rate_limits::() + .saturating_add(migrate_tx_rate_limits::()) + .saturating_add(migrate_set_weights_rate_limits::()) + .saturating_add(migrate_network_rate_limits::()) + .saturating_add(migrate_tx_delegate_take_rate_limits::()) + .saturating_add(migrate_tx_childkey_take_rate_limit::()) +} + +pub fn migrate_tx_childkey_take_rate_limit() -> Weight { + let migration_name = b"migrate_tx_childkey_take_rate_limit".to_vec(); + let pallet_name = "SubtensorModule"; + let storage_name = "TxChildkeyTakeRateLimit"; + + migrate_value::(migration_name, pallet_name, storage_name, |limit| { + Pallet::::set_tx_childkey_take_rate_limit(limit, true); + }) +} +pub fn migrate_tx_delegate_take_rate_limits() -> Weight { + let migration_name = b"migrate_tx_delegate_take_rate_limits".to_vec(); + let pallet_name = "SubtensorModule"; + let storage_name = "TxDelegateTakeRateLimit"; + + migrate_value::(migration_name, pallet_name, storage_name, |limit| { + Pallet::::set_tx_delegate_take_rate_limit(limit, true); + }) +} +pub fn migrate_network_rate_limits() -> Weight { + let migration_name = b"migrate_network_rate_limits".to_vec(); + let pallet_name = "SubtensorModule"; + let storage_name = "NetworkRateLimit"; + + migrate_value::(migration_name, pallet_name, storage_name, |limit| { + Pallet::::set_network_rate_limit(limit, true); + }) +} +pub fn migrate_tx_rate_limits() -> Weight { + let migration_name = b"migrate_tx_rate_limits".to_vec(); + let pallet_name = "SubtensorModule"; + let storage_name = "TxRateLimit"; + + migrate_value::(migration_name, pallet_name, storage_name, |limit| { + Pallet::::set_tx_rate_limit(limit, true); + }) +} + +pub fn migrate_serving_rate_limits() -> Weight { + let migration_name = b"migrate_serving_rate_limits".to_vec(); + let pallet_name = "SubtensorModule"; + let storage_name = "ServingRateLimit"; + + migrate_limit_map_netuids::( + migration_name, + pallet_name, + storage_name, + |netuid| netuid.encode(), + |netuid, limit| { + Pallet::::set_serving_rate_limit(netuid, limit, true); + }, + ) +} + +pub fn migrate_set_weights_rate_limits() -> Weight { + let migration_name = b"migrate_set_weights_rate_limits".to_vec(); + let pallet_name = "SubtensorModule"; + let storage_name = "WeightsSetRateLimit"; + + migrate_limit_map_netuids::( + migration_name, + pallet_name, + storage_name, + |netuid| netuid.encode(), + |netuid, limit| { + Pallet::::set_weights_set_rate_limit(netuid, limit, true); + }, + ) +} + +fn migrate_limit_map_netuids( + migration_name: Vec, + pallet_name: &str, + storage_name: &str, + key: KeyFunction, + set_value: SetValueFunction, +) -> Weight +where + T: Config, + KeyFunction: Fn(u16 /*netuid*/) -> Vec, + SetValueFunction: Fn(u16 /*netuid*/, u64 /*limit in blocks*/), +{ + // Initialize the weight with one read operation. + let mut weight = T::DbWeight::get().reads(1); + + // Check if the migration has already run + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + migration_name + ); + return weight; + } + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + let netuids: Vec = as IterableStorageMap>::iter() + .map(|(netuid, _)| netuid) + .collect(); + weight = weight.saturating_add(T::DbWeight::get().reads(netuids.len() as u64)); + + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + for netuid in netuids.into_iter() { + let mut full_key = prefix.clone(); + let mut key = key(netuid); + + full_key.append(&mut key); + + if let Some(value_bytes) = get(&full_key) { + if let Ok(rate_limit) = Decode::decode(&mut &value_bytes[..]) { + set_value(netuid, rate_limit); + } + + clear(&full_key); + } + + weight = weight.saturating_add(T::DbWeight::get().writes(2)); + weight = weight.saturating_add(T::DbWeight::get().reads(1)); + } + + // Mark the migration as completed + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed.", + String::from_utf8_lossy(&migration_name) + ); + + // Return the migration weight. + weight +} + +fn migrate_value( + migration_name: Vec, + pallet_name: &str, + storage_name: &str, + set_value: SetValueFunction, +) -> Weight +where + T: Config, + SetValueFunction: Fn(u64 /*limit in blocks*/), +{ + // Initialize the weight with one read operation. + let mut weight = T::DbWeight::get().reads(1); + + // Check if the migration has already run + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + migration_name + ); + return weight; + } + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let full_key = [pallet_name_hash, storage_name_hash].concat(); + + if let Some(value_bytes) = get(&full_key) { + if let Ok(rate_limit) = Decode::decode(&mut &value_bytes[..]) { + set_value(rate_limit); + } + + clear(&full_key); + } + + weight = weight.saturating_add(T::DbWeight::get().writes(2)); + weight = weight.saturating_add(T::DbWeight::get().reads(1)); + + // Mark the migration as completed + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed.", + String::from_utf8_lossy(&migration_name) + ); + + // Return the migration weight. + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 5c6347034f..9a1e2a5eff 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -12,6 +12,7 @@ pub mod migrate_delete_subnet_3; pub mod migrate_fix_is_network_member; pub mod migrate_identities_v2; pub mod migrate_init_total_issuance; +pub mod migrate_obsolete_rate_limiting_maps; pub mod migrate_orphaned_storage_items; pub mod migrate_populate_owned_hotkeys; pub mod migrate_rao; diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index b122bfa049..896a8f23d9 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -85,9 +85,21 @@ impl Pallet { /// Sets the network rate limit and emit the `NetworkRateLimitSet` event /// - pub fn set_network_rate_limit(limit: u64) { - NetworkRateLimit::::set(limit); - Self::deposit_event(Event::NetworkRateLimitSet(limit)); + pub fn set_network_rate_limit(limit: u64, skip_event: bool) { + LastRateLimitedBlock::::insert(RateLimitKey::NetworkRateLimit, limit); + + if !skip_event { + Self::deposit_event(Event::NetworkRateLimitSet(limit)); + } + } + /// Gets the network rate limit + pub fn get_network_rate_limit() -> u64 { + let limit_key = RateLimitKey::NetworkRateLimit; + if !LastRateLimitedBlock::::contains_key(&limit_key) { + return T::InitialNetworkRateLimit::get(); + } + + LastRateLimitedBlock::::get(limit_key) } /// Checks if registrations are allowed for a given subnet. @@ -147,7 +159,7 @@ impl Pallet { let current_block = Self::get_current_block_as_u64(); let last_lock_block = Self::get_network_last_lock_block(); ensure!( - current_block.saturating_sub(last_lock_block) >= NetworkRateLimit::::get(), + current_block.saturating_sub(last_lock_block) >= Self::get_network_rate_limit(), Error::::NetworkTxRateLimitExceeded ); diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 1a9016f13f..227286b925 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -934,11 +934,11 @@ fn test_childkey_take_rate_limiting() { // Set a rate limit for childkey take changes let rate_limit: u64 = 100; - SubtensorModule::set_tx_childkey_take_rate_limit(rate_limit); + SubtensorModule::set_tx_childkey_take_rate_limit(rate_limit, false); log::info!( "Set TxChildkeyTakeRateLimit: {:?}", - TxChildkeyTakeRateLimit::::get() + SubtensorModule::get_tx_childkey_take_rate_limit() ); // Helper function to log rate limit information @@ -2625,7 +2625,7 @@ fn test_childkey_set_weights_single_parent() { 1_000_000, ); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Set parent-child relationship mock_set_children_no_epochs(netuid, &parent, &[(u64::MAX, child)]); @@ -2720,7 +2720,7 @@ fn test_set_weights_no_parent() { stake_to_give_child, ); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Has stake and no parent step_block(7200 + 1); @@ -2824,7 +2824,7 @@ fn test_childkey_take_drain() { &nominator, stake + ExistentialDeposit::get(), ); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_max_allowed_validators(netuid, 2); step_block(subnet_tempo); SubnetOwnerCut::::set(0); @@ -3575,7 +3575,7 @@ fn test_dynamic_parent_child_relationships() { let version_key = SubtensorModule::get_weights_version_key(netuid); // Ensure we can set weights without rate limiting - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); assert_ok!(SubtensorModule::set_weights( origin, diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 1345f36b7d..d3199f4350 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -1902,7 +1902,7 @@ fn test_drain_pending_emission_zero_emission() { let tempo = 2; SubtensorModule::set_tempo(netuid, tempo); // Set weight-set limit to 0. - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, hotkey, coldkey, 0); register_ok_neuron(netuid, miner_hk, miner_ck, 0); @@ -1975,7 +1975,7 @@ fn test_run_coinbase_not_started() { let tempo = 2; SubtensorModule::set_tempo(netuid, tempo); // Set weight-set limit to 0. - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, hotkey, coldkey, 0); register_ok_neuron(netuid, miner_hk, miner_ck, 0); @@ -2057,7 +2057,7 @@ fn test_run_coinbase_not_started_start_after() { let tempo = 2; SubtensorModule::set_tempo(netuid, tempo); // Set weight-set limit to 0. - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, hotkey, coldkey, 0); register_ok_neuron(netuid, miner_hk, miner_ck, 0); diff --git a/pallets/subtensor/src/tests/epoch.rs b/pallets/subtensor/src/tests/epoch.rs index 2557709912..28f4da6535 100644 --- a/pallets/subtensor/src/tests/epoch.rs +++ b/pallets/subtensor/src/tests/epoch.rs @@ -999,7 +999,7 @@ fn test_bonds() { assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), n); SubtensorModule::set_max_registrations_per_block( netuid, n ); SubtensorModule::set_target_registrations_per_interval(netuid, n); - SubtensorModule::set_weights_set_rate_limit( netuid, 0 ); + SubtensorModule::set_weights_set_rate_limit( netuid, 0, false ); SubtensorModule::set_min_allowed_weights( netuid, 1 ); SubtensorModule::set_max_weight_limit( netuid, u16::MAX ); SubtensorModule::set_bonds_penalty(netuid, u16::MAX); @@ -1546,7 +1546,7 @@ fn test_outdated_weights() { let stake: u64 = 1; add_network(netuid, tempo, 0); SubtensorModule::set_max_allowed_uids(netuid, n); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_max_registrations_per_block(netuid, n); SubtensorModule::set_target_registrations_per_interval(netuid, n); SubtensorModule::set_min_allowed_weights(netuid, 0); @@ -1733,7 +1733,7 @@ fn test_zero_weights() { let stake: u64 = 1; add_network(netuid, tempo, 0); SubtensorModule::set_max_allowed_uids(netuid, n); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_max_registrations_per_block(netuid, n); SubtensorModule::set_target_registrations_per_interval(netuid, n); SubtensorModule::set_min_allowed_weights(netuid, 0); @@ -1927,7 +1927,7 @@ fn test_deregistered_miner_bonds() { let stake: u64 = 1; add_network(netuid, high_tempo, 0); SubtensorModule::set_max_allowed_uids(netuid, n); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_max_registrations_per_block(netuid, n); SubtensorModule::set_target_registrations_per_interval(netuid, n); SubtensorModule::set_min_allowed_weights(netuid, 0); @@ -2639,7 +2639,7 @@ fn setup_yuma_3_scenario(netuid: u16, n: u16, sparse: bool, max_stake: u64, stak assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), n); SubtensorModule::set_max_registrations_per_block(netuid, n); SubtensorModule::set_target_registrations_per_interval(netuid, n); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_min_allowed_weights(netuid, 1); SubtensorModule::set_max_weight_limit(netuid, u16::MAX); SubtensorModule::set_bonds_penalty(netuid, 0); diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 1dfac06ad5..1b13f93135 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -820,3 +820,359 @@ fn test_migrate_remove_commitments_rate_limit() { assert!(!weight.is_zero(), "Migration weight should be non-zero"); }); } + +#[test] +fn test_migrate_serving_rate_limit() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entry + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_serving_rate_limits"; + + let pallet_name = "SubtensorModule"; + let storage_name = "ServingRateLimit"; + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + let netuid = 1u16; + add_network(netuid, 1, 0); + let mut encoded_netuid = netuid.encode(); + let mut full_key = prefix.clone(); + + full_key.append(&mut encoded_netuid); + + let original_value: u64 = 123; + put_raw(&full_key, &original_value.encode()); + + let stored_before = get_raw(&full_key).expect("Expected RateLimit to exist"); + assert_eq!( + u64::decode(&mut &stored_before[..]).expect("Failed to decode RateLimit"), + original_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = crate::migrations::migrate_obsolete_rate_limiting_maps:: + migrate_obsolete_rate_limiting_maps::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as completed" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + + assert_eq!( + SubtensorModule::get_serving_rate_limit(netuid), + original_value + ); + assert_eq!( + get_raw(&full_key), + None, + "RateLimit storage should have been cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} + +#[test] +fn test_migrate_tx_rate_limit() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entry + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_tx_rate_limits"; + + let pallet_name = "SubtensorModule"; + let storage_name = "TxRateLimit"; + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + let mut full_key = prefix.clone(); + + let original_value: u64 = 123; + put_raw(&full_key, &original_value.encode()); + + let stored_before = get_raw(&full_key).expect("Expected RateLimit to exist"); + assert_eq!( + u64::decode(&mut &stored_before[..]).expect("Failed to decode RateLimit"), + original_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = crate::migrations::migrate_obsolete_rate_limiting_maps:: + migrate_obsolete_rate_limiting_maps::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as completed" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + + assert_eq!(SubtensorModule::get_tx_rate_limit(), original_value); + assert_eq!( + get_raw(&full_key), + None, + "RateLimit storage should have been cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} + +#[test] +fn test_migrate_set_weights_rate_limit() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entry + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_set_weights_rate_limits"; + + let pallet_name = "SubtensorModule"; + let storage_name = "WeightsSetRateLimit"; + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + let netuid = 1u16; + add_network(netuid, 1, 0); + let mut encoded_netuid = netuid.encode(); + let mut full_key = prefix.clone(); + + full_key.append(&mut encoded_netuid); + + let original_value: u64 = 123; + put_raw(&full_key, &original_value.encode()); + + let stored_before = get_raw(&full_key).expect("Expected RateLimit to exist"); + assert_eq!( + u64::decode(&mut &stored_before[..]).expect("Failed to decode RateLimit"), + original_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = crate::migrations::migrate_obsolete_rate_limiting_maps:: + migrate_obsolete_rate_limiting_maps::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as completed" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + + assert_eq!( + SubtensorModule::get_weights_set_rate_limit(netuid), + original_value + ); + assert_eq!( + get_raw(&full_key), + None, + "RateLimit storage should have been cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} +#[test] +fn test_migrate_network_rate_limit() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entry + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_network_rate_limits"; + + let pallet_name = "SubtensorModule"; + let storage_name = "NetworkRateLimit"; + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + let mut full_key = prefix.clone(); + + let original_value: u64 = 123; + put_raw(&full_key, &original_value.encode()); + + let stored_before = get_raw(&full_key).expect("Expected RateLimit to exist"); + assert_eq!( + u64::decode(&mut &stored_before[..]).expect("Failed to decode RateLimit"), + original_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = crate::migrations::migrate_obsolete_rate_limiting_maps:: + migrate_obsolete_rate_limiting_maps::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as completed" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + + assert_eq!(SubtensorModule::get_network_rate_limit(), original_value); + assert_eq!( + get_raw(&full_key), + None, + "RateLimit storage should have been cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} +#[test] +fn test_migrate_tx_delegate_take_rate_limit() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entry + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_tx_delegate_take_rate_limits"; + + let pallet_name = "SubtensorModule"; + let storage_name = "TxDelegateTakeRateLimit"; + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + let mut full_key = prefix.clone(); + + let original_value: u64 = 123; + put_raw(&full_key, &original_value.encode()); + + let stored_before = get_raw(&full_key).expect("Expected RateLimit to exist"); + assert_eq!( + u64::decode(&mut &stored_before[..]).expect("Failed to decode RateLimit"), + original_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = crate::migrations::migrate_obsolete_rate_limiting_maps:: + migrate_obsolete_rate_limiting_maps::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as completed" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + + assert_eq!( + SubtensorModule::get_tx_delegate_take_rate_limit(), + original_value + ); + assert_eq!( + get_raw(&full_key), + None, + "RateLimit storage should have been cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} + +#[test] +fn test_migrate_tx_childkey_take_rate_limit() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // Step 1: Simulate Old Storage Entry + // ------------------------------ + const MIGRATION_NAME: &str = "migrate_tx_childkey_take_rate_limit"; + + let pallet_name = "SubtensorModule"; + let storage_name = "TxChildkeyTakeRateLimit"; + let pallet_name_hash = twox_128(pallet_name.as_bytes()); + let storage_name_hash = twox_128(storage_name.as_bytes()); + let prefix = [pallet_name_hash, storage_name_hash].concat(); + + let mut full_key = prefix.clone(); + + let original_value: u64 = 123; + put_raw(&full_key, &original_value.encode()); + + let stored_before = get_raw(&full_key).expect("Expected RateLimit to exist"); + assert_eq!( + u64::decode(&mut &stored_before[..]).expect("Failed to decode RateLimit"), + original_value + ); + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should not have run yet" + ); + + // ------------------------------ + // Step 2: Run the Migration + // ------------------------------ + let weight = crate::migrations::migrate_obsolete_rate_limiting_maps:: + migrate_obsolete_rate_limiting_maps::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.as_bytes().to_vec()), + "Migration should be marked as completed" + ); + + // ------------------------------ + // Step 3: Verify Migration Effects + // ------------------------------ + + assert_eq!( + SubtensorModule::get_tx_childkey_take_rate_limit(), + original_value + ); + assert_eq!( + get_raw(&full_key), + None, + "RateLimit storage should have been cleared" + ); + + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + }); +} diff --git a/pallets/subtensor/src/tests/serving.rs b/pallets/subtensor/src/tests/serving.rs index 251dde2078..26a1425695 100644 --- a/pallets/subtensor/src/tests/serving.rs +++ b/pallets/subtensor/src/tests/serving.rs @@ -283,7 +283,7 @@ fn test_axon_serving_rate_limit_exceeded() { placeholder1, placeholder2 )); - SubtensorModule::set_serving_rate_limit(netuid, 2); + SubtensorModule::set_serving_rate_limit(netuid, 2, false); run_to_block(2); // Go to block 2 // Needs to be 2 blocks apart, we are only 1 block apart assert_eq!( @@ -485,7 +485,7 @@ fn test_prometheus_serving_rate_limit_exceeded() { port, ip_type )); - SubtensorModule::set_serving_rate_limit(netuid, 1); + SubtensorModule::set_serving_rate_limit(netuid, 1, false); // Same block, need 1 block to pass assert_eq!( SubtensorModule::serve_prometheus( diff --git a/pallets/subtensor/src/tests/staking.rs b/pallets/subtensor/src/tests/staking.rs index 9a672676ee..4cb6cf25e5 100644 --- a/pallets/subtensor/src/tests/staking.rs +++ b/pallets/subtensor/src/tests/staking.rs @@ -3257,7 +3257,7 @@ fn test_mining_emission_distribution_validator_valiminer_miner() { &miner_coldkey, stake + ExistentialDeposit::get(), ); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); step_block(subnet_tempo); SubnetOwnerCut::::set(0); // There are two validators and three neurons diff --git a/pallets/subtensor/src/tests/swap_hotkey.rs b/pallets/subtensor/src/tests/swap_hotkey.rs index a82972c2f7..a6d2b1b625 100644 --- a/pallets/subtensor/src/tests/swap_hotkey.rs +++ b/pallets/subtensor/src/tests/swap_hotkey.rs @@ -729,7 +729,7 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { log::info!("current_tx_rate_limit: {:?}", current_tx_rate_limit); // Set the transaction rate limit - SubtensorModule::set_tx_rate_limit(tx_rate_limit); + SubtensorModule::set_tx_rate_limit(tx_rate_limit, false); // assert the rate limit is set to 1000 blocks assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit); diff --git a/pallets/subtensor/src/tests/weights.rs b/pallets/subtensor/src/tests/weights.rs index 3d240750cf..6d19936dfd 100644 --- a/pallets/subtensor/src/tests/weights.rs +++ b/pallets/subtensor/src/tests/weights.rs @@ -684,7 +684,7 @@ fn test_weights_err_setting_weights_too_fast() { netuid, 1, ); - SubtensorModule::set_weights_set_rate_limit(netuid, 10); + SubtensorModule::set_weights_set_rate_limit(netuid, 10, false); assert_eq!(SubtensorModule::get_weights_set_rate_limit(netuid), 10); let weights_keys: Vec = vec![1, 2]; @@ -1526,7 +1526,7 @@ fn test_reveal_weights_when_commit_reveal_disabled() { // Register neurons and set up configurations register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); @@ -1587,7 +1587,7 @@ fn test_commit_reveal_weights_ok() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -1655,7 +1655,7 @@ fn test_commit_reveal_tempo_interval() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -1791,7 +1791,7 @@ fn test_commit_reveal_hash() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1); @@ -1891,7 +1891,7 @@ fn test_commit_reveal_disabled_or_enabled() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1); @@ -1970,7 +1970,7 @@ fn test_toggle_commit_reveal_weights_and_set_weights() { SubtensorModule::set_stake_threshold(0); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::add_balance_to_coldkey_account(&U256::from(0), 1); SubtensorModule::add_balance_to_coldkey_account(&U256::from(1), 1); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( @@ -2053,7 +2053,7 @@ fn test_tempo_change_during_commit_reveal_process() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -2202,7 +2202,7 @@ fn test_commit_reveal_multiple_commits() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -2601,7 +2601,7 @@ fn test_expired_commits_handling_in_commit_and_reveal() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Register neurons register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); @@ -2800,7 +2800,7 @@ fn test_reveal_at_exact_epoch() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); @@ -2964,7 +2964,7 @@ fn test_tempo_and_reveal_period_change_during_commit_reveal_process() { SubtensorModule::set_reveal_period(netuid, initial_reveal_period); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); @@ -3154,7 +3154,7 @@ fn test_commit_reveal_order_enforcement() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); @@ -3256,7 +3256,7 @@ fn test_reveal_at_exact_block() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); @@ -3426,7 +3426,7 @@ fn test_successful_batch_reveal() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); @@ -3504,7 +3504,7 @@ fn test_batch_reveal_with_expired_commits() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); @@ -3756,7 +3756,7 @@ fn test_batch_reveal_before_reveal_period() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); @@ -3814,7 +3814,7 @@ fn test_batch_reveal_after_commits_expired() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); @@ -3921,7 +3921,7 @@ fn test_batch_reveal_with_out_of_order_commits() { add_network(netuid, tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); @@ -4032,7 +4032,7 @@ fn test_highly_concurrent_commits_and_reveals_with_multiple_hotkeys() { // ==== Setup Network ==== add_network(netuid, initial_tempo, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_reveal_period(netuid, initial_reveal_period); SubtensorModule::set_max_registrations_per_block(netuid, u16::MAX); SubtensorModule::set_target_registrations_per_interval(netuid, u16::MAX); @@ -4329,7 +4329,7 @@ fn test_get_reveal_blocks() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -4463,7 +4463,7 @@ fn test_commit_weights_rate_limit() { register_ok_neuron(netuid, U256::from(3), U256::from(4), 300_000); register_ok_neuron(netuid, U256::from(1), U256::from(2), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 10); // Rate limit is 10 blocks + SubtensorModule::set_weights_set_rate_limit(netuid, 10, false); // Rate limit is 10 blocks SubtensorModule::set_validator_permit_for_uid(netuid, 0, true); SubtensorModule::set_validator_permit_for_uid(netuid, 1, true); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); @@ -4646,7 +4646,7 @@ fn test_reveal_crv3_commits_success() { register_ok_neuron(netuid, hotkey1, U256::from(3), 100_000); register_ok_neuron(netuid, hotkey2, U256::from(4), 100_000); SubtensorModule::set_stake_threshold(0); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 3); @@ -4801,7 +4801,7 @@ fn test_reveal_crv3_commits_cannot_reveal_after_reveal_epoch() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey1, U256::from(3), 100_000); register_ok_neuron(netuid, hotkey2, U256::from(4), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 3); @@ -4925,7 +4925,7 @@ fn test_do_commit_crv3_weights_success() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); assert_ok!(SubtensorModule::do_commit_crv3_weights( @@ -4959,7 +4959,7 @@ fn test_do_commit_crv3_weights_disabled() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, false); assert_err!( @@ -4988,7 +4988,7 @@ fn test_do_commit_crv3_weights_hotkey_not_registered() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); assert_err!( @@ -5017,7 +5017,7 @@ fn test_do_commit_crv3_weights_committing_too_fast() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 5); + SubtensorModule::set_weights_set_rate_limit(netuid, 5, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); let neuron_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey).expect("Expected uid"); @@ -5087,7 +5087,7 @@ fn test_do_commit_crv3_weights_too_many_unrevealed_commits() { register_ok_neuron(netuid, hotkey1, U256::from(2), 100_000); register_ok_neuron(netuid, hotkey2, U256::from(3), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Hotkey1 submits 10 commits successfully for i in 0..10 { @@ -5189,7 +5189,7 @@ fn test_reveal_crv3_commits_decryption_failure() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); let commit_bytes: Vec = vec![0xff; 100]; @@ -5246,7 +5246,7 @@ fn test_reveal_crv3_commits_multiple_commits_some_fail_some_succeed() { register_ok_neuron(netuid, hotkey2, U256::from(4), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 1); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Prepare a valid payload for hotkey1 let neuron_uid1 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey1) @@ -5368,7 +5368,7 @@ fn test_reveal_crv3_commits_do_set_weights_failure() { register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 3); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Prepare payload with mismatched uids and values lengths let version_key = SubtensorModule::get_weights_version_key(netuid); @@ -5454,7 +5454,7 @@ fn test_reveal_crv3_commits_payload_decoding_failure() { register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 3); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); let invalid_payload = vec![0u8; 10]; // Not a valid encoding of WeightsTlockPayload @@ -5533,7 +5533,7 @@ fn test_reveal_crv3_commits_signature_deserialization_failure() { register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 3); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); let version_key = SubtensorModule::get_weights_version_key(netuid); let payload = WeightsTlockPayload { @@ -5612,7 +5612,7 @@ fn test_do_commit_crv3_weights_commit_size_exceeds_limit() { add_network(netuid, 5, 0); register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); let max_commit_size = MAX_CRV3_COMMIT_SIZE_BYTES as usize; let commit_data_exceeding: Vec = vec![0u8; max_commit_size + 1]; // Exceeds max size @@ -5652,7 +5652,7 @@ fn test_reveal_crv3_commits_with_empty_commit_queue() { add_network(netuid, 5, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); step_epochs(2, netuid); @@ -5678,7 +5678,7 @@ fn test_reveal_crv3_commits_with_incorrect_identity_message() { register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 1); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); // Prepare a valid payload but use incorrect identity message during encryption let neuron_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey) @@ -5764,7 +5764,7 @@ fn test_multiple_commits_by_same_hotkey_within_limit() { register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 1); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); for i in 0..10 { let commit_data: Vec = vec![i; 5]; @@ -5802,7 +5802,7 @@ fn test_reveal_crv3_commits_removes_past_epoch_commits() { register_ok_neuron(netuid, hotkey, U256::from(2), 100_000); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 1); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); let current_block = SubtensorModule::get_current_block_as_u64(); let current_epoch = SubtensorModule::get_epoch_index(netuid, current_block); @@ -5867,7 +5867,7 @@ fn test_reveal_crv3_commits_multiple_valid_commits_all_processed() { add_network(netuid, 5, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 1); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_max_registrations_per_block(netuid, 100); SubtensorModule::set_target_registrations_per_interval(netuid, 100); @@ -6055,7 +6055,7 @@ fn test_reveal_crv3_commits_max_neurons() { add_network(netuid, 5, 0); SubtensorModule::set_commit_reveal_weights_enabled(netuid, true); SubtensorModule::set_reveal_period(netuid, 1); - SubtensorModule::set_weights_set_rate_limit(netuid, 0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0, false); SubtensorModule::set_max_registrations_per_block(netuid, 10000); SubtensorModule::set_target_registrations_per_interval(netuid, 10000); SubtensorModule::set_max_allowed_uids(netuid, 10024); diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 899fa83646..b7373fd6c8 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -293,18 +293,34 @@ impl Pallet { // Configure tx rate limiting pub fn get_tx_rate_limit() -> u64 { - TxRateLimit::::get() + let limit_key = RateLimitKey::TxRateLimit; + if !LastRateLimitedBlock::::contains_key(&limit_key) { + return T::InitialTxRateLimit::get(); + } + + LastRateLimitedBlock::::get(limit_key) } - pub fn set_tx_rate_limit(tx_rate_limit: u64) { - TxRateLimit::::put(tx_rate_limit); - Self::deposit_event(Event::TxRateLimitSet(tx_rate_limit)); + pub fn set_tx_rate_limit(tx_rate_limit: u64, skip_event: bool) { + LastRateLimitedBlock::::set(RateLimitKey::TxRateLimit, tx_rate_limit); + + if !skip_event { + Self::deposit_event(Event::TxRateLimitSet(tx_rate_limit)); + } } pub fn get_tx_delegate_take_rate_limit() -> u64 { - TxDelegateTakeRateLimit::::get() + let limit_key = RateLimitKey::TxDelegateRateLimit; + if !LastRateLimitedBlock::::contains_key(&limit_key) { + return T::InitialTxDelegateTakeRateLimit::get(); + } + + LastRateLimitedBlock::::get(limit_key) } - pub fn set_tx_delegate_take_rate_limit(tx_rate_limit: u64) { - TxDelegateTakeRateLimit::::put(tx_rate_limit); - Self::deposit_event(Event::TxDelegateTakeRateLimitSet(tx_rate_limit)); + pub fn set_tx_delegate_take_rate_limit(tx_rate_limit: u64, skip_event: bool) { + LastRateLimitedBlock::::set(RateLimitKey::TxDelegateRateLimit, tx_rate_limit); + + if !skip_event { + Self::deposit_event(Event::TxDelegateTakeRateLimitSet(tx_rate_limit)); + } } pub fn set_min_delegate_take(take: u16) { MinDelegateTake::::put(take); @@ -330,11 +346,19 @@ impl Pallet { MinChildkeyTake::::get() } pub fn get_tx_childkey_take_rate_limit() -> u64 { - TxChildkeyTakeRateLimit::::get() + let limit_key = RateLimitKey::TxChildkeyTakeRateLimit; + if !LastRateLimitedBlock::::contains_key(&limit_key) { + return T::InitialTxChildKeyTakeRateLimit::get(); + } + + LastRateLimitedBlock::::get(limit_key) } - pub fn set_tx_childkey_take_rate_limit(tx_rate_limit: u64) { - TxChildkeyTakeRateLimit::::put(tx_rate_limit); - Self::deposit_event(Event::TxChildKeyTakeRateLimitSet(tx_rate_limit)); + pub fn set_tx_childkey_take_rate_limit(tx_rate_limit: u64, skip_event: bool) { + LastRateLimitedBlock::::insert(RateLimitKey::TxChildkeyTakeRateLimit, tx_rate_limit); + + if !skip_event { + Self::deposit_event(Event::TxChildKeyTakeRateLimitSet(tx_rate_limit)); + } } pub fn set_min_childkey_take(take: u16) { MinChildkeyTake::::put(take); @@ -353,11 +377,20 @@ impl Pallet { } pub fn get_serving_rate_limit(netuid: u16) -> u64 { - ServingRateLimit::::get(netuid) + let limit_key = RateLimitKey::ServingRateLimit(netuid); + if !LastRateLimitedBlock::::contains_key(&limit_key) { + return T::InitialServingRateLimit::get(); + } + + Self::get_rate_limited_last_block(&limit_key) } - pub fn set_serving_rate_limit(netuid: u16, serving_rate_limit: u64) { - ServingRateLimit::::insert(netuid, serving_rate_limit); - Self::deposit_event(Event::ServingRateLimitSet(netuid, serving_rate_limit)); + pub fn set_serving_rate_limit(netuid: u16, serving_rate_limit: u64, skip_event: bool) { + let limit_key = RateLimitKey::ServingRateLimit(netuid); + Self::set_rate_limited_last_block(&limit_key, serving_rate_limit); + + if !skip_event { + Self::deposit_event(Event::ServingRateLimitSet(netuid, serving_rate_limit)); + } } pub fn get_min_difficulty(netuid: u16) -> u64 { @@ -385,14 +418,25 @@ impl Pallet { } pub fn get_weights_set_rate_limit(netuid: u16) -> u64 { - WeightsSetRateLimit::::get(netuid) + const DEFAULT: u64 = 100; + let limit_key = RateLimitKey::SetWeightsRateLimit(netuid); + + if !LastRateLimitedBlock::::contains_key(&limit_key) { + return DEFAULT; + } + + LastRateLimitedBlock::::get(&limit_key) } - pub fn set_weights_set_rate_limit(netuid: u16, weights_set_rate_limit: u64) { - WeightsSetRateLimit::::insert(netuid, weights_set_rate_limit); - Self::deposit_event(Event::WeightsSetRateLimitSet( - netuid, - weights_set_rate_limit, - )); + pub fn set_weights_set_rate_limit(netuid: u16, weights_set_rate_limit: u64, skip_event: bool) { + let limit_key = RateLimitKey::SetWeightsRateLimit(netuid); + LastRateLimitedBlock::::insert(&limit_key, weights_set_rate_limit); + + if !skip_event { + Self::deposit_event(Event::WeightsSetRateLimitSet( + netuid, + weights_set_rate_limit, + )); + } } pub fn get_adjustment_interval(netuid: u16) -> u16 { diff --git a/pallets/subtensor/src/utils/rate_limiting.rs b/pallets/subtensor/src/utils/rate_limiting.rs index 7edaebc98a..9351df9a13 100644 --- a/pallets/subtensor/src/utils/rate_limiting.rs +++ b/pallets/subtensor/src/utils/rate_limiting.rs @@ -46,8 +46,8 @@ impl Pallet { pub fn get_rate_limit(tx_type: &TransactionType) -> u64 { match tx_type { TransactionType::SetChildren => 150, // 30 minutes - TransactionType::SetChildkeyTake => TxChildkeyTakeRateLimit::::get(), - TransactionType::RegisterNetwork => NetworkRateLimit::::get(), + TransactionType::SetChildkeyTake => Self::get_tx_childkey_take_rate_limit(), + TransactionType::RegisterNetwork => Self::get_network_rate_limit(), TransactionType::Unknown => 0, // Default to no limit for unknown types (no limit) _ => 0, diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index 7d4dd175e3..ae0d25a5f2 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -1,5 +1,6 @@ use core::marker::PhantomData; +use crate::{PrecompileExt, PrecompileHandleExt}; use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo}; use frame_support::traits::ConstU32; use frame_system::RawOrigin; @@ -8,8 +9,6 @@ use precompile_utils::{EvmResult, prelude::BoundedString}; use sp_core::H256; use sp_runtime::traits::Dispatchable; -use crate::{PrecompileExt, PrecompileHandleExt}; - pub struct SubnetPrecompile(PhantomData); impl PrecompileExt for SubnetPrecompile @@ -98,7 +97,7 @@ where #[precompile::public("getServingRateLimit(uint16)")] #[precompile::view] fn get_serving_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::ServingRateLimit::::get(netuid)) + Ok(pallet_subtensor::pallet::Pallet::::get_serving_rate_limit(netuid)) } #[precompile::public("setServingRateLimit(uint16,uint64)")] @@ -194,7 +193,7 @@ where #[precompile::public("getWeightsSetRateLimit(uint16)")] #[precompile::view] fn get_weights_set_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - Ok(pallet_subtensor::WeightsSetRateLimit::::get(netuid)) + Ok(pallet_subtensor::pallet::Pallet::::get_weights_set_rate_limit(netuid)) } #[precompile::public("setWeightsSetRateLimit(uint16,uint64)")]