diff --git a/pallets/certification/src/lib.rs b/pallets/certification/src/lib.rs index 7287287cb3cfed3a3026d293c40999d7df82232b..ebe684a06dd0c071e3e1483584dd1ac387edf7fb 100644 --- a/pallets/certification/src/lib.rs +++ b/pallets/certification/src/lib.rs @@ -33,6 +33,10 @@ pub mod pallet { pub trait Config<I: Instance = DefaultInstance>: frame_system::Config { /// Duration after which a certification is renewable type ChainabilityPeriod: Get<Self::BlockNumber>; + /// Origin allowed to add a certification + type AddCertOrigin: EnsureOrigin<(Self::Origin, Self::IdtyIndex)>; + /// Origin allowed to delete a certification + type DelCertOrigin: EnsureOrigin<(Self::Origin, Self::IdtyIndex)>; /// The overarching event type. type Event: From<Event<Self, I>> + Into<<Self as frame_system::Config>::Event>; /// A short identity index. @@ -55,20 +59,28 @@ pub mod pallet { frame_support::decl_event! { pub enum Event<T, I=DefaultInstance> where - <T as frame_system::Config>::Hash, - <T as frame_system::Config>::AccountId, + <T as Config<I>>::IdtyIndex, { - /// A motion (given hash) has been proposed (by given account) with a threshold (given - /// `MemberCount`). - /// \[account, proposal_hash\] - Proposed(AccountId, Hash), + /// New certification + /// \[issuer, receiver\] + NewCert(IdtyIndex, IdtyIndex), + /// Removed certification + /// \[issuer, receiver, expiration\] + RemovedCert(IdtyIndex, IdtyIndex, bool), + /// Renewed certification + /// \[issuer, receiver\] + RenewedCert(IdtyIndex, IdtyIndex), } } frame_support::decl_error! { pub enum Error for Module<T: Config<I>, I: Instance> { - /// Account is not a member - NotMember, + /// This identity has already issued the maximum number of certifications + IssuedTooManyCert, + /// This certification has already been issued or renewed recently + NotRespectChainabilityPeriodPeriod, + /// This identity has already issued a certification too recently + NotRespectSignPeriod, } } @@ -166,6 +178,74 @@ pub mod pallet { fn on_initialize(n: T::BlockNumber) -> Weight { Self::prune_certifications(n) } + + #[weight = 0] + pub fn add_cert(origin, issuer: T::IdtyIndex, receiver: T::IdtyIndex) { + T::AddCertOrigin::ensure_origin((origin, issuer))?; + + let block_number = frame_system::pallet::Pallet::<T>::block_number(); + let mut create = false; + let removable_on = block_number + T::ValidityPeriod::get(); + let certs = if let Ok(CertsByIssuer { mut certs, next_issuable_on }) = <StorageCertsByIssuer<T, I>>::try_get(issuer) { + if next_issuable_on > block_number { + return Err(Error::<T, I>::NotRespectSignPeriod.into()); + } else if certs.len() >= T::MaxByIssuer::get() as usize { + return Err(Error::<T, I>::IssuedTooManyCert.into()); + } + let insert_index = match certs.binary_search_by( + |CertValue { + receiver: receiver_, + .. + }| receiver.cmp(&receiver_), + ) { + Ok(index) => { + if certs[index].chainable_on > block_number { + return Err(Error::<T, I>::NotRespectChainabilityPeriodPeriod.into()); + } + create = true; + index + }, + Err(index) => index, + }; + certs.insert(insert_index, CertValue { + receiver, + chainable_on: block_number + T::ChainabilityPeriod::get(), + removable_on, + }); + certs + } else { + vec![CertValue { + receiver, + chainable_on: block_number + T::ChainabilityPeriod::get(), + removable_on, + }] + }; + + <StorageCertsByIssuer<T, I>>::insert(issuer, CertsByIssuer { + certs, + next_issuable_on: block_number + T::SignPeriod::get() + }); + if !create { + <StorageCertsByReceiver<T, I>>::mutate_exists(receiver, |issuers_opt| { + let issuers = issuers_opt.get_or_insert(vec![]); + if let Err(index) = issuers.binary_search(&issuer) { + issuers.insert(index, issuer); + } + }); + } + <StorageCertsRemovableOn<T, I>>::append(removable_on, (issuer, receiver)); + + if create { + Self::deposit_event(RawEvent::NewCert(issuer, receiver)); + } else { + Self::deposit_event(RawEvent::RenewedCert(issuer, receiver)); + } + } + #[weight = 0] + pub fn del_cert(origin, issuer: T::IdtyIndex, receiver: T::IdtyIndex) { + T::DelCertOrigin::ensure_origin((origin, issuer))?; + Self::remove_cert_inner(issuer, receiver, None); + } } } @@ -213,6 +293,11 @@ pub mod pallet { certs_by_receiver.remove(index); } } + Self::deposit_event(RawEvent::RemovedCert( + issuer, + receiver, + block_number_opt.is_some(), + )); } } }