diff --git a/end2end-tests/tests/common/cert.rs b/end2end-tests/tests/common/cert.rs index 021dfa2ea970f5b75bd89d618739255631be74f6..6e1a363be9c512faabc9ab4efe6e09cb1b9ff45a 100644 --- a/end2end-tests/tests/common/cert.rs +++ b/end2end-tests/tests/common/cert.rs @@ -18,7 +18,7 @@ use super::node_runtime::runtime_types::gdev_runtime; use super::node_runtime::runtime_types::pallet_certification; use super::*; use sp_keyring::AccountKeyring; -use subxt::{sp_runtime::MultiAddress, PairSigner}; +use subxt::{sp_runtime::MultiAddress, PairSigner, Signer}; pub async fn certify( api: &Api, @@ -26,15 +26,29 @@ pub async fn certify( from: AccountKeyring, to: AccountKeyring, ) -> Result<()> { - let from = PairSigner::new(from.pair()); + let signer = PairSigner::new(from.pair()); + let from = from.to_account_id(); let to = to.to_account_id(); + let issuer_index = api + .storage() + .identity() + .identity_index_of(from, None) + .await? + .unwrap(); + let receiver_index = api + .storage() + .identity() + .identity_index_of(to, None) + .await? + .unwrap(); + let _events = create_block_with_extrinsic( client, api.tx() .cert() - .add_cert(to) - .create_signed(&from, ()) + .add_cert(issuer_index, receiver_index) + .create_signed(&signer, ()) .await?, ) .await?; diff --git a/pallets/certification/src/lib.rs b/pallets/certification/src/lib.rs index 1c3e5936d0884f406f787b28dc4ffa3dcac896fc..a7e20c39d5103daa613252e3edd5b630c5162e6a 100644 --- a/pallets/certification/src/lib.rs +++ b/pallets/certification/src/lib.rs @@ -68,8 +68,8 @@ pub mod pallet { + MaybeSerializeDeserialize + Debug + MaxEncodedLen; - /// Something that give the IdtyIndex on an account id - type IdtyIndexOf: Convert<Self::AccountId, Option<Self::IdtyIndex>>; + /// Something that give the owner key of an identity + type OwnerKeyOf: Convert<Self::IdtyIndex, Option<Self::AccountId>>; /// type IsCertAllowed: IsCertAllowed<Self::IdtyIndex>; #[pallet::constant] @@ -238,8 +238,6 @@ pub mod pallet { CannotCertifySelf, /// Certification non autorisée CertNotAllowed, - /// An identity must receive certifications before it can issue them. - IdtyMustReceiveCertsBeforeCanIssue, /// This identity has already issued the maximum number of certifications IssuedTooManyCert, /// Issuer not found @@ -248,8 +246,6 @@ pub mod pallet { NotEnoughCertReceived, /// This identity has already issued a certification too recently NotRespectCertPeriod, - /// Receiver not found - ReceiverNotFound, } #[pallet::hooks] @@ -272,23 +268,31 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { ensure_root(origin)?; + // Forbid self cert + ensure!(issuer != receiver, Error::<T, I>::CannotCertifySelf); + let block_number = frame_system::pallet::Pallet::<T>::block_number(); if verify_rules { - let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer); - if issuer_idty_cert_meta.received_count == 0 { - return Err(Error::<T, I>::IdtyMustReceiveCertsBeforeCanIssue.into()); - } - // Verify rules CertPeriod and MaxByIssuer - if issuer_idty_cert_meta.received_count - < T::MinReceivedCertToBeAbleToIssueCert::get() - { - return Err(Error::<T, I>::NotEnoughCertReceived.into()); - } else if issuer_idty_cert_meta.next_issuable_on > block_number { - return Err(Error::<T, I>::NotRespectCertPeriod.into()); - } else if issuer_idty_cert_meta.issued_count >= T::MaxByIssuer::get() { - return Err(Error::<T, I>::IssuedTooManyCert.into()); - } + // Verify rule MinReceivedCertToBeAbleToIssueCert + let issuer_idty_cert_meta = StorageIdtyCertMeta::<T, I>::get(issuer); + ensure!( + issuer_idty_cert_meta.received_count + >= T::MinReceivedCertToBeAbleToIssueCert::get(), + Error::<T, I>::NotEnoughCertReceived + ); + + // Verify rule MaxByIssuer + ensure!( + issuer_idty_cert_meta.issued_count < T::MaxByIssuer::get(), + Error::<T, I>::IssuedTooManyCert + ); + + // Verify rule CertPeriod + ensure!( + block_number >= issuer_idty_cert_meta.next_issuable_on, + Error::<T, I>::NotRespectCertPeriod + ); }; Self::do_add_cert(block_number, issuer, receiver) @@ -301,32 +305,45 @@ pub mod pallet { #[pallet::weight(1_000_000_000)] pub fn add_cert( origin: OriginFor<T>, - receiver: T::AccountId, + issuer: T::IdtyIndex, + receiver: T::IdtyIndex, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(who != receiver, Error::<T, I>::CannotCertifySelf); - let issuer = T::IdtyIndexOf::convert(who).ok_or(Error::<T, I>::IssuerNotFound)?; - let receiver = - T::IdtyIndexOf::convert(receiver).ok_or(Error::<T, I>::ReceiverNotFound)?; - if !T::IsCertAllowed::is_cert_allowed(issuer, receiver) { - return Err(Error::<T, I>::CertNotAllowed.into()); - } - let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer); - if issuer_idty_cert_meta.received_count == 0 { - return Err(Error::<T, I>::IdtyMustReceiveCertsBeforeCanIssue.into()); - } + // Forbid self cert + ensure!(issuer != receiver, Error::<T, I>::CannotCertifySelf); - let block_number = frame_system::pallet::Pallet::<T>::block_number(); + // Verify caller ownership + let issuer_owner_key = + T::OwnerKeyOf::convert(issuer).ok_or(Error::<T, I>::IssuerNotFound)?; + ensure!(issuer_owner_key == who, DispatchError::BadOrigin); - // Verify rules CertPeriod and MaxByIssuer - if issuer_idty_cert_meta.received_count < T::MinReceivedCertToBeAbleToIssueCert::get() { - return Err(Error::<T, I>::NotEnoughCertReceived.into()); - } else if issuer_idty_cert_meta.next_issuable_on > block_number { - return Err(Error::<T, I>::NotRespectCertPeriod.into()); - } else if issuer_idty_cert_meta.issued_count >= T::MaxByIssuer::get() { - return Err(Error::<T, I>::IssuedTooManyCert.into()); - } + // Verify compatibility with other pallets state + ensure!( + T::IsCertAllowed::is_cert_allowed(issuer, receiver), + Error::<T, I>::CertNotAllowed + ); + + // Verify rule MinReceivedCertToBeAbleToIssueCert + let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer); + ensure!( + issuer_idty_cert_meta.received_count + >= T::MinReceivedCertToBeAbleToIssueCert::get(), + Error::<T, I>::NotEnoughCertReceived + ); + + // Verify rule MaxByIssuer + ensure!( + issuer_idty_cert_meta.issued_count < T::MaxByIssuer::get(), + Error::<T, I>::IssuedTooManyCert + ); + + // Verify rule CertPeriod + let block_number = frame_system::pallet::Pallet::<T>::block_number(); + ensure!( + block_number >= issuer_idty_cert_meta.next_issuable_on, + Error::<T, I>::NotRespectCertPeriod + ); Self::do_add_cert(block_number, issuer, receiver) } diff --git a/pallets/certification/src/mock.rs b/pallets/certification/src/mock.rs index 3bbbe3c22ace119776d449683ffb3d0ae2f7939a..96e919f7ce2c6cbe6f739468d19bdfb2bc9fb88f 100644 --- a/pallets/certification/src/mock.rs +++ b/pallets/certification/src/mock.rs @@ -102,7 +102,7 @@ impl pallet_certification::Config for Test { type CertPeriod = CertPeriod; type Event = Event; type IdtyIndex = IdtyIndex; - type IdtyIndexOf = sp_runtime::traits::ConvertInto; + type OwnerKeyOf = sp_runtime::traits::ConvertInto; type IsCertAllowed = (); type MaxByIssuer = MaxByIssuer; type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert; diff --git a/pallets/certification/src/tests.rs b/pallets/certification/src/tests.rs index 37c56ad3b9089e5687939e567506e099bf92c922..2667ecce5b552287cb3898b6ed5d0c75d87def9f 100644 --- a/pallets/certification/src/tests.rs +++ b/pallets/certification/src/tests.rs @@ -30,8 +30,8 @@ fn test_must_receive_cert_before_can_issue() { }) .execute_with(|| { assert_eq!( - DefaultCertification::add_cert(Origin::signed(0), 1), - Err(Error::<Test, _>::IdtyMustReceiveCertsBeforeCanIssue.into()) + DefaultCertification::add_cert(Origin::signed(0), 0, 1), + Err(Error::<Test, _>::NotEnoughCertReceived.into()) ); }); } @@ -51,7 +51,7 @@ fn test_cannot_certify_self() { run_to_block(2); assert_eq!( - DefaultCertification::add_cert(Origin::signed(0), 0), + DefaultCertification::add_cert(Origin::signed(0), 0, 0), Err(Error::<Test, _>::CannotCertifySelf.into()) ); }); @@ -155,17 +155,17 @@ fn test_cert_period() { } ); assert_eq!( - DefaultCertification::add_cert(Origin::signed(0), 3), + DefaultCertification::add_cert(Origin::signed(0), 0, 3), Err(Error::<Test, _>::NotRespectCertPeriod.into()) ); run_to_block(CertPeriod::get()); - assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 3)); + assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 0, 3)); run_to_block(CertPeriod::get() + 1); assert_eq!( - DefaultCertification::add_cert(Origin::signed(0), 4), + DefaultCertification::add_cert(Origin::signed(0), 0, 4), Err(Error::<Test, _>::NotRespectCertPeriod.into()) ); run_to_block((2 * CertPeriod::get()) + 1); - assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 4)); + assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 0, 4)); }); } diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs index 2b457332402349f07e6213ace646bcc5c2e7ea1b..919cc9393cfdb72820bda28ad332a66b6c5aee10 100644 --- a/pallets/duniter-wot/src/lib.rs +++ b/pallets/duniter-wot/src/lib.rs @@ -116,6 +116,9 @@ where .is_ok() } fn can_validate_identity(idty_index: IdtyIndex) -> bool { + // TODO replace this code by te commented one for distance feature + /*let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index); + idty_cert_meta.received_count >= T::MinCertForMembership::get() as u32*/ pallet_membership::Pallet::<T, I>::claim_membership( RawOrigin::Root.into(), Some(idty_index), @@ -154,6 +157,15 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::IsCertAllowed<IdtyI } } +impl<T: Config<I>, I: 'static> sp_membership::traits::IsIdtyAllowedToClaimMembership<IdtyIndex> + for Pallet<T, I> +{ + fn is_idty_allowed_to_claim_membership(idty_index: &IdtyIndex) -> bool { + let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index); + idty_cert_meta.received_count >= T::MinCertForMembership::get() as u32 + } +} + impl<T: Config<I>, I: 'static> sp_membership::traits::IsIdtyAllowedToRenewMembership<IdtyIndex> for Pallet<T, I> { @@ -205,22 +217,7 @@ where // So, in any case, we must do nothing sp_membership::Event::<IdtyIndex, MetaData>::MembershipRevoked(_) => {} sp_membership::Event::<IdtyIndex, MetaData>::MembershipRenewed(_) => {} - sp_membership::Event::<IdtyIndex, MetaData>::MembershipRequested(idty_index) => { - let idty_cert_meta = - pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index); - let received_count = idty_cert_meta.received_count; - - // TODO insert `receiver` in distance queue if received_count >= MinCertForMembership - if received_count >= T::MinCertForMembership::get() as u32 { - // TODO insert `receiver` in distance queue - if Self::dispath_idty_call(pallet_identity::Call::validate_identity { - idty_index: *idty_index, - }) && received_count == T::MinReceivedCertToBeAbleToIssueCert::get() - { - Self::do_apply_first_issuable_on(*idty_index); - } - } - } + sp_membership::Event::<IdtyIndex, MetaData>::MembershipRequested(_) => {} sp_membership::Event::<IdtyIndex, MetaData>::PendingMembershipExpired(idty_index) => { Self::dispath_idty_call(pallet_identity::Call::remove_identity { idty_index: *idty_index, @@ -243,7 +240,7 @@ impl<T: Config<I>, I: 'static> pallet_identity::traits::OnIdtyChange<T> for Pall true, ) { sp_std::if_std! { - println!("fail to force add cert: {:?}", e) + println!("fail to force add cert: {:?}", e) } } } @@ -274,32 +271,8 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::OnNewcert<IdtyIndex receiver: IdtyIndex, receiver_received_count: u32, ) -> Weight { - if pallet_membership::Pallet::<T, I>::is_member(&receiver) { - if receiver_received_count == T::MinReceivedCertToBeAbleToIssueCert::get() { - Self::do_apply_first_issuable_on(receiver); - } - } else if pallet_membership::Pallet::<T, I>::is_in_pending_memberships(receiver) - && receiver_received_count >= T::MinCertForMembership::get() - { - if T::IsSubWot::get() { - if let Err(e) = pallet_membership::Pallet::<T, I>::claim_membership( - RawOrigin::Root.into(), - Some(receiver), - ) { - sp_std::if_std! { - println!("fail to claim membership: {:?}", e) - } - } - } else { - // TODO insert `receiver` in distance queue - Self::dispath_idty_call(pallet_identity::Call::validate_identity { - idty_index: receiver, - }); - } - - if receiver_received_count == T::MinReceivedCertToBeAbleToIssueCert::get() { - Self::do_apply_first_issuable_on(receiver); - } + if receiver_received_count == T::MinReceivedCertToBeAbleToIssueCert::get() { + Self::do_apply_first_issuable_on(receiver); } 0 } diff --git a/pallets/duniter-wot/src/mock.rs b/pallets/duniter-wot/src/mock.rs index 7c1490b3832e86baf553667202748277f6e24f7d..b94c67dd58bfc9acb6831623d0102177194ac8a8 100644 --- a/pallets/duniter-wot/src/mock.rs +++ b/pallets/duniter-wot/src/mock.rs @@ -29,6 +29,15 @@ type AccountId = u64; type Block = frame_system::mocking::MockBlock<Test>; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>; +pub struct IdentityIndexOf<T: pallet_identity::Config>(PhantomData<T>); +impl<T: pallet_identity::Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>> + for IdentityIndexOf<T> +{ + fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> { + pallet_identity::Pallet::<T>::identity_index_of(account_id) + } +} + // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( pub enum Test where @@ -118,8 +127,6 @@ impl pallet_identity::Config for Test { type IdtyData = (); type IdtyNameValidator = IdtyNameValidatorTestImpl; type IdtyIndex = IdtyIndex; - type IdtyValidationOrigin = system::EnsureRoot<AccountId>; - type IsMember = Membership; type NewOwnerKeySigner = UintAuthorityId; type NewOwnerKeySignature = TestSignature; type OnIdtyChange = DuniterWot; @@ -136,11 +143,12 @@ parameter_types! { } impl pallet_membership::Config<Instance1> for Test { + type IsIdtyAllowedToClaimMembership = DuniterWot; type IsIdtyAllowedToRenewMembership = DuniterWot; type IsIdtyAllowedToRequestMembership = DuniterWot; type Event = Event; type IdtyId = IdtyIndex; - type IdtyIdOf = Identity; + type IdtyIdOf = IdentityIndexOf<Self>; type MembershipPeriod = MembershipPeriod; type MetaData = crate::MembershipMetaData<u64>; type OnEvent = DuniterWot; @@ -160,7 +168,7 @@ impl pallet_certification::Config<Instance1> for Test { type CertPeriod = CertPeriod; type Event = Event; type IdtyIndex = IdtyIndex; - type IdtyIndexOf = Identity; + type OwnerKeyOf = Identity; type IsCertAllowed = DuniterWot; type MaxByIssuer = MaxByIssuer; type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert; @@ -191,11 +199,12 @@ parameter_types! { } impl pallet_membership::Config<Instance2> for Test { + type IsIdtyAllowedToClaimMembership = SmithsSubWot; type IsIdtyAllowedToRenewMembership = SmithsSubWot; type IsIdtyAllowedToRequestMembership = SmithsSubWot; type Event = Event; type IdtyId = IdtyIndex; - type IdtyIdOf = Identity; + type IdtyIdOf = IdentityIndexOf<Self>; type MembershipPeriod = SmithsMembershipPeriod; type MetaData = crate::MembershipMetaData<u64>; type OnEvent = SmithsSubWot; @@ -215,7 +224,7 @@ impl pallet_certification::Config<Instance2> for Test { type CertPeriod = SmithsCertPeriod; type Event = Event; type IdtyIndex = IdtyIndex; - type IdtyIndexOf = Identity; + type OwnerKeyOf = Identity; type IsCertAllowed = SmithsSubWot; type MaxByIssuer = SmithsMaxByIssuer; type MinReceivedCertToBeAbleToIssueCert = SmithsMinReceivedCertToBeAbleToIssueCert; diff --git a/pallets/duniter-wot/src/tests.rs b/pallets/duniter-wot/src/tests.rs index 4a712578504a246ed12fe0a41f20d1e969d1f9b9..bd3fb937c79637ed3d2d32f7a61d27cd78b14911 100644 --- a/pallets/duniter-wot/src/tests.rs +++ b/pallets/duniter-wot/src/tests.rs @@ -66,11 +66,18 @@ fn test_join_smiths() { // Then, Alice should be able to send a smith cert to Dave run_to_block(3); - assert_ok!(SmithsCert::add_cert(Origin::signed(1), 4)); + assert_ok!(SmithsCert::add_cert(Origin::signed(1), 1, 4)); - // Then, if Bob certify Dave, he should become member + // Then, Bob should be able to send a smith cert to Dave run_to_block(4); - assert_ok!(SmithsCert::add_cert(Origin::signed(2), 4)); + assert_ok!(SmithsCert::add_cert(Origin::signed(2), 2, 4)); + + // Then, Dave should be able to claim his membership + run_to_block(4); + assert_ok!(SmithsMembership::claim_membership( + Origin::signed(4), + Some(4) + )); System::assert_has_event(Event::SmithsMembership( pallet_membership::Event::MembershipAcquired(4), )); @@ -114,7 +121,7 @@ fn test_revoke_smiths_them_rejoin() { )); // Then, Alice should be able to send a smith cert to Dave - assert_ok!(SmithsCert::add_cert(Origin::signed(1), 4)); + assert_ok!(SmithsCert::add_cert(Origin::signed(1), 1, 4)); }); } @@ -173,40 +180,23 @@ fn test_new_idty_validation() { // Bob should be able to certify Ferdie run_to_block(4); - assert_ok!(Cert::add_cert(Origin::signed(2), 6)); - - let events = System::events(); - // 3 events should have occurred: NewCert, MembershipAcquired and IdtyValidated - assert_eq!(events.len(), 3); - assert_eq!( - events[0], - EventRecord { - phase: Phase::Initialization, - event: Event::Cert(pallet_certification::Event::NewCert { - issuer: 2, - issuer_issued_count: 5, - receiver: 6, - receiver_received_count: 2 - }), - topics: vec![], - } - ); - assert_eq!( - events[1], - EventRecord { - phase: Phase::Initialization, - event: Event::Membership(pallet_membership::Event::MembershipAcquired(6)), - topics: vec![], - } - ); - assert_eq!( - events[2], - EventRecord { - phase: Phase::Initialization, - event: Event::Identity(pallet_identity::Event::IdtyValidated { idty_index: 6 }), - topics: vec![], - } - ); + assert_ok!(Cert::add_cert(Origin::signed(2), 2, 6)); + System::assert_has_event(Event::Cert(pallet_certification::Event::NewCert { + issuer: 2, + issuer_issued_count: 5, + receiver: 6, + receiver_received_count: 2, + })); + + // Anyone should be able to validate Ferdie identity + run_to_block(5); + assert_ok!(Identity::validate_identity(Origin::signed(42), 6)); + System::assert_has_event(Event::Membership( + pallet_membership::Event::MembershipAcquired(6), + )); + System::assert_has_event(Event::Identity(pallet_identity::Event::IdtyValidated { + idty_index: 6, + })); // After PendingMembershipPeriod, Ferdie identity should not expire run_to_block(6); @@ -304,8 +294,8 @@ fn test_idty_membership_expire_them_requested() { // Alice can't renew her cert to Charlie assert_noop!( - Cert::add_cert(Origin::signed(1), 3), - pallet_certification::Error::<Test, Instance1>::ReceiverNotFound + Cert::add_cert(Origin::signed(1), 1, 3), + pallet_certification::Error::<Test, Instance1>::CertNotAllowed ); }); } diff --git a/pallets/identity/src/lib.rs b/pallets/identity/src/lib.rs index 5c54f9495cc3956a35e6b363158b0eade2051ab2..d3d36af60d540b796342ca43c4047e59ca13c461 100644 --- a/pallets/identity/src/lib.rs +++ b/pallets/identity/src/lib.rs @@ -94,10 +94,6 @@ pub mod pallet { + MaxEncodedLen; /// Handle logic to validate an identity name type IdtyNameValidator: IdtyNameValidator; - /// Origin allowed to validate identity - type IdtyValidationOrigin: EnsureOrigin<Self::Origin>; - /// - type IsMember: sp_runtime::traits::IsMember<Self::IdtyIndex>; /// On identity confirmed by its owner type OnIdtyChange: OnIdtyChange<Self>; /// Signing key of new owner key payload @@ -366,7 +362,7 @@ pub mod pallet { idty_index: T::IdtyIndex, ) -> DispatchResultWithPostInfo { // Verification phase // - T::IdtyValidationOrigin::ensure_origin(origin)?; + let _ = ensure_signed(origin)?; let mut idty_value = Identities::<T>::try_get(idty_index).map_err(|_| Error::<T>::IdtyNotFound)?; @@ -639,9 +635,9 @@ pub mod pallet { } } -impl<T: Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>> for Pallet<T> { - fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> { - Self::identity_index_of(account_id) +impl<T: Config> sp_runtime::traits::Convert<T::IdtyIndex, Option<T::AccountId>> for Pallet<T> { + fn convert(idty_index: T::IdtyIndex) -> Option<T::AccountId> { + Identities::<T>::get(idty_index).map(|idty_val| idty_val.owner_key) } } diff --git a/pallets/identity/src/mock.rs b/pallets/identity/src/mock.rs index d6f973e040d38c5d3112d71b7c2e809f102f0d1c..082cb28a1daac7024c8b619b5002bd62e8b5670a 100644 --- a/pallets/identity/src/mock.rs +++ b/pallets/identity/src/mock.rs @@ -24,7 +24,7 @@ use frame_system as system; use sp_core::H256; use sp_runtime::{ testing::{Header, TestSignature, UintAuthorityId}, - traits::{BlakeTwo256, IdentityLookup, IsMember}, + traits::{BlakeTwo256, IdentityLookup}, }; type AccountId = u64; @@ -90,13 +90,6 @@ impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl { } } -pub struct IsMemberTestImpl; -impl IsMember<u64> for IsMemberTestImpl { - fn is_member(_: &u64) -> bool { - true - } -} - impl pallet_identity::Config for Test { type ChangeOwnerKeyPeriod = ChangeOwnerKeyPeriod; type ConfirmPeriod = ConfirmPeriod; @@ -106,8 +99,6 @@ impl pallet_identity::Config for Test { type IdtyData = (); type IdtyNameValidator = IdtyNameValidatorTestImpl; type IdtyIndex = u64; - type IdtyValidationOrigin = system::EnsureRoot<AccountId>; - type IsMember = IsMemberTestImpl; type NewOwnerKeySigner = UintAuthorityId; type NewOwnerKeySignature = TestSignature; type OnIdtyChange = (); diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs index 1232c04d9e276baf3ae70a94612901aa9740fac5..657c4f152931f7f25280536facf2d465075f6354 100644 --- a/pallets/membership/src/lib.rs +++ b/pallets/membership/src/lib.rs @@ -59,7 +59,11 @@ pub mod pallet { #[pallet::config] pub trait Config<I: 'static = ()>: frame_system::Config { + /// Ask the runtime if the identity can claim the membership + type IsIdtyAllowedToClaimMembership: IsIdtyAllowedToClaimMembership<Self::IdtyId>; + /// Ask the runtime if the identity can renew his membership type IsIdtyAllowedToRenewMembership: IsIdtyAllowedToRenewMembership<Self::IdtyId>; + /// Ask the runtime if the identity can request the membership type IsIdtyAllowedToRequestMembership: IsIdtyAllowedToRequestMembership<Self::IdtyId>; /// Because this pallet emits events, it depends on the runtime's definition of an event. type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>; @@ -169,6 +173,8 @@ pub mod pallet { #[pallet::error] pub enum Error<T, I = ()> { + /// Identity not allowed to claim membership + IdtyNotAllowedToClaimMembership, /// Identity not allowed to request membership IdtyNotAllowedToRequestMembership, /// Identity not allowed to renew membership @@ -248,9 +254,15 @@ pub mod pallet { // Verify phase let idty_id = Self::ensure_origin_and_get_idty_id(origin, maybe_idty_id)?; - if Membership::<T, I>::contains_key(&idty_id) { - return Err(Error::<T, I>::MembershipAlreadyAcquired.into()); - } + ensure!( + !Membership::<T, I>::contains_key(&idty_id), + Error::<T, I>::MembershipAlreadyAcquired + ); + + ensure!( + T::IsIdtyAllowedToClaimMembership::is_idty_allowed_to_claim_membership(&idty_id), + Error::<T, I>::IdtyNotAllowedToClaimMembership + ); let metadata = PendingMembership::<T, I>::take(&idty_id) .ok_or(Error::<T, I>::MembershipRequestNotFound)?; @@ -271,15 +283,16 @@ pub mod pallet { // Verify phase let idty_id = Self::ensure_origin_and_get_idty_id(origin, maybe_idty_id)?; - if !T::IsIdtyAllowedToRenewMembership::is_idty_allowed_to_renew_membership(&idty_id) { - return Err(Error::<T, I>::IdtyNotAllowedToRenewMembership.into()); - } - ensure!( Self::get_membership(&idty_id).is_some(), Error::<T, I>::MembershipNotFound ); + ensure!( + T::IsIdtyAllowedToRenewMembership::is_idty_allowed_to_renew_membership(&idty_id), + Error::<T, I>::IdtyNotAllowedToRenewMembership, + ); + let _ = Self::do_renew_membership(idty_id); Ok(().into()) diff --git a/pallets/membership/src/mock.rs b/pallets/membership/src/mock.rs index 4e1b49dd5772e86dfbc7455b0242229bad2b768d..e9ea07467cbde7fc38e857443f417048e26574dd 100644 --- a/pallets/membership/src/mock.rs +++ b/pallets/membership/src/mock.rs @@ -84,6 +84,7 @@ parameter_types! { } impl pallet_membership::Config for Test { + type IsIdtyAllowedToClaimMembership = (); type IsIdtyAllowedToRenewMembership = (); type IsIdtyAllowedToRequestMembership = (); type Event = Event; diff --git a/primitives/membership/src/traits.rs b/primitives/membership/src/traits.rs index 2690cb58e6b164e675f038b268329d133d34744e..a6e7d6ad6fc9f87a04a878954f5169413fe953f8 100644 --- a/primitives/membership/src/traits.rs +++ b/primitives/membership/src/traits.rs @@ -16,6 +16,16 @@ use frame_support::pallet_prelude::Weight; +pub trait IsIdtyAllowedToClaimMembership<IdtyId> { + fn is_idty_allowed_to_claim_membership(idty_id: &IdtyId) -> bool; +} + +impl<IdtyId> IsIdtyAllowedToClaimMembership<IdtyId> for () { + fn is_idty_allowed_to_claim_membership(_: &IdtyId) -> bool { + true + } +} + pub trait IsIdtyAllowedToRenewMembership<IdtyId> { fn is_idty_allowed_to_renew_membership(idty_id: &IdtyId) -> bool; } diff --git a/resources/metadata.scale b/resources/metadata.scale index 90750afa43fe6d866bf9ea3912c915d6b4a4ed08..745d186e552bbd0323d9e2e78cf80fd620892fe9 100644 Binary files a/resources/metadata.scale and b/resources/metadata.scale differ diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs index bc5e82e5a2cd58b8de55327a998033f2c325c48f..20dc90e790acc01fa39c977bd067a0eb29c71719 100644 --- a/runtime/common/src/pallets_config.rs +++ b/runtime/common/src/pallets_config.rs @@ -193,7 +193,7 @@ macro_rules! pallets_config { type OnNewSession = OnNewSessionHandler<Runtime>; type OnRemovedMember = OnRemovedAuthorityMemberHandler<Runtime>; type MemberId = IdtyIndex; - type MemberIdOf = Identity; + type MemberIdOf = common_runtime::providers::IdentityIndexOf<Self>; type MaxAuthorities = MaxAuthorities; type MaxKeysLife = frame_support::pallet_prelude::ConstU32<1_500>; type MaxOfflineSessions = frame_support::pallet_prelude::ConstU32<2_400>; @@ -427,8 +427,6 @@ macro_rules! pallets_config { type IdtyData = IdtyData; type IdtyIndex = IdtyIndex; type IdtyNameValidator = IdtyNameValidatorImpl; - type IdtyValidationOrigin = EnsureRoot<Self::AccountId>; - type IsMember = Membership; type NewOwnerKeySigner = <NewOwnerKeySignature as sp_runtime::traits::Verify>::Signer; type NewOwnerKeySignature = NewOwnerKeySignature; type OnIdtyChange = (common_runtime::handlers::OnIdtyChangeHandler<Runtime>, Wot); @@ -438,11 +436,12 @@ macro_rules! pallets_config { } impl pallet_membership::Config<frame_support::instances::Instance1> for Runtime { + type IsIdtyAllowedToClaimMembership = Wot; type IsIdtyAllowedToRenewMembership = Wot; type IsIdtyAllowedToRequestMembership = Wot; type Event = Event; type IdtyId = IdtyIndex; - type IdtyIdOf = Identity; + type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>; type MembershipPeriod = MembershipPeriod; type MetaData = pallet_duniter_wot::MembershipMetaData<AccountId>; type OnEvent = OnMembershipEventHandler<Wot, Runtime>; @@ -454,7 +453,7 @@ macro_rules! pallets_config { type CertPeriod = CertPeriod; type Event = Event; type IdtyIndex = IdtyIndex; - type IdtyIndexOf = Identity; + type OwnerKeyOf = Identity; type IsCertAllowed = Wot; type MaxByIssuer = MaxByIssuer; type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert; @@ -474,11 +473,12 @@ macro_rules! pallets_config { } impl pallet_membership::Config<Instance2> for Runtime { - type IsIdtyAllowedToRenewMembership = (); - type IsIdtyAllowedToRequestMembership = (); + type IsIdtyAllowedToClaimMembership = SmithsSubWot; + type IsIdtyAllowedToRenewMembership = SmithsSubWot; + type IsIdtyAllowedToRequestMembership = SmithsSubWot; type Event = Event; type IdtyId = IdtyIndex; - type IdtyIdOf = Identity; + type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>; type MembershipPeriod = SmithMembershipPeriod; type MetaData = SmithsMembershipMetaData<opaque::SessionKeysWrapper>; type OnEvent = OnSmithMembershipEventHandler<SmithsSubWot, Runtime>; @@ -490,7 +490,7 @@ macro_rules! pallets_config { type CertPeriod = SmithCertPeriod; type Event = Event; type IdtyIndex = IdtyIndex; - type IdtyIndexOf = Identity; + type OwnerKeyOf = Identity; type IsCertAllowed = SmithsSubWot; type MaxByIssuer = SmithMaxByIssuer; type MinReceivedCertToBeAbleToIssueCert = SmithMinReceivedCertToBeAbleToIssueCert; @@ -514,7 +514,7 @@ macro_rules! pallets_config { impl sp_runtime::traits::IsMember<AccountId> for SmithMembersStorage { fn is_member(account_id: &AccountId) -> bool { use sp_runtime::traits::Convert as _; - if let Some(idty_index) = Identity::convert(account_id.clone()) { + if let Some(idty_index) = common_runtime::providers::IdentityIndexOf::<Runtime>::convert(account_id.clone()) { pallet_membership::Pallet::<Runtime, Instance2>::is_member(&idty_index) } else { false diff --git a/runtime/common/src/providers.rs b/runtime/common/src/providers.rs index 3e32943062b3f258ff3796b490a83de9f7501edd..9a20e56a26d4b5e5ca7acb6c215d75a41ba74c11 100644 --- a/runtime/common/src/providers.rs +++ b/runtime/common/src/providers.rs @@ -33,6 +33,16 @@ impl< } } +pub struct IdentityIndexOf<T: pallet_identity::Config>(PhantomData<T>); + +impl<T: pallet_identity::Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>> + for IdentityIndexOf<T> +{ + fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> { + pallet_identity::Pallet::<T>::identity_index_of(account_id) + } +} + pub struct UdMembersStorage<T: pallet_identity::Config>(PhantomData<T>); impl<T> frame_support::traits::StoredMap<AccountId, FirstEligibleUd> for UdMembersStorage<T> diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs index 7e05a45b77e1e3b3971fdad75b231b4b790d6d4f..4255e3e6dd68e822badc905c699489d52fca8b88 100644 --- a/runtime/g1/src/lib.rs +++ b/runtime/g1/src/lib.rs @@ -137,7 +137,6 @@ impl Contains<Call> for BaseCallFilter { pallet_membership::Call::claim_membership { .. } | pallet_membership::Call::revoke_membership { .. } ) | Call::Session(_) - | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. }) ) } } diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs index 80744615582a146b6557207d353a641bc9631cca..8476ea5e79ff7c3ad7ad8a05bc8fd86e0a74f26f 100644 --- a/runtime/gdev/src/lib.rs +++ b/runtime/gdev/src/lib.rs @@ -144,7 +144,6 @@ impl Contains<Call> for BaseCallFilter { | pallet_membership::Call::claim_membership { .. } | pallet_membership::Call::revoke_membership { .. } ) | Call::Session(_) - | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. }) | Call::AuthorityMembers(pallet_authority_members::Call::go_online { .. }) ) } @@ -159,7 +158,6 @@ impl Contains<Call> for BaseCallFilter { | pallet_membership::Call::claim_membership { .. } | pallet_membership::Call::revoke_membership { .. } ) | Call::Session(_) - | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. }) ) } } diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs index 2553564fc4a5f09871b0e586f62401e4db1fb564..4baa629356fdee62ea773043f3f2d4ce0e623f96 100644 --- a/runtime/gtest/src/lib.rs +++ b/runtime/gtest/src/lib.rs @@ -138,7 +138,6 @@ impl Contains<Call> for BaseCallFilter { pallet_membership::Call::claim_membership { .. } | pallet_membership::Call::revoke_membership { .. } ) | Call::Session(_) - | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. }) ) } }