diff --git a/pallets/ddc-clusters/src/lib.rs b/pallets/ddc-clusters/src/lib.rs index 59ce7fb52..f17ce26a1 100644 --- a/pallets/ddc-clusters/src/lib.rs +++ b/pallets/ddc-clusters/src/lib.rs @@ -31,6 +31,10 @@ use frame_support::{ use frame_system::pallet_prelude::*; pub use pallet::*; use pallet_ddc_nodes::{NodeRepository, NodeTrait}; +use sp_runtime::{ + traits::{IdentifyAccount, Verify}, + AccountId32, MultiSignature, MultiSigner, +}; use sp_std::prelude::*; mod cluster; @@ -56,6 +60,12 @@ pub mod pallet { type NodeRepository: NodeRepository; // todo: get rid of tight coupling with nodes-pallet type StakingVisitor: StakingVisitor; type Currency: LockableCurrency; + + type Signature: Verify + + Encode + + Decode + + Parameter + + From; } #[pallet::event] @@ -84,6 +94,8 @@ pub mod pallet { /// Cluster candidate should not plan to chill. NodeChillingIsProhibited, NodeAuthContractCallFailed, + SignatureValidationFailed, + SignatureMismatch, } #[pallet::storage] @@ -225,10 +237,16 @@ pub mod pallet { origin: OriginFor, cluster_id: ClusterId, cluster_gov_params: ClusterGovParams>, + signature: T::Signature, + data: Vec, ) -> DispatchResult { let caller_id = ensure_signed(origin)?; let cluster = Clusters::::try_get(&cluster_id).map_err(|_| Error::::ClusterDoesNotExist)?; + let is_cluster_manager = + Self::validate_signature(&cluster.manager_id, &signature, &data)?; + ensure!(is_cluster_manager, Error::::SignatureMismatch); + ensure!(cluster.manager_id == caller_id, Error::::OnlyClusterManager); ClustersGovParams::::insert(cluster_id.clone(), cluster_gov_params); Self::deposit_event(Event::::ClusterGovParamsSet { cluster_id }); @@ -237,6 +255,20 @@ pub mod pallet { } } + impl Pallet { + fn validate_signature( + signer_id: &T::AccountId, + signature: &T::Signature, + data: &Vec, + ) -> Result> { + let pub_key: [u8; 32] = match signer_id.encode().as_slice()[..].try_into() { + Ok(pub_key) => pub_key, + Err(_) => return Err(Error::::SignatureValidationFailed), + }; + Ok(signature.verify(data.as_slice(), &AccountId32::from(pub_key))) + } + } + impl ClusterVisitor for Pallet { fn cluster_has_node(cluster_id: &ClusterId, node_pub_key: &NodePubKey) -> bool { ClustersNodes::::get(cluster_id, node_pub_key).is_some() diff --git a/runtime/cere-dev/src/lib.rs b/runtime/cere-dev/src/lib.rs index b2ff75c80..059de7c9b 100644 --- a/runtime/cere-dev/src/lib.rs +++ b/runtime/cere-dev/src/lib.rs @@ -71,11 +71,12 @@ use sp_runtime::{ curve::PiecewiseLinear, generic, impl_opaque_keys, traits::{ - self, BlakeTwo256, Block as BlockT, ConvertInto, NumberFor, OpaqueKeys, - SaturatedConversion, StaticLookup, + self, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, OpaqueKeys, + SaturatedConversion, StaticLookup, Verify, }, transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perbill, Percent, Permill, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perbill, + Percent, Permill, Perquintill, }; use sp_staking::EraIndex; use sp_std::prelude::*; @@ -1358,6 +1359,7 @@ impl pallet_ddc_clusters::Config for Runtime { type NodeRepository = pallet_ddc_nodes::Pallet; type StakingVisitor = pallet_ddc_staking::Pallet; type Currency = Balances; + type Signature = MultiSignature; } construct_runtime!(