diff --git a/pallets/authority-members/src/lib.rs b/pallets/authority-members/src/lib.rs
index c60df43b7dde52cc9da701caf577ff90aef1403e..9284bb25c88a8d02111a972a59f910fc7ab7f14a 100644
--- a/pallets/authority-members/src/lib.rs
+++ b/pallets/authority-members/src/lib.rs
@@ -69,6 +69,8 @@ pub mod pallet {
type IsMember: IsMember<Self::MemberId>;
type OnNewSession: OnNewSession;
type OnRemovedMember: OnRemovedMember<Self::MemberId>;
+ type OnOutgoingMember: OnOutgoingMember<Self::MemberId>;
+ type OnIncomingMember: OnIncomingMember<Self::MemberId>;
/// Max number of authorities allowed
#[pallet::constant]
type MaxAuthorities: Get<u32>;
@@ -542,6 +544,13 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
});
}
+ for member_id in members_ids_to_add.iter() {
+ T::OnIncomingMember::on_incoming_member(member_id.clone());
+ }
+ for member_id in members_ids_to_del.iter() {
+ T::OnOutgoingMember::on_outgoing_member(member_id.clone());
+ }
+
// updates the list of OnlineAuthorities and returns the list of their key
Some(
OnlineAuthorities::<T>::mutate(|members_ids| {
diff --git a/pallets/authority-members/src/traits.rs b/pallets/authority-members/src/traits.rs
index eb3452b58af951f88da5ad940aaef19e5263e577..639ef95df0b0bfc94434137df489064b4dd5a7d7 100644
--- a/pallets/authority-members/src/traits.rs
+++ b/pallets/authority-members/src/traits.rs
@@ -41,6 +41,16 @@ impl<MemberId> OnBlacklistedMember<MemberId> for () {
fn on_blacklisted_member(_: MemberId) {}
}
+/// Handle the consequences of going in the authority set for other pallets.
+/// Typically, a smith won't expire as long as he is in the authority set.
+pub trait OnIncomingMember<MemberId> {
+ fn on_incoming_member(member_id: MemberId);
+}
+/// By default: no consequences
+impl<MemberId> OnIncomingMember<MemberId> for () {
+ fn on_incoming_member(_: MemberId) {}
+}
+
/// Handle the consequences of going out of authority set for other pallets.
/// Typically, the smiths are not allowed to stay offline for a too long time.
pub trait OnOutgoingMember<MemberId> {
diff --git a/pallets/smith-members/src/impls.rs b/pallets/smith-members/src/impls.rs
index d1a576043d9c2e30e1786a1576dbdf5b5aba99b4..be6180f05c9523ce5c916dc52c4dcb0bd07ebc26 100644
--- a/pallets/smith-members/src/impls.rs
+++ b/pallets/smith-members/src/impls.rs
@@ -1,4 +1,7 @@
-use crate::{Config, Pallet};
+use crate::{Config, CurrentSession, Pallet};
+use frame_support::StorageValue;
+use pallet_authority_members::SessionIndex;
+use sp_runtime::traits::Convert;
/// We want to remove a Smith when he is removed from the higher level set of "authorities".
impl<T: Config> pallet_authority_members::OnRemovedMember<T> for Pallet<T> {
@@ -19,8 +22,27 @@ impl<T: Config> pallet_authority_members::OnBlacklistedMember<T> for Pallet<T> {
}
///
-impl<T: Config> pallet_authority_members::OnOutgoingMember<T> for Pallet<T> {
- fn on_outgoing_member(member_id: T) {
- todo!("Has gone out of authority set, start offline counter")
+impl<T: Config> pallet_authority_members::OnOutgoingMember<T::MemberId> for Pallet<T> {
+ fn on_outgoing_member(member_id: T::MemberId) {
+ Pallet::<T>::smith_goes_offline(
+ T::IdtyIdOfAuthorityId::convert(member_id).expect("convertion should be ok"),
+ );
+ }
+}
+
+/// As long as a Smith is in the authority set, he will not expire.
+impl<T: Config> pallet_authority_members::OnIncomingMember<T::MemberId> for Pallet<T> {
+ fn on_incoming_member(member_id: T::MemberId) {
+ Pallet::<T>::smith_goes_online(
+ T::IdtyIdOfAuthorityId::convert(member_id).expect("convertion should be ok"),
+ );
+ }
+}
+
+///
+impl<T: Config> pallet_authority_members::OnNewSession for Pallet<T> {
+ fn on_new_session(index: SessionIndex) {
+ CurrentSession::<T>::put(index);
+ Pallet::<T>::remove_expired_smiths(index);
}
}
diff --git a/pallets/smith-members/src/lib.rs b/pallets/smith-members/src/lib.rs
index c34deaccbe6a1e77ebea21230d97407adf1f6094..040e4fb039eefa4af66fcd6790a98fa1aae69e58 100644
--- a/pallets/smith-members/src/lib.rs
+++ b/pallets/smith-members/src/lib.rs
@@ -19,9 +19,10 @@
#[cfg(test)]
mod mock;
-mod impls;
#[cfg(test)]
mod tests;
+
+mod impls;
mod traits;
mod types;
@@ -33,7 +34,9 @@ use sp_runtime::traits::AtLeast32BitUnsigned;
use sp_std::fmt::Debug;
use sp_std::prelude::*;
+use crate::traits::OnSmithDelete;
pub use pallet::*;
+use pallet_authority_members::SessionIndex;
pub use types::*;
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
@@ -43,7 +46,7 @@ pub enum SmithRemovalReason {
Blacklisted,
}
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub enum SmithStatus {
/// The identity has been invited by a smith but has not accepted yet
Invited,
@@ -63,6 +66,7 @@ pub mod pallet {
use frame_support::{pallet_prelude::*, traits::ReservableCurrency};
use frame_system::pallet_prelude::*;
use frame_system::pallet_prelude::*;
+ use pallet_authority_members::SessionIndex;
use sp_runtime::traits::{Convert, IsMember};
use std::collections::BTreeMap;
@@ -76,7 +80,10 @@ pub mod pallet {
/// The pallet's config trait.
#[pallet::config]
pub trait Config: frame_system::Config {
+ /// To only allow WoT members to be invited
type IsWoTMember: IsMember<Self::IdtyIndex>;
+ /// Notify when a smith is removed (for authority-members to react)
+ type OnSmithDelete: traits::OnSmithDelete<Self::IdtyIndex>;
/// The overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// A short identity index.
@@ -89,9 +96,10 @@ pub mod pallet {
+ MaybeSerializeDeserialize
+ Debug
+ MaxEncodedLen;
- /// Duration of validity of a certification
- type ValidityPeriod: Get<Self::BlockNumber>;
+ /// Identifier for an authority-member
+ type MemberId: Copy + Ord + MaybeSerializeDeserialize + Parameter;
/// Maximum number of active certifications by issuer
+ #[pallet::constant]
type MaxByIssuer: Get<u32>;
/// Minimum number of certifications to be able to create a smith
#[pallet::constant]
@@ -99,8 +107,13 @@ pub mod pallet {
/// Minimum number of certifications to become a Smith
#[pallet::constant]
type MinCertForMembership: Get<u32>;
+ /// Maximum duration of inactivity before a smith is removed
+ #[pallet::constant]
+ type InactivityMaxDuration: Get<u32>;
/// Something that gives the IdtyId of an AccountId
type IdtyIdOf: Convert<Self::AccountId, Option<Self::IdtyIndex>>;
+ /// Something that gives the IdtyId of an AccountId
+ type IdtyIdOfAuthorityId: Convert<Self::MemberId, Option<Self::IdtyIndex>>;
}
/// Events type.
@@ -132,6 +145,7 @@ pub mod pallet {
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
+ CurrentSession::<T>::put(0);
let mut cert_meta_by_issuer =
BTreeMap::<T::IdtyIndex, SmithCertMeta<T::BlockNumber>>::new();
for (receiver, issuers) in &self.certs_by_receiver {
@@ -165,7 +179,19 @@ pub mod pallet {
} else {
SmithStatus::Pending
};
- Smiths::<T>::insert(receiver, smith_status);
+ Smiths::<T>::insert(
+ receiver,
+ SmithMeta {
+ status: smith_status,
+ expires_on: Some(
+ CurrentSession::<T>::get() + T::InactivityMaxDuration::get(),
+ ),
+ },
+ );
+ ExpiresOn::<T>::append(
+ CurrentSession::<T>::get() + T::InactivityMaxDuration::get(),
+ receiver,
+ );
}
}
}
@@ -177,8 +203,16 @@ pub mod pallet {
/// maps identity index to smith status
#[pallet::storage]
- pub type Smiths<T: Config> =
- StorageMap<_, Twox64Concat, T::IdtyIndex, SmithStatus, OptionQuery>;
+ pub type Smiths<T: Config> = StorageMap<_, Twox64Concat, T::IdtyIndex, SmithMeta, OptionQuery>;
+
+ /// maps session index to possible smith removals
+ #[pallet::storage]
+ pub type ExpiresOn<T: Config> =
+ StorageMap<_, Twox64Concat, SessionIndex, Vec<T::IdtyIndex>, OptionQuery>;
+
+ /// maps session index to possible smith removals
+ #[pallet::storage]
+ pub type CurrentSession<T: Config> = StorageValue<_, SessionIndex, ValueQuery>;
// ERRORS //
@@ -218,8 +252,9 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin.clone())?;
let issuer = T::IdtyIdOf::convert(who.clone()).ok_or(Error::<T>::UnknownIssuer)?;
- let issuer_status =
- Smiths::<T>::get(issuer).ok_or(Error::<T>::IssuerHasNoSmithStatus)?;
+ let issuer_status = Smiths::<T>::get(issuer)
+ .ok_or(Error::<T>::IssuerHasNoSmithStatus)?
+ .status;
ensure!(
issuer_status == SmithStatus::Smith,
Error::<T>::CannotInvite
@@ -229,7 +264,15 @@ pub mod pallet {
Error::<T>::ReceveirAlreadyHasSmithStatus
);
- Smiths::<T>::insert(receiver, SmithStatus::Invited);
+ let new_expires_on = CurrentSession::<T>::get() + T::InactivityMaxDuration::get();
+ Smiths::<T>::insert(
+ receiver,
+ SmithMeta {
+ status: SmithStatus::Invited,
+ expires_on: Some(new_expires_on),
+ },
+ );
+ ExpiresOn::<T>::append(new_expires_on, receiver);
Ok(().into())
}
@@ -239,13 +282,18 @@ pub mod pallet {
pub fn accept_invitation(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin.clone())?;
let pretender = T::IdtyIdOf::convert(who.clone()).ok_or(Error::<T>::UnknownIssuer)?;
- let pretender_status = Smiths::<T>::get(pretender).ok_or(Error::<T>::NotInvited)?;
+ let pretender_status = Smiths::<T>::get(pretender)
+ .ok_or(Error::<T>::NotInvited)?
+ .status;
ensure!(
pretender_status == SmithStatus::Invited,
Error::<T>::AlreadyAcceptedInvitation
);
- Smiths::<T>::insert(pretender, SmithStatus::Pending);
+ Smiths::<T>::mutate(pretender, |maybe_smith_meta| {
+ let maybe_smith_meta = maybe_smith_meta.as_mut().expect("status checked earlier");
+ maybe_smith_meta.status = SmithStatus::Pending;
+ });
Ok(().into())
}
@@ -259,14 +307,16 @@ pub mod pallet {
let who = ensure_signed(origin)?;
let issuer = T::IdtyIdOf::convert(who.clone()).ok_or(Error::<T>::UnknownIssuer)?;
ensure!(issuer != receiver, Error::<T>::CannotCertifySelf);
- let issuer_status =
- Smiths::<T>::get(issuer).ok_or(Error::<T>::IssuerHasNoSmithStatus)?;
+ let issuer_status = Smiths::<T>::get(issuer)
+ .ok_or(Error::<T>::IssuerHasNoSmithStatus)?
+ .status;
ensure!(
issuer_status == SmithStatus::Smith,
Error::<T>::IssuerIsNotASmith
);
- let receiver_status =
- Smiths::<T>::get(receiver).ok_or(Error::<T>::ReceiverHasNotBeenInvited)?;
+ let receiver_status = Smiths::<T>::get(receiver)
+ .ok_or(Error::<T>::ReceiverHasNotBeenInvited)?
+ .status;
ensure!(
receiver_status != SmithStatus::Invited,
Error::<T>::ReceveirMustAcceptInvitation
@@ -275,23 +325,73 @@ pub mod pallet {
CertsByReceiver::<T>::mutate(receiver, |certs| {
let certs = certs.get_or_insert(vec![]);
certs.push(issuer);
- // TODO: "as u32" allowed?
- if certs.len() as u32 >= T::MinCertForMembership::get() {
- Smiths::<T>::insert(receiver, SmithStatus::Smith);
- } else {
- Smiths::<T>::insert(receiver, SmithStatus::Pending);
- }
+ Smiths::<T>::mutate(receiver, |maybe_smith_meta| {
+ let maybe_smith_meta =
+ maybe_smith_meta.as_mut().expect("status checked earlier");
+ // TODO: "as u32" allowed?
+ maybe_smith_meta.status =
+ if certs.len() as u32 >= T::MinCertForMembership::get() {
+ SmithStatus::Smith
+ } else {
+ SmithStatus::Pending
+ };
+ });
});
Ok(().into())
}
}
+}
+
+impl<T: Config> Pallet<T> {
+ // TODO: return what?
+ fn remove_expired_smiths(at: SessionIndex) {
+ if let Some(smiths_to_remove) = ExpiresOn::<T>::get(at) {
+ for smith in smiths_to_remove {
+ if let Some(smith_meta) = Smiths::<T>::get(smith) {
+ if let Some(expires_on) = smith_meta.expires_on {
+ if expires_on == at {
+ Smiths::<T>::remove(smith);
+ T::OnSmithDelete::on_smith_delete(
+ smith,
+ SmithRemovalReason::OfflineTooLong,
+ );
+ }
+ }
+ }
+ }
+ }
+ }
- // TODO: on confirm
- // ensure!(
- // T::IsWoTMember::is_member(&receiver),
- // Error::<T>::NotAMember
- // );
+ // TODO: return what?
+ fn smith_goes_online(idty_index: T::IdtyIndex) {
+ if let Some(smith_meta) = Smiths::<T>::get(idty_index) {
+ if smith_meta.expires_on.is_some() {
+ Smiths::<T>::mutate(idty_index, |maybe_smith_meta| {
+ let maybe_smith_meta = maybe_smith_meta.as_mut().expect("checked earlier");
+ // As long as the smith is online, it cannot expire
+ maybe_smith_meta.expires_on = None;
+ // FIXME: also update ExpiresOn storage
+ });
+ }
+ }
+ }
+
+ // TODO: return what?
+ fn smith_goes_offline(idty_index: T::IdtyIndex) {
+ if let Some(smith_meta) = Smiths::<T>::get(idty_index) {
+ if smith_meta.expires_on.is_none() {
+ Smiths::<T>::mutate(idty_index, |maybe_smith_meta| {
+ let maybe_smith_meta = maybe_smith_meta.as_mut().expect("checked earlier");
+ // As long as the smith is online, it cannot expire
+ let new_expires_on =
+ CurrentSession::<T>::get() + T::InactivityMaxDuration::get();
+ maybe_smith_meta.expires_on = Some(new_expires_on);
+ ExpiresOn::<T>::append(new_expires_on, idty_index);
+ });
+ }
+ }
+ }
}
impl<T: Config> Pallet<T> {
diff --git a/pallets/smith-members/src/mock.rs b/pallets/smith-members/src/mock.rs
index 36fca3cd989c0db444b88171c7a7b905e88db5b8..b32cf9b0ffc4999c9d63d9cad0eb8ff3120afc41 100644
--- a/pallets/smith-members/src/mock.rs
+++ b/pallets/smith-members/src/mock.rs
@@ -16,8 +16,9 @@
#![cfg(test)]
+use crate::traits::OnSmithDelete;
use crate::{self as pallet_smith_members};
-use frame_support::pallet_prelude::GenesisBuild;
+use frame_support::pallet_prelude::{GenesisBuild, Hooks};
use frame_support::{
parameter_types,
traits::{ConstU32, ConstU64},
@@ -92,10 +93,13 @@ impl pallet_smith_members::Config for Runtime {
type IdtyIndex = u64;
type IsWoTMember = EveryoneExceptIdZero;
type IdtyIdOf = ConvertInto;
- type ValidityPeriod = ConstU64<1>;
type MinCertForMembership = ConstU32<2>;
type MinCertForCreateIdtyRight = ConstU32<3>;
type MaxByIssuer = ConstU32<5>;
+ type InactivityMaxDuration = ConstU32<5>;
+ type OnSmithDelete = ();
+ type IdtyIdOfAuthorityId = ConvertInto;
+ type MemberId = u64;
}
pub fn new_test_ext(
diff --git a/pallets/smith-members/src/tests.rs b/pallets/smith-members/src/tests.rs
index c2868d5148edfbfb270f682c4c3ef0d7acfd1a93..a88d5e7062f3777c36a91bd47df4cb66c0bede52 100644
--- a/pallets/smith-members/src/tests.rs
+++ b/pallets/smith-members/src/tests.rs
@@ -22,9 +22,10 @@ use frame_support::{assert_err, assert_ok};
#[cfg(test)]
use maplit::btreemap;
+use pallet_authority_members::OnNewSession;
#[test]
-fn process_to_become_a_smith() {
+fn process_to_become_a_smith_and_lose_it() {
new_test_ext(GenesisConfig {
certs_by_receiver: btreemap![
1 => btreemap![
@@ -51,21 +52,41 @@ fn process_to_become_a_smith() {
)));
// State after
assert_eq!(CertsByReceiver::<Runtime>::get(5), None);
- assert_eq!(Smiths::<Runtime>::get(5).unwrap(), SmithStatus::Pending);
+ assert_eq!(
+ Smiths::<Runtime>::get(5).unwrap().status,
+ SmithStatus::Pending
+ );
// Then certification 1/2
assert_ok!(Pallet::<Runtime>::certify_smith(
RuntimeOrigin::signed(1),
5
));
assert_eq!(CertsByReceiver::<Runtime>::get(5).unwrap().len(), 1);
- assert_eq!(Smiths::<Runtime>::get(5).unwrap(), SmithStatus::Pending);
+ assert_eq!(
+ Smiths::<Runtime>::get(5).unwrap().status,
+ SmithStatus::Pending
+ );
// Then certification 2/2
assert_ok!(Pallet::<Runtime>::certify_smith(
RuntimeOrigin::signed(2),
5
));
assert_eq!(CertsByReceiver::<Runtime>::get(5).unwrap().len(), 2);
- assert_eq!(Smiths::<Runtime>::get(5).unwrap(), SmithStatus::Smith);
+ assert_eq!(
+ Smiths::<Runtime>::get(5).unwrap().status,
+ SmithStatus::Smith
+ );
+
+ // On session 4 everything if fine
+ Pallet::<Runtime>::on_new_session(4);
+ assert_eq!(Smiths::<Runtime>::get(1).is_some(), true);
+ assert_eq!(Smiths::<Runtime>::get(2).is_some(), true);
+ assert_eq!(Smiths::<Runtime>::get(5).is_some(), true);
+ // On session 5 no more smiths because of lack of activity
+ Pallet::<Runtime>::on_new_session(5);
+ assert_eq!(Smiths::<Runtime>::get(1), None);
+ assert_eq!(Smiths::<Runtime>::get(2), None);
+ assert_eq!(Smiths::<Runtime>::get(5), None);
});
}
@@ -94,10 +115,22 @@ fn should_have_checks_on_certify() {
.execute_with(|| {
// Initially
assert_eq!(CertsByReceiver::<Runtime>::iter().count(), 4);
- assert_eq!(Smiths::<Runtime>::get(1).unwrap(), SmithStatus::Smith);
- assert_eq!(Smiths::<Runtime>::get(2).unwrap(), SmithStatus::Smith);
- assert_eq!(Smiths::<Runtime>::get(3).unwrap(), SmithStatus::Pending);
- assert_eq!(Smiths::<Runtime>::get(4).unwrap(), SmithStatus::Smith);
+ assert_eq!(
+ Smiths::<Runtime>::get(1).unwrap().status,
+ SmithStatus::Smith
+ );
+ assert_eq!(
+ Smiths::<Runtime>::get(2).unwrap().status,
+ SmithStatus::Smith
+ );
+ assert_eq!(
+ Smiths::<Runtime>::get(3).unwrap().status,
+ SmithStatus::Pending
+ );
+ assert_eq!(
+ Smiths::<Runtime>::get(4).unwrap().status,
+ SmithStatus::Smith
+ );
assert_eq!(CertsByReceiver::<Runtime>::get(1).unwrap().len(), 3);
assert_eq!(CertsByReceiver::<Runtime>::get(2).unwrap().len(), 2);
assert_eq!(CertsByReceiver::<Runtime>::get(3).unwrap().len(), 1);
@@ -123,7 +156,10 @@ fn should_have_checks_on_certify() {
// #3: state before
assert_eq!(CertsByReceiver::<Runtime>::get(3).unwrap().len(), 1);
- assert_eq!(Smiths::<Runtime>::get(3).unwrap(), SmithStatus::Pending);
+ assert_eq!(
+ Smiths::<Runtime>::get(3).unwrap().status,
+ SmithStatus::Pending
+ );
// Try to certify #3
assert_ok!(Pallet::<Runtime>::certify_smith(
RuntimeOrigin::signed(1),
@@ -131,6 +167,73 @@ fn should_have_checks_on_certify() {
));
// #3: state after
assert_eq!(CertsByReceiver::<Runtime>::get(3).unwrap().len(), 2);
- assert_eq!(Smiths::<Runtime>::get(3).unwrap(), SmithStatus::Smith);
+ assert_eq!(
+ Smiths::<Runtime>::get(3).unwrap().status,
+ SmithStatus::Smith
+ );
+ });
+}
+
+#[test]
+fn smith_activity_postpones_expiration() {
+ new_test_ext(GenesisConfig {
+ certs_by_receiver: btreemap![
+ 1 => btreemap![
+ 2 => None,
+ 3 => None,
+ 4 => None,
+ ],
+ 2 => btreemap![
+ 4 => None,
+ 4 => None,
+ 5 => None,
+ ]
+ ],
+ })
+ .execute_with(|| {
+ // On session 4 everything is fine
+ Pallet::<Runtime>::on_new_session(4);
+ assert_eq!(Smiths::<Runtime>::get(1).is_some(), true);
+ assert_eq!(Smiths::<Runtime>::get(2).is_some(), true);
+
+ // Smith #2 is online but not #1
+ Pallet::<Runtime>::smith_goes_online(2);
+
+ // On session 5 no more smiths because of lack of activity
+ Pallet::<Runtime>::on_new_session(5);
+ assert_eq!(Smiths::<Runtime>::get(1), None);
+ assert_eq!(
+ Smiths::<Runtime>::get(2),
+ Some(SmithMeta {
+ status: SmithStatus::Smith,
+ expires_on: None
+ })
+ );
+
+ // Smith #2 goes offline
+ Pallet::<Runtime>::on_new_session(6);
+ Pallet::<Runtime>::smith_goes_offline(2);
+ assert_eq!(Smiths::<Runtime>::get(1), None);
+ assert_eq!(
+ Smiths::<Runtime>::get(2),
+ Some(SmithMeta {
+ status: SmithStatus::Smith,
+ expires_on: Some(11)
+ })
+ );
+ // Still not expired on session 10
+ Pallet::<Runtime>::on_new_session(10);
+ assert_eq!(Smiths::<Runtime>::get(1), None);
+ assert_eq!(
+ Smiths::<Runtime>::get(2),
+ Some(SmithMeta {
+ status: SmithStatus::Smith,
+ expires_on: Some(11)
+ })
+ );
+ // Finally expired on session 11
+ Pallet::<Runtime>::on_new_session(11);
+ assert_eq!(Smiths::<Runtime>::get(1), None);
+ assert_eq!(Smiths::<Runtime>::get(2), None);
});
}
diff --git a/pallets/smith-members/src/traits.rs b/pallets/smith-members/src/traits.rs
index 7b15e78b98dc77eaca5d38f1cf88aea2a6393420..f59b6fc1c775e15ba69e32704da9238516a18db4 100644
--- a/pallets/smith-members/src/traits.rs
+++ b/pallets/smith-members/src/traits.rs
@@ -1,8 +1,8 @@
use crate::SmithRemovalReason;
-pub trait OnSmithDelete {
- fn on_smith_delete(reason: SmithRemovalReason);
+pub trait OnSmithDelete<IdtyIndex> {
+ fn on_smith_delete(idty_index: IdtyIndex, reason: SmithRemovalReason);
}
-impl OnSmithDelete for () {
- fn on_smith_delete(_: SmithRemovalReason) {}
+impl<IdtyIndex> OnSmithDelete<IdtyIndex> for () {
+ fn on_smith_delete(_: IdtyIndex, _: SmithRemovalReason) {}
}
diff --git a/pallets/smith-members/src/types.rs b/pallets/smith-members/src/types.rs
index d47d5704ed2128ebdbbf5375697adcdc023ae936..f1298055190fa798a3e670ff83a476fc249d30ee 100644
--- a/pallets/smith-members/src/types.rs
+++ b/pallets/smith-members/src/types.rs
@@ -16,11 +16,21 @@
//! Various basic types for use in the identity pallet.
+use crate::SmithStatus;
use codec::{Decode, Encode};
use frame_support::pallet_prelude::*;
-use scale_info::TypeInfo;
#[cfg(feature = "std")]
-use serde::{Deserialize, Serialize};
+use pallet_authority_members::SessionIndex;
+use scale_info::TypeInfo;
+
+/// certification metadata attached to an identity
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+pub struct SmithMeta {
+ /// current status of the smith
+ pub status: SmithStatus,
+ /// the session at which the smith will expire (for lack of validation activity)
+ pub expires_on: Option<SessionIndex>,
+}
/// certification metadata attached to an identity
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]