From 3d4edcf7646bf3889b7c58078a6772a9576a1c13 Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 7 Jan 2025 23:36:51 +0800 Subject: [PATCH] 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,