From 3d4edcf7646bf3889b7c58078a6772a9576a1c13 Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 7 Jan 2025 23:36:51 +0800 Subject: [PATCH 1/4] extrinsic to enable disable precompile --- pallets/admin-utils/src/lib.rs | 66 +++++++++++++++++++++++- pallets/admin-utils/src/tests/mock.rs | 1 + pallets/admin-utils/src/tests/mod.rs | 72 +++++++++++++++++++++++++++ runtime/src/precompiles/mod.rs | 49 ++++++++++++++++-- 4 files changed, 182 insertions(+), 6 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index d709c70c5..e91a4b88a 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -23,9 +23,9 @@ mod tests; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::dispatch::DispatchResult; use frame_support::pallet_prelude::*; use frame_support::traits::tokens::Balance; + use frame_support::{dispatch::DispatchResult, pallet_prelude::StorageMap}; use frame_system::pallet_prelude::*; use pallet_evm_chain_id::{self, ChainId}; use sp_runtime::BoundedVec; @@ -69,7 +69,16 @@ pub mod pallet { } #[pallet::event] - pub enum Event {} + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event emitted when a precompile operation is updated. + PrecompileUpdated { + /// The type of precompile operation being updated. + precompile_id: PrecompileEnum, + /// Indicates if the precompile operation is enabled or not. + enabled: bool, + }, + } // Errors inform users that something went wrong. #[pallet::error] @@ -81,6 +90,39 @@ pub mod pallet { /// The maximum number of subnet validators must be more than the current number of UIDs already in the subnet. MaxAllowedUIdsLessThanCurrentUIds, } + /// Enum for specifying the type of precompile operation. + #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug, Copy)] + pub enum PrecompileEnum { + /// Enum for balance transfer precompile + BalanceTransfer, + /// Enum for staking precompile + Staking, + /// Enum for subnet precompile + Subnet, + /// Enum for metagraph precompile + Metagraph, + /// Enum for subnets precompile + Subnets, + /// Enum for neurons precompile + Neurons, + } + + #[pallet::type_value] + /// Default value for precompile enable + pub fn DefaultPrecompileEnabled() -> bool { + true + } + + #[pallet::storage] + /// Map PrecompileEnum --> enabled + pub type PrecompileEnable = StorageMap< + _, + Blake2_128Concat, + PrecompileEnum, + bool, + ValueQuery, + DefaultPrecompileEnabled, + >; /// Dispatchable functions allows users to interact with the pallet and invoke state changes. #[pallet::call] @@ -1276,6 +1318,26 @@ pub mod pallet { ensure_root(origin)?; T::Grandpa::schedule_change(next_authorities, in_blocks, forced) } + + /// A public interface for `pallet_grandpa::Pallet::schedule_grandpa_change`. + #[pallet::call_index(60)] + #[pallet::weight(Weight::from_parts(46_000_000, 0))] + pub fn sudo_toggle_evm_precompile( + origin: OriginFor, + precompile_id: PrecompileEnum, + enabled: bool, + ) -> DispatchResult { + ensure_root(origin)?; + if PrecompileEnable::::get(precompile_id) != enabled { + PrecompileEnable::::insert(precompile_id, enabled); + Self::deposit_event(Event::PrecompileUpdated { + precompile_id, + enabled, + }); + } + // T::Grandpa::schedule_change(next_authorities, in_blocks, forced) + Ok(()) + } } } diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index 8c9110e6e..18de6e6af 100644 --- a/pallets/admin-utils/src/tests/mock.rs +++ b/pallets/admin-utils/src/tests/mock.rs @@ -390,6 +390,7 @@ pub(crate) fn run_to_block(n: u64) { while System::block_number() < n { SubtensorModule::on_finalize(System::block_number()); System::on_finalize(System::block_number()); + System::reset_events(); System::set_block_number(System::block_number() + 1); System::on_initialize(System::block_number()); SubtensorModule::on_initialize(System::block_number()); diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index 9bdf133f5..94c72d104 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -10,6 +10,7 @@ use pallet_subtensor::{migrations, Event}; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{ed25519, Pair, U256}; +use crate::pallet::PrecompileEnable; use crate::Error; use mock::*; @@ -1490,3 +1491,74 @@ fn test_schedule_grandpa_change() { assert_eq!(Grandpa::grandpa_authorities(), vec![(bob, 1)]); }); } + +#[test] +fn test_sudo_toggle_evm_precompile() { + new_test_ext().execute_with(|| { + let precompile_id = crate::PrecompileEnum::BalanceTransfer; + let initial_enabled = PrecompileEnable::::get(precompile_id); + assert_eq!(initial_enabled, true); // Assuming the default is true + + run_to_block(1); + + assert_eq!( + AdminUtils::sudo_toggle_evm_precompile( + <::RuntimeOrigin>::signed(U256::from(0)), + precompile_id, + false + ), + Err(DispatchError::BadOrigin) + ); + + assert_ok!(AdminUtils::sudo_toggle_evm_precompile( + RuntimeOrigin::root(), + precompile_id, + false + )); + + assert_eq!( + System::events() + .iter() + .filter(|r| r.event + == RuntimeEvent::AdminUtils(crate::Event::PrecompileUpdated { + precompile_id, + enabled: false + })) + .count(), + 1 + ); + + let updated_enabled = PrecompileEnable::::get(precompile_id); + assert_eq!(updated_enabled, false); + + run_to_block(2); + + assert_ok!(AdminUtils::sudo_toggle_evm_precompile( + RuntimeOrigin::root(), + precompile_id, + false + )); + + // no event without status change + assert_eq!( + System::events() + .iter() + .filter(|r| r.event + == RuntimeEvent::AdminUtils(crate::Event::PrecompileUpdated { + precompile_id, + enabled: false + })) + .count(), + 0 + ); + + assert_ok!(AdminUtils::sudo_toggle_evm_precompile( + RuntimeOrigin::root(), + precompile_id, + true + )); + + let final_enabled = PrecompileEnable::::get(precompile_id); + assert_eq!(final_enabled, true); + }); +} diff --git a/runtime/src/precompiles/mod.rs b/runtime/src/precompiles/mod.rs index e13516e95..524c252f0 100644 --- a/runtime/src/precompiles/mod.rs +++ b/runtime/src/precompiles/mod.rs @@ -10,6 +10,9 @@ use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use crate::Runtime; +use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; + // Include custom precompiles mod balance_transfer; mod ed25519; @@ -70,14 +73,52 @@ where // Non-Frontier specific nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)), - a if a == hash(EDVERIFY_PRECOMPILE_INDEX) => Some(Ed25519Verify::execute(handle)), + + a if a == hash(EDVERIFY_PRECOMPILE_INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::BalanceTransfer) { + Some(Ed25519Verify::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + "Precompile Ed25519Verify is disabled".into(), + ), + })) + } + } // Subtensor specific precompiles : a if a == hash(BALANCE_TRANSFER_INDEX) => { - Some(BalanceTransferPrecompile::execute(handle)) + if PrecompileEnable::::get(PrecompileEnum::BalanceTransfer) { + Some(BalanceTransferPrecompile::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + "Precompile Balance Transfer is disabled".into(), + ), + })) + } } - a if a == hash(STAKING_PRECOMPILE_INDEX) => Some(StakingPrecompile::execute(handle)), + a if a == hash(STAKING_PRECOMPILE_INDEX) => { + if PrecompileEnable::::get(PrecompileEnum::Staking) { + Some(StakingPrecompile::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + "Precompile Balance Transfer is disabled".into(), + ), + })) + } + } + a if a == hash(METAGRAPH_PRECOMPILE_INDEX) => { - Some(MetagraphPrecompile::execute(handle)) + if PrecompileEnable::::get(PrecompileEnum::Metagraph) { + Some(MetagraphPrecompile::execute(handle)) + } else { + Some(Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + "Precompile Balance Transfer is disabled".into(), + ), + })) + } } _ => None, From b2e216e3fa20eb47d7793753e083e2d48f6b343c Mon Sep 17 00:00:00 2001 From: open-junius Date: Sat, 11 Jan 2025 00:03:03 +0800 Subject: [PATCH 2/4] fix clippy --- pallets/admin-utils/src/lib.rs | 1 - pallets/admin-utils/src/tests/mod.rs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 2de97d745..09a4ce0c8 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -1321,7 +1321,6 @@ pub mod pallet { enabled, }); } - // T::Grandpa::schedule_change(next_authorities, in_blocks, forced) Ok(()) } } diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index 77bce472b..e970ddee4 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -1469,7 +1469,7 @@ fn test_sudo_toggle_evm_precompile() { new_test_ext().execute_with(|| { let precompile_id = crate::PrecompileEnum::BalanceTransfer; let initial_enabled = PrecompileEnable::::get(precompile_id); - assert_eq!(initial_enabled, true); // Assuming the default is true + assert!(initial_enabled); // Assuming the default is true run_to_block(1); @@ -1501,7 +1501,7 @@ fn test_sudo_toggle_evm_precompile() { ); let updated_enabled = PrecompileEnable::::get(precompile_id); - assert_eq!(updated_enabled, false); + assert!(!updated_enabled); run_to_block(2); @@ -1531,6 +1531,6 @@ fn test_sudo_toggle_evm_precompile() { )); let final_enabled = PrecompileEnable::::get(precompile_id); - assert_eq!(final_enabled, true); + assert!(final_enabled); }); } From 335f9b2af13723ae5fa26a2169c9f77e45ff6f6d Mon Sep 17 00:00:00 2001 From: open-junius Date: Mon, 13 Jan 2025 14:47:56 +0800 Subject: [PATCH 3/4] update doc and weigths --- pallets/admin-utils/src/lib.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 09a4ce0c8..01106daf9 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -1305,9 +1305,20 @@ pub mod pallet { T::Grandpa::schedule_change(next_authorities, in_blocks, forced) } - /// A public interface for `pallet_grandpa::Pallet::schedule_grandpa_change`. + /// Toggles the enablement of an EVM precompile. + /// + /// # Arguments + /// * `origin` - The origin of the call, which must be the root account. + /// * `precompile_id` - The identifier of the EVM precompile to toggle. + /// * `enabled` - The new enablement state of the precompile. + /// + /// # Errors + /// * `BadOrigin` - If the caller is not the root account. + /// + /// # Weight + /// Weight is handled by the `#[pallet::weight]` attribute. #[pallet::call_index(60)] - #[pallet::weight(Weight::from_parts(46_000_000, 0))] + #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_toggle_evm_precompile( origin: OriginFor, precompile_id: PrecompileEnum, From d03bea9dc8487c8e3a826ab42a2d909b8196091c Mon Sep 17 00:00:00 2001 From: open-junius Date: Fri, 17 Jan 2025 23:22:06 +0800 Subject: [PATCH 4/4] remove subnets --- pallets/admin-utils/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 01106daf9..4223067c4 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -101,10 +101,8 @@ pub mod pallet { Subnet, /// Enum for metagraph precompile Metagraph, - /// Enum for subnets precompile - Subnets, - /// Enum for neurons precompile - Neurons, + /// Enum for neuron precompile + Neuron, } #[pallet::type_value]