Skip to content
Snippets Groups Projects
Commit f4c15a0d authored by Hugo Trentesaux's avatar Hugo Trentesaux
Browse files

doc calls

parent 1d2bb1b9
No related branches found
No related tags found
No related merge requests found
# Duniter authority members pallet # Duniter authority members pallet
In a permissioned network, we have to define the set of authorities, and among these authorities, the ones taking part in the next session. That's what authority members pallet does. In practice: In a permissioned network, we have to define the set of authorities, and among these authorities, the ones validators in the next session. That's what authority members pallet does. In practice:
- it manages a `Members` set with some custom rules - it manages a `Members` set with some custom rules
- it implements the `SessionManager` trait from the session frame pallet - it implements the `SessionManager` trait from the session frame pallet
...@@ -19,3 +19,11 @@ Then one can "go online" and "go offline" to enter or leave two sessions after. ...@@ -19,3 +19,11 @@ Then one can "go online" and "go offline" to enter or leave two sessions after.
## Staying in the set of authorities ## Staying in the set of authorities
If a smith is offline more than `MaxOfflineSessions`, he leaves the set of authorities. If a smith is offline more than `MaxOfflineSessions`, he leaves the set of authorities.
## Some vocabulary
*Smiths* are people allowed to forge blocks, but in details this is:
- **smith** status required to become an authority
- **authority** status required to become validator
- **validator** status required to add blocks
\ No newline at end of file
...@@ -220,6 +220,7 @@ pub mod pallet { ...@@ -220,6 +220,7 @@ pub mod pallet {
#[pallet::call] #[pallet::call]
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// ask to leave the set of validators two sessions after
pub fn go_offline(origin: OriginFor<T>) -> DispatchResultWithPostInfo { pub fn go_offline(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
// Verification phase // // Verification phase //
let who = ensure_signed(origin)?; let who = ensure_signed(origin)?;
...@@ -246,6 +247,7 @@ pub mod pallet { ...@@ -246,6 +247,7 @@ pub mod pallet {
Ok(().into()) Ok(().into())
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// ask to join the set of validators two sessions after
pub fn go_online(origin: OriginFor<T>) -> DispatchResultWithPostInfo { pub fn go_online(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
// Verification phase // // Verification phase //
let who = ensure_signed(origin)?; let who = ensure_signed(origin)?;
...@@ -282,6 +284,7 @@ pub mod pallet { ...@@ -282,6 +284,7 @@ pub mod pallet {
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// declare new session keys to replace current ones
pub fn set_session_keys( pub fn set_session_keys(
origin: OriginFor<T>, origin: OriginFor<T>,
keys: T::KeysWrapper, keys: T::KeysWrapper,
...@@ -314,6 +317,7 @@ pub mod pallet { ...@@ -314,6 +317,7 @@ pub mod pallet {
Ok(().into()) Ok(().into())
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// remove an identity from the set of authorities
pub fn remove_member( pub fn remove_member(
origin: OriginFor<T>, origin: OriginFor<T>,
member_id: T::MemberId, member_id: T::MemberId,
...@@ -330,8 +334,12 @@ pub mod pallet { ...@@ -330,8 +334,12 @@ pub mod pallet {
// PUBLIC FUNCTIONS // // PUBLIC FUNCTIONS //
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
/// Should be transactional // Should be transactional (if an error occurs, storage should not be modified at all)
// Execute the annotated function in a new storage transaction.
// The return type of the annotated function must be `Result`. All changes to storage performed
// by the annotated function are discarded if it returns `Err`, or committed if `Ok`.
#[frame_support::transactional] #[frame_support::transactional]
/// change owner key of an authority member
pub fn change_owner_key( pub fn change_owner_key(
member_id: T::MemberId, member_id: T::MemberId,
new_owner_key: T::AccountId, new_owner_key: T::AccountId,
...@@ -370,6 +378,7 @@ pub mod pallet { ...@@ -370,6 +378,7 @@ pub mod pallet {
// INTERNAL FUNCTIONS // // INTERNAL FUNCTIONS //
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
/// perform authority member removal
fn do_remove_member(member_id: T::MemberId, owner_key: T::AccountId) -> Weight { fn do_remove_member(member_id: T::MemberId, owner_key: T::AccountId) -> Weight {
if Self::is_online(member_id) { if Self::is_online(member_id) {
// Trigger the member deletion for next session // Trigger the member deletion for next session
...@@ -398,6 +407,7 @@ pub mod pallet { ...@@ -398,6 +407,7 @@ pub mod pallet {
Weight::zero() Weight::zero()
} }
/// perform planned expiration of authority member for the given session
pub(super) fn expire_memberships(current_session_index: SessionIndex) { pub(super) fn expire_memberships(current_session_index: SessionIndex) {
for member_id in MembersExpireOn::<T>::take(current_session_index) { for member_id in MembersExpireOn::<T>::take(current_session_index) {
if let Some(member_data) = Members::<T>::get(member_id) { if let Some(member_data) = Members::<T>::get(member_id) {
...@@ -414,6 +424,7 @@ pub mod pallet { ...@@ -414,6 +424,7 @@ pub mod pallet {
} }
} }
} }
/// perform incoming authorities insertion
fn insert_in(member_id: T::MemberId) -> bool { fn insert_in(member_id: T::MemberId) -> bool {
let not_already_inserted = IncomingAuthorities::<T>::mutate(|members_ids| { let not_already_inserted = IncomingAuthorities::<T>::mutate(|members_ids| {
if let Err(index) = members_ids.binary_search(&member_id) { if let Err(index) = members_ids.binary_search(&member_id) {
...@@ -429,6 +440,7 @@ pub mod pallet { ...@@ -429,6 +440,7 @@ pub mod pallet {
} }
not_already_inserted not_already_inserted
} }
/// perform outgoing authority insertion
fn insert_out(member_id: T::MemberId) -> bool { fn insert_out(member_id: T::MemberId) -> bool {
let not_already_inserted = OutgoingAuthorities::<T>::mutate(|members_ids| { let not_already_inserted = OutgoingAuthorities::<T>::mutate(|members_ids| {
if let Err(index) = members_ids.binary_search(&member_id) { if let Err(index) = members_ids.binary_search(&member_id) {
...@@ -448,21 +460,25 @@ pub mod pallet { ...@@ -448,21 +460,25 @@ pub mod pallet {
} }
not_already_inserted not_already_inserted
} }
/// check if member is incoming
fn is_incoming(member_id: T::MemberId) -> bool { fn is_incoming(member_id: T::MemberId) -> bool {
IncomingAuthorities::<T>::get() IncomingAuthorities::<T>::get()
.binary_search(&member_id) .binary_search(&member_id)
.is_ok() .is_ok()
} }
/// check if member is online
fn is_online(member_id: T::MemberId) -> bool { fn is_online(member_id: T::MemberId) -> bool {
OnlineAuthorities::<T>::get() OnlineAuthorities::<T>::get()
.binary_search(&member_id) .binary_search(&member_id)
.is_ok() .is_ok()
} }
/// check if member is outgoing
fn is_outgoing(member_id: T::MemberId) -> bool { fn is_outgoing(member_id: T::MemberId) -> bool {
OutgoingAuthorities::<T>::get() OutgoingAuthorities::<T>::get()
.binary_search(&member_id) .binary_search(&member_id)
.is_ok() .is_ok()
} }
/// perform removal from incoming authorities
fn remove_in(member_id: T::MemberId) { fn remove_in(member_id: T::MemberId) {
AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_sub(1)); AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_sub(1));
IncomingAuthorities::<T>::mutate(|members_ids| { IncomingAuthorities::<T>::mutate(|members_ids| {
...@@ -471,6 +487,7 @@ pub mod pallet { ...@@ -471,6 +487,7 @@ pub mod pallet {
} }
}) })
} }
/// perform removal from online authorities
fn remove_online(member_id: T::MemberId) { fn remove_online(member_id: T::MemberId) {
AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_add(1)); AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_add(1));
OnlineAuthorities::<T>::mutate(|members_ids| { OnlineAuthorities::<T>::mutate(|members_ids| {
...@@ -479,6 +496,7 @@ pub mod pallet { ...@@ -479,6 +496,7 @@ pub mod pallet {
} }
}); });
} }
/// perform removal from outgoing authorities
fn remove_out(member_id: T::MemberId) { fn remove_out(member_id: T::MemberId) {
OutgoingAuthorities::<T>::mutate(|members_ids| { OutgoingAuthorities::<T>::mutate(|members_ids| {
if let Ok(index) = members_ids.binary_search(&member_id) { if let Ok(index) = members_ids.binary_search(&member_id) {
...@@ -486,6 +504,7 @@ pub mod pallet { ...@@ -486,6 +504,7 @@ pub mod pallet {
} }
}); });
} }
/// check that accountid is member
fn verify_ownership_and_membership( fn verify_ownership_and_membership(
who: &T::AccountId, who: &T::AccountId,
) -> Result<T::MemberId, DispatchError> { ) -> Result<T::MemberId, DispatchError> {
...@@ -596,6 +615,7 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> { ...@@ -596,6 +615,7 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
} }
} }
// see substrate FullIdentification
fn add_full_identification<T: Config>( fn add_full_identification<T: Config>(
validator_id: T::ValidatorId, validator_id: T::ValidatorId,
) -> Option<(T::ValidatorId, T::FullIdentification)> { ) -> Option<(T::ValidatorId, T::FullIdentification)> {
...@@ -604,6 +624,7 @@ fn add_full_identification<T: Config>( ...@@ -604,6 +624,7 @@ fn add_full_identification<T: Config>(
.map(|full_ident| (validator_id, full_ident)) .map(|full_ident| (validator_id, full_ident))
} }
// implement SessionManager with FullIdentification
impl<T: Config> pallet_session::historical::SessionManager<T::ValidatorId, T::FullIdentification> impl<T: Config> pallet_session::historical::SessionManager<T::ValidatorId, T::FullIdentification>
for Pallet<T> for Pallet<T>
{ {
......
...@@ -25,8 +25,11 @@ use sp_staking::SessionIndex; ...@@ -25,8 +25,11 @@ use sp_staking::SessionIndex;
#[cfg_attr(feature = "std", derive(Debug, Deserialize, Serialize))] #[cfg_attr(feature = "std", derive(Debug, Deserialize, Serialize))]
#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] #[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)]
pub struct MemberData<AccountId> { pub struct MemberData<AccountId> {
/// session at which the membership expires
pub expire_on_session: SessionIndex, pub expire_on_session: SessionIndex,
/// session before which the member must have rotated keys
pub must_rotate_keys_before: SessionIndex, pub must_rotate_keys_before: SessionIndex,
/// pubkey of the member
pub owner_key: AccountId, pub owner_key: AccountId,
} }
......
...@@ -162,6 +162,7 @@ where ...@@ -162,6 +162,7 @@ where
// TODO replace this code by the commented one for distance feature // TODO replace this code by the commented one for distance feature
/*let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index); /*let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index);
idty_cert_meta.received_count >= T::MinCertForMembership::get() as u32*/ idty_cert_meta.received_count >= T::MinCertForMembership::get() as u32*/
// in the main wot, automatically claim membership when the identity is validated
pallet_membership::Pallet::<T, I>::claim_membership( pallet_membership::Pallet::<T, I>::claim_membership(
RawOrigin::Root.into(), RawOrigin::Root.into(),
Some(idty_index), Some(idty_index),
......
...@@ -133,19 +133,19 @@ pub mod pallet { ...@@ -133,19 +133,19 @@ pub mod pallet {
#[pallet::event] #[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)] #[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config<I>, I: 'static = ()> { pub enum Event<T: Config<I>, I: 'static = ()> {
/// A membership has acquired /// A membership was acquired
/// [idty_id] /// [idty_id]
MembershipAcquired(T::IdtyId), MembershipAcquired(T::IdtyId),
/// A membership has expired /// A membership expired
/// [idty_id] /// [idty_id]
MembershipExpired(T::IdtyId), MembershipExpired(T::IdtyId),
/// A membership has renewed /// A membership was renewed
/// [idty_id] /// [idty_id]
MembershipRenewed(T::IdtyId), MembershipRenewed(T::IdtyId),
/// An identity requested membership /// An membership was requested
/// [idty_id] /// [idty_id]
MembershipRequested(T::IdtyId), MembershipRequested(T::IdtyId),
/// A membership has revoked /// A membership was revoked
/// [idty_id] /// [idty_id]
MembershipRevoked(T::IdtyId), MembershipRevoked(T::IdtyId),
/// A pending membership request has expired /// A pending membership request has expired
...@@ -191,6 +191,7 @@ pub mod pallet { ...@@ -191,6 +191,7 @@ pub mod pallet {
#[pallet::call] #[pallet::call]
impl<T: Config<I>, I: 'static> Pallet<T, I> { impl<T: Config<I>, I: 'static> Pallet<T, I> {
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// request membership without checks
pub fn force_request_membership( pub fn force_request_membership(
origin: OriginFor<T>, origin: OriginFor<T>,
idty_id: T::IdtyId, idty_id: T::IdtyId,
...@@ -202,6 +203,8 @@ pub mod pallet { ...@@ -202,6 +203,8 @@ pub mod pallet {
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// submit a membership request (must have a declared identity)
/// (only available for sub wot, automatic for main wot)
pub fn request_membership( pub fn request_membership(
origin: OriginFor<T>, origin: OriginFor<T>,
metadata: T::MetaData, metadata: T::MetaData,
...@@ -218,6 +221,8 @@ pub mod pallet { ...@@ -218,6 +221,8 @@ pub mod pallet {
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// claim that the previously requested membership fullfills the requirements
/// (only available for sub wot, automatic for main wot)
pub fn claim_membership( pub fn claim_membership(
origin: OriginFor<T>, origin: OriginFor<T>,
maybe_idty_id: Option<T::IdtyId>, maybe_idty_id: Option<T::IdtyId>,
...@@ -244,6 +249,7 @@ pub mod pallet { ...@@ -244,6 +249,7 @@ pub mod pallet {
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// extend the validity period of an active membership
pub fn renew_membership( pub fn renew_membership(
origin: OriginFor<T>, origin: OriginFor<T>,
maybe_idty_id: Option<T::IdtyId>, maybe_idty_id: Option<T::IdtyId>,
...@@ -264,6 +270,8 @@ pub mod pallet { ...@@ -264,6 +270,8 @@ pub mod pallet {
} }
#[pallet::weight(1_000_000_000)] #[pallet::weight(1_000_000_000)]
/// revoke an active membership
/// (only available for sub wot, automatic for main wot)
pub fn revoke_membership( pub fn revoke_membership(
origin: OriginFor<T>, origin: OriginFor<T>,
maybe_idty_id: Option<T::IdtyId>, maybe_idty_id: Option<T::IdtyId>,
...@@ -284,12 +292,14 @@ pub mod pallet { ...@@ -284,12 +292,14 @@ pub mod pallet {
// INTERNAL FUNCTIONS // // INTERNAL FUNCTIONS //
impl<T: Config<I>, I: 'static> Pallet<T, I> { impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// perform the membership renewal and emit events
pub(super) fn do_renew_membership(idty_id: T::IdtyId) -> Weight { pub(super) fn do_renew_membership(idty_id: T::IdtyId) -> Weight {
let total_weight = Self::do_renew_membership_inner(idty_id); let total_weight = Self::do_renew_membership_inner(idty_id);
Self::deposit_event(Event::MembershipRenewed(idty_id)); Self::deposit_event(Event::MembershipRenewed(idty_id));
T::OnEvent::on_event(&sp_membership::Event::MembershipRenewed(idty_id)); T::OnEvent::on_event(&sp_membership::Event::MembershipRenewed(idty_id));
total_weight total_weight
} }
/// perform the membership renewal
fn do_renew_membership_inner(idty_id: T::IdtyId) -> Weight { fn do_renew_membership_inner(idty_id: T::IdtyId) -> Weight {
let block_number = frame_system::pallet::Pallet::<T>::block_number(); let block_number = frame_system::pallet::Pallet::<T>::block_number();
let expire_on = block_number + T::MembershipPeriod::get(); let expire_on = block_number + T::MembershipPeriod::get();
...@@ -298,6 +308,7 @@ pub mod pallet { ...@@ -298,6 +308,7 @@ pub mod pallet {
MembershipsExpireOn::<T, I>::append(expire_on, idty_id); MembershipsExpireOn::<T, I>::append(expire_on, idty_id);
Weight::zero() Weight::zero()
} }
/// perform the membership request
fn do_request_membership( fn do_request_membership(
idty_id: T::IdtyId, idty_id: T::IdtyId,
metadata: T::MetaData, metadata: T::MetaData,
...@@ -319,6 +330,7 @@ pub mod pallet { ...@@ -319,6 +330,7 @@ pub mod pallet {
Ok(().into()) Ok(().into())
} }
/// check the origin and get identity id if valid
fn ensure_origin_and_get_idty_id( fn ensure_origin_and_get_idty_id(
origin: OriginFor<T>, origin: OriginFor<T>,
maybe_idty_id: Option<T::IdtyId>, maybe_idty_id: Option<T::IdtyId>,
...@@ -332,6 +344,7 @@ pub mod pallet { ...@@ -332,6 +344,7 @@ pub mod pallet {
_ => Err(BadOrigin.into()), _ => Err(BadOrigin.into()),
} }
} }
/// perform the membership expiration if it has not been renewed meanwhile
fn expire_memberships(block_number: T::BlockNumber) -> Weight { fn expire_memberships(block_number: T::BlockNumber) -> Weight {
let mut total_weight: Weight = Weight::zero(); let mut total_weight: Weight = Weight::zero();
...@@ -348,6 +361,7 @@ pub mod pallet { ...@@ -348,6 +361,7 @@ pub mod pallet {
total_weight total_weight
} }
/// perform the expiration of pending membership planned at given block
fn expire_pending_memberships(block_number: T::BlockNumber) -> Weight { fn expire_pending_memberships(block_number: T::BlockNumber) -> Weight {
let mut total_weight: Weight = Weight::zero(); let mut total_weight: Weight = Weight::zero();
...@@ -363,21 +377,27 @@ pub mod pallet { ...@@ -363,21 +377,27 @@ pub mod pallet {
total_weight total_weight
} }
/// check if identity is member
pub(super) fn is_member_inner(idty_id: &T::IdtyId) -> bool { pub(super) fn is_member_inner(idty_id: &T::IdtyId) -> bool {
Membership::<T, I>::contains_key(idty_id) Membership::<T, I>::contains_key(idty_id)
} }
/// insert membership in storage
fn insert_membership(idty_id: T::IdtyId, membership_data: MembershipData<T::BlockNumber>) { fn insert_membership(idty_id: T::IdtyId, membership_data: MembershipData<T::BlockNumber>) {
Membership::<T, I>::insert(idty_id, membership_data); Membership::<T, I>::insert(idty_id, membership_data);
} }
/// retreive membership from storage
fn get_membership(idty_id: &T::IdtyId) -> Option<MembershipData<T::BlockNumber>> { fn get_membership(idty_id: &T::IdtyId) -> Option<MembershipData<T::BlockNumber>> {
Membership::<T, I>::try_get(idty_id).ok() Membership::<T, I>::try_get(idty_id).ok()
} }
/// remove membership from storage
fn remove_membership(idty_id: &T::IdtyId) -> bool { fn remove_membership(idty_id: &T::IdtyId) -> bool {
Membership::<T, I>::take(idty_id).is_some() Membership::<T, I>::take(idty_id).is_some()
} }
} }
} }
// implement traits
impl<T: Config<I>, I: 'static> IsInPendingMemberships<T::IdtyId> for Pallet<T, I> { impl<T: Config<I>, I: 'static> IsInPendingMemberships<T::IdtyId> for Pallet<T, I> {
fn is_in_pending_memberships(idty_id: T::IdtyId) -> bool { fn is_in_pending_memberships(idty_id: T::IdtyId) -> bool {
PendingMembership::<T, I>::contains_key(idty_id) PendingMembership::<T, I>::contains_key(idty_id)
......
...@@ -129,10 +129,11 @@ impl CallCategory { ...@@ -129,10 +129,11 @@ impl CallCategory {
"remove_identity" | "prune_item_identities_names" | "prune_item_identity_index_of", "remove_identity" | "prune_item_identities_names" | "prune_item_identity_index_of",
) => Self::Root, ) => Self::Root,
("Membership", "force_request_membership") => Self::Root, ("Membership", "force_request_membership") => Self::Root,
("Membership", "claim_membership" | "revoke_membership") => Self::Disabled, ("Membership", "request_membership" | "claim_membership" | "revoke_membership") => {
Self::Disabled
}
("Cert", "force_add_cert" | "del_cert" | "remove_all_certs_received_by") => Self::Root, ("Cert", "force_add_cert" | "del_cert" | "remove_all_certs_received_by") => Self::Root,
("SmithsMembership", "force_request_membership") => Self::Root, ("SmithsMembership", "force_request_membership") => Self::Root,
("SmithsMembership", "claim_membership") => Self::Disabled,
("SmithsCert", "force_add_cert" | "del_cert" | "remove_all_certs_received_by") => { ("SmithsCert", "force_add_cert" | "del_cert" | "remove_all_certs_received_by") => {
Self::Root Self::Root
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment