diff --git a/distance-oracle/src/lib.rs b/distance-oracle/src/lib.rs index 53a7503ea28f577684febf1ce09c2744746ba29b..965ed8b20ee0d8f79eb261600ae948536b466559 100644 --- a/distance-oracle/src/lib.rs +++ b/distance-oracle/src/lib.rs @@ -49,6 +49,7 @@ impl subxt::config::Config for RuntimeConfig { type Signature = subxt::ext::sp_runtime::MultiSignature; } +/// Represents a tipping amount. #[derive(Copy, Clone, Debug, Default, Encode)] pub struct Tip { #[codec(compact)] @@ -67,6 +68,7 @@ impl From<u64> for Tip { } } +/// Represents configuration parameters. pub struct Settings { pub evaluation_result_dir: PathBuf, pub rpc_url: String, @@ -81,6 +83,7 @@ impl Default for Settings { } } +/// Asynchronously runs a computation using the provided client and saves the result to a file. pub async fn run_and_save(client: &api::Client, settings: Settings) { let Some((evaluation, current_pool_index, evaluation_result_path)) = run(client, &settings, true).await @@ -138,7 +141,8 @@ pub async fn run_and_save(client: &api::Client, settings: Settings) { }); } -/// Returns `Option<(evaluation, current_pool_index, evaluation_result_path)>` +/// Asynchronously runs a computation based on the provided client and settings. +/// Returns `Option<(evaluation, current_pool_index, evaluation_result_path)>`. pub async fn run( client: &api::Client, settings: &Settings, diff --git a/docs/api/runtime-calls.md b/docs/api/runtime-calls.md index 68c737183f1d8f5bcd74be7f2bf5c27925823891..efdbb573ccd4698ecbff097f7f1f7fe11acb4e49 100644 --- a/docs/api/runtime-calls.md +++ b/docs/api/runtime-calls.md @@ -28,7 +28,7 @@ Taking 0.0107 % of a block. </details> -unlink the identity associated with the account +Unlink the identity associated with the account. ### Scheduler - 2 @@ -430,7 +430,7 @@ receiver: T::IdtyIndex </details> -Invite a WoT member to try becoming a Smith +Invite a member of the Web of Trust to attempt becoming a Smith. #### accept_invitation - 1 @@ -443,7 +443,7 @@ Taking 0.0122 % of a block. </details> -Accept an invitation (must have been invited first) +Accept an invitation to become a Smith (must have been invited first). #### certify_smith - 2 @@ -457,7 +457,7 @@ receiver: T::IdtyIndex </details> -Certify an invited smith which can lead the certified to become a Smith +Certify an invited Smith, which can lead the certified to become a Smith. ### AuthorityMembers - 11 @@ -472,7 +472,7 @@ Taking 0.0165 % of a block. </details> -ask to leave the set of validators two sessions after +Request to leave the set of validators two sessions later. #### go_online - 1 @@ -485,7 +485,7 @@ Taking 0.0188 % of a block. </details> -ask to join the set of validators two sessions after +Request to join the set of validators two sessions later. #### set_session_keys - 2 @@ -499,7 +499,7 @@ keys: T::Keys </details> -declare new session keys to replace current ones +Declare new session keys to replace current ones. #### remove_member_from_blacklist - 4 @@ -513,6 +513,7 @@ member_id: T::MemberId </details> +Remove a member from the blacklist. remove an identity from the blacklist ### Grandpa - 16 @@ -774,7 +775,7 @@ Taking 0.0218 % of a block. </details> -Claim Universal Dividends +Claim Universal Dividends. #### transfer_ud - 1 @@ -804,7 +805,7 @@ value: BalanceOf<T> </details> -Transfer some liquid free balance to another account, in milliUD. +Transfer some liquid free balance to another account in milliUD and keep the account alive. ### Identity - 41 @@ -812,7 +813,7 @@ Transfer some liquid free balance to another account, in milliUD. <details><summary><code>create_identity(owner_key)</code></summary> -Taking 0.0912 % of a block. +Taking 0.0914 % of a block. ```rust owner_key: T::AccountId @@ -830,7 +831,7 @@ The origin must be allowed to create an identity. <details><summary><code>confirm_identity(idty_name)</code></summary> -Taking 0.0338 % of a block. +Taking 0.0339 % of a block. ```rust idty_name: IdtyName @@ -869,7 +870,7 @@ The origin should be the old identity owner key. <details><summary><code>revoke_identity(idty_index, revocation_key, revocation_sig)</code></summary> -Taking 0.0416 % of a block. +Taking 0.0417 % of a block. ```rust idty_index: T::IdtyIndex @@ -901,7 +902,15 @@ inc: bool </details> -change sufficient ref count for given key +Change sufficient reference count for a given key. + +This function allows a privileged root origin to increment or decrement the sufficient +reference count associated with a specified owner key. + +- `origin` - The origin of the call. It must be root. +- `owner_key` - The account whose sufficient reference count will be modified. +- `inc` - A boolean indicating whether to increment (`true`) or decrement (`false`) the count. + #### link_account - 8 @@ -916,7 +925,14 @@ payload_sig: T::Signature </details> -Link an account to an identity +Link an account to an identity. + +This function links a specified account to an identity, requiring both the account and the +identity to sign the operation. + +- `origin` - The origin of the call, which must have an associated identity index. +- `account_id` - The account ID to link, which must sign the payload. +- `payload_sig` - The signature with the linked identity. ### Certification - 43 @@ -961,7 +977,9 @@ receiver: T::IdtyIndex </details> -remove a certification (only root) +Remove one certification given the issuer and the receiver. + +- `origin`: Must be `Root`. #### remove_all_certs_received_by - 2 @@ -975,7 +993,9 @@ idty_index: T::IdtyIndex </details> -remove all certifications received by an identity (only root) +Remove all certifications received by an identity. + +- `origin`: Must be `Root`. ### Distance - 44 @@ -990,9 +1010,11 @@ Taking 0.0325 % of a block. </details> -Request caller identity to be evaluated -positive evaluation will result in claim/renew membership -negative evaluation will result in slash for caller +Request evaluation of the caller's identity distance. + +This function allows the caller to request an evaluation of their distance. +A positive evaluation will lead to claiming or renewing membership, while a negative +evaluation will result in slashing for the caller. #### request_distance_evaluation_for - 4 @@ -1006,8 +1028,10 @@ target: T::IdtyIndex </details> -Request target identity to be evaluated -only possible for unvalidated identity +Request evaluation of a target identity's distance. + +This function allows the caller to request an evaluation of a specific target identity's distance. +This action is only permitted for unvalidated identities. #### update_evaluation - 1 @@ -1021,8 +1045,10 @@ computation_result: ComputationResult </details> -(Inherent) Push an evaluation result to the pool -this is called internally by validators (= inherent) +Push an evaluation result to the pool. + +This inherent function is called internally by validators to push an evaluation result +to the evaluation pool. #### force_update_evaluation - 2 @@ -1037,7 +1063,11 @@ computation_result: ComputationResult </details> -Force push an evaluation result to the pool +Force push an evaluation result to the pool. + +It is primarily used for testing purposes. + +- `origin`: Must be `Root`. #### force_valid_distance_status - 3 @@ -1051,7 +1081,11 @@ identity: <T as pallet_identity::Config>::IdtyIndex </details> -Force set the distance evaluation status of an identity +Force set the distance evaluation status of an identity. + +It is primarily used for testing purposes. + +- `origin`: Must be `Root`. ### AtomicSwap - 50 @@ -1307,7 +1341,7 @@ salt: H256 </details> -Request a randomness +Request randomness. ### Proxy - 53 @@ -2161,7 +2195,7 @@ member_id: T::MemberId </details> -remove an identity from the set of authorities +Remove a member from the set of validators. ### Grandpa - 16 @@ -2261,7 +2295,7 @@ O(P) where P is the number of max proposals <details><summary><code>prune_item_identities_names(names)</code></summary> -Taking 6.0421 % of a block. +Taking 6.0424 % of a block. ```rust names: Vec<IdtyName> @@ -2269,7 +2303,13 @@ names: Vec<IdtyName> </details> -remove identity names from storage +Remove identity names from storage. + +This function allows a privileged root origin to remove multiple identity names from storage +in bulk. + +- `origin` - The origin of the call. It must be root. +- `names` - A vector containing the identity names to be removed from storage. ### Utility - 54 diff --git a/docs/api/runtime-errors.md b/docs/api/runtime-errors.md index 667342478644643900f109e811a5308e55ecc1e3..48bc9f68cd283b12f69b94f32606a3cff83a6d2f 100644 --- a/docs/api/runtime-errors.md +++ b/docs/api/runtime-errors.md @@ -1,6 +1,6 @@ # Runtime errors -There are **189** errors from **35** pallets. +There are **190** errors from **35** pallets. <ul> <li>System - 0 @@ -972,6 +972,13 @@ Can not revoke identity that never was member. Cannot link to an inexisting account. </details> </li> +<li> +<details> +<summary> +<code>InsufficientBalance</code> - 17</summary> +Insufficient balance to create an identity. +</details> +</li> </ul> </li> <li>Membership - 42 diff --git a/node/src/chain_spec/gdev.rs b/node/src/chain_spec/gdev.rs index 370da7b0b27b4054089196d3e4f56a7860c703d3..57a3e530613fd7dfc3ddf8d88160759711dc4427 100644 --- a/node/src/chain_spec/gdev.rs +++ b/node/src/chain_spec/gdev.rs @@ -74,8 +74,6 @@ fn get_parameters(parameters_from_file: &Option<GenesisParameters>) -> CommonPar universal_dividend_square_money_growth_rate: parameters::SquareMoneyGrowthRate::get(), universal_dividend_ud_creation_period: parameters_from_file.ud_creation_period, universal_dividend_ud_reeval_period: parameters_from_file.ud_reeval_period, - universal_dividend_units_per_ud: - <Runtime as pallet_universal_dividend::Config>::UnitsPerUd::get(), wot_first_issuable_on: parameters_from_file.wot_first_cert_issuable_on, wot_min_cert_for_membership: parameters_from_file.wot_min_cert_for_membership, wot_min_cert_for_create_idty_right: parameters_from_file.wot_min_cert_for_create_idty_right, diff --git a/node/src/chain_spec/gen_genesis_data.rs b/node/src/chain_spec/gen_genesis_data.rs index d87347c4409e6b729e01f6bb837f2dc8223676ef..28014f16eb177273c7d4fb103bd9783a9cef0aae 100644 --- a/node/src/chain_spec/gen_genesis_data.rs +++ b/node/src/chain_spec/gen_genesis_data.rs @@ -749,11 +749,6 @@ fn dump_genesis_info(info: GenesisInfo) { get_best_unit_and_diviser_for_ms(p.universal_dividend_ud_creation_period as f32); let (universal_dividend_ud_reeval_period, universal_dividend_ud_reeval_period_unit) = get_best_unit_and_diviser_for_ms(p.universal_dividend_ud_reeval_period as f32); - let (universal_dividend_units_per_ud, universal_dividend_units_per_ud_unit) = - get_best_unit_and_diviser_for_currency_units( - p.universal_dividend_units_per_ud, - p.currency_name.clone(), - ); let (wot_first_issuable_on, wot_first_issuable_on_unit) = get_best_unit_and_diviser_for_blocks(p.wot_first_issuable_on); let (wot_min_cert_for_membership, wot_min_cert_for_membership_unit) = @@ -810,7 +805,6 @@ fn dump_genesis_info(info: GenesisInfo) { - universal_dividend.square_money_growth_rate: {} {}/equinox - universal_dividend.ud_creation_period: {} {} - universal_dividend.ud_reeval_period: {} {} - - universal_dividend.units_per_ud: {} {} - wot.first_issuable_on: {} {} - wot.min_cert_for_membership: {} {} - wot.min_cert_for_create_idty_right: {} {} @@ -852,8 +846,6 @@ fn dump_genesis_info(info: GenesisInfo) { universal_dividend_ud_creation_period_unit, universal_dividend_ud_reeval_period, universal_dividend_ud_reeval_period_unit, - universal_dividend_units_per_ud, - universal_dividend_units_per_ud_unit, wot_first_issuable_on, wot_first_issuable_on_unit, wot_min_cert_for_membership, @@ -1935,7 +1927,6 @@ pub struct CommonParameters { pub universal_dividend_square_money_growth_rate: Perbill, pub universal_dividend_ud_creation_period: u64, pub universal_dividend_ud_reeval_period: u64, - pub universal_dividend_units_per_ud: u64, pub wot_first_issuable_on: u32, pub wot_min_cert_for_membership: u32, pub wot_min_cert_for_create_idty_right: u32, diff --git a/node/src/chain_spec/gtest.rs b/node/src/chain_spec/gtest.rs index 3154b76cf236a83e14676a65cfa0338c31cbc9bb..0646b6e2a4148b1f38d2155125e0a7fda83e17cd 100644 --- a/node/src/chain_spec/gtest.rs +++ b/node/src/chain_spec/gtest.rs @@ -77,8 +77,6 @@ fn get_parameters(_: &Option<GenesisParameters>) -> CommonParameters { universal_dividend_square_money_growth_rate: parameters::SquareMoneyGrowthRate::get(), universal_dividend_ud_creation_period: parameters::UdCreationPeriod::get() as u64, universal_dividend_ud_reeval_period: parameters::UdReevalPeriod::get() as u64, - universal_dividend_units_per_ud: - <Runtime as pallet_universal_dividend::Config>::UnitsPerUd::get(), wot_first_issuable_on: parameters::WotFirstCertIssuableOn::get(), wot_min_cert_for_membership: parameters::WotMinCertForMembership::get(), wot_min_cert_for_create_idty_right: parameters::WotMinCertForCreateIdtyRight::get(), diff --git a/pallets/authority-members/Cargo.toml b/pallets/authority-members/Cargo.toml index 2e3aa3a14701a2d6e84086fe6ef47f4b73575ccb..0062b5c52f3b1628794c7bbf6a89b062f26ac85f 100644 --- a/pallets/authority-members/Cargo.toml +++ b/pallets/authority-members/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-authority-members" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/authority-members/README.md b/pallets/authority-members/README.md deleted file mode 100644 index 3edf76eba9a5e7702065681758bd89966a0747f5..0000000000000000000000000000000000000000 --- a/pallets/authority-members/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Duniter authority members pallet - -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 implements the `SessionManager` trait from the FRAME session pallet - -## Entering the set of authorities - -To become part of Duniter authorities, one has to complete these steps: - -1. become member of the main web of trust -1. request membership to the smith sub wot -1. get enough certs to get smith membership -1. claim membership to the set of authorities - -Then one can "go online" and "go offline" to enter or leave two sessions after. - -## 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 diff --git a/pallets/authority-members/src/lib.rs b/pallets/authority-members/src/lib.rs index 052d4130a4fcb68ef538d69bea94b278af3fbff9..1f5150bde02ea022c0ea391cb4037be5d1845ad5 100644 --- a/pallets/authority-members/src/lib.rs +++ b/pallets/authority-members/src/lib.rs @@ -14,6 +14,33 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Authority Members Pallet +//! +//! In a permissioned network, defining the set of authorities and selecting validators for the next session is crucial. +//! The authority members pallet is responsible for this. Specifically, it: +//! +//! - Manages a `Members` set with custom rules. +//! - Implements the `SessionManager` trait from the FRAME session pallet. +//! +//! ## Entering the Set of Authorities +//! +//! To become part of Duniter authorities, one must follow these steps: +//! +//! 1. Become a member of the main web of trust. +//! 2. Request membership to the smith sub web of trust. +//! 3. Obtain enough certifications to gain smith membership. +//! 4. Claim membership to the set of authorities. +//! +//! After becoming an authority, one can "go online" and "go offline" to enter or leave two sessions later. +//! +//! ## Some Vocabulary +//! +//! *Smiths* are individuals allowed to forge blocks. Specifically, this entails: +//! +//! - **Smith** status is required to become an authority. +//! - **Authority** status is required to become a validator. +//! - **Validator** status is required to add blocks. + #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::type_complexity)] @@ -31,7 +58,6 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -//pub use impls::*; pub use pallet::*; pub use sp_staking::SessionIndex; pub use traits::*; @@ -67,17 +93,35 @@ pub mod pallet { pub trait Config: frame_system::Config + pallet_session::Config + pallet_session::historical::Config { + /// Specifies the type that determines membership status. type IsMember: IsMember<Self::MemberId>; + + /// Handler for when a new session is initiated. type OnNewSession: OnNewSession; + + /// Handler for when a member is removed from authorities. type OnOutgoingMember: OnOutgoingMember<Self::MemberId>; + + /// Handler for when a new member is added to authorities. type OnIncomingMember: OnIncomingMember<Self::MemberId>; - /// Max number of authorities allowed + + /// Maximum number of authorities allowed. #[pallet::constant] type MaxAuthorities: Get<u32>; + + /// Type representing the identifier of a member. type MemberId: Copy + Ord + MaybeSerializeDeserialize + Parameter; + + /// Converts an `AccountId` to an optional `MemberId`. type MemberIdOf: Convert<Self::AccountId, Option<Self::MemberId>>; + + /// Specifies the origin type required to remove a member. type RemoveMemberOrigin: EnsureOrigin<Self::RuntimeOrigin>; + + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; + + /// Type representing the weight of this pallet type WeightInfo: WeightInfo; } @@ -123,28 +167,28 @@ pub mod pallet { // STORAGE // - /// list incoming authorities + /// The incoming authorities. #[pallet::storage] #[pallet::getter(fn incoming)] pub type IncomingAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>; - /// list online authorities + /// The online authorities. #[pallet::storage] #[pallet::getter(fn online)] pub type OnlineAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>; - /// list outgoing authorities + /// The outgoing authorities. #[pallet::storage] #[pallet::getter(fn outgoing)] pub type OutgoingAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>; - /// maps member id to member data + /// The member data. #[pallet::storage] #[pallet::getter(fn member)] pub type Members<T: Config> = StorageMap<_, Twox64Concat, T::MemberId, MemberData<T::AccountId>, OptionQuery>; - // Blacklist. + /// The blacklisted authorities. #[pallet::storage] #[pallet::getter(fn blacklist)] pub type Blacklist<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>; @@ -204,7 +248,7 @@ pub mod pallet { #[pallet::call] impl<T: Config> Pallet<T> { - /// ask to leave the set of validators two sessions after + /// Request to leave the set of validators two sessions later. #[pallet::call_index(0)] #[pallet::weight(<T as pallet::Config>::WeightInfo::go_offline())] pub fn go_offline(origin: OriginFor<T>) -> DispatchResultWithPostInfo { @@ -233,7 +277,7 @@ pub mod pallet { Ok(().into()) } - /// ask to join the set of validators two sessions after + /// Request to join the set of validators two sessions later. #[pallet::call_index(1)] #[pallet::weight(<T as pallet::Config>::WeightInfo::go_online())] pub fn go_online(origin: OriginFor<T>) -> DispatchResultWithPostInfo { @@ -274,7 +318,7 @@ pub mod pallet { Ok(().into()) } - /// declare new session keys to replace current ones + /// Declare new session keys to replace current ones. #[pallet::call_index(2)] #[pallet::weight(<T as pallet::Config>::WeightInfo::set_session_keys())] pub fn set_session_keys(origin: OriginFor<T>, keys: T::Keys) -> DispatchResultWithPostInfo { @@ -292,7 +336,7 @@ pub mod pallet { Ok(().into()) } - /// remove an identity from the set of authorities + /// Remove a member from the set of validators. #[pallet::call_index(3)] #[pallet::weight(<T as pallet::Config>::WeightInfo::remove_member())] pub fn remove_member( @@ -307,6 +351,7 @@ pub mod pallet { Ok(().into()) } + /// Remove a member from the blacklist. #[pallet::call_index(4)] #[pallet::weight(<T as pallet::Config>::WeightInfo::remove_member_from_blacklist())] /// remove an identity from the blacklist @@ -335,7 +380,7 @@ pub mod pallet { // 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] - /// change owner key of an authority member + /// Change the owner key of an authority member. pub fn change_owner_key( member_id: T::MemberId, new_owner_key: T::AccountId, @@ -370,6 +415,7 @@ pub mod pallet { Ok(().into()) } + /// Get the number of authorities. pub fn authorities_counter() -> u32 { let count = OnlineAuthorities::<T>::get().len() + IncomingAuthorities::<T>::get().len() - OutgoingAuthorities::<T>::get().len(); @@ -380,7 +426,7 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { - /// perform authority member removal + /// Perform authority member removal. fn do_remove_member(member_id: T::MemberId, owner_key: T::AccountId) { if Self::is_online(member_id) { // Trigger the member deletion for next session @@ -407,7 +453,7 @@ pub mod pallet { Self::deposit_event(Event::MemberRemoved { member: member_id }); } - /// perform incoming authorities insertion + /// Perform incoming authorities insertion. fn insert_in(member_id: T::MemberId) -> bool { let not_already_inserted = IncomingAuthorities::<T>::mutate(|members_ids| { if let Err(index) = members_ids.binary_search(&member_id) { @@ -423,7 +469,7 @@ pub mod pallet { not_already_inserted } - /// perform outgoing authority insertion + /// Perform outgoing authority insertion. pub fn insert_out(member_id: T::MemberId) -> bool { let not_already_inserted = OutgoingAuthorities::<T>::mutate(|members_ids| { if let Err(index) = members_ids.binary_search(&member_id) { @@ -439,33 +485,33 @@ pub mod pallet { not_already_inserted } - /// check if member is incoming + /// Check if member is incoming. fn is_incoming(member_id: T::MemberId) -> bool { IncomingAuthorities::<T>::get() .binary_search(&member_id) .is_ok() } - /// check if member is online + /// C&heck if member is online. fn is_online(member_id: T::MemberId) -> bool { OnlineAuthorities::<T>::get() .binary_search(&member_id) .is_ok() } - /// check if member is outgoing + /// Check if member is outgoing. fn is_outgoing(member_id: T::MemberId) -> bool { OutgoingAuthorities::<T>::get() .binary_search(&member_id) .is_ok() } - /// check if member is blacklisted + /// Check if member is blacklisted. fn is_blacklisted(member_id: T::MemberId) -> bool { Blacklist::<T>::get().contains(&member_id) } - /// perform removal from incoming authorities + /// Perform removal from incoming authorities. fn remove_in(member_id: T::MemberId) { IncomingAuthorities::<T>::mutate(|members_ids| { if let Ok(index) = members_ids.binary_search(&member_id) { @@ -474,7 +520,7 @@ pub mod pallet { }) } - /// perform removal from online authorities + /// Perform removal from online authorities. fn remove_online(member_id: T::MemberId) { OnlineAuthorities::<T>::mutate(|members_ids| { if let Ok(index) = members_ids.binary_search(&member_id) { @@ -483,7 +529,7 @@ pub mod pallet { }); } - /// perform removal from outgoing authorities + /// Perform removal from outgoing authorities. fn remove_out(member_id: T::MemberId) { OutgoingAuthorities::<T>::mutate(|members_ids| { if let Ok(index) = members_ids.binary_search(&member_id) { @@ -492,7 +538,7 @@ pub mod pallet { }); } - /// check that accountid is member + /// Check that account is member. fn verify_ownership_and_membership( who: &T::AccountId, ) -> Result<T::MemberId, DispatchError> { diff --git a/pallets/authority-members/src/types.rs b/pallets/authority-members/src/types.rs index bec91587a7c82061ffd27b1f6e5cdfd022fa1bba..577ed751b1ef4cbbed4190ed797d665cc5df72f6 100644 --- a/pallets/authority-members/src/types.rs +++ b/pallets/authority-members/src/types.rs @@ -21,10 +21,11 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; +/// Represents data associated with a member. #[cfg_attr(feature = "std", derive(Debug, Deserialize, Serialize))] #[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct MemberData<AccountId> { - /// pubkey of the member + /// Public key of the member. pub owner_key: AccountId, } diff --git a/pallets/certification/Cargo.toml b/pallets/certification/Cargo.toml index eff126ff965729be10b2f487ec5ffa34b6b54ac3..86a5b131e239d6d4c8f7844779a6c3f612ff6477 100644 --- a/pallets/certification/Cargo.toml +++ b/pallets/certification/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-certification" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/certification/README.md b/pallets/certification/README.md deleted file mode 100644 index a84e9f9eadc0250a756b32d0bfb1cf3e24c198bb..0000000000000000000000000000000000000000 --- a/pallets/certification/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Duniter certification pallet - -Duniter certifications are the *edges* in the Duniter [Web of Trust](../duniter-wot/). They can have different meanings: - -- in the case of the main WoT, they mean "I have met this person IRL and trust them" (see Äž1 Licence) -- in the case of the smith sub-WoT, they mean "I trust this person to be able to run Duniter securely" (see smith Licence) - -This pallet manages certifications creation, deletion... \ No newline at end of file diff --git a/pallets/certification/src/lib.rs b/pallets/certification/src/lib.rs index 01df9634942b863530bfe7f9fe57ee7e85e610a9..bd535195ee5ec17f942460d3c5f1fe572770f9e2 100644 --- a/pallets/certification/src/lib.rs +++ b/pallets/certification/src/lib.rs @@ -14,6 +14,15 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Certification Pallet +//! +//! This pallet manages certification creation and deletion. +//! +//! Duniter certifications are the *edges* in the Duniter [Web of Trust](../duniter-wot/). They can have different meanings: +//! +//! - In the case of the main WoT, they mean "I have met this person in real life and trust them" (see Äž1 Licence). +//! - In the case of the smith sub-WoT, they mean "I trust this person to be able to run Duniter securely" (see smith Licence). + #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "runtime-benchmarks")] @@ -58,10 +67,11 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { + /// The minimum duration (in blocks) between two certifications issued by the same issuer. #[pallet::constant] - /// Minimum duration between two certifications issued by the same issuer. type CertPeriod: Get<BlockNumberFor<Self>>; - /// A short identity index. + + /// A short identity index type. type IdtyIndex: Parameter + Member + AtLeast32BitUnsigned @@ -71,26 +81,36 @@ pub mod pallet { + MaybeSerializeDeserialize + Debug + MaxEncodedLen; - /// Something that gives the IdtyId of an AccountId and reverse + + /// A type that provides methods to get the IdtyIndex of an AccountId and vice versa. type IdtyAttr: duniter_primitives::Idty<Self::IdtyIndex, Self::AccountId>; - /// Provide method to check that cert is allowed. + + /// A type that provides a method to check if issuing a certification is allowed. type CheckCertAllowed: CheckCertAllowed<Self::IdtyIndex>; + + /// The maximum number of active certifications that can be issued by a single issuer. #[pallet::constant] - /// Maximum number of active certifications by issuer. type MaxByIssuer: Get<u32>; - /// Minimum number of certifications received to be allowed to issue a certification. + + /// The minimum number of certifications received that an identity must have + /// to be allowed to issue a certification. #[pallet::constant] type MinReceivedCertToBeAbleToIssueCert: Get<u32>; - /// Handler for NewCert event. + + /// A handler that is called when a new certification event (`NewCert`) occurs. type OnNewcert: OnNewcert<Self::IdtyIndex>; - /// Handler for Removed event. + + /// A handler that is called when a certification is removed (`RemovedCert`). type OnRemovedCert: OnRemovedCert<Self::IdtyIndex>; - /// Because this pallet emits events, it depends on the runtime's definition of an event. + + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// Type representing the weight of this pallet. + + /// Type representing the weight of this pallet type WeightInfo: WeightInfo; + + /// The duration (in blocks) for which a certification remains valid. #[pallet::constant] - /// Duration of validity of a certification. type ValidityPeriod: Get<BlockNumberFor<Self>>; } @@ -199,13 +219,13 @@ pub mod pallet { // STORAGE // - /// Certifications metada by issuer. + /// The certification metadata for each issuer. #[pallet::storage] #[pallet::getter(fn idty_cert_meta)] pub type StorageIdtyCertMeta<T: Config> = StorageMap<_, Twox64Concat, T::IdtyIndex, IdtyCertMeta<BlockNumberFor<T>>, ValueQuery>; - /// Certifications by receiver. + /// The certifications for each receiver. #[pallet::storage] #[pallet::getter(fn certs_by_receiver)] pub type CertsByReceiver<T: Config> = StorageMap< @@ -216,7 +236,7 @@ pub mod pallet { ValueQuery, >; - /// Certifications removable on. + /// The certifications that should expire at a given block. #[pallet::storage] #[pallet::getter(fn certs_removable_on)] pub type CertsRemovableOn<T: Config> = StorageMap< @@ -309,7 +329,9 @@ pub mod pallet { Ok(().into()) } - /// remove a certification (only root) + /// Remove one certification given the issuer and the receiver. + /// + /// - `origin`: Must be `Root`. #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::del_cert())] pub fn del_cert( @@ -322,7 +344,9 @@ pub mod pallet { Ok(().into()) } - /// remove all certifications received by an identity (only root) + /// Remove all certifications received by an identity. + /// + /// - `origin`: Must be `Root`. #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::remove_all_certs_received_by(CertsByReceiver::<T>::get(idty_index).len() as u32))] pub fn remove_all_certs_received_by( @@ -338,6 +362,7 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { + /// Perform removal of all certifications received by an identity. pub fn do_remove_all_certs_received_by(idty_index: T::IdtyIndex) -> Weight { let mut weight = T::DbWeight::get().reads_writes(1, 0); for (issuer, _) in CertsByReceiver::<T>::get(idty_index) { @@ -346,15 +371,17 @@ pub mod pallet { weight } - /// get issuer index from origin + /// Get the issuer index from the origin. pub fn origin_to_index(origin: OriginFor<T>) -> Result<T::IdtyIndex, DispatchError> { let who = ensure_signed(origin)?; T::IdtyAttr::idty_index(who).ok_or(Error::<T>::OriginMustHaveAnIdentity.into()) } - /// add a certification without checks - // this is used on identity creation to add the first certification - // The weight is approximated on the worst path. + /// Add a certification without performing checks. + /// + /// This function is used during identity creation to add the first certification without + /// validation checks. + // The weight is approximated based on the worst-case scenario path. pub fn do_add_cert_checked( issuer: T::IdtyIndex, receiver: T::IdtyIndex, @@ -371,7 +398,7 @@ pub mod pallet { Ok(().into()) } - /// perform cert addition if not existing, else CertAlreadyExists + /// Perform certification addition if it does not already exist, otherwise return `CertAlreadyExists`. // must be transactional fn try_add_cert( block_number: BlockNumberFor<T>, @@ -423,7 +450,7 @@ pub mod pallet { Ok(().into()) } - /// perform cert renewal if exisiting, else error with CertDoesNotExist + /// Perform certification renewal if it exists, otherwise return an error indicating `CertDoesNotExist`. // must be used in transactional context // (it can fail if certification does not exist after having modified state) fn try_renew_cert( @@ -455,7 +482,7 @@ pub mod pallet { Ok(().into()) } - /// remove the certifications due to expire on the given block + /// Remove certifications that are due to expire on the given block. // (run at on_initialize step) fn prune_certifications(block_number: BlockNumberFor<T>) -> Weight { // See on initialize for the overhead weight accounting @@ -473,9 +500,11 @@ pub mod pallet { weight } - /// perform the certification removal - /// if block number is given only remove cert if still set to expire at this block number - // this is used because cert expiry unscheduling is not done (#110) + /// Perform the certification removal. + /// + /// If a block number is provided, this function removes certifications only if they are still + /// scheduled to expire at that block number. + // This function is used because the unscheduling of certification expiry (#110) is not yet implemented. pub fn do_remove_cert( issuer: T::IdtyIndex, receiver: T::IdtyIndex, @@ -535,7 +564,7 @@ pub mod pallet { total_weight } - /// check cert allowed + /// Check if adding a certification is allowed. // 1. no self cert // 2. issuer received cert count // 3. issuer max emitted cert @@ -572,7 +601,7 @@ pub mod pallet { Ok(()) } - /// check cert allowed + /// Check if adding a certification is allowed. // first internal checks // then external checks fn check_add_cert( @@ -592,7 +621,7 @@ pub mod pallet { Ok(()) } - /// check renew cert allowed + /// Check if renewing a certification is allowed based. fn check_renew_cert( issuer: T::IdtyIndex, receiver: T::IdtyIndex, diff --git a/pallets/certification/src/traits.rs b/pallets/certification/src/traits.rs index ae6e37c0f2a1b15baf3658897559cdbd19d9fcc0..7ee7832d575f98d788c02627f18366608ea7b086 100644 --- a/pallets/certification/src/traits.rs +++ b/pallets/certification/src/traits.rs @@ -16,7 +16,9 @@ use frame_support::pallet_prelude::*; +/// Trait for checking if a certification is allowed between two identities. pub trait CheckCertAllowed<IdtyIndex> { + /// Check if the certification is allowed from the issuer to the receiver. fn check_cert_allowed(issuer: IdtyIndex, receiver: IdtyIndex) -> Result<(), DispatchError>; } @@ -26,7 +28,9 @@ impl<IdtyIndex> CheckCertAllowed<IdtyIndex> for () { } } +/// Trait for handling actions to take when a new certification is issued. pub trait OnNewcert<IdtyIndex> { + /// Called when a new certification is issued. fn on_new_cert( issuer: IdtyIndex, issuer_issued_count: u32, @@ -34,6 +38,7 @@ pub trait OnNewcert<IdtyIndex> { receiver_received_count: u32, ); } + impl<IdtyIndex> OnNewcert<IdtyIndex> for () { fn on_new_cert( _issuer: IdtyIndex, @@ -44,7 +49,9 @@ impl<IdtyIndex> OnNewcert<IdtyIndex> for () { } } +/// Trait for handling actions to take when a certification is removed. pub trait OnRemovedCert<IdtyIndex> { + /// Called when a certification is removed. fn on_removed_cert( issuer: IdtyIndex, issuer_issued_count: u32, @@ -53,6 +60,7 @@ pub trait OnRemovedCert<IdtyIndex> { expiration: bool, ); } + impl<IdtyIndex> OnRemovedCert<IdtyIndex> for () { fn on_removed_cert( _issuer: IdtyIndex, @@ -64,6 +72,8 @@ impl<IdtyIndex> OnRemovedCert<IdtyIndex> for () { } } +/// Trait for setting the next issuable block number for an identity. pub trait SetNextIssuableOn<BlockNumber, IdtyIndex> { + /// Set the next block number when the identity can issue a certification. fn set_next_issuable_on(idty_index: IdtyIndex, next_issuable_on: BlockNumber); } diff --git a/pallets/certification/src/types.rs b/pallets/certification/src/types.rs index 7eadcabc5ba714f2d1d5a130fb94f79d79c5a24b..5a158f8a9aa9805df642eb1ed51be3a6c76cd1ea 100644 --- a/pallets/certification/src/types.rs +++ b/pallets/certification/src/types.rs @@ -20,14 +20,14 @@ use codec::{Decode, Encode}; use frame_support::pallet_prelude::*; use scale_info::TypeInfo; -/// certification metadata attached to an identity +/// Represents the certification metadata attached to an identity. #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct IdtyCertMeta<BlockNumber: Default> { - /// count issued certifications + /// Number of certifications issued by this identity. pub issued_count: u32, - /// block before which identity not allowed to issue a new certification + /// Block number before which the identity is not allowed to issue a new certification. pub next_issuable_on: BlockNumber, - /// number of certifications received + /// Number of certifications received by this identity. pub received_count: u32, } diff --git a/pallets/distance/Cargo.toml b/pallets/distance/Cargo.toml index a878035017afde01f5de90b182930280123502fd..447ffca742d1362a1dd76f3cba074b54614eab97 100644 --- a/pallets/distance/Cargo.toml +++ b/pallets/distance/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-distance" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/distance/README.md b/pallets/distance/README.md deleted file mode 100644 index d34bdb64604a138c1c2717b67db4e7cbba6999bc..0000000000000000000000000000000000000000 --- a/pallets/distance/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Distance pallet - -The distance pallet uses results provided in a file by the `distance-oracle` offchain worker. -At some point an inherent is called to submit the results of this file to the blockchain. -The pallet then selects the median of the results (reach perbill) of an evaluation pool and fills the storage with the result status. -The status of an identity can be: - -- inexistant: distance evaluation has not been requested or has expired -- pending: distance evaluation for this identity has been requested and is waiting two evaluation periods for results -- valid: distance has been evaluated positively for this identity - -The result of the evaluation is used by `duniter-wot` pallet to determine if an identity can get / should loose membership to the web of trust. - -## Process - -Any account can request a distance evaluation for a given identity provided it has enough currency to be reserved. In this case, the distance status is marked as pending and in the next evaluation period, inherents can start to publish results. - -This is how a result is published: - -1. local worker creates a file containing the result of computation -1. inherent is created with the data from this file -1. author is registered as an evaluator -1. the result is added to the current evaluation pool -1. a flag is set to prevent other distance evaluation in the same block - -On each new evaluation period: - -1. old results set to expire at this period do expire -1. results from the current pool (previous period's result pool) are taken and for each identity - - the median of the distance results for this identity is chosen - - if the distance is ok, the distance is marked as valid - - if the distance is ko, the result for this identity is removed and reserved currency is slashed (from the account which requested the evaluation) - -Then, in other pallets, when a membership is claimed, it is possible to look if there is a valid evaluation of distance for this identity. - -## Pools - -Evaluation pools are made of two components: - -- a set of evaluators -- a vec of results - -The evaluation are separated in three pools: - -- pool number N - 1 % 3: results from the previous evaluation period used in the current one (let empty for next evaluation period) -- pool number N + 0 % 3: inherent results are added there -- pool number N + 1 % 3: identities are added there for evaluation diff --git a/pallets/distance/src/lib.rs b/pallets/distance/src/lib.rs index b52e2bb084db727aa30568f5a4d90aaacc2e6006..e7e42dff2f181e56c83734446d6c9c5ff4804f3a 100644 --- a/pallets/distance/src/lib.rs +++ b/pallets/distance/src/lib.rs @@ -14,6 +14,54 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Distance Pallet +//! +//! The distance pallet utilizes results provided in a file by the `distance-oracle` offchain worker. +//! At a some point, an inherent is called to submit the results of this file to the blockchain. +//! The pallet then selects the median of the results (reach perbill) from an evaluation pool and fills the storage with the result status. +//! The status of an identity can be: +//! +//! - **Non-existent**: Distance evaluation has not been requested or has expired. +//! - **Pending**: Distance evaluation for this identity has been requested and is awaiting results after two evaluation periods. +//! - **Valid**: Distance has been evaluated positively for this identity. +//! +//! The evaluation result is used by the `duniter-wot` pallet to determine if an identity can gain or should lose membership in the web of trust. +//! +//! ## Process +//! +//! Any account can request a distance evaluation for a given identity provided it has enough currency to reserve. In this case, the distance status is marked as pending, and in the next evaluation period, inherents can start to publish results. +//! +//! This is the process for publishing a result: +//! +//! 1. A local worker creates a file containing the computation result. +//! 2. An inherent is created with the data from this file. +//! 3. The author is registered as an evaluator. +//! 4. The result is added to the current evaluation pool. +//! 5. A flag is set to prevent other distance evaluations in the same block. +//! +//! At the start of each new evaluation period: +//! +//! 1. Old results set to expire at this period are removed. +//! 2. Results from the current pool (results from the previous period's pool) are processed, and for each identity: +//! - The median of the distance results for this identity is chosen. +//! - If the distance is acceptable, it is marked as valid. +//! - If the distance is not acceptable, the result for this identity is discarded, and reserved currency is slashed (from the account which requested the evaluation). +//! +//! Then, in other pallets, when a membership is claimed, it is possible to check if there is a valid distance evaluation for this identity. +//! +//! ## Pools +//! +//! Evaluation pools consist of two components: +//! +//! - A set of evaluators. +//! - A vector of results. +//! +//! The evaluations are divided into three pools: +//! +//! - Pool number N - 1 % 3: Results from the previous evaluation period used in the current one (emptied for the next evaluation period). +//! - Pool number N + 0 % 3: Inherent results are added here. +//! - Pool number N + 1 % 3: Identities are added here for evaluation. + #![cfg_attr(not(feature = "std"), no_std)] mod median; @@ -82,40 +130,49 @@ pub mod pallet { + pallet_authorship::Config + pallet_identity::Config<IdtyIndex = IdtyIndex> { - /// Currency type used in this pallet (used for reserve/slash) + /// Currency type used in this pallet for reserve and slash operations. type Currency: Mutate<Self::AccountId> + MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason> + Balanced<Self::AccountId>; - /// Overarching hold reason. + + /// The overarching hold reason type. type RuntimeHoldReason: From<HoldReason>; - /// Amount reserved during evaluation + + /// The amount reserved during evaluation. #[pallet::constant] type EvaluationPrice: Get<BalanceOf<Self>>; - /// Evaluation period number of blocks. - /// As the evaluation is done using 3 pools, - /// the evaluation will take 3 * EvaluationPeriod. + + /// The evaluation period in blocks. + /// Since the evaluation uses 3 pools, the total evaluation time will be 3 * EvaluationPeriod. #[pallet::constant] type EvaluationPeriod: Get<u32>; - /// Maximum distance used to define referee's accessibility - /// Unused by runtime but needed by client distance oracle + + /// The maximum distance used to define a referee's accessibility. + /// This value is not used by the runtime but is needed by the client distance oracle. #[pallet::constant] type MaxRefereeDistance: Get<u32>; - /// Minimum ratio of accessible referees + + /// The minimum ratio of accessible referees required. #[pallet::constant] type MinAccessibleReferees: Get<Perbill>; + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; + /// Type representing the weight of this pallet type WeightInfo: WeightInfo; - /// Handler for successful distance evaluation + + /// A handler that is called when a distance evaluation is successfully validated. type OnValidDistanceStatus: OnValidDistanceStatus<Self>; - /// Trait to check that distance evaluation request is allowed + + /// A trait that provides a method to check if a distance evaluation request is allowed. type CheckRequestDistanceEvaluation: CheckRequestDistanceEvaluation<Self>; } // STORAGE // - /// Identities queued for distance evaluation + /// The first evaluation pool for distance evaluation queuing identities to evaluate for a given + /// evaluator account. #[pallet::storage] #[pallet::getter(fn evaluation_pool_0)] pub type EvaluationPool0<T: Config> = StorageValue< @@ -126,7 +183,9 @@ pub mod pallet { >, ValueQuery, >; - /// Identities queued for distance evaluation + + /// The second evaluation pool for distance evaluation queuing identities to evaluate for a given + /// evaluator account. #[pallet::storage] #[pallet::getter(fn evaluation_pool_1)] pub type EvaluationPool1<T: Config> = StorageValue< @@ -137,7 +196,9 @@ pub mod pallet { >, ValueQuery, >; - /// Identities queued for distance evaluation + + /// The third evaluation pool for distance evaluation queuing identities to evaluate for a given + /// evaluator account. #[pallet::storage] #[pallet::getter(fn evaluation_pool_2)] pub type EvaluationPool2<T: Config> = StorageValue< @@ -149,15 +210,12 @@ pub mod pallet { ValueQuery, >; - /// Block for which the distance rule must be checked + /// The block at which the distance is evaluated. #[pallet::storage] pub type EvaluationBlock<T: Config> = StorageValue<_, <T as frame_system::Config>::Hash, ValueQuery>; - /// Pending evaluation requesters - /// - /// account who requested an evaluation and reserved the price, - /// for whom the price will be unreserved or slashed when the evaluation completes. + /// The pending evaluation requesters. #[pallet::storage] #[pallet::getter(fn pending_evaluation_request)] pub type PendingEvaluationRequest<T: Config> = StorageMap< @@ -168,11 +226,11 @@ pub mod pallet { OptionQuery, >; - /// Did evaluation get updated in this block? + /// Store if the evaluation was updated in this block. #[pallet::storage] pub(super) type DidUpdate<T: Config> = StorageValue<_, bool, ValueQuery>; - /// Current evaluation pool. + /// The current evaluation pool index. #[pallet::storage] #[pallet::getter(fn current_pool_index)] pub(super) type CurrentPoolIndex<T: Config> = StorageValue<_, u32, ValueQuery>; @@ -257,9 +315,11 @@ pub mod pallet { #[pallet::call] impl<T: Config> Pallet<T> { - /// Request caller identity to be evaluated - /// positive evaluation will result in claim/renew membership - /// negative evaluation will result in slash for caller + /// Request evaluation of the caller's identity distance. + /// + /// This function allows the caller to request an evaluation of their distance. + /// A positive evaluation will lead to claiming or renewing membership, while a negative + /// evaluation will result in slashing for the caller. #[pallet::call_index(0)] #[pallet::weight(<T as pallet::Config>::WeightInfo::request_distance_evaluation())] pub fn request_distance_evaluation(origin: OriginFor<T>) -> DispatchResultWithPostInfo { @@ -271,8 +331,10 @@ pub mod pallet { Ok(().into()) } - /// Request target identity to be evaluated - /// only possible for unvalidated identity + /// Request evaluation of a target identity's distance. + /// + /// This function allows the caller to request an evaluation of a specific target identity's distance. + /// This action is only permitted for unvalidated identities. #[pallet::call_index(4)] #[pallet::weight(<T as pallet::Config>::WeightInfo::request_distance_evaluation_for())] pub fn request_distance_evaluation_for( @@ -287,8 +349,10 @@ pub mod pallet { Ok(().into()) } - /// (Inherent) Push an evaluation result to the pool - /// this is called internally by validators (= inherent) + /// Push an evaluation result to the pool. + /// + /// This inherent function is called internally by validators to push an evaluation result + /// to the evaluation pool. #[pallet::call_index(1)] #[pallet::weight(<T as pallet::Config>::WeightInfo::update_evaluation(MAX_EVALUATIONS_PER_SESSION))] pub fn update_evaluation( @@ -309,8 +373,11 @@ pub mod pallet { Ok(()) } - /// Force push an evaluation result to the pool - // (it is convenient to have this call in end2end tests) + /// Force push an evaluation result to the pool. + /// + /// It is primarily used for testing purposes. + /// + /// - `origin`: Must be `Root`. #[pallet::call_index(2)] #[pallet::weight(<T as pallet::Config>::WeightInfo::force_update_evaluation(MAX_EVALUATIONS_PER_SESSION))] pub fn force_update_evaluation( @@ -323,8 +390,11 @@ pub mod pallet { Pallet::<T>::do_update_evaluation(evaluator, computation_result) } - /// Force set the distance evaluation status of an identity - // (it is convenient to have this in test network) + /// Force set the distance evaluation status of an identity. + /// + /// It is primarily used for testing purposes. + /// + /// - `origin`: Must be `Root`. #[pallet::call_index(3)] #[pallet::weight(<T as pallet::Config>::WeightInfo::force_valid_distance_status())] pub fn force_valid_distance_status( @@ -364,7 +434,7 @@ pub mod pallet { } } - /// Mutate the evaluation pool containing the results sent by evaluators on this period. + /// Mutate the evaluation pool containing the results sent by evaluators for this period. fn mutate_next_pool< R, F: FnOnce( @@ -385,7 +455,7 @@ pub mod pallet { } } - /// Take (and leave empty) the evaluation pool containing: + /// Take (*and leave empty*) the evaluation pool containing: /// * when this period begins: the evaluation results to be applied. /// * when this period ends: the evaluation requests. #[allow(clippy::type_complexity)] @@ -403,7 +473,7 @@ pub mod pallet { } } - /// check that request distance evaluation is allowed + /// Check if requested distance evaluation is allowed. fn check_request_distance_evaluation_self( who: &T::AccountId, ) -> Result<<T as pallet_identity::Config>::IdtyIndex, DispatchError> { @@ -465,7 +535,7 @@ pub mod pallet { T::CheckRequestDistanceEvaluation::check_request_distance_evaluation(target) } - /// request distance evaluation in current pool + /// Request distance evaluation in the current pool. fn do_request_distance_evaluation( who: &T::AccountId, idty_index: <T as pallet_identity::Config>::IdtyIndex, @@ -498,7 +568,7 @@ pub mod pallet { }) } - /// update distance evaluation in next pool + /// Update distance evaluation in the next pool. fn do_update_evaluation( evaluator: <T as frame_system::Config>::AccountId, computation_result: ComputationResult, @@ -532,7 +602,7 @@ pub mod pallet { }) } - /// Set the distance status using IdtyIndex and AccountId + /// Set the distance status using for an identity. pub fn do_valid_distance_status( idty: <T as pallet_identity::Config>::IdtyIndex, distance: Perbill, @@ -546,6 +616,13 @@ pub mod pallet { }); } + /// Perform evaluation for a specified pool. + /// + /// This function executes evaluation logic based on the provided pool index. It retrieves the current + /// evaluation pool for the index, processes each evaluation, and handles the outcomes based on the + /// computed median distances. If a positive evaluation result is obtained, it releases reserved funds + /// and updates the distance status accordingly. For negative or inconclusive results, it slashes funds + /// or releases them, respectively. pub fn do_evaluation(index: u32) -> Weight { let mut weight = <T as pallet::Config>::WeightInfo::do_evaluation_overhead(); // set evaluation block diff --git a/pallets/distance/src/median.rs b/pallets/distance/src/median.rs index feab0d863176a4d24e33b85856717346a1ec29a7..5569d6f26984e09b292b081071cb7378ab5ab12e 100644 --- a/pallets/distance/src/median.rs +++ b/pallets/distance/src/median.rs @@ -17,6 +17,7 @@ use frame_support::pallet_prelude::*; use sp_std::cmp::Ordering; +/// Represents a median accumulator. #[derive(Clone, Debug, Decode, Default, Encode, TypeInfo)] pub struct MedianAcc< T: Clone + Decode + Encode + Ord + TypeInfo, @@ -35,6 +36,7 @@ pub struct MedianAcc< fn type_info() -> scale_info::Type<scale_info::form::MetaForm> {} }*/ +/// Represents the result of a median calculation. #[derive(Clone, Debug, Eq, PartialEq)] pub enum MedianResult<T: Clone + Ord> { One(T), diff --git a/pallets/distance/src/traits.rs b/pallets/distance/src/traits.rs index 6849d9c250c29421bffb67f4d52c0cf626271a59..8313abcf9437e0b2ffb53c7ac2c603620c162065 100644 --- a/pallets/distance/src/traits.rs +++ b/pallets/distance/src/traits.rs @@ -17,8 +17,9 @@ use crate::*; use frame_support::pallet_prelude::*; +/// Trait for handling actions when an identity has a valid distance status. pub trait OnValidDistanceStatus<T: Config> { - /// Handler for valid distance evaluation + /// Called when an identity has been determined to have a valid distance status. fn on_valid_distance_status(idty_index: T::IdtyIndex); } @@ -26,7 +27,9 @@ impl<T: Config> OnValidDistanceStatus<T> for () { fn on_valid_distance_status(_idty_index: T::IdtyIndex) {} } +/// Trait for checking if a request for distance evaluation is allowed. pub trait CheckRequestDistanceEvaluation<T: Config> { + /// Check if the request for distance evaluation is allowed for the given identity. fn check_request_distance_evaluation(idty_index: T::IdtyIndex) -> Result<(), DispatchError>; } diff --git a/pallets/distance/src/types.rs b/pallets/distance/src/types.rs index cb9f32924f8f2a2be96ba987fe06d7378886ff2f..63408283bff888466c071aa7f65ee3ad9d32f46d 100644 --- a/pallets/distance/src/types.rs +++ b/pallets/distance/src/types.rs @@ -21,31 +21,30 @@ use codec::{Decode, Encode}; use frame_support::pallet_prelude::*; use sp_runtime::Perbill; -/// Status of the distance evaluation of an identity +/// Status of the distance evaluation of an identity. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum DistanceStatus { /// Identity is in evaluation. Pending, - /// Identity respects the distance + /// Identity respects the distance. Valid, - /// Identity doesn't respect the distance + /// Identity doesn't respect the distance. Invalid, } -/// Pool where distance evaluation requests and results are stored +/// Represents a pool where distance evaluation requests and results are stored. /// -/// Depending on the pool rotation, this may not be complete, and still be accepting -/// new evaluation requests (with empty median accumulators) or new evaluations (with evaluators -/// and new samples in the median accumulators). +/// Depending on the pool rotation, this may not be complete and may still be accepting +/// new evaluation requests (with empty median accumulators) or new evaluations (with evaluators and new samples in the median accumulators). #[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo)] pub struct EvaluationPool<AccountId: Ord, IdtyIndex> { - /// List of identities with their evaluation result + /// List of identities with their evaluation result. /// The result is the median of all the evaluations. pub evaluations: BoundedVec< (IdtyIndex, MedianAcc<Perbill, MAX_EVALUATORS_PER_SESSION>), ConstU32<MAX_EVALUATIONS_PER_SESSION>, >, - /// Evaluators who have published a result + /// Evaluators who have published a result. /// Its length should be the same as the number of samples /// in each evaluation result `MedianAcc`. /// An evaluator is not allowed to publish twice in a single session. diff --git a/pallets/duniter-account/Cargo.toml b/pallets/duniter-account/Cargo.toml index 6b0737d783019605791004815da0c68f28097bd4..d09510ebca0b89865b1a21f6376fed6a134653e9 100644 --- a/pallets/duniter-account/Cargo.toml +++ b/pallets/duniter-account/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-duniter-account" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/duniter-account/README.md b/pallets/duniter-account/README.md deleted file mode 100644 index 185e37ce5496a348698d413f9166637a41a22692..0000000000000000000000000000000000000000 --- a/pallets/duniter-account/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Duniter account pallet - -Duniter customizes the `AccountData` of the `Balances` Substrate pallet. In particular, it adds the field `linked_idty`. - -## Account creation fee - -DuniterAccount defines a creation fee that is preleved to the account one block after its creation. This fee goes to the treasury. - -## Sufficient - -DuniterAccount tweaks the substrate AccountInfo to allow identity accounts to exist without existential deposit. This allows to spare the creation fee. - -## Linked identity - -Duniter offers the possibility to link an account to an identity with the `linked_idty` field. It allows to request refund of transaction fees in `OnChargeTransaction`. \ No newline at end of file diff --git a/pallets/duniter-account/src/lib.rs b/pallets/duniter-account/src/lib.rs index 76209d0427d0cb2bcb5ede65795a0796d594ba5e..be8a98e7ecbb55ab3fb327808258b64a316b3ba7 100644 --- a/pallets/duniter-account/src/lib.rs +++ b/pallets/duniter-account/src/lib.rs @@ -14,7 +14,20 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. -// Note: refund queue mechanism is inspired from frame contract +//! # Duniter Account Pallet +//! +//! Duniter customizes the `AccountData` of the `Balances` Substrate pallet to include additional fields +//! such as `linked_idty`. +//! +//! ## Sufficiency +//! +//! DuniterAccount adjusts the Substrate `AccountInfo` to accommodate identity-linked accounts without requiring +//! an existential deposit. This flexibility helps reduce barriers to account creation. +//! +//! ## Linked Identity +//! +//! Duniter allows accounts to be linked to identities using the `linked_idty` field. This linkage facilitates +//! transaction fee refunds through the `OnChargeTransaction` mechanism. #![cfg_attr(not(feature = "std"), no_std)] @@ -74,11 +87,14 @@ pub mod pallet { { /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// Type representing the weight of this pallet + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; - /// wrapped type + + /// A wrapped type that handles the charging of transaction fees. type InnerOnChargeTransaction: OnChargeTransaction<Self>; - /// type implementing refund behavior + + /// A type that implements the refund behavior for transaction fees. type Refund: pallet_quota::traits::RefundFee<Self>; } @@ -165,7 +181,7 @@ pub mod pallet { // CALLS // #[pallet::call] impl<T: Config> Pallet<T> { - /// unlink the identity associated with the account + /// Unlink the identity associated with the account. #[pallet::call_index(0)] #[pallet::weight(<T as pallet::Config>::WeightInfo::unlink_identity())] pub fn unlink_identity(origin: OriginFor<T>) -> DispatchResultWithPostInfo { @@ -177,7 +193,7 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { - /// unlink account + /// Unlink the account from its associated identity. pub fn do_unlink_identity(account_id: T::AccountId) { // no-op if account already linked to nothing frame_system::Account::<T>::mutate(&account_id, |account| { @@ -188,7 +204,7 @@ pub mod pallet { }) } - /// link account to identity + /// Link an account to an identity. pub fn do_link_identity(account_id: &T::AccountId, idty_id: IdtyIdOf<T>) { // no-op if identity does not change if frame_system::Account::<T>::get(account_id).data.linked_idty != Some(idty_id) { diff --git a/pallets/duniter-account/src/types.rs b/pallets/duniter-account/src/types.rs index c44cb08734204b753a4fe1852b86c337d2de0160..5e25ff783ff660b2b5d9465c5938a0e691cab7dc 100644 --- a/pallets/duniter-account/src/types.rs +++ b/pallets/duniter-account/src/types.rs @@ -19,18 +19,18 @@ use frame_support::pallet_prelude::*; use scale_info::TypeInfo; use sp_runtime::traits::Zero; -// see `struct AccountData` for details in substrate code +/// Account data structure. +/// +/// For details, refer to `struct AccountData` in Substrate code. #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] // Default, pub struct AccountData<Balance, IdtyId> { - // see Substrate AccountData + /// Free balance of the account. pub(super) free: Balance, - // see Substrate AccountData + /// Reserved balance of the account. pub(super) reserved: Balance, - // see Substrate AccountData + /// Frozen fee balance of the account. fee_frozen: Balance, - /// an optional pointer to an identity - // used to know if this account is linked to a member - // used in quota system to refund fees + /// Optional pointer to an identity used to determine if this account is linked to a member and in the quota system for fee refunds. pub linked_idty: Option<IdtyId>, } diff --git a/pallets/duniter-test-parameters/README.md b/pallets/duniter-test-parameters/README.md deleted file mode 100644 index 80a352ff46980635c72de80029cedc324ea6da30..0000000000000000000000000000000000000000 --- a/pallets/duniter-test-parameters/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Duniter test parameters - -This pallet allows ÄžDev runtime to tweak parameter values instead of having it runtime constants. \ No newline at end of file diff --git a/pallets/duniter-test-parameters/src/lib.rs b/pallets/duniter-test-parameters/src/lib.rs index 39775e7c42ecbefd0f8e6569dbdc3efff91ab8e9..346a8823035c4707e5f209f865bcdd05122f08f7 100644 --- a/pallets/duniter-test-parameters/src/lib.rs +++ b/pallets/duniter-test-parameters/src/lib.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Test Parameters Pallet +//! +//! This pallet allows ÄžDev runtime to tweak parameter values instead of having it as runtime constants. + #![cfg_attr(not(feature = "std"), no_std)] pub use pallet::*; diff --git a/pallets/duniter-wot/Cargo.toml b/pallets/duniter-wot/Cargo.toml index dd247896ebd67929680cdc85cc248b684023a654..1b8885b78d805bd6d17ac55998a97085f084acb3 100644 --- a/pallets/duniter-wot/Cargo.toml +++ b/pallets/duniter-wot/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-duniter-wot" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/duniter-wot/README.md b/pallets/duniter-wot/README.md deleted file mode 100644 index 4ac1baf7bc13165d1eb323ea5ef82018492e08a3..0000000000000000000000000000000000000000 --- a/pallets/duniter-wot/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Duniter Web of Trust pallet - -Duniter WoT is at the core of its identity system and is a big improvement compared to PGP WoT. It is a dynamic directed graph whose nodes are [identities](../identity/) and edges [certifications](../certification/). - -There are two instances: - -- the main WoT, for every human -- the smith sub-WoT, for authorities - -It has both static and dynamic rules, controlling the condition to join and remain [member](../membership/). - -- static rules - - minimum number of received certifications (min indegree) - - maximum number of emited certifications (max outdegree) - - distance criterion (see distance pallet) -- dynamic rules - - time interval between two certifications - - certification duration (see certification pallet) - - membership renewal (see membership pallet) - -This pallet's main role is to check the Web of Trust rules. \ No newline at end of file diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs index 0abf864d596aca0f4e9b26a882f3e96d6e085c53..ef8d51f1f0f98b9fee6b2db9449db8f444a2115a 100644 --- a/pallets/duniter-wot/src/lib.rs +++ b/pallets/duniter-wot/src/lib.rs @@ -14,6 +14,35 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Web of Trust Pallet +//! +//! Duniter Web of Trust (WoT) lies at the heart of its identity system, representing a significant improvement over PGP Web of Trust. It functions as a dynamic directed graph where nodes are [identities](../identity/) and edges are [certifications](../certification/). +//! +//! ## Instances +//! +//! Duniter WoT consists of two distinct instances: +//! +//! - **Main WoT**: Designed for every human participant in the Duniter network. +//! - **Smith Sub-WoT**: Intended for authorities. +//! +//! ## Rules +//! +//! The Duniter WoT operates under a set of static and dynamic rules that govern membership conditions. +//! +//! ### Static Rules +//! +//! - **Minimum Received Certifications (Min Indegree)**: Specifies the minimum number of certifications an identity must receive to join the WoT. +//! - **Maximum Emitted Certifications (Max Outdegree)**: Limits the maximum number of certifications an identity can issue. +//! - **Distance Criterion**: Governed by the distance pallet, it defines the permissible distance between identities within the WoT graph. +//! +//! ### Dynamic Rules +//! +//! - **Time Interval Between Certifications**: Sets the minimum time interval required between two consecutive certifications issued by the same identity. +//! - **Certification Duration**: Managed by the certification pallet, it determines the validity duration of a certification. +//! - **Membership Renewal**: Regulates the frequency and conditions under which an identity must renew its membership within the WoT. +//! +//! This pallet is responsible for enforcing and validating the rules of the Duniter Web of Trust. It ensures compliance with both static prerequisites for joining and dynamic conditions for ongoing participation. + #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::type_complexity)] @@ -23,11 +52,6 @@ mod mock; #[cfg(test)] mod tests; -pub mod traits; - -/*#[cfg(feature = "runtime-benchmarks")] -mod benchmarking;*/ - pub use pallet::*; use frame_support::pallet_prelude::*; @@ -59,10 +83,15 @@ pub mod pallet { + pallet_identity::Config<IdtyIndex = IdtyIndex> + pallet_membership::Config<IdtyId = IdtyIndex> { + /// The block number from which the first certification can be issued. #[pallet::constant] type FirstIssuableOn: Get<frame_system::pallet_prelude::BlockNumberFor<Self>>; + + /// The minimum number of certifications required for membership eligibility. #[pallet::constant] type MinCertForMembership: Get<u32>; + + /// The minimum number of certifications required to create an identity. #[pallet::constant] type MinCertForCreateIdtyRight: Get<u32>; } diff --git a/pallets/duniter-wot/src/traits.rs b/pallets/duniter-wot/src/traits.rs deleted file mode 100644 index f3474822b34656f1c99a9b12d34a548316c87941..0000000000000000000000000000000000000000 --- a/pallets/duniter-wot/src/traits.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2023 Axiom-Team -// -// This file is part of Duniter-v2S. -// -// Duniter-v2S is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, version 3 of the License. -// -// Duniter-v2S is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. diff --git a/pallets/identity/Cargo.toml b/pallets/identity/Cargo.toml index c62eaa2cc27b01629d44e80d31be52f7489fc924..bdf37b8d64c346502862aa494f4759f4fb2538ef 100644 --- a/pallets/identity/Cargo.toml +++ b/pallets/identity/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-identity" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/identity/README.md b/pallets/identity/README.md deleted file mode 100644 index e8da9f126f9ff87610106d9323a479af506881e1..0000000000000000000000000000000000000000 --- a/pallets/identity/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Duniter identity pallet - -Duniter has a builtin identity system that does not work with external registrar compared to [parity identity pallet](https://github.com/paritytech/substrate/tree/master/frame/identity). - -## Duniter identity - -A Duniter identity contains: - -- its **owner key** (that can change) -- an optional **old owner key** with the date of the key change -- a **status** that can be - - unconfirmed (created by a member identity) - - unvalidated (confirmed by owner = given a name) - - member (of the main wot) - - notmember (of the main wot) - - revoked (automatically of manually) - -It also contains: - -- the block number at which it can emit its **next certification** (TODO distinguish next certification and next identity creation) -- the block number at which it can be **removed from storage** - -It also contains attached data defined by the runtime that can be for example - -- the number of the first UD it is eligible to - -### Name - -Each identity is declared with a name emited on confirmation event. Duniter keeps a list of identity names hash to ensure unicity. - -### Owner key - -The idea of the owner key is to allow the user to keep a fixed identity while changing the keys for security reasons. For example when a device with the keys might have been compromised. There is a limit to the frequency of owner key change and the old owner key can still revoke the identity for a given period. - -### Status / removable date - -The status is a temporary value allowing to prune identities before they become member. When an identity is not valiated (not member of the WoT for instance), it can be removed when the date is reached. The remove date of a validated identity is block zero. - -### Next certification - -The next certification is a rate limit to the emission of certification (and then identity creation). - -### Revokation - -Revoking an identity basically means deleting it. diff --git a/pallets/identity/src/lib.rs b/pallets/identity/src/lib.rs index f41a81e4693c8ebaf5cb915dda00e52b649cabd4..d306d9ca5f079acb988c8cc5ca4bcff44435e203 100644 --- a/pallets/identity/src/lib.rs +++ b/pallets/identity/src/lib.rs @@ -14,6 +14,43 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Identity Pallet +//! +//! Duniter features a built-in identity system that does not rely on external registrars, unlike the [Parity Identity Pallet](https://github.com/paritytech/substrate/tree/master/frame/identity). +//! +//! ## Duniter Identity Structure +//! +//! A Duniter identity comprises several key components: +//! +//! ### Name +//! +//! Each identity is declared with a name emitted during the confirmation event. Duniter maintains a hashed list of identity names to ensure uniqueness. +//! +//! ### Owner Key +//! +//! The owner key allows users to maintain a fixed identity while changing keys for security reasons, such as when a device with the keys might have been compromised. Changes are subject to frequency limits, and the old owner key can still revoke the identity for a given period. +//! +//! ### Status / Removable Date +//! +//! The status is a temporary value that allows pruning of identities before they become full members: +//! - **Unconfirmed**: Created by a member identity but not yet confirmed by the owner. +//! - **Unvalidated**: Confirmed by the owner, including assignment of a name. +//! - **Member**: Part of the main Web of Trust (WoT). +//! - **NotMember**: Not part of the main WoT. +//! - **Revoked**: Automatically or manually revoked. +//! +//! An identity that is not yet validated (e.g., not a member of the WoT) can be removed when its removable date is reached. The removable date of a validated identity is set to block zero. +//! +//! ### Next Certification +//! +//! The next certification specifies the block number from which the identity can issue its next certification, acting as a rate limit for certification issuance and identity creation. +//! +//! ### Revocation +//! +//! Revoking an identity essentially means deleting it from the system. +//! +//! Additional runtime-defined data may also be attached to identities, such the number of the first Universal Dividends (UD) it is eligible to. + #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::type_complexity)] @@ -65,34 +102,37 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - /// Period during which the owner can confirm the new identity. - // something like 2 days but this should be done quickly as the first certifier is helping + /// The period during which the owner can confirm the new identity. #[pallet::constant] type ConfirmPeriod: Get<BlockNumberFor<Self>>; - /// Period before which the identity has to be validated (become member). - // this is the 2 month period in v1 + + /// The period during which the identity has to be validated to become a member. #[pallet::constant] type ValidationPeriod: Get<BlockNumberFor<Self>>; - /// Period before which an identity who lost membership is automatically revoked. - // this is the 1 year period in v1 + + /// The period before which an identity that lost membership is automatically revoked. #[pallet::constant] type AutorevocationPeriod: Get<BlockNumberFor<Self>>; - /// Period after which a revoked identity is removed and the keys are freed. + + /// The period after which a revoked identity is removed and the keys are freed. #[pallet::constant] type DeletionPeriod: Get<BlockNumberFor<Self>>; - /// Minimum duration between two owner key changes. - // to avoid stealing the identity without means to revoke + + /// The minimum duration between two owner key changes to prevent identity theft. #[pallet::constant] type ChangeOwnerKeyPeriod: Get<BlockNumberFor<Self>>; - /// Minimum duration between the creation of 2 identities by the same creator. - // it should be greater or equal than the certification period in certification pallet + + /// The minimum duration between the creation of two identities by the same creator. + /// Should be greater than or equal to the certification period defined in the certification pallet. #[pallet::constant] type IdtyCreationPeriod: Get<BlockNumberFor<Self>>; - /// Management of the authorizations of the different calls. - /// The default implementation allows everything. + + /// Management of the authorizations of the different calls related to identity. type CheckIdtyCallAllowed: CheckIdtyCallAllowed<Self>; + /// The type used to check account worthiness. type CheckAccountWorthiness: CheckAccountWorthiness<Self>; + /// Custom data to store in each identity. type IdtyData: Clone + Codec @@ -101,7 +141,8 @@ pub mod pallet { + TypeInfo + MaybeSerializeDeserialize + MaxEncodedLen; - /// A short identity index. + + /// A short identity index type. type IdtyIndex: Parameter + Member + AtLeast32BitUnsigned @@ -111,20 +152,28 @@ pub mod pallet { + MaybeSerializeDeserialize + Debug + MaxEncodedLen; - /// Custom type for account data. + + /// A type for linking account data to identity. type AccountLinker: LinkIdty<Self::AccountId, Self::IdtyIndex>; - /// Handle logic to validate an identity name + + /// Handle logic to validate an identity name. type IdtyNameValidator: IdtyNameValidator; - /// On identity created. + + /// Handler called when a new identity is created. type OnNewIdty: OnNewIdty<Self>; - /// On identity removed. + + /// Handler called when an identity is removed. type OnRemoveIdty: OnRemoveIdty<Self>; - /// Signing key of a payload + + /// Signing key type used for payload signatures. type Signer: IdentifyAccount<AccountId = Self::AccountId>; - /// Signature of a payload + + /// Signature type for payload verification. type Signature: Parameter + Verify<Signer = Self::Signer>; - /// Because this pallet emits events, it depends on the runtime's definition of an event. + + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; + /// Type representing the weight of this pallet type WeightInfo: WeightInfo; } @@ -190,7 +239,7 @@ pub mod pallet { // STORAGE // - /// maps identity index to identity value + /// The identity value for each identity. #[pallet::storage] #[pallet::getter(fn identity)] pub type Identities<T: Config> = CountedStorageMap< @@ -201,23 +250,23 @@ pub mod pallet { OptionQuery, >; - /// maps account id to identity index + /// The identity associated with each account. #[pallet::storage] #[pallet::getter(fn identity_index_of)] pub type IdentityIndexOf<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, T::IdtyIndex, OptionQuery>; - /// maps identity name to identity index (simply a set) + /// The name associated with each identity. #[pallet::storage] #[pallet::getter(fn identity_by_did)] pub type IdentitiesNames<T: Config> = StorageMap<_, Blake2_128Concat, IdtyName, T::IdtyIndex, OptionQuery>; - /// counter of the identity index to give to the next identity + /// The identity index to assign to the next created identity. #[pallet::storage] pub(super) type NextIdtyIndex<T: Config> = StorageValue<_, T::IdtyIndex, ValueQuery>; - /// maps block number to the list of identities set to be removed at this bloc + /// The identities to remove at a given block. #[pallet::storage] #[pallet::getter(fn next_scheduled)] pub type IdentityChangeSchedule<T: Config> = @@ -513,9 +562,15 @@ pub mod pallet { Ok(().into()) } + /// Remove identity names from storage. + /// + /// This function allows a privileged root origin to remove multiple identity names from storage + /// in bulk. + /// + /// - `origin` - The origin of the call. It must be root. + /// - `names` - A vector containing the identity names to be removed from storage. #[pallet::call_index(6)] #[pallet::weight(T::WeightInfo::prune_item_identities_names(names.len() as u32))] - /// remove identity names from storage pub fn prune_item_identities_names( origin: OriginFor<T>, names: Vec<IdtyName>, @@ -529,9 +584,17 @@ pub mod pallet { Ok(().into()) } + /// Change sufficient reference count for a given key. + /// + /// This function allows a privileged root origin to increment or decrement the sufficient + /// reference count associated with a specified owner key. + /// + /// - `origin` - The origin of the call. It must be root. + /// - `owner_key` - The account whose sufficient reference count will be modified. + /// - `inc` - A boolean indicating whether to increment (`true`) or decrement (`false`) the count. + /// #[pallet::call_index(7)] #[pallet::weight(T::WeightInfo::fix_sufficients())] - /// change sufficient ref count for given key pub fn fix_sufficients( origin: OriginFor<T>, owner_key: T::AccountId, @@ -548,17 +611,23 @@ pub mod pallet { Ok(().into()) } - /// Link an account to an identity - // both must sign (target account and identity) + /// Link an account to an identity. + /// + /// This function links a specified account to an identity, requiring both the account and the + /// identity to sign the operation. + /// + /// - `origin` - The origin of the call, which must have an associated identity index. + /// - `account_id` - The account ID to link, which must sign the payload. + /// - `payload_sig` - The signature with the linked identity. // can be used for quota system // re-uses new owner key payload for simplicity // with other custom prefix #[pallet::call_index(8)] #[pallet::weight(T::WeightInfo::link_account())] pub fn link_account( - origin: OriginFor<T>, // origin must have an identity index - account_id: T::AccountId, // id of account to link (must sign the payload) - payload_sig: T::Signature, // signature with linked identity + origin: OriginFor<T>, + account_id: T::AccountId, + payload_sig: T::Signature, ) -> DispatchResultWithPostInfo { // verif let who = ensure_signed(origin)?; @@ -627,15 +696,16 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { - /// get identity count + /// Get the number of identities. pub fn identities_count() -> u32 { Identities::<T>::count() } - /// membership added - // when an identity becomes member, update its status - // unschedule identity action, this falls back to membership scheduling - // no identity schedule while membership is active + /// Handle the addition of membership to an identity. + /// + /// This function is called when an identity transitions to a member status. It updates + /// the identity's status, unschedules any pending identity change actions, and resets + /// the identity's next scheduled action to zero. pub fn membership_added(idty_index: T::IdtyIndex) { if let Some(mut idty_value) = Identities::<T>::get(idty_index) { Self::unschedule_identity_change(idty_index, idty_value.next_scheduled); @@ -650,10 +720,11 @@ pub mod pallet { // else should not happen } - /// membership removed - // only does something if identity is actually member - // a membership can be removed when the identity is revoked - // in this case, this does nothing + /// Handle the removal of membership from an identity. + /// + /// This function is called when membership is revoked from an identity. It checks + /// if the identity is currently a member, and if so, updates its status to `NotMember`. + /// If the identity is already revoked, this function does nothing. pub fn membership_removed(idty_index: T::IdtyIndex) -> Weight { if let Some(idty_value) = Identities::<T>::get(idty_index) { if idty_value.status == IdtyStatus::Member { @@ -669,10 +740,11 @@ pub mod pallet { // else should not happen } - /// perform identity removal - // (kind of garbage collector) - // this should not be called while the identity is still member - // otherwise there will still be a membership in storage, but no more identity + /// Perform the removal of an identity. + /// + /// This function acts as a garbage collector for identities. It should not be called + /// while the identity is still a member; otherwise, there will still be a membership + /// in storage, but no more identity. pub fn do_remove_identity(idty_index: T::IdtyIndex, reason: RemovalReason) -> Weight { if let Some(idty_value) = Identities::<T>::get(idty_index) { // this line allows the owner key to be used after that @@ -693,7 +765,10 @@ pub mod pallet { T::WeightInfo::do_remove_identity_noop() } - /// revoke identity + /// Revoke an identity. + /// + /// This function revokes an identity, updating its status to `Revoked` and scheduling + /// it for removal after the specified deletion period. pub fn do_revoke_identity(idty_index: T::IdtyIndex, reason: RevocationReason) -> Weight { if let Some(idty_value) = Identities::<T>::get(idty_index) { Self::update_identity_status( @@ -721,7 +796,7 @@ pub mod pallet { } } - /// remove identities planned for removal at the given block + /// Prune identities planned for removal at the given block number. pub fn prune_identities(block_number: BlockNumberFor<T>) -> Weight { let mut total_weight = Weight::zero(); @@ -773,7 +848,7 @@ pub mod pallet { total_weight.saturating_add(T::WeightInfo::prune_identities_noop()) } - /// change identity status and reschedule next action + /// Change the identity status and reschedule the next action accordingly. fn update_identity_status( idty_index: T::IdtyIndex, mut idty_value: IdtyValue<BlockNumberFor<T>, T::AccountId, T::IdtyData>, @@ -786,7 +861,7 @@ pub mod pallet { <Identities<T>>::insert(idty_index, idty_value); } - /// unschedule identity change + /// Unschedules the change related to an identity. fn unschedule_identity_change(idty_id: T::IdtyIndex, block_number: BlockNumberFor<T>) { let mut scheduled = IdentityChangeSchedule::<T>::get(block_number); if let Some(pos) = scheduled.iter().position(|x| *x == idty_id) { @@ -795,7 +870,7 @@ pub mod pallet { } } - /// schedule identity change after given period + /// Schedule an identity change after a specified period. fn schedule_identity_change( idty_id: T::IdtyIndex, period: BlockNumberFor<T>, @@ -806,7 +881,7 @@ pub mod pallet { next_scheduled } - /// check create identity + /// Check if creating an identity is allowed. // first internal checks // then other pallet checks trough trait fn check_create_identity( @@ -871,7 +946,7 @@ impl<T> frame_support::traits::StoredMap<T::AccountId, T::IdtyData> for Pallet<T where T: Config, { - /// get identity data for an account id + /// Get identity data for an account. fn get(key: &T::AccountId) -> T::IdtyData { if let Some(idty_index) = Self::identity_index_of(key) { if let Some(idty_val) = Identities::<T>::get(idty_index) { @@ -884,7 +959,7 @@ where } } - /// mutate an account given a function of its data + /// Mutate an account in function of its data. fn try_mutate_exists<R, E: From<sp_runtime::DispatchError>>( key: &T::AccountId, f: impl FnOnce(&mut Option<T::IdtyData>) -> Result<R, E>, diff --git a/pallets/identity/src/traits.rs b/pallets/identity/src/traits.rs index 548d666f3f413a4de6eaa8cc527c8491d17d1714..73c759cffbf0a2c9130a033ef87f583ffd6a1aef 100644 --- a/pallets/identity/src/traits.rs +++ b/pallets/identity/src/traits.rs @@ -17,9 +17,9 @@ use crate::*; use frame_support::pallet_prelude::*; -/// A trait defining operations for checking if identity-related calls are allowed. +/// Trait defining operations for checking if identity-related calls are allowed. pub trait CheckIdtyCallAllowed<T: Config> { - /// Checks if creating an identity is allowed. + /// Check if creating an identity is allowed. fn check_create_identity(creator: T::IdtyIndex) -> Result<(), DispatchError>; } @@ -31,14 +31,14 @@ impl<T: Config> CheckIdtyCallAllowed<T> for () { /// Trait to check the worthiness of an account. pub trait CheckAccountWorthiness<T: Config> { - /// Checks the worthiness of an account. + /// Check the worthiness of an account. fn check_account_worthiness(account: &T::AccountId) -> Result<(), DispatchError>; + /// Set an account as worthy. Only available for runtime benchmarks. #[cfg(feature = "runtime-benchmarks")] fn set_worthy(account: &T::AccountId); } impl<T: Config> CheckAccountWorthiness<T> for () { - /// Default no-op check for account worthiness. fn check_account_worthiness(_account: &T::AccountId) -> Result<(), DispatchError> { Ok(()) } @@ -47,19 +47,19 @@ impl<T: Config> CheckAccountWorthiness<T> for () { fn set_worthy(_account: &T::AccountId) {} } -/// A trait defining operations for validating identity names. +/// Trait defining operations for validating identity names. pub trait IdtyNameValidator { - /// Validates an identity name. + /// Validate an identity name. fn validate(idty_name: &IdtyName) -> bool; } -/// A trait defining behavior for handling new identities creation. +/// Trait defining behavior for handling new identities creation. pub trait OnNewIdty<T: Config> { /// Called when a new identity is created. fn on_created(idty_index: &T::IdtyIndex, creator: &T::IdtyIndex); } -/// A trait defining behavior for handling removed identities. +/// Trait defining behavior for handling removed identities. /// As the weight accounting can be complicated it should be done /// at the handler level. pub trait OnRemoveIdty<T: Config> { @@ -83,7 +83,7 @@ impl<T: Config> OnRemoveIdty<T> for () { } } -/// A trait defining operations for linking identities to accounts. +/// Trait defining operations for linking identities to accounts. pub trait LinkIdty<AccountId, IdtyIndex> { /// Links an identity to an account. fn link_identity(account_id: &AccountId, idty_index: IdtyIndex) -> Result<(), DispatchError>; diff --git a/pallets/identity/src/types.rs b/pallets/identity/src/types.rs index 868d8f0a7a8c06427b48feede911f8ec76669ad3..bb841489a16979c4ab21e64059f7e164c5ffed36 100644 --- a/pallets/identity/src/types.rs +++ b/pallets/identity/src/types.rs @@ -21,49 +21,54 @@ use frame_support::pallet_prelude::*; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; -/// internal events related to identity +/// Internal events related to identity. pub enum IdtyEvent<T: crate::Config> { - /// IdtyEvent::Created - /// creation of a new identity by an other + /// Creation of a new identity by another. // pallet account links account to identity // pallet wot adds certification // pallet quota adds storage item for this identity Created { + /// Identity of the creator. creator: T::IdtyIndex, + /// Account of the identity owner. owner_key: T::AccountId, }, - /// IdtyEvent::Removed - /// removing an identity (unvalidated or revoked) + /// Removing an identity (unvalidated or revoked). // pallet wot removes associated certifications if status is not revoked // pallet quota removes associated quota // pallet smith-members exclude smith - Removed { status: IdtyStatus }, + Removed { + /// Status of the identity. + status: IdtyStatus, + }, // TODO add a way to unlink accounts corresponding to revoked or removed identities } +/// Reasons for revocation. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum RevocationReason { - /// revoked by root (e.g. governance or migration) + /// Revoked by root (e.g., governance or migration). Root, - /// revoked by user action (revocation document) + /// Revoked by user action (revocation document). User, - /// revoked due to inactive period + /// Revoked due to inactive period. Expired, } +/// Reasons for removal. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum RemovalReason { - /// removed by root + /// Removed by root. Root, - /// removed because unconfirmed + /// Removed because unconfirmed. Unconfirmed, - /// removed because unvalidated + /// Removed because unvalidated. Unvalidated, - /// removed automatically after revocation buffer + /// Removed automatically after revocation buffer. Revoked, } -/// name of the identity, ascii encoded +/// Represents the name of an identity, ASCII encoded. #[derive( Encode, Decode, @@ -86,8 +91,7 @@ impl From<&str> for IdtyName { } } -/// status of the identity -// this is a kind of index to tell the state of the identity +/// State of an identity. #[derive( Encode, Decode, @@ -102,56 +106,60 @@ impl From<&str> for IdtyName { Serialize, )] pub enum IdtyStatus { - /// created through a first certification but unconfirmed + /// Created through a first certification but unconfirmed. #[default] Unconfirmed, - /// confirmed by key owner with a name published but unvalidated + /// Confirmed by key owner with a name published but unvalidated. Unvalidated, - /// member of the main web of trust + /// Member of the main web of trust. // (there must be a membership in membership pallet storage) Member, - /// not member of the main web of trust, auto-revocation planned + /// Not a member of the main web of trust, auto-revocation planned. NotMember, - /// revoked manually or automatically, deletion possible + /// Revoked manually or automatically, deletion possible. Revoked, } -/// identity value (as in key/value) +/// Identity value structure. +/// +/// Represents the value associated with an identity, akin to key/value pairs. #[derive(Serialize, Deserialize, Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct IdtyValue<BlockNumber, AccountId, IdtyData> { - /// data shared between pallets defined by runtime - /// only contains first_eligible_ud in our case + /// Data shared between pallets defined by runtime. + /// Only contains `first_eligible_ud` in our case. pub data: IdtyData, - /// block before which creating a new identity is not allowed + /// Block before which creating a new identity is not allowed. pub next_creatable_identity_on: BlockNumber, - /// previous owner key of this identity (optional) + /// Previous owner key of this identity (optional). pub old_owner_key: Option<(AccountId, BlockNumber)>, - /// current owner key of this identity + /// Current owner key of this identity. pub owner_key: AccountId, - /// next action scheduled on identity - // 0 if no action scheduled + /// Next action scheduled on identity. + /// + /// `0` if no action is scheduled. pub next_scheduled: BlockNumber, - /// current status of the identity (until validation) + /// Current status of the identity (until validation). pub status: IdtyStatus, } -/// payload to define a new owner key +/// Reprensent the payload to define a new owner key. #[derive(Clone, Copy, Encode, RuntimeDebug)] pub struct IdtyIndexAccountIdPayload<'a, AccountId, IdtyIndex, Hash> { - /// hash of the genesis block - // Avoid replay attack across networks + /// Hash of the genesis block. + // Used to avoid replay attacks across networks. pub genesis_hash: &'a Hash, - /// identity index + /// Identity index. pub idty_index: IdtyIndex, - /// old owner key of the identity + /// Old owner key of the identity. pub old_owner_key: &'a AccountId, } +/// Represents the payload for identity revocation. #[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, TypeInfo, RuntimeDebug)] pub struct RevocationPayload<IdtyIndex, Hash> { - /// hash of the genesis block - // Avoid replay attack across networks + /// Hash of the genesis block. + // Used to avoid replay attacks across networks. pub genesis_hash: Hash, - /// identity index + /// Identity index. pub idty_index: IdtyIndex, } diff --git a/pallets/membership/Cargo.toml b/pallets/membership/Cargo.toml index b43852aa0be7ea53b58ccc63dc187292ed2f6b96..041da990915cda5e654b04fda0d5dae929745ece 100644 --- a/pallets/membership/Cargo.toml +++ b/pallets/membership/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-membership" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/membership/README.md b/pallets/membership/README.md deleted file mode 100644 index c6dc0da834a30d0766609fc20773da17e1fd3136..0000000000000000000000000000000000000000 --- a/pallets/membership/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Duniter membership pallet - -Duniter membership is related to duniter Web of Trust and more specific than [parity membership pallet](https://github.com/paritytech/substrate/tree/master/frame/membership). It is used only internally by the identity, WoT, and distance pallets. - -## Main Web of Trust - -Membership pallet manages all events related to web of trust membership of an identity. It exposes no calls to the user and its features are only available trough distance evaluation provided by distance oracle. diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs index 714d4bb09d4b85510568cc7c199ae8c0652d7d97..860d3bd25db0736968a4dac5a3b882b9fff70074 100644 --- a/pallets/membership/src/lib.rs +++ b/pallets/membership/src/lib.rs @@ -14,6 +14,14 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Membership Pallet +//! +//! The Duniter Membership Pallet is closely integrated with the Duniter Web of Trust (WoT) and is tailored specifically for Duniter, in contrast to the [Parity Membership Pallet](https://github.com/paritytech/substrate/tree/master/frame/membership). It operates exclusively within the Duniter ecosystem and is utilized internally by the Identity, Web of Trust, and Distance Pallets. +//! +//! ## Main Web of Trust (WoT) +//! +//! The Membership Pallet manages all aspects related to the membership of identities within the Duniter Web of Trust. Unlike traditional membership systems, it does not expose any external calls to users. Instead, its functionalities are accessible through distance evaluations provided by the Distance Oracle. + #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::type_complexity)] @@ -49,15 +57,16 @@ impl<IdtyId, AccountId> SetupBenchmark<IdtyId, AccountId> for () { fn add_cert(_issuer: &IdtyId, _receiver: &IdtyId) {} } +/// Represent reasons for the removal of membership. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum MembershipRemovalReason { - // reach end of life + /// Indicates membership was removed because it reached the end of its life. Expired, - // was explicitly revoked + /// Indicates membership was explicitly revoked. Revoked, - // received certs count passed below threshold + /// Indicates membership was removed because the received certifications count fell below the threshold. NotEnoughCerts, - // system reasons (consumers, authority members, or root) + /// Indicates membership was removed due to system reasons (e.g., consumers, authority members, or root). System, } @@ -79,27 +88,36 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - /// Ask the runtime whether the identity can perform membership operations + /// Check if the identity can perform membership operations. type CheckMembershipOpAllowed: CheckMembershipOpAllowed<Self::IdtyId>; - /// Something that identifies an identity + + /// Something that identifies an identity. type IdtyId: Copy + MaybeSerializeDeserialize + Parameter + Ord; - /// Something that gives the IdtyId of an AccountId and reverse + + /// Something that gives the IdtyId of an AccountId and reverse. type IdtyAttr: duniter_primitives::Idty<Self::IdtyId, Self::AccountId>; - /// Maximum life span of a single membership (in number of blocks) - // (this could be renamed "validity" or "duration") + + /// Maximum lifespan of a single membership (in number of blocks). #[pallet::constant] type MembershipPeriod: Get<BlockNumberFor<Self>>; - /// Minimum delay to wait before renewing membership - // i.e. asking for distance evaluation + + /// Minimum delay to wait before renewing membership, i.e., asking for distance evaluation. #[pallet::constant] type MembershipRenewalPeriod: Get<BlockNumberFor<Self>>; - /// On new and renew membership handler. + + /// Handler called when a new membership is created or renewed. type OnNewMembership: OnNewMembership<Self::IdtyId>; - /// On revoked and removed membership handler. + + /// Handler called when a membership is revoked or removed. type OnRemoveMembership: OnRemoveMembership<Self::IdtyId>; - /// Because this pallet emits events, it depends on the runtime's definition of an event. + + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; + + /// Benchmark setup handler for runtime benchmarks (feature-dependent). #[cfg(feature = "runtime-benchmarks")] type BenchmarkSetupHandler: SetupBenchmark<Self::IdtyId, Self::AccountId>; } @@ -131,8 +149,7 @@ pub mod pallet { // STORAGE // - /// maps identity id to membership data - // (expiration block for instance) + /// The membership data for each identity. #[pallet::storage] #[pallet::getter(fn membership)] pub type Membership<T: Config> = CountedStorageMap< @@ -143,7 +160,7 @@ pub mod pallet { OptionQuery, >; - /// maps block number to the list of identity id set to expire at this block + /// The identities of memberships to expire at a given block. #[pallet::storage] #[pallet::getter(fn memberships_expire_on)] pub type MembershipsExpireOn<T: Config> = @@ -202,7 +219,7 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { - /// unschedule membership expiry + /// Unschedules membership expiry. fn unschedule_membership_expiry(idty_id: T::IdtyId, block_number: BlockNumberFor<T>) { let mut scheduled = MembershipsExpireOn::<T>::get(block_number); @@ -212,7 +229,7 @@ pub mod pallet { } } - /// schedule membership expiry + /// Insert membership and schedule its expiry. fn insert_membership_and_schedule_expiry(idty_id: T::IdtyId) -> BlockNumberFor<T> { let block_number = frame_system::pallet::Pallet::<T>::block_number(); let expire_on = block_number + T::MembershipPeriod::get(); @@ -222,7 +239,7 @@ pub mod pallet { expire_on } - /// check that membership can be claimed + /// Check if membership can be claimed. pub fn check_add_membership(idty_id: T::IdtyId) -> Result<(), DispatchError> { // no-op is error ensure!( @@ -235,7 +252,7 @@ pub mod pallet { Ok(()) } - /// check that membership can be renewed + /// Check if membership renewal is allowed. pub fn check_renew_membership( idty_id: T::IdtyId, ) -> Result<MembershipData<BlockNumberFor<T>>, DispatchError> { @@ -247,21 +264,21 @@ pub mod pallet { Ok(membership_data) } - /// try claim membership + /// Attempt to add membership. pub fn try_add_membership(idty_id: T::IdtyId) -> Result<(), DispatchError> { Self::check_add_membership(idty_id)?; Self::do_add_membership(idty_id); Ok(()) } - /// try renew membership + /// Attempt to renew membership. pub fn try_renew_membership(idty_id: T::IdtyId) -> Result<(), DispatchError> { let membership_data = Self::check_renew_membership(idty_id)?; Self::do_renew_membership(idty_id, membership_data); Ok(()) } - /// perform membership addition + /// Perform membership addition. fn do_add_membership(idty_id: T::IdtyId) { let expire_on = Self::insert_membership_and_schedule_expiry(idty_id); Self::deposit_event(Event::MembershipAdded { @@ -271,7 +288,7 @@ pub mod pallet { T::OnNewMembership::on_created(&idty_id); } - /// perform membership renewal + /// Perform membership renewal. fn do_renew_membership( idty_id: T::IdtyId, membership_data: MembershipData<BlockNumberFor<T>>, @@ -285,7 +302,7 @@ pub mod pallet { T::OnNewMembership::on_renewed(&idty_id); } - /// perform membership removal + /// Perform membership removal. pub fn do_remove_membership(idty_id: T::IdtyId, reason: MembershipRemovalReason) -> Weight { let mut weight = T::DbWeight::get().reads_writes(2, 3); if let Some(membership_data) = Membership::<T>::take(idty_id) { @@ -299,7 +316,7 @@ pub mod pallet { weight } - /// perform the membership expiry scheduled at given block + /// Perform membership expiry scheduled at the given block number. pub fn expire_memberships(block_number: BlockNumberFor<T>) -> Weight { let mut expired_idty_count = 0u32; @@ -311,7 +328,7 @@ pub mod pallet { T::WeightInfo::expire_memberships(expired_idty_count) } - /// check if identity is member + /// Check if an identity is a member. pub fn is_member(idty_id: &T::IdtyId) -> bool { Membership::<T>::contains_key(idty_id) } diff --git a/pallets/offences/Cargo.toml b/pallets/offences/Cargo.toml index ccc57523e523a7dd5c60aed1d4b82e2415483c77..86733790b8b4687d66581eb01c1e5fbf20b33bd1 100644 --- a/pallets/offences/Cargo.toml +++ b/pallets/offences/Cargo.toml @@ -6,7 +6,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true repository.workspace = true -readme = "README.md" version.workspace = true [package.metadata.docs.rs] diff --git a/pallets/offences/README.md b/pallets/offences/README.md deleted file mode 100644 index 62fa734c335500b442f440ab9100beed1ebeab68..0000000000000000000000000000000000000000 --- a/pallets/offences/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Duniter offences pallet - -This is a fork of the Substrate `offences` pallet that is modified to agree with the offence rules based on the `authority-member` pallet and not in the Substrate `staking` pallet. - -Duniter provides a basic way to process offences: -* On offences from `im-online` pallet, the offender disconnection is required. -* On other offences, the offender disconnection is required and the offender is required to be blacklisted and only an authorized origin can remove the offender from the blacklist. - -The offences triage is realized in the `offences` pallet and the slashing execution is done in the `authority-member` pallet. \ No newline at end of file diff --git a/pallets/offences/src/lib.rs b/pallets/offences/src/lib.rs index f6b30289d9ad283633cb4636a9df800abe748649..66ee776938a46221898fe00fc1bf67e2729c8dc9 100644 --- a/pallets/offences/src/lib.rs +++ b/pallets/offences/src/lib.rs @@ -14,6 +14,25 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Offences Pallet +//! +//! This pallet is a fork of the Substrate `offences` pallet, customized to align with the offence rules specified by the `authority-member` pallet rather than the Substrate `staking` pallet. +//! +//! ## Offences Processing +//! +//! The Duniter Offences Pallet manages various types of offences as follows: +//! +//! - **`im-online` Pallet Offences**: Offences from the `im-online` pallet necessitate disconnection of the offender. +//! +//! - **Other Offences**: For all other offences, the pallet enforces: +//! - Disconnection of the offender. +//! - Addition of the offender to a blacklist. +//! - Authorization from a designated origin to remove offenders from the blacklist. +//! +//! ## Offences Triage and Slashing Execution +//! +//! This pallet handles the triage of offences, categorizing them based on predefined rules. The actual execution of slashing and other punitive measures is delegated to the `authority-member` pallet. + #![cfg_attr(not(feature = "std"), no_std)] #[cfg(test)] @@ -63,8 +82,10 @@ pub mod pallet { pub trait Config: frame_system::Config { /// The overarching event type. type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>; + /// Full identification of the validator. type IdentificationTuple: Parameter; + /// A handler called for every offence report. type OnOffenceHandler: OnOffenceHandler<Self::AccountId, Self::IdentificationTuple, Weight>; } diff --git a/pallets/offences/src/traits.rs b/pallets/offences/src/traits.rs index 69dfe649d87f4a6d88d38f530321cb064dbb48cb..cbc203ff4f863d9cb34e4c388c79f6373c2f56b4 100644 --- a/pallets/offences/src/traits.rs +++ b/pallets/offences/src/traits.rs @@ -18,8 +18,9 @@ use sp_staking::{offence::OffenceDetails, SessionIndex}; use crate::SlashStrategy; +/// Trait for handling offences. pub trait OnOffenceHandler<Reporter, Offender, Res> { - // Required method + /// Handle an offence committed by one or more offenders. fn on_offence( offenders: &[OffenceDetails<Reporter, Offender>], slash_strategy: SlashStrategy, diff --git a/pallets/oneshot-account/Cargo.toml b/pallets/oneshot-account/Cargo.toml index d019ccef62160a32576c5be677050be6254143af..4eb9435a9f881e48b788e70060b6acc47bd53b2c 100644 --- a/pallets/oneshot-account/Cargo.toml +++ b/pallets/oneshot-account/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-oneshot-account" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/oneshot-account/README.md b/pallets/oneshot-account/README.md deleted file mode 100644 index 7d3f030eabb1384ae07203d6577dae0bde54b5fa..0000000000000000000000000000000000000000 --- a/pallets/oneshot-account/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Duniter oneshot account pallet - -Duniter provides light accounts without `AccountInfo` (nonce, consumers, providers, sufficients, free, reserved, misc_frozen, fee_frozen) that can only be consumed once. This should reduce transaction weight and then fees. The use case is anonymous accounts or physical supports. \ No newline at end of file diff --git a/pallets/oneshot-account/src/check_nonce.rs b/pallets/oneshot-account/src/check_nonce.rs index 3f365453196738d0edbf4c8e74223ae82282f137..0f1a2fccfb0aade09db2606065a82120aa8cbc5d 100644 --- a/pallets/oneshot-account/src/check_nonce.rs +++ b/pallets/oneshot-account/src/check_nonce.rs @@ -25,6 +25,7 @@ use sp_runtime::{ transaction_validity::{TransactionValidity, TransactionValidityError}, }; +/// Wrapper around `frame_system::CheckNonce<T>`. #[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(Runtime))] pub struct CheckNonce<T: Config>(pub frame_system::CheckNonce<T>); diff --git a/pallets/oneshot-account/src/lib.rs b/pallets/oneshot-account/src/lib.rs index f1bff130b57d855fac2564fde450cf601bb6d416..3bef8281a38bd21d1acdfb96c39b15f07d99da7b 100644 --- a/pallets/oneshot-account/src/lib.rs +++ b/pallets/oneshot-account/src/lib.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Oneshot Account Pallet +//! +//! Duniter Oneshot Account Pallet introduces lightweight accounts that do not utilize `AccountInfo`, including fields like nonce, consumers, providers, sufficients, free, reserved. These accounts are designed for single-use scenarios, aiming to reduce transaction weight and associated fees. The primary use cases include anonymous transactions and physical support scenarios where lightweight and disposable accounts are beneficial. + #![cfg_attr(not(feature = "std"), no_std)] mod benchmarking; @@ -57,15 +61,22 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config + pallet_transaction_payment::Config { + /// The currency type. type Currency: fungible::Balanced<Self::AccountId> + fungible::Mutate<Self::AccountId>; + + /// A handler for charging transactions. type InnerOnChargeTransaction: OnChargeTransaction<Self>; + + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// Type representing the weight of this pallet + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; } // STORAGE // + /// The balance for each oneshot account. #[pallet::storage] #[pallet::getter(fn oneshot_account)] pub type OneshotAccounts<T: Config> = diff --git a/pallets/oneshot-account/src/types.rs b/pallets/oneshot-account/src/types.rs index ee8b45bd048920c57868523408a45c0e04dbfe91..f81d051a05cc3388bc204c543a6cf9f7dda51d51 100644 --- a/pallets/oneshot-account/src/types.rs +++ b/pallets/oneshot-account/src/types.rs @@ -17,8 +17,11 @@ use codec::{Decode, Encode}; use frame_support::pallet_prelude::*; +/// The type of account. #[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] pub enum Account<AccountId> { + /// Normal account type. Normal(AccountId), + /// Oneshot account type. Oneshot(AccountId), } diff --git a/pallets/provide-randomness/README.md b/pallets/provide-randomness/README.md deleted file mode 100644 index 12138fbd60ba21715edbbb1cd42ad7c477d8bbf4..0000000000000000000000000000000000000000 --- a/pallets/provide-randomness/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Duniter provide randomness pallet - -TODO \ No newline at end of file diff --git a/pallets/provide-randomness/src/lib.rs b/pallets/provide-randomness/src/lib.rs index 159be9f870da11d576e13598a0d3d062afafa674..28c4f1dcdd5aa74913bf8088c0988f6c6ce3cb6a 100644 --- a/pallets/provide-randomness/src/lib.rs +++ b/pallets/provide-randomness/src/lib.rs @@ -14,6 +14,12 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Provides Randomness Pallet +//! +//! The Provides Randomness Pallet facilitates the generation of randomness within the Duniter blockchain. +//! +//! This pallet manages randomness requests and emits events upon requesting and fulfilling randomness. + #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::boxed_local)] @@ -72,47 +78,61 @@ pub mod pallet { /// Configuration trait. #[pallet::config] pub trait Config: frame_system::Config<Hash = H256> { - // The currency + // The currency type. type Currency: fungible::Balanced<Self::AccountId> + fungible::Mutate<Self::AccountId>; - /// Get the current epoch index + + /// Type providing the current epoch index. type GetCurrentEpochIndex: Get<u64>; - /// Maximum number of not yet filled requests + + /// Maximum number of not yet filled requests. #[pallet::constant] type MaxRequests: Get<u32>; - /// The price of a request + + /// The price of a request. #[pallet::constant] type RequestPrice: Get<BalanceOf<Self>>; - /// On filled randomness + + /// Handler called when randomness is filled. type OnFilledRandomness: OnFilledRandomness; - /// Handler for the unbalanced reduction when the requestor pays fees. + + /// Handler for unbalanced reduction when the requestor pays fees. type OnUnbalanced: OnUnbalanced<Credit<Self::AccountId, Self::Currency>>; - /// A safe source of randomness from the parent block + + /// A safe source of randomness from the parent block. type ParentBlockRandomness: Randomness<Option<H256>, BlockNumberFor<Self>>; - /// A safe source of randomness from one epoch ago + + /// A safe source of randomness from one epoch ago. type RandomnessFromOneEpochAgo: Randomness<H256, BlockNumberFor<Self>>; + /// The overarching event type. type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// Type representing the weight of this pallet + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; } // STORAGE // + /// The number of blocks before the next epoch. #[pallet::storage] pub(super) type NexEpochHookIn<T: Config> = StorageValue<_, u8, ValueQuery>; + /// The request ID. #[pallet::storage] pub(super) type RequestIdProvider<T: Config> = StorageValue<_, RequestId, ValueQuery>; + /// The requests that will be fulfilled at the next block. #[pallet::storage] #[pallet::getter(fn requests_ready_at_next_block)] pub type RequestsReadyAtNextBlock<T: Config> = StorageValue<_, Vec<Request>, ValueQuery>; + /// The requests that will be fulfilled at the next epoch. #[pallet::storage] #[pallet::getter(fn requests_ready_at_epoch)] pub type RequestsReadyAtEpoch<T: Config> = StorageMap<_, Twox64Concat, u64, Vec<Request>, ValueQuery>; + /// The requests being processed. #[pallet::storage] #[pallet::getter(fn requests_ids)] pub type RequestsIds<T: Config> = @@ -148,7 +168,7 @@ pub mod pallet { #[pallet::call] impl<T: Config> Pallet<T> { - /// Request a randomness + /// Request randomness. #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::request())] pub fn request( @@ -221,6 +241,7 @@ pub mod pallet { // PUBLIC FUNCTIONS // impl<T: Config> Pallet<T> { + /// Initiates a randomness request with specified parameters. pub fn do_request( requestor: &T::AccountId, randomness_type: RandomnessType, @@ -238,10 +259,12 @@ pub mod pallet { Ok(Self::apply_request(randomness_type, salt)) } + /// Forcefully initiates a randomness request using the specified parameters. pub fn force_request(randomness_type: RandomnessType, salt: H256) -> RequestId { Self::apply_request(randomness_type, salt) } + /// Set the next epoch hook value to 5. pub fn on_new_epoch() { NexEpochHookIn::<T>::put(5) } @@ -250,6 +273,7 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { + /// Withdraw funds from the requestor's account to pay for a request. fn pay_request(requestor: &T::AccountId) -> DispatchResult { let imbalance = T::Currency::withdraw( requestor, @@ -262,6 +286,7 @@ pub mod pallet { Ok(()) } + /// Apply a randomness request with the specified type and salt. fn apply_request(randomness_type: RandomnessType, salt: H256) -> RequestId { let request_id = RequestIdProvider::<T>::mutate(|next_request_id| { core::mem::replace(next_request_id, next_request_id.saturating_add(1)) diff --git a/pallets/provide-randomness/src/types.rs b/pallets/provide-randomness/src/types.rs index 8e7b883011a98aeb3d77b334ba9468c38a5741ea..4dfeda203152ff43330ecf9814644845ffe7d3de 100644 --- a/pallets/provide-randomness/src/types.rs +++ b/pallets/provide-randomness/src/types.rs @@ -22,15 +22,22 @@ use frame_support::pallet_prelude::*; use scale_info::TypeInfo; use sp_core::H256; +/// The type of randomness source. #[derive(Clone, Copy, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub enum RandomnessType { + /// Randomness derived from the previous block. RandomnessFromPreviousBlock, + /// Randomness derived from one epoch ago. RandomnessFromOneEpochAgo, + /// Randomness derived from two epochs ago. RandomnessFromTwoEpochsAgo, } +/// Represents a randomness request. #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct Request { + /// Request ID. pub request_id: RequestId, + /// Salt used for the request. pub salt: H256, } diff --git a/pallets/quota/Cargo.toml b/pallets/quota/Cargo.toml index 3c92a89ec438d823a34d91fe3a6eacaaf77b4adc..7b951e025cd341c3cafbc8012a269ac2493bbbbd 100644 --- a/pallets/quota/Cargo.toml +++ b/pallets/quota/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true name = "pallet-quota" -readme = "README.md" repository.workspace = true version.workspace = true diff --git a/pallets/quota/README.md b/pallets/quota/README.md deleted file mode 100644 index 485460de592face6a99597fef19eb952df5936d4..0000000000000000000000000000000000000000 --- a/pallets/quota/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Duniter quota pallet - -Duniter identity system allows to allocate quota and refund transaction fees when not consumed. - -## General behavior - -Quota system is plugged to transactions fees which is a rather critical aspect of substrate. -That's why in `duniter-account` pallet `OnChargeTransaction` implementation, the default behavior is preserved, and refunds are added to a queue handled in `on_idle`. - -## Path for a refund - -This is what happens on a transaction: - -- `frame-executive` calls `OnChargeTransaction` implementations -- `duniter-account` `OnChargeTransaction` implementation is called, and if an identity is linked to the account who pays the fees, `request_refund` is called -- `request_refund` implementation of `quota` pallet determines whether the fees are eligible for refund based on the identity and then call `queue_refund` -- `queue_refund` adds a refund to the `RefundQueue` which will be processed in `on_idle` -- during `on_idle`, `quota` pallet processes the refund queue within the supplied weight limit with `process_refund_queue` -- for each refund in the `RefundQueue`, `try_refund` is called -- it first tries to use quotas to refund fees with `spend_quota` -- if a certain amount of quotas has been spend, it actually performs the refund with `do_refund`, taking currency from the `RefundAccount` to give it back to the account who paid the fee - -The conditions for a refund to happen are: - -1. an identity is linked to the account who pays the fees -1. some quotas are defined for the identity and have a non-null value after update - - -## TODO - -- [ ] sanity test checking that only member identities have quota \ No newline at end of file diff --git a/pallets/quota/src/lib.rs b/pallets/quota/src/lib.rs index 79772ba8c58087cafa33e00c83086fa1386bbc94..8b24f8a61308eeb16f7a0b739d90483636f118c5 100644 --- a/pallets/quota/src/lib.rs +++ b/pallets/quota/src/lib.rs @@ -14,6 +14,27 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Quota Pallet +//! +//! ## Overview +//! +//! This pallet is designed to manage transaction fee refunds based on quotas allocated to identities within the Duniter identity system. Quotas are linked to transaction fees, ensuring efficient handling of fee refunds when transactions occur. +//! +//! ## Refund Mechanism +//! +//! When a transaction is processed: +//! - The `OnChargeTransaction` implementation in the `frame-executive` pallet is called. +//! - The `OnChargeTransaction` implementation in the `duniter-account` pallet checks if the paying account is linked to an identity. +//! - If linked, the `request_refund` function in the `quota` pallet evaluates the eligibility for fee refund based on the identity's quota. +//! - Eligible refunds are added to the `RefundQueue`, managed by `process_refund_queue` during the `on_idle` phase. +//! - Refunds are processed with `try_refund`, using quotas to refund fees via `spend_quota`, and then executing the refund through `do_refund` by transferring currency from the `RefundAccount` back to the paying account. +//! +//! ## Conditions for Refund +//! +//! Refunds are executed under the following conditions: +//! 1. The paying account is linked to an identity. +//! 2. Quotas are allocated to the identity and have a non-zero value after updates. + #![cfg_attr(not(feature = "std"), no_std)] pub mod traits; @@ -61,46 +82,52 @@ pub mod pallet { pub trait Config: frame_system::Config + pallet_balances::Config + pallet_identity::Config { - /// Because this pallet emits events, it depends on the runtime's definition of an event. + /// The overarching event type. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// number of blocks in which max quota is replenished + + /// Number of blocks after which the maximum quota is replenished. type ReloadRate: Get<BlockNumberFor<Self>>; - /// maximum amount of quota an identity can get + + /// Maximum amount of quota an identity can receive. type MaxQuota: Get<BalanceOf<Self>>; - /// Account used to refund fee + + /// Account used to refund fees. #[pallet::constant] type RefundAccount: Get<Self::AccountId>; - /// Weight + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; } // TYPES // + /// Represents a refund. #[derive(Encode, Decode, Clone, TypeInfo, Debug, PartialEq, MaxEncodedLen)] pub struct Refund<AccountId, IdtyId, Balance> { - /// account to refund + /// Account to refund. pub account: AccountId, - /// identity to use quota + /// Identity to use quota. pub identity: IdtyId, - /// amount of refund + /// Amount of refund. pub amount: Balance, } + /// Represents a quota. #[derive(Encode, Decode, Clone, TypeInfo, Debug, PartialEq, MaxEncodedLen)] pub struct Quota<BlockNumber, Balance> { - /// block number of last quota use + /// Block number of the last quota used. pub last_use: BlockNumber, - /// amount of remaining quota + /// Amount of remaining quota. pub amount: Balance, } // STORAGE // - /// maps identity index to quota + /// The quota for each identity. #[pallet::storage] #[pallet::getter(fn quota)] pub type IdtyQuota<T: Config> = StorageMap<_, Twox64Concat, IdtyId<T>, Quota<BlockNumberFor<T>, BalanceOf<T>>, OptionQuery>; - /// fees waiting for refund + /// The fees waiting to be refunded. #[pallet::storage] pub type RefundQueue<T: Config> = StorageValue< _, @@ -137,14 +164,14 @@ pub mod pallet { // INTERNAL FUNCTIONS // impl<T: Config> Pallet<T> { - /// add a new refund to the queue + /// Adds a new refund request to the refund queue. pub fn queue_refund(refund: Refund<T::AccountId, IdtyId<T>, BalanceOf<T>>) { if RefundQueue::<T>::mutate(|v| v.try_push(refund)).is_err() { Self::deposit_event(Event::RefundQueueFull); } } - /// try to refund using quota if available + /// Attempts to process a refund using available quota. pub fn try_refund(queued_refund: Refund<T::AccountId, IdtyId<T>, BalanceOf<T>>) -> Weight { // get the amount of quota that identity is able to spend let amount = Self::spend_quota(queued_refund.identity, queued_refund.amount); @@ -159,7 +186,7 @@ pub mod pallet { .saturating_add(<T as pallet::Config>::WeightInfo::do_refund()) } - /// do refund a non-null amount + /// Performs a refund operation for a specified non-null amount from the refund account to the requester's account. // opti: more accurate estimation of consumed weight pub fn do_refund( queued_refund: Refund<T::AccountId, IdtyId<T>, BalanceOf<T>>, @@ -199,7 +226,7 @@ pub mod pallet { } } - /// perform as many refunds as possible within the supplied weight limit + /// Processes as many refunds as possible from the refund queue within the supplied weight limit. pub fn process_refund_queue(weight_limit: Weight) -> Weight { RefundQueue::<T>::mutate(|queue| { // The weight to process an empty queue @@ -232,7 +259,7 @@ pub mod pallet { }) } - /// spend quota of identity + /// Spends the quota of an identity by deducting the specified `amount` from its quota balance. pub fn spend_quota(idty_id: IdtyId<T>, amount: BalanceOf<T>) -> BalanceOf<T> { IdtyQuota::<T>::mutate_exists(idty_id, |quota| { if let Some(ref mut quota) = quota { @@ -246,7 +273,7 @@ pub mod pallet { }) } - /// update quota according to the growth rate, max value, and last use + /// Update the quota according to the growth rate, maximum value, and last use. fn update_quota(quota: &mut Quota<BlockNumberFor<T>, BalanceOf<T>>) { let current_block = frame_system::pallet::Pallet::<T>::block_number(); let quota_growth = sp_runtime::Perbill::from_rational( @@ -259,7 +286,7 @@ pub mod pallet { quota.amount = core::cmp::min(quota.amount + quota_growth, T::MaxQuota::get()); } - /// spend a certain amount of quota and return what was spent + /// Spend a certain amount of quota and return the amount that was spent. fn do_spend_quota( quota: &mut Quota<BlockNumberFor<T>, BalanceOf<T>>, amount: BalanceOf<T>, diff --git a/pallets/quota/src/traits.rs b/pallets/quota/src/traits.rs index fb2e377fd0fed6a6718703a0a3b893ad62e6b332..9b1f4298d08abf61c712f2d1d2861635676ff1e3 100644 --- a/pallets/quota/src/traits.rs +++ b/pallets/quota/src/traits.rs @@ -16,12 +16,12 @@ use crate::*; -/// trait used to request refund of a fee +/// Trait for managing refund operations. pub trait RefundFee<T: Config> { - /// request refund for the account `account` using the quotas of identity `identity` + /// Request a refund of a fee for a specific account and identity. fn request_refund(account: T::AccountId, identity: IdtyId<T>, amount: BalanceOf<T>); } -// dummy impl + impl<T: Config> RefundFee<T> for () { fn request_refund(_account: T::AccountId, _identity: IdtyId<T>, _amount: BalanceOf<T>) {} } diff --git a/pallets/session-benchmarking/Cargo.toml b/pallets/session-benchmarking/Cargo.toml index 3da6b64a6edc96811e58a6ae367922d750305869..0ce08a13dbd7189c5a1290fe05633316fe95f3a8 100644 --- a/pallets/session-benchmarking/Cargo.toml +++ b/pallets/session-benchmarking/Cargo.toml @@ -6,7 +6,6 @@ license.workspace = true homepage.workspace = true repository.workspace = true description = "FRAME sessions pallet benchmarking" -readme = "README.md" version.workspace = true [package.metadata.docs.rs] diff --git a/pallets/session-benchmarking/README.md b/pallets/session-benchmarking/README.md deleted file mode 100644 index 8d0946772e12c530b15d43fe41738bffe1301c06..0000000000000000000000000000000000000000 --- a/pallets/session-benchmarking/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Duniter session-benchmarking pallet - -Benchmark crate for the `pallet-session` that is decoupled from the `staking-pallet` not used in Duniter. -In Duniter, the `SessionManager `and `SessionHandler` hooks are implemented in the `authority-members` pallet. \ No newline at end of file diff --git a/pallets/session-benchmarking/src/lib.rs b/pallets/session-benchmarking/src/lib.rs index dd22408a1a7e1918bd8da529f2bd296bdd0ba916..d38e9d933d1b5b3aa6255d02eb16ae0c55fa541c 100644 --- a/pallets/session-benchmarking/src/lib.rs +++ b/pallets/session-benchmarking/src/lib.rs @@ -14,8 +14,13 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. -//! Benchmarks for the Session Pallet. -// This is separated into its own crate due to cyclic dependency issues. +//! # Duniter Session Benchmarking Pallet +//! +//! This crate provides benchmarks specifically for the `pallet-session` within Duniter. Unlike traditional setups, this implementation is decoupled from the `staking-pallet`, which is not utilized in Duniter's architecture. Instead, session management functionalities are integrated into the `authority-members` pallet. +//! +//! ## Note +//! +//! This crate is separated from the main codebase due to cyclic dependency issues, focusing solely on session-related benchmarking independent of staking-related functionalities. #![cfg_attr(not(feature = "std"), no_std)] #![cfg(feature = "runtime-benchmarks")] diff --git a/pallets/smith-members/Cargo.toml b/pallets/smith-members/Cargo.toml index d18fc3cfbe1f1569203394d88dd5634100058fd0..47f3b24f2c318e2ae20ae671501e05232232a216 100644 --- a/pallets/smith-members/Cargo.toml +++ b/pallets/smith-members/Cargo.toml @@ -6,7 +6,6 @@ edition.workspace = true homepage.workspace = true license.workspace = true repository.workspace = true -readme = "README.md" version.workspace = true [package.metadata.docs.rs] diff --git a/pallets/smith-members/README.md b/pallets/smith-members/README.md deleted file mode 100644 index 655534a2a74d357c3d0f856dd3e4de6493eddd44..0000000000000000000000000000000000000000 --- a/pallets/smith-members/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Duniter smith pallet - -The bridge between `identity` and `authority-members` pallet. \ No newline at end of file diff --git a/pallets/smith-members/src/lib.rs b/pallets/smith-members/src/lib.rs index 883ed202de2797dea5737498640c1c695a598ceb..b9bf58af2cba92bcd7fa5d7a0a0ad3887832efa2 100644 --- a/pallets/smith-members/src/lib.rs +++ b/pallets/smith-members/src/lib.rs @@ -14,6 +14,29 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Smith Pallet +//! +//! The Smith pallet in Duniter serves as a bridge between the `identity` and `authority-members` pallets. +//! +//! ## Overview +//! +//! The Smith pallet manages the certification and membership status of Smiths. Smiths are identities that have met certain requirements and play a critical role in the network's operations (block authoring, distance evaluation). +//! +//! ## Key Concepts +//! +//! ### Smith Status +//! +//! The status of an identity within the Smith pallet can be one of the following: +//! - **Invited**: The identity has been invited by a Smith but has not yet accepted the invitation. +//! - **Pending**: The identity has accepted the invitation and is pending to become a full Smith. +//! - **Smith**: The identity has fulfilled the requirements and is a full-fledged Smith, eligible to perform critical network functions. +//! - **Excluded**: The identity has been removed from the Smiths set but its certifications are retained for tracking purposes. +//! +//! ### Certifications +//! +//! Certifications are crucial in determining Smith status: +//! - An identity needs a minimum number of certifications to become a Smith (`MinCertForMembership`). + #![cfg_attr(not(feature = "std"), no_std)] #[cfg(test)] @@ -48,22 +71,27 @@ pub use pallet::*; use pallet_authority_members::SessionIndex; pub use types::*; +/// Reasons for the removal of a Smith identity. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum SmithRemovalReason { + /// Membership was lost due to expiration or other reasons. LostMembership, + /// Smith was offline for too long. OfflineTooLong, + /// Smith was blacklisted. Blacklisted, } +/// Possible statuses of a Smith identity. #[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 + /// The identity has been invited by a Smith but has not accepted yet. Invited, - /// The identity has accepted to eventually become a smith + /// The identity has accepted to eventually become a Smith. Pending, - /// The identity has reached the requirements to become a smith and can now goGoOnline() or invite/certify other smiths + /// The identity has reached the requirements to become a Smith and can now perform Smith operations. Smith, - /// The identity has been removed from the smiths set but is kept to keep track of its certifications + /// The identity has been removed from the Smiths set but is kept to track its certifications. Excluded, } @@ -85,13 +113,15 @@ pub mod pallet { /// The pallet's config trait. #[pallet::config] pub trait Config: frame_system::Config { - /// To only allow WoT members to be invited + /// Trait to check if identity is a WoT members. 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. + + /// The overarching event type for this pallet. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// A short identity index. + + /// A short identity index type. type IdtyIndex: Parameter + Member + AtLeast32BitUnsigned @@ -101,22 +131,29 @@ pub mod pallet { + MaybeSerializeDeserialize + Debug + MaxEncodedLen; - /// Identifier for an authority-member + + /// Identifier type for an authority-member. type MemberId: Copy + Ord + MaybeSerializeDeserialize + Parameter; - /// Something that gives the IdtyId of an AccountId and reverse + + /// Something that gives the IdtyIndex of an AccountId and reverse. type IdtyAttr: duniter_primitives::Idty<Self::IdtyIndex, Self::AccountId>; - // /// Something that give the owner key of an identity + + /// Something that gives the AccountId of an identity. type IdtyIdOfAuthorityId: Convert<Self::MemberId, Option<Self::IdtyIndex>>; - /// Maximum number of active certifications by issuer + + /// Maximum number of active certifications per issuer. #[pallet::constant] type MaxByIssuer: Get<u32>; - /// Minimum number of certifications to become a Smith + + /// Minimum number of certifications required to become a Smith. #[pallet::constant] type MinCertForMembership: Get<u32>; - /// Maximum duration of inactivity before a smith is removed + + /// Maximum duration of inactivity allowed before a Smith is removed. #[pallet::constant] type SmithInactivityMaxDuration: Get<u32>; - /// Type representing the weight of this pallet + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; } @@ -220,19 +257,19 @@ pub mod pallet { } } - /// maps identity index to smith status + /// The Smith metadata for each identity. #[pallet::storage] #[pallet::getter(fn smiths)] pub type Smiths<T: Config> = StorageMap<_, Twox64Concat, T::IdtyIndex, SmithMeta<T::IdtyIndex>, OptionQuery>; - /// maps session index to possible smith removals + /// The indexes of Smith to remove at a given session. #[pallet::storage] #[pallet::getter(fn expires_on)] pub type ExpiresOn<T: Config> = StorageMap<_, Twox64Concat, SessionIndex, Vec<T::IdtyIndex>, OptionQuery>; - /// stores the current session index + /// The current session index. #[pallet::storage] #[pallet::getter(fn current_session)] pub type CurrentSession<T: Config> = StorageValue<_, SessionIndex, ValueQuery>; @@ -275,7 +312,7 @@ pub mod pallet { #[pallet::call] impl<T: Config> Pallet<T> { - /// Invite a WoT member to try becoming a Smith + /// Invite a member of the Web of Trust to attempt becoming a Smith. #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::invite_smith())] pub fn invite_smith( @@ -290,7 +327,7 @@ pub mod pallet { Ok(().into()) } - /// Accept an invitation (must have been invited first) + /// Accept an invitation to become a Smith (must have been invited first). #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::accept_invitation())] pub fn accept_invitation(origin: OriginFor<T>) -> DispatchResultWithPostInfo { @@ -302,7 +339,7 @@ pub mod pallet { Ok(().into()) } - /// Certify an invited smith which can lead the certified to become a Smith + /// Certify an invited Smith, which can lead the certified to become a Smith. #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::certify_smith())] pub fn certify_smith( @@ -320,6 +357,7 @@ pub mod pallet { } impl<T: Config> Pallet<T> { + /// Check conditions before inviting a potential Smith. fn check_invite_smith( issuer: T::IdtyIndex, receiver: T::IdtyIndex, @@ -347,6 +385,7 @@ impl<T: Config> Pallet<T> { Ok(().into()) } + /// Perform the invitation of a potential Smith. fn do_invite_smith(issuer: T::IdtyIndex, receiver: T::IdtyIndex) { let new_expires_on = CurrentSession::<T>::get() + T::SmithInactivityMaxDuration::get(); let mut existing = Smiths::<T>::get(receiver).unwrap_or_default(); @@ -358,6 +397,7 @@ impl<T: Config> Pallet<T> { Self::deposit_event(Event::<T>::InvitationSent { issuer, receiver }); } + /// Check conditions before accepting an invitation to become a Smith. fn check_accept_invitation(receiver: T::IdtyIndex) -> DispatchResultWithPostInfo { let pretender_status = Smiths::<T>::get(receiver) .ok_or(Error::<T>::OriginHasNeverBeenInvited)? @@ -369,6 +409,7 @@ impl<T: Config> Pallet<T> { Ok(().into()) } + /// Accept the invitation to become a Smith. fn do_accept_invitation(receiver: T::IdtyIndex) -> DispatchResultWithPostInfo { Smiths::<T>::mutate(receiver, |maybe_smith_meta| { if let Some(smith_meta) = maybe_smith_meta { @@ -381,6 +422,7 @@ impl<T: Config> Pallet<T> { Ok(().into()) } + /// Check conditions before certifying a potential Smith. fn check_certify_smith( issuer_index: T::IdtyIndex, receiver_index: T::IdtyIndex, @@ -424,6 +466,7 @@ impl<T: Config> Pallet<T> { Ok(().into()) } + /// Perform certification of a potential Smith by another Smith. fn do_certify_smith(receiver: T::IdtyIndex, issuer: T::IdtyIndex) { // - adds a certification in issuer issued list Smiths::<T>::mutate(issuer, |maybe_smith_meta| { @@ -471,6 +514,7 @@ impl<T: Config> Pallet<T> { }); } + /// Handle the removal of Smiths whose expiration time has been reached at a given session index. fn on_exclude_expired_smiths(at: SessionIndex) { if let Some(smiths_to_remove) = ExpiresOn::<T>::get(at) { for smith in smiths_to_remove { @@ -485,6 +529,7 @@ impl<T: Config> Pallet<T> { } } + /// Handle actions upon the removal of a Web of Trust member. pub fn on_removed_wot_member(idty_index: T::IdtyIndex) -> Weight { let mut weight = T::WeightInfo::on_removed_wot_member_empty(); if Smiths::<T>::get(idty_index).is_some() { @@ -494,6 +539,7 @@ impl<T: Config> Pallet<T> { weight } + /// Perform the exclusion of a Smith. fn _do_exclude_smith(receiver: T::IdtyIndex, reason: SmithRemovalReason) { let mut lost_certs = vec![]; Smiths::<T>::mutate(receiver, |maybe_smith_meta| { @@ -528,6 +574,7 @@ impl<T: Config> Pallet<T> { }); } + /// Handle the event when a Smith goes online. pub fn on_smith_goes_online(idty_index: T::IdtyIndex) { if let Some(smith_meta) = Smiths::<T>::get(idty_index) { if smith_meta.expires_on.is_some() { @@ -542,6 +589,7 @@ impl<T: Config> Pallet<T> { } } + /// Handle the event when a Smith goes offline. pub fn on_smith_goes_offline(idty_index: T::IdtyIndex) { if let Some(smith_meta) = Smiths::<T>::get(idty_index) { if smith_meta.expires_on.is_none() { @@ -558,6 +606,7 @@ impl<T: Config> Pallet<T> { } } + /// Provide whether the given identity index is a Smith. fn provide_is_member(idty_id: &T::IdtyIndex) -> bool { let Some(smith) = Smiths::<T>::get(idty_id) else { return false; diff --git a/pallets/smith-members/src/traits.rs b/pallets/smith-members/src/traits.rs index f59b6fc1c775e15ba69e32704da9238516a18db4..3fc6aaecb1ca95189d91bbc60c5e25f21607e238 100644 --- a/pallets/smith-members/src/traits.rs +++ b/pallets/smith-members/src/traits.rs @@ -1,8 +1,11 @@ use crate::SmithRemovalReason; +/// Trait for handling actions when a Smith is deleted. pub trait OnSmithDelete<IdtyIndex> { + /// Handle the deletion of a smith. fn on_smith_delete(idty_index: IdtyIndex, reason: 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 d19aabf34066b94df15953113d4050f2fdc357d5..48761f3d5ab342672b6cab22f8eb5e756347b897 100644 --- a/pallets/smith-members/src/types.rs +++ b/pallets/smith-members/src/types.rs @@ -22,16 +22,16 @@ use frame_support::pallet_prelude::*; use scale_info::TypeInfo; use sp_staking::SessionIndex; -/// certification metadata attached to an identity +/// Represents a certification metadata attached to a Smith identity. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct SmithMeta<IdtyIndex> { - /// current status of the smith + /// Current status of the Smith. pub status: SmithStatus, - /// the session at which the smith will expire (for lack of validation activity) + /// The session at which the Smith will expire (for lack of validation activity). pub expires_on: Option<SessionIndex>, - /// the certifications issued to other smiths + /// Certifications issued to other Smiths. pub issued_certs: sp_std::vec::Vec<IdtyIndex>, - /// the certifications received from other smiths + /// Certifications received from other Smiths. pub received_certs: sp_std::vec::Vec<IdtyIndex>, } diff --git a/pallets/universal-dividend/README.md b/pallets/universal-dividend/README.md deleted file mode 100644 index b7e862551d60c73dd215e25d31647c2357dfc4e0..0000000000000000000000000000000000000000 --- a/pallets/universal-dividend/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Duniter universal dividend pallet - -One of the main features of Duniter is the Universal Dividend based on the Relative Theory of Money. It is both a daily monetary creation and a measure unit. - -This pallet provides functions to create UDs and transfer an amount of currency counted in UD. It should be noted that the UD is not actually created every day on every account which would be very resource consuming but must be claimed by the member in a given extrinsic. \ No newline at end of file diff --git a/pallets/universal-dividend/src/lib.rs b/pallets/universal-dividend/src/lib.rs index 4609384d45c083b74d8f89b2cdf8066b3fe05419..70518f7fd0f83752431c2e5f5c69a5385401cde9 100644 --- a/pallets/universal-dividend/src/lib.rs +++ b/pallets/universal-dividend/src/lib.rs @@ -14,6 +14,18 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. +//! # Duniter Universal Dividend Pallet +//! +//! One of Duniter's core features is the Universal Dividend (UD), which operates based on the Relative Theory of Money. The UD serves both as a daily monetary creation mechanism and a unit of measure within the Duniter ecosystem. +//! +//! ## Overview +//! +//! This pallet enables: +//! - Creation of Universal Dividends (UD) as a daily monetary issuance and measure unit. +//! - Transfer of currency denominated in UD between accounts. +//! +//! **Note**: The UD is not automatically created daily for every account due to resource constraints. Instead, members must claim their UD using a specific extrinsic. + #![cfg_attr(not(feature = "std"), no_std)] mod benchmarking; @@ -62,60 +74,63 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] - //#[pallet::without_storage_info] pub struct Pallet<T>(_); #[pallet::config] pub trait Config: frame_system::Config + pallet_timestamp::Config { - // Moment into Balance converter + /// Something that convert a Moment inot a Balance. type MomentIntoBalance: Convert<Self::Moment, BalanceOf<Self>>; - // The currency + + /// The currency type used in this pallet. type Currency: fungible::Balanced<Self::AccountId> + fungible::Mutate<Self::AccountId>; + /// Maximum number of past UD revaluations to keep in storage. #[pallet::constant] type MaxPastReeval: Get<u32>; - /// Somethings that must provide the number of accounts allowed to create the universal dividend + + /// Provides the number of accounts allowed to create the universal dividend. type MembersCount: Get<BalanceOf<Self>>; - /// Somethings that must provide the list of accounts ids allowed to create the universal dividend + + /// Storage for mapping AccountId to their first eligible UD creation time. type MembersStorage: frame_support::traits::StoredMap<Self::AccountId, FirstEligibleUd>; - /// Because this pallet emits events, it depends on the runtime's definition of an event. + + /// The overarching event type for this pallet. type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// Square of the money growth rate per ud reevaluation period + + /// Square of the money growth rate per UD reevaluation period. #[pallet::constant] type SquareMoneyGrowthRate: Get<Perbill>; - /// Universal dividend creation period (ms) + + /// Universal dividend creation period in milliseconds. #[pallet::constant] type UdCreationPeriod: Get<Self::Moment>; - /// Universal dividend reevaluation period (ms) + + /// Universal dividend reevaluation period in milliseconds. #[pallet::constant] type UdReevalPeriod: Get<Self::Moment>; - /// The number of units to divide the amounts expressed in number of UDs - /// Example: If you wish to express the UD amounts with a maximum precision of the order - /// of the milliUD, choose 1000 - #[pallet::constant] - type UnitsPerUd: Get<BalanceOf<Self>>; - /// Pallet weights info + + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; - /// Something that gives the IdtyId of an AccountId and reverse + + /// Something that gives the IdtyIndex of an AccountId and reverse, used for benchmarks. #[cfg(feature = "runtime-benchmarks")] type IdtyAttr: duniter_primitives::Idty<u32, Self::AccountId>; } // STORAGE // - /// Current UD amount + /// The current Universal Dividend value. #[pallet::storage] #[pallet::getter(fn current_ud)] pub type CurrentUd<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>; - // default value for number of the next UD + /// The default index for the current Universal Dividend. #[pallet::type_value] pub fn DefaultForCurrentUdIndex() -> UdIndex { 1 } - /// Current UD index - // (more like the index of the ongoing UD = the next one) + /// The current Universal Dividend index. #[pallet::storage] #[pallet::getter(fn ud_index)] pub type CurrentUdIndex<T: Config> = @@ -136,22 +151,22 @@ pub mod pallet { ConstU32<300_000>, >; - /// Total quantity of money created by universal dividend (does not take into account the possible destruction of money) + /// The total quantity of money created by Universal Dividend, excluding potential money destruction. #[pallet::storage] #[pallet::getter(fn total_money_created)] pub type MonetaryMass<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>; - /// Next UD reevaluation + /// The next Universal Dividend re-evaluation. #[pallet::storage] #[pallet::getter(fn next_reeval)] pub type NextReeval<T: Config> = StorageValue<_, T::Moment, OptionQuery>; - /// Next UD creation + /// The next Universal Dividend creation. #[pallet::storage] #[pallet::getter(fn next_ud)] pub type NextUd<T: Config> = StorageValue<_, T::Moment, OptionQuery>; - /// Past UD reevaluations + /// The past Universal Dividend re-evaluations. #[pallet::storage] #[pallet::getter(fn past_reevals)] pub type PastReevals<T: Config> = @@ -330,7 +345,7 @@ pub mod pallet { }) } - /// like balance.transfer, but give an amount in UD + /// like balance.transfer, but give an amount in milliUD fn do_transfer_ud( origin: OriginFor<T>, dest: <T::Lookup as StaticLookup>::Source, @@ -343,7 +358,7 @@ pub mod pallet { T::Currency::transfer( &who, &dest, - value.saturating_mul(ud_amount) / T::UnitsPerUd::get(), + value.saturating_mul(ud_amount) / 1_000u32.into(), preservation, )?; Ok(().into()) @@ -406,7 +421,7 @@ pub mod pallet { #[pallet::call] impl<T: Config> Pallet<T> { - /// Claim Universal Dividends + /// Claim Universal Dividends. #[pallet::call_index(0)] #[pallet::weight(<T as pallet::Config>::WeightInfo::claim_uds(T::MaxPastReeval::get()))] pub fn claim_uds(origin: OriginFor<T>) -> DispatchResultWithPostInfo { @@ -425,7 +440,7 @@ pub mod pallet { Self::do_transfer_ud(origin, dest, value, Preservation::Expendable) } - /// Transfer some liquid free balance to another account, in milliUD. + /// Transfer some liquid free balance to another account in milliUD and keep the account alive. #[pallet::call_index(2)] #[pallet::weight(<T as pallet::Config>::WeightInfo::transfer_ud_keep_alive())] pub fn transfer_ud_keep_alive( @@ -440,12 +455,12 @@ pub mod pallet { // PUBLIC FUNCTIONS impl<T: Config> Pallet<T> { + /// Initialize the first eligible Universal Dividend index. pub fn init_first_eligible_ud() -> FirstEligibleUd { CurrentUdIndex::<T>::get().into() } - /// function to call when removing a member - /// auto-claims UDs + /// Handle the removal of a member, which automatically claims Universal Dividends. pub fn on_removed_member(first_ud_index: UdIndex, who: &T::AccountId) -> Weight { let current_ud_index = CurrentUdIndex::<T>::get(); if first_ud_index < current_ud_index { diff --git a/pallets/universal-dividend/src/mock.rs b/pallets/universal-dividend/src/mock.rs index b1397ffe57790f6f8b624fbb69e49bb4633bf5c2..233ec61e7aa9e8c538c362a05036e56b6eec9835 100644 --- a/pallets/universal-dividend/src/mock.rs +++ b/pallets/universal-dividend/src/mock.rs @@ -150,7 +150,6 @@ impl pallet_universal_dividend::Config for Test { type SquareMoneyGrowthRate = SquareMoneyGrowthRate; type UdCreationPeriod = UdCreationPeriod; type UdReevalPeriod = UdReevalPeriod; - type UnitsPerUd = frame_support::traits::ConstU64<1_000>; type WeightInfo = (); } diff --git a/pallets/universal-dividend/src/types.rs b/pallets/universal-dividend/src/types.rs index b7bc2bed90975e3e5dc699921daa3b011e959b50..bcebf1bd781e81c6a14903b532da1788d383f441 100644 --- a/pallets/universal-dividend/src/types.rs +++ b/pallets/universal-dividend/src/types.rs @@ -20,6 +20,7 @@ use sp_runtime::RuntimeDebug; pub type UdIndex = u16; +/// Represents the first eligible Universal Dividend. #[derive( Clone, Copy, Default, Eq, PartialEq, RuntimeDebug, serde::Deserialize, serde::Serialize, )] diff --git a/pallets/upgrade-origin/README.md b/pallets/upgrade-origin/README.md deleted file mode 100644 index 204c2a034feefc807118bd55572fc21b5c5be25c..0000000000000000000000000000000000000000 --- a/pallets/upgrade-origin/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Duniter upgrade origin pallet - -TODO \ No newline at end of file diff --git a/pallets/upgrade-origin/src/lib.rs b/pallets/upgrade-origin/src/lib.rs index bcd8ad688774727ba61fbd5eaa1c2d0c0a38cc5e..cf108ff25c0efa448f5311086c0e2b9b94e234be 100644 --- a/pallets/upgrade-origin/src/lib.rs +++ b/pallets/upgrade-origin/src/lib.rs @@ -54,18 +54,18 @@ pub mod pallet { /// The overarching event type. type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>; - /// The upgradable origin + /// The origin type required for performing upgradable operations. type UpgradableOrigin: EnsureOrigin<Self::RuntimeOrigin>; - /// Pallet weights info + /// Type representing the weight of this pallet. type WeightInfo: WeightInfo; + /// Type representing the worst case origin type used in weight benchmarks. #[cfg(feature = "runtime-benchmarks")] - /// The worst case origin type to use in weights benchmarking type WorstCaseOriginType: Into<Self::RuntimeOrigin>; + /// Retrieves the worst case origin for use in weight benchmarks. #[cfg(feature = "runtime-benchmarks")] - /// The worst case origin to use in weights benchmarking type WorstCaseOrigin: Get<Self::WorstCaseOriginType>; } diff --git a/primitives/distance/src/lib.rs b/primitives/distance/src/lib.rs index 1d4690942ba82b0bbb72500f24910bda56827146..9e67b72f8ba6b6b4dacba77b9dfb31871e2453a9 100644 --- a/primitives/distance/src/lib.rs +++ b/primitives/distance/src/lib.rs @@ -29,6 +29,7 @@ use std::marker::PhantomData; pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"distanc0"; +/// Represents the result of a distance computation. #[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] pub struct ComputationResult { pub distances: sp_std::vec::Vec<Perbill>, diff --git a/primitives/membership/src/lib.rs b/primitives/membership/src/lib.rs index c98121711ad55d7e3504356af62b1e1b5539e6b6..96e37af823353829e8014756053b371d5a77bb11 100644 --- a/primitives/membership/src/lib.rs +++ b/primitives/membership/src/lib.rs @@ -27,7 +27,7 @@ use frame_support::pallet_prelude::{RuntimeDebug, Weight}; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; -/// membership events +/// Represent membership-related events. pub enum Event<IdtyId> { /// A membership was acquired. MembershipAdded(IdtyId), @@ -37,6 +37,7 @@ pub enum Event<IdtyId> { MembershipRenewed(IdtyId), } +/// Represent membership data. #[derive( Encode, Decode, diff --git a/resources/metadata.scale b/resources/metadata.scale index bf88b3ce9a6e05e2a98b8c43493369f717191571..cd7176512ddbd3d7cfa4b633e8d3ef6a071d0813 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 967139552b6cbbf29ff5c93245f2aebd3073d12e..ef3af870aae2010247505dde5ba9f7de59d8a4d3 100644 --- a/runtime/common/src/pallets_config.rs +++ b/runtime/common/src/pallets_config.rs @@ -448,7 +448,6 @@ macro_rules! pallets_config { type SquareMoneyGrowthRate = SquareMoneyGrowthRate; type UdCreationPeriod = UdCreationPeriod; type UdReevalPeriod = UdReevalPeriod; - type UnitsPerUd = frame_support::traits::ConstU64<1_000>; type WeightInfo = common_runtime::weights::pallet_universal_dividend::WeightInfo<Runtime>; }