diff --git a/pallets/offworker/src/dispatches/mod.rs b/pallets/offworker/src/dispatches/mod.rs index 9a4ac6dd3..f6c78b5e4 100644 --- a/pallets/offworker/src/dispatches/mod.rs +++ b/pallets/offworker/src/dispatches/mod.rs @@ -22,7 +22,7 @@ pub mod dispatches { #[pallet::weight((Weight::zero(), DispatchClass::Normal, Pays::No))] pub fn send_decrypted_weights( origin: OriginFor, - payload: DecryptedWeightsPayload>, /* make payload accept zk proofs of wrong encryption */ + payload: DecryptedWeightsPayload>, _signature: T::Signature, ) -> DispatchResultWithPostInfo { // Signature valiadation is performed by the validate unsigned function @@ -31,35 +31,45 @@ pub mod dispatches { let DecryptedWeightsPayload { subnet_id, decrypted_weights, - delta, + delta: _, block_number, public, + forced_send_by_rotation, } = payload; - let decryption_data = SubnetDecryptionData::::get(subnet_id); - if let Some(decryption_data) = decryption_data { + let acc_id = public.into_account(); + + // Modify this section to handle the forced rotation case + SubnetDecryptionData::::try_mutate(subnet_id, |maybe_data| -> DispatchResult { + let decryption_data = maybe_data.as_mut().ok_or(Error::::InvalidSubnetId)?; + ensure!( - decryption_data.node_id == public.into_account(), + decryption_data.node_id == acc_id, Error::::InvalidDecryptionKey ); - } else { - return Err(Error::::InvalidSubnetId.into()); - } - // Get all epochs for this subnet + // If this was a forced rotation send, clear the rotating_from field + if forced_send_by_rotation { + decryption_data.rotating_from = None; + } + + Ok(()) + })?; + + // Rest of the function remains the same let epoch_count = ConsensusParameters::::iter_prefix(subnet_id).count(); - // dbg!("lenght check", decrypted_weights.len(), epoch_count); - // Check if the length matches ensure!( decrypted_weights.len() == epoch_count, Error::::DecryptedWeightsLengthMismatch ); // TODO: make a periodical irrationality delta reseter that subnet owner can control - IrrationalityDelta::::mutate(subnet_id, |current| { - *current = current.saturating_add(delta) - }); + // IrrationalityDelta::::mutate(subnet_id, |current| { + // *current = current.saturating_add(delta) + // }); + IrrationalityDelta::::set(subnet_id, I64F64::from_num(0)); + pallet_subnet_emission::Pallet::::handle_decrypted_weights( subnet_id, decrypted_weights, diff --git a/pallets/offworker/src/lib.rs b/pallets/offworker/src/lib.rs index e26a66feb..417673651 100644 --- a/pallets/offworker/src/lib.rs +++ b/pallets/offworker/src/lib.rs @@ -339,7 +339,11 @@ impl Pallet { .collect() } - fn do_send_weights(subnet_id: u16, delta: I64F64) -> Result<(), &'static str> { + fn do_send_weights( + subnet_id: u16, + delta: I64F64, + forced_send_by_rotation: bool, + ) -> Result<(), &'static str> { let signer = Signer::::all_accounts(); if !signer.can_sign() { return Err( @@ -359,6 +363,7 @@ impl Pallet { delta, block_number: >::block_number(), public: account.public.clone(), + forced_send_by_rotation, }, |payload, signature| Call::send_decrypted_weights { payload, signature }, ); diff --git a/pallets/offworker/src/process.rs b/pallets/offworker/src/process.rs index 7daf81744..aa65673a6 100644 --- a/pallets/offworker/src/process.rs +++ b/pallets/offworker/src/process.rs @@ -52,7 +52,7 @@ impl Pallet { .filter(|(block, _)| *block > last_processed_block) .collect::>(); - let (send_weights, result) = process_consensus_params::( + let (send_weights, result, forced_send) = process_consensus_params::( subnet_id, acc_id.clone(), new_params, @@ -61,7 +61,7 @@ impl Pallet { if !send_weights { Self::save_subnet_state(subnet_id, max_block, result.simulation_result); - } else if let Err(err) = Self::do_send_weights(subnet_id, result.delta) { + } else if let Err(err) = Self::do_send_weights(subnet_id, result.delta, forced_send) { log::error!( "Couldn't send weights to runtime for subnet {}: {}", subnet_id, diff --git a/pallets/offworker/src/types.rs b/pallets/offworker/src/types.rs index 25fbf0588..b6847cce9 100644 --- a/pallets/offworker/src/types.rs +++ b/pallets/offworker/src/types.rs @@ -84,6 +84,7 @@ pub struct DecryptedWeightsPayload { pub delta: I64F64, pub block_number: BlockNumber, pub public: Public, + pub forced_send_by_rotation: bool, } #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, scale_info::TypeInfo)] diff --git a/pallets/offworker/src/util.rs b/pallets/offworker/src/util.rs index 92ecf3690..2ebec8476 100644 --- a/pallets/offworker/src/util.rs +++ b/pallets/offworker/src/util.rs @@ -2,32 +2,12 @@ use super::*; use crate::profitability::{get_copier_stake, is_copying_irrational}; use types::SimulationYumaParams; -fn should_send_rotation_weights(subnet_id: u16, acc_id: &T::AccountId) -> bool -where - T: pallet_subspace::Config + pallet_subnet_emission::Config + pallet::Config, -{ - // Get subnet decryption data and return early if None - let decryption_info = match SubnetDecryptionData::::get(subnet_id) { - Some(data) => data, - None => return false, - }; - - // If there's rotation info and we're the one rotating from, return true - if let Some((rotating_from_id, _block)) = decryption_info.rotating_from { - if &rotating_from_id == acc_id { - return true; - } - } - - false -} - pub fn process_consensus_params( subnet_id: u16, acc_id: T::AccountId, consensus_params: Vec<(u64, ConsensusParams)>, simulation_result: ConsensusSimulationResult, -) -> (bool, ShouldDecryptResult) +) -> (bool, ShouldDecryptResult, bool) where T: pallet_subspace::Config + pallet_subnet_emission::Config + pallet::Config, { @@ -38,6 +18,7 @@ where }; let mut final_should_send = false; + let mut forced_send = false; log::info!("Processing consensus params for subnet {}", subnet_id); log::info!( @@ -149,8 +130,12 @@ where ); let current_should_send = if !should_decrypt_result.should_decrypt { - let rotation_should_send = should_send_rotation_weights::(subnet_id, &acc_id); + let rotation_should_send = + pallet_subnet_emission::Pallet::::should_send_rotation_weights( + subnet_id, &acc_id, + ); if rotation_should_send { + forced_send = true; should_decrypt_result.delta = I64F64::from_num(0); } rotation_should_send @@ -169,7 +154,7 @@ where final_should_send = current_should_send; } log::info!("should_decrypt: {}", result.should_decrypt); - (final_should_send, result) + (final_should_send, result, forced_send) } /// Returns @@ -281,8 +266,7 @@ pub fn compute_simulation_yuma_params( decrypted_weights .iter() .cloned() - .chain(sp_std::iter::once((copier_uid, copier_weights))), /* HONZA TODO figure out - * this validator key */ + .chain(sp_std::iter::once((copier_uid, copier_weights))), ); Some(SimulationYumaParams { diff --git a/pallets/subnet_emission/src/decryption.rs b/pallets/subnet_emission/src/decryption.rs index 3b5490155..0782ec0e5 100644 --- a/pallets/subnet_emission/src/decryption.rs +++ b/pallets/subnet_emission/src/decryption.rs @@ -607,7 +607,7 @@ impl Pallet { node_public_key: new_node.node_public_key, activation_block: None, /* This will get updated based on the first encrypted * weights */ - rotating_from: Some((previous_node_id, block_number)), + rotating_from: Some(previous_node_id), last_keep_alive: block_number, }), ); @@ -616,4 +616,25 @@ impl Pallet { Self::cleanup_weight_encryption_data(subnet_id); } } + + pub fn should_send_rotation_weights(subnet_id: u16, acc_id: &T::AccountId) -> bool { + // Iterate through all subnet decryption data + let rotated_subnets: Vec = SubnetDecryptionData::::iter() + .filter_map(|(subnet, decryption_info)| { + // Check if there's rotation information and the rotating_from matches acc_id + if let Some(rotating_from_id) = decryption_info.rotating_from { + if &rotating_from_id == acc_id { + Some(subnet) + } else { + None + } + } else { + None + } + }) + .collect(); + + // Check if the input subnet_id is in the collected rotated subnets + rotated_subnets.contains(&subnet_id) + } } diff --git a/pallets/subnet_emission/src/types.rs b/pallets/subnet_emission/src/types.rs index d43b26f82..e79edaa48 100644 --- a/pallets/subnet_emission/src/types.rs +++ b/pallets/subnet_emission/src/types.rs @@ -16,5 +16,5 @@ where // gets assigned when first encrypted weights appear on the subnet pub activation_block: Option, pub last_keep_alive: u64, - pub rotating_from: Option<(T::AccountId, u64)>, // rotating from at block + pub rotating_from: Option, } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 30b7adcf3..6a9fe51a7 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -186,7 +186,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node-subspace"), impl_name: create_runtime_str!("node-subspace"), authoring_version: 1, - spec_version: 494, + spec_version: 497, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -468,7 +468,9 @@ impl pallet_subnet_emission::Config for Runtime { type Decimals = ConstU8<9>; type HalvingInterval = ConstU64<250_000_000>; type MaxSupply = ConstU64<1_000_000_000>; - type DecryptionNodeRotationInterval = ConstU64<5_000>; + // type DecryptionNodeRotationInterval = ConstU64<5_000>; + type DecryptionNodeRotationInterval = ConstU64<5_0>; + type MaxAuthorities = ConstU32<100>; // Represented in number of blocks, defines how long decryption node will be banned for. // Ban presists even if ping are being sent.