Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store Role key while creating profile #401

Merged
merged 9 commits into from
Jan 8, 2024
26 changes: 11 additions & 15 deletions pallets/jobs/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ impl<T: Config> Pallet<T> {
let mut participant_keys: Vec<Vec<u8>> = Default::default();

for participant in participants.clone() {
let key = T::RolesHandler::get_validator_metadata(participant, role_type);
ensure!(key.is_some(), Error::<T>::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::<T>::ValidatorRoleKeyNotFound);
participant_keys.push(key.expect("checked above"));
}

let job_result = JobResult::DKGPhaseOne(DKGTSSKeySubmissionResult {
Expand Down Expand Up @@ -341,12 +341,10 @@ impl<T: Config> Pallet<T> {

let participants = phase_one_result.participants().ok_or(Error::<T>::InvalidJobPhase)?;
for participant in participants {
let key = T::RolesHandler::get_validator_metadata(participant, role_type);
ensure!(key.is_some(), Error::<T>::ValidatorMetadataNotFound);
let pub_key = sp_core::ecdsa::Public::from_slice(
&key.expect("checked above").get_authority_key()[0..33],
)
.map_err(|_| Error::<T>::InvalidValidator)?;
let key = T::RolesHandler::get_validator_role_key(participant);
ensure!(key.is_some(), Error::<T>::ValidatorRoleKeyNotFound);
let pub_key = sp_core::ecdsa::Public::from_slice(&key.expect("checked above")[0..33])
.map_err(|_| Error::<T>::InvalidValidator)?;
participant_keys.push(pub_key);
}
let signing_key = match phase_one_result.result {
Expand Down Expand Up @@ -399,12 +397,10 @@ impl<T: Config> Pallet<T> {
let mut participant_keys: Vec<sp_core::ecdsa::Public> = Default::default();

for participant in participants.clone() {
let key = T::RolesHandler::get_validator_metadata(participant, role_type);
ensure!(key.is_some(), Error::<T>::ValidatorMetadataNotFound);
let pub_key = sp_core::ecdsa::Public::from_slice(
&key.expect("checked above").get_authority_key()[0..33],
)
.map_err(|_| Error::<T>::InvalidValidator)?;
let key = T::RolesHandler::get_validator_role_key(participant);
ensure!(key.is_some(), Error::<T>::ValidatorRoleKeyNotFound);
let pub_key = sp_core::ecdsa::Public::from_slice(&key.expect("checked above")[0..33])
.map_err(|_| Error::<T>::InvalidValidator)?;
participant_keys.push(pub_key);
}

Expand Down
4 changes: 2 additions & 2 deletions pallets/jobs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 3 additions & 17 deletions pallets/jobs/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -133,22 +129,12 @@ impl RolesHandler<AccountId32> for MockRolesHandler {
Ok(())
}

fn get_validator_metadata(
address: AccountId32,
role_type: RoleType,
) -> Option<RoleTypeMetadata> {
fn get_validator_role_key(address: AccountId32) -> Option<Vec<u8>> {
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())
}
}
}
Expand Down
28 changes: 5 additions & 23 deletions pallets/roles/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -65,20 +62,10 @@ impl<T: Config> RolesHandler<T::AccountId> for Pallet<T> {
Self::report_offence(offence_report)
}

fn get_validator_metadata(
address: T::AccountId,
role_type: RoleType,
) -> Option<RoleTypeMetadata> {
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<Vec<u8>> {
let maybe_ledger = Self::ledger(&address);
if let Some(ledger) = maybe_ledger {
Some(ledger.role_key)
} else {
return None
}
Expand Down Expand Up @@ -126,11 +113,6 @@ impl<T: Config> Pallet<T> {
Error::<T>::InsufficientRestakingBond
);
}
// validate the metadata
T::MPCHandler::validate_authority_key(
account.clone(),
record.metadata.get_authority_key(),
)?;
}
Ok(())
}
Expand Down
45 changes: 33 additions & 12 deletions pallets/roles/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -68,18 +72,20 @@ pub struct RoleStakingLedger<T: Config> {
pub profile: Profile<T>,
/// Roles map with their respective records.
pub roles: BTreeMap<RoleType, Record<T>>,
/// Role key
pub role_key: Vec<u8>,
}

impl<T: Config> RoleStakingLedger<T> {
/// New staking ledger for a stash account.
pub fn new(stash: T::AccountId, profile: Profile<T>) -> Self {
pub fn new(stash: T::AccountId, profile: Profile<T>, role_key: Vec<u8>) -> 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::<BTreeMap<_, _>>();
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.
Expand Down Expand Up @@ -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<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -272,9 +282,25 @@ pub mod pallet {
Error::<T>::NotValidator
);

// Get Role key of validator.
let validator_id =
<T as pallet_session::Config>::ValidatorIdOf::convert(stash_account.clone())
.ok_or(Error::<T>::NotValidator)?;

let session_keys = pallet_session::NextKeys::<T>::get(validator_id)
.ok_or(Error::<T>::SessionKeysNotProvided)?;
let role_key = OpaqueKeys::get_raw(&session_keys, ROLE_KEY_TYPE);

salman01zp marked this conversation as resolved.
Show resolved Hide resolved
// 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::<T>::contains_key(&stash_account), Error::<T>::ProfileAlreadyExists);
let ledger = RoleStakingLedger::<T>::new(stash_account.clone(), profile.clone());
let ledger = RoleStakingLedger::<T>::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.
Expand Down Expand Up @@ -304,11 +330,6 @@ pub mod pallet {
Error::<T>::InsufficientRestakingBond
);
}
// validate the metadata
T::MPCHandler::validate_authority_key(
stash_account.clone(),
record.metadata.get_authority_key(),
)?;
}

let profile_roles: BoundedVec<RoleType, T::MaxRolesPerAccount> =
Expand Down
25 changes: 10 additions & 15 deletions pallets/roles/src/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Config> {
pub metadata: RoleTypeMetadata,
pub role: RoleType,
pub amount: Option<BalanceOf<T>>,
}

Expand Down Expand Up @@ -89,34 +89,29 @@ impl<T: Config> Profile<T> {
pub fn get_roles(&self) -> Vec<RoleType> {
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),
}
}

/// Removes given role from the 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);
},
}
}
Expand Down
30 changes: 21 additions & 9 deletions pallets/roles/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Runtime> {
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(),
};
Expand All @@ -36,8 +42,8 @@ pub fn independent_profile() -> Profile<Runtime> {
pub fn shared_profile() -> Profile<Runtime> {
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,
Expand Down Expand Up @@ -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,
Expand All @@ -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),
},
])
Expand Down
7 changes: 2 additions & 5 deletions precompiles/jobs/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use tangle_primitives::{
traits::{JobToFee, MPCHandler},
*,
},
roles::{traits::RolesHandler, RoleTypeMetadata},
roles::traits::RolesHandler,
};

pub type AccountId = MockAccount;
Expand Down Expand Up @@ -203,10 +203,7 @@ impl RolesHandler<AccountId> for MockRolesHandler {
validators.contains(&address)
}

fn get_validator_metadata(
_address: AccountId,
_role_type: RoleType,
) -> Option<RoleTypeMetadata> {
fn get_validator_role_key(_address: AccountId) -> Option<Vec<u8>> {
None
}

Expand Down
Loading
Loading