diff --git a/pallets/jobs/src/functions.rs b/pallets/jobs/src/functions.rs index af7037108..0865ce21c 100644 --- a/pallets/jobs/src/functions.rs +++ b/pallets/jobs/src/functions.rs @@ -285,9 +285,9 @@ impl Pallet { let mut participant_keys: Vec> = Default::default(); for participant in participants.clone() { - let key = T::RolesHandler::get_validator_metadata(participant, role_type); - ensure!(key.is_some(), Error::::ValidatorMetadataNotFound); - participant_keys.push(key.expect("checked above").get_authority_key()); + let key = T::RolesHandler::get_validator_role_key(participant); + ensure!(key.is_some(), Error::::ValidatorRoleKeyNotFound); + participant_keys.push(key.expect("checked above")); } let job_result = JobResult::DKGPhaseOne(DKGTSSKeySubmissionResult { @@ -341,12 +341,10 @@ impl Pallet { let participants = phase_one_result.participants().ok_or(Error::::InvalidJobPhase)?; for participant in participants { - let key = T::RolesHandler::get_validator_metadata(participant, role_type); - ensure!(key.is_some(), Error::::ValidatorMetadataNotFound); - let pub_key = sp_core::ecdsa::Public::from_slice( - &key.expect("checked above").get_authority_key()[0..33], - ) - .map_err(|_| Error::::InvalidValidator)?; + let key = T::RolesHandler::get_validator_role_key(participant); + ensure!(key.is_some(), Error::::ValidatorRoleKeyNotFound); + let pub_key = sp_core::ecdsa::Public::from_slice(&key.expect("checked above")[0..33]) + .map_err(|_| Error::::InvalidValidator)?; participant_keys.push(pub_key); } let signing_key = match phase_one_result.result { @@ -399,12 +397,10 @@ impl Pallet { let mut participant_keys: Vec = Default::default(); for participant in participants.clone() { - let key = T::RolesHandler::get_validator_metadata(participant, role_type); - ensure!(key.is_some(), Error::::ValidatorMetadataNotFound); - let pub_key = sp_core::ecdsa::Public::from_slice( - &key.expect("checked above").get_authority_key()[0..33], - ) - .map_err(|_| Error::::InvalidValidator)?; + let key = T::RolesHandler::get_validator_role_key(participant); + ensure!(key.is_some(), Error::::ValidatorRoleKeyNotFound); + let pub_key = sp_core::ecdsa::Public::from_slice(&key.expect("checked above")[0..33]) + .map_err(|_| Error::::InvalidValidator)?; participant_keys.push(pub_key); } diff --git a/pallets/jobs/src/lib.rs b/pallets/jobs/src/lib.rs index fad071a33..8c23f33af 100644 --- a/pallets/jobs/src/lib.rs +++ b/pallets/jobs/src/lib.rs @@ -117,8 +117,8 @@ pub mod module { EmptyResult, /// empty job EmptyJob, - /// Validator metadata not found - ValidatorMetadataNotFound, + /// Validator role key not found. + ValidatorRoleKeyNotFound, /// Unexpected result provided ResultNotExpectedType, /// No permission to change permitted caller diff --git a/pallets/jobs/src/mock.rs b/pallets/jobs/src/mock.rs index 04fd28548..79e8c2089 100644 --- a/pallets/jobs/src/mock.rs +++ b/pallets/jobs/src/mock.rs @@ -30,11 +30,7 @@ use sp_core::ecdsa; use sp_io::crypto::ecdsa_generate; use sp_keystore::{testing::MemoryKeystore, KeystoreExt, KeystorePtr}; use sp_std::sync::Arc; -use tangle_primitives::{ - currency::UNIT, - jobs::*, - roles::{RoleType, RoleTypeMetadata, TssRoleMetadata}, -}; +use tangle_primitives::{currency::UNIT, jobs::*, roles::RoleType}; impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; @@ -133,22 +129,12 @@ impl RolesHandler for MockRolesHandler { Ok(()) } - fn get_validator_metadata( - address: AccountId32, - role_type: RoleType, - ) -> Option { + fn get_validator_role_key(address: AccountId32) -> Option> { let mock_err_account = AccountId32::new([100u8; 32]); if address == mock_err_account { None } else { - match role_type { - RoleType::Tss(threshold_signature_role) => - Some(RoleTypeMetadata::Tss(TssRoleMetadata { - role_type: threshold_signature_role, - authority_key: mock_pub_key().to_raw_vec(), - })), - _ => None, - } + Some(mock_pub_key().to_raw_vec()) } } } diff --git a/pallets/roles/src/impls.rs b/pallets/roles/src/impls.rs index 78549db3e..b6e7d3654 100644 --- a/pallets/roles/src/impls.rs +++ b/pallets/roles/src/impls.rs @@ -28,10 +28,7 @@ use sp_runtime::{ use sp_staking::offence::Offence; use tangle_primitives::{ - jobs::{ - traits::{JobsHandler, MPCHandler}, - ReportValidatorOffence, - }, + jobs::{traits::JobsHandler, ReportValidatorOffence}, roles::traits::RolesHandler, }; @@ -65,20 +62,10 @@ impl RolesHandler for Pallet { Self::report_offence(offence_report) } - fn get_validator_metadata( - address: T::AccountId, - role_type: RoleType, - ) -> Option { - if Self::is_validator(address.clone(), role_type) { - let ledger = Self::ledger(&address); - if let Some(ledger) = ledger { - return match ledger.roles.get(&role_type) { - Some(stake) => Some(stake.metadata.clone()), - None => None, - } - } else { - return None - } + fn get_validator_role_key(address: T::AccountId) -> Option> { + let maybe_ledger = Self::ledger(&address); + if let Some(ledger) = maybe_ledger { + Some(ledger.role_key) } else { return None } @@ -126,11 +113,6 @@ impl Pallet { Error::::InsufficientRestakingBond ); } - // validate the metadata - T::MPCHandler::validate_authority_key( - account.clone(), - record.metadata.get_authority_key(), - )?; } Ok(()) } diff --git a/pallets/roles/src/lib.rs b/pallets/roles/src/lib.rs index d4baf3746..e66319a8a 100644 --- a/pallets/roles/src/lib.rs +++ b/pallets/roles/src/lib.rs @@ -29,10 +29,14 @@ pub use pallet::*; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_core::ecdsa; -use sp_runtime::{traits::Zero, Saturating}; +use sp_runtime::{ + traits::{Convert, OpaqueKeys, Zero}, + Saturating, +}; use sp_staking::offence::ReportOffence; use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, prelude::*, vec}; -use tangle_primitives::roles::{RoleType, RoleTypeMetadata}; +use tangle_crypto_primitives::ROLE_KEY_TYPE; +use tangle_primitives::roles::RoleType; mod impls; mod profile; @@ -68,18 +72,20 @@ pub struct RoleStakingLedger { pub profile: Profile, /// Roles map with their respective records. pub roles: BTreeMap>, + /// Role key + pub role_key: Vec, } impl RoleStakingLedger { /// New staking ledger for a stash account. - pub fn new(stash: T::AccountId, profile: Profile) -> Self { + pub fn new(stash: T::AccountId, profile: Profile, role_key: Vec) -> Self { let total_restake = profile.get_total_profile_restake(); let roles = profile .get_records() .into_iter() - .map(|record| (record.metadata.get_role_type(), record)) + .map(|record| (record.role, record)) .collect::>(); - Self { stash, total: total_restake.into(), profile, roles } + Self { stash, total: total_restake.into(), profile, roles, role_key } } /// Returns the total amount of the stash's balance that is restaked for all selected roles. @@ -124,7 +130,9 @@ pub mod pallet { /// Configuration trait. #[pallet::config] - pub trait Config: frame_system::Config + pallet_staking::Config { + pub trait Config: + frame_system::Config + pallet_staking::Config + pallet_session::Config + { /// The overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; @@ -221,6 +229,8 @@ pub mod pallet { /// Profile delete request failed due to pending jobs, which can't be opted out at the /// moment. ProfileDeleteRequestFailed, + /// SessionKeys not provided + SessionKeysNotProvided, } /// Map from all "controller" accounts to the info regarding the staking. @@ -272,9 +282,25 @@ pub mod pallet { Error::::NotValidator ); + // Get Role key of validator. + let validator_id = + ::ValidatorIdOf::convert(stash_account.clone()) + .ok_or(Error::::NotValidator)?; + + let session_keys = pallet_session::NextKeys::::get(validator_id) + .ok_or(Error::::SessionKeysNotProvided)?; + let role_key = OpaqueKeys::get_raw(&session_keys, ROLE_KEY_TYPE); + + // Validate role key. + T::MPCHandler::validate_authority_key(stash_account.clone(), role_key.to_vec())?; + // Ensure no profile is assigned to the validator. ensure!(!Ledger::::contains_key(&stash_account), Error::::ProfileAlreadyExists); - let ledger = RoleStakingLedger::::new(stash_account.clone(), profile.clone()); + let ledger = RoleStakingLedger::::new( + stash_account.clone(), + profile.clone(), + role_key.to_vec(), + ); let total_profile_restake = profile.get_total_profile_restake(); // Restaking amount of profile should meet min Restaking amount requirement. @@ -304,11 +330,6 @@ pub mod pallet { Error::::InsufficientRestakingBond ); } - // validate the metadata - T::MPCHandler::validate_authority_key( - stash_account.clone(), - record.metadata.get_authority_key(), - )?; } let profile_roles: BoundedVec = diff --git a/pallets/roles/src/profile.rs b/pallets/roles/src/profile.rs index e5c5418be..f5797e34c 100644 --- a/pallets/roles/src/profile.rs +++ b/pallets/roles/src/profile.rs @@ -18,14 +18,14 @@ use crate::{BalanceOf, Config}; use frame_support::pallet_prelude::*; use sp_runtime::traits::Zero; use sp_std::vec::Vec; -use tangle_primitives::roles::{RoleType, RoleTypeMetadata}; +use tangle_primitives::roles::RoleType; #[derive( PartialEqNoBound, EqNoBound, CloneNoBound, Encode, Decode, RuntimeDebugNoBound, TypeInfo, )] #[scale_info(skip_type_params(T))] pub struct Record { - pub metadata: RoleTypeMetadata, + pub role: RoleType, pub amount: Option>, } @@ -89,23 +89,18 @@ impl Profile { pub fn get_roles(&self) -> Vec { match self { Profile::Independent(profile) => - profile.records.iter().map(|record| record.metadata.get_role_type()).collect(), - Profile::Shared(profile) => - profile.records.iter().map(|record| record.metadata.get_role_type()).collect(), + profile.records.iter().map(|record| record.role).collect(), + Profile::Shared(profile) => profile.records.iter().map(|record| record.role).collect(), } } /// Checks if the profile contains given role. pub fn has_role(&self, role_type: RoleType) -> bool { match self { - Profile::Independent(profile) => profile - .records - .iter() - .any(|record| record.metadata.get_role_type() == role_type), - Profile::Shared(profile) => profile - .records - .iter() - .any(|record| record.metadata.get_role_type() == role_type), + Profile::Independent(profile) => + profile.records.iter().any(|record| record.role == role_type), + Profile::Shared(profile) => + profile.records.iter().any(|record| record.role == role_type), } } @@ -113,10 +108,10 @@ impl Profile { pub fn remove_role_from_profile(&mut self, role_type: RoleType) { match self { Profile::Independent(profile) => { - profile.records.retain(|record| record.metadata.get_role_type() != role_type); + profile.records.retain(|record| record.role != role_type); }, Profile::Shared(profile) => { - profile.records.retain(|record| record.metadata.get_role_type() != role_type); + profile.records.retain(|record| record.role != role_type); }, } } diff --git a/pallets/roles/src/tests.rs b/pallets/roles/src/tests.rs index 77f1675dc..27138d960 100644 --- a/pallets/roles/src/tests.rs +++ b/pallets/roles/src/tests.rs @@ -20,13 +20,19 @@ use frame_support::{assert_err, assert_ok, BoundedVec}; use mock::*; use profile::{IndependentRestakeProfile, Record, SharedRestakeProfile}; use sp_std::{default::Default, vec}; -use tangle_primitives::jobs::ReportValidatorOffence; +use tangle_primitives::{ + jobs::ReportValidatorOffence, + roles::{ThresholdSignatureRoleType, ZeroKnowledgeRoleType}, +}; pub fn independent_profile() -> Profile { let profile = IndependentRestakeProfile { records: BoundedVec::try_from(vec![ - Record { metadata: RoleTypeMetadata::Tss(Default::default()), amount: Some(2500) }, - Record { metadata: RoleTypeMetadata::ZkSaas(Default::default()), amount: Some(2500) }, + Record { role: RoleType::Tss(ThresholdSignatureRoleType::TssGG20), amount: Some(2500) }, + Record { + role: RoleType::ZkSaaS(ZeroKnowledgeRoleType::ZkSaaSGroth16), + amount: Some(2500), + }, ]) .unwrap(), }; @@ -36,8 +42,8 @@ pub fn independent_profile() -> Profile { pub fn shared_profile() -> Profile { let profile = SharedRestakeProfile { records: BoundedVec::try_from(vec![ - Record { metadata: RoleTypeMetadata::Tss(Default::default()), amount: None }, - Record { metadata: RoleTypeMetadata::ZkSaas(Default::default()), amount: None }, + Record { role: RoleType::Tss(ThresholdSignatureRoleType::TssGG20), amount: None }, + Record { role: RoleType::ZkSaaS(ZeroKnowledgeRoleType::ZkSaaSGroth16), amount: None }, ]) .unwrap(), amount: 5000, @@ -118,8 +124,11 @@ fn test_create_profile_should_fail_if_min_required_restake_condition_is_not_met( let profile = Profile::Shared(SharedRestakeProfile { records: BoundedVec::try_from(vec![ - Record { metadata: RoleTypeMetadata::Tss(Default::default()), amount: None }, - Record { metadata: RoleTypeMetadata::ZkSaas(Default::default()), amount: None }, + Record { role: RoleType::Tss(ThresholdSignatureRoleType::TssGG20), amount: None }, + Record { + role: RoleType::ZkSaaS(ZeroKnowledgeRoleType::ZkSaaSGroth16), + amount: None, + }, ]) .unwrap(), amount: 1000, @@ -143,9 +152,12 @@ fn test_create_profile_should_fail_if_min_required_restake_condition_is_not_met_ let profile = Profile::Independent(IndependentRestakeProfile { records: BoundedVec::try_from(vec![ - Record { metadata: RoleTypeMetadata::Tss(Default::default()), amount: Some(1000) }, Record { - metadata: RoleTypeMetadata::ZkSaas(Default::default()), + role: RoleType::Tss(ThresholdSignatureRoleType::TssGG20), + amount: Some(1000), + }, + Record { + role: RoleType::ZkSaaS(ZeroKnowledgeRoleType::ZkSaaSGroth16), amount: Some(1000), }, ]) diff --git a/precompiles/jobs/src/mock.rs b/precompiles/jobs/src/mock.rs index 4f3dee4e9..b1be8a760 100644 --- a/precompiles/jobs/src/mock.rs +++ b/precompiles/jobs/src/mock.rs @@ -30,7 +30,7 @@ use tangle_primitives::{ traits::{JobToFee, MPCHandler}, *, }, - roles::{traits::RolesHandler, RoleTypeMetadata}, + roles::traits::RolesHandler, }; pub type AccountId = MockAccount; @@ -203,10 +203,7 @@ impl RolesHandler for MockRolesHandler { validators.contains(&address) } - fn get_validator_metadata( - _address: AccountId, - _role_type: RoleType, - ) -> Option { + fn get_validator_role_key(_address: AccountId) -> Option> { None } diff --git a/primitives/src/roles/traits.rs b/primitives/src/roles/traits.rs index a2aec4db8..7732837c3 100644 --- a/primitives/src/roles/traits.rs +++ b/primitives/src/roles/traits.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Tangle. If not, see . -use crate::{jobs::ReportValidatorOffence, roles::RoleTypeMetadata}; +use crate::jobs::ReportValidatorOffence; use sp_runtime::DispatchResult; +use sp_std::vec::Vec; use super::RoleType; @@ -44,16 +45,15 @@ pub trait RolesHandler { /// Returns Ok() if validator offence report is submitted successfully. fn report_offence(offence_report: ReportValidatorOffence) -> DispatchResult; - /// Retrieves metadata information for a validator associated with a specific job key. + /// Retrieves role key associated with given validator /// /// # Arguments /// - /// * `address` - The account ID of the validator for which metadata is to be retrieved. - /// * `role_type` - The role data associated with the validator. + /// * `address` - The account ID of the validator for which role key is to be retrieved. /// /// # Returns /// - /// Returns an `Option` containing metadata information for the specified - /// validator, or `None` if no metadata is found. - fn get_validator_metadata(address: AccountId, role_type: RoleType) -> Option; + /// Returns an `Option>` containing role key information for the specified + /// validator, or `None` if no role key is found. + fn get_validator_role_key(address: AccountId) -> Option>; }