From 244f2523449ac0458a1ca7087b3c5b0ca19432b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Moreau?= <cem.moreau@gmail.com> Date: Mon, 15 Jan 2024 13:19:10 +0100 Subject: [PATCH] smith-members (nodes/rust/duniter-v2s!217) * rebase: update metadata.scale * review: replace `expect` by `if let Some` * review: lost membership is to be handled by `OnMembershipEventHandler` * feat(smith-members): review: docstring * feat(smith-members): review: auteur * fix(smith-members): test * clean(smith-members): dead code * feat(smith-members): disable certification replay * refac(smith-members): prefix "on_" for handlers * fix(smith-members): clippy again * fix(smith-members): clippy * feat(smith-members): benchmarks * fix(smith-members): clippy for benchmarking * refac(smith-members): u32 / usize * refac(smith-members): cleaner code for smith invitation * refac(smith-members): wrong TODO * refac(smith-members): SmithInactivityMaxDuration * refac(smith-members): remove comment TODO * refac(smith-members): authority-members OnBlacklistedMember is no more used * refac(smith-members): authority-members OnRemovedMember is no more used * fix(smith-members): remove some TODO * refac(smith-members): remove Instance1 for WoT * refac(smith-members): remove IsSubWoT * test(smith-members): non-applicable tests * test(smith-members): test_revoke_idty * test(smith-members): test_smith_member_can_revoke_its_idty * test(smith-members): change_owner_key * feat(smith-members): replace smith-wot by smith-members * feat(smith-members): only online smiths can invite/certify other smiths * feat(smith-members): only WoT members can be invited * feat(smith-members): check IsWoTMember * feat(smith-members): refac error names + fix cert on excluded * feat(smith-members): events * feat(smith-members): clippy * feat(smith-members): refact: constants * feat(smith-members): max stock of certifications per smith * feat(smith-members): smith account can be excluded, not deleted * feat(smith-members): refact: renaming * feat(smith-members): refact: provide_is_member * feat(smith-members): refact: check_* and do_* functions * feat(smith-members): remove CertsByReceiver (all in Smiths) * feat(smith-members): weird things * feat(smith-members): blacklisting stub * feat(smith-members): smith expires_on * feat(smith-members): remove Counted * feat(smith-members): accept_invitation * feat(smith-members): invite_smith + certify --- .gitlab-ci.yml | 1 + Cargo.lock | 25 + Cargo.toml | 1 + end2end-tests/cucumber-genesis/default.json | 7 +- end2end-tests/cucumber-genesis/wot.json | 7 +- node/src/chain_spec/gdev.rs | 36 +- node/src/chain_spec/gen_genesis_data.rs | 179 +++--- node/src/chain_spec/gtest.rs | 25 +- pallets/authority-members/src/impls.rs | 10 +- pallets/authority-members/src/lib.rs | 28 +- pallets/authority-members/src/mock.rs | 3 +- pallets/authority-members/src/traits.rs | 20 +- pallets/certification/src/benchmarking.rs | 50 +- pallets/certification/src/lib.rs | 83 ++- pallets/certification/src/tests.rs | 10 +- pallets/distance/src/mock.rs | 3 +- pallets/duniter-test-parameters/src/lib.rs | 18 +- pallets/duniter-wot/src/lib.rs | 143 ++--- pallets/duniter-wot/src/mock.rs | 112 +--- pallets/duniter-wot/src/tests.rs | 281 +-------- pallets/identity/src/lib.rs | 2 - pallets/identity/src/traits.rs | 5 - pallets/identity/src/types.rs | 1 + pallets/membership/src/benchmarking.rs | 26 +- pallets/membership/src/lib.rs | 57 +- pallets/membership/src/tests.rs | 2 +- pallets/smith-members/Cargo.toml | 56 ++ pallets/smith-members/README.md | 3 + pallets/smith-members/src/benchmarking.rs | 105 ++++ pallets/smith-members/src/impls.rs | 28 + pallets/smith-members/src/lib.rs | 552 +++++++++++++++++ pallets/smith-members/src/mock.rs | 123 ++++ pallets/smith-members/src/tests.rs | 577 ++++++++++++++++++ pallets/smith-members/src/traits.rs | 8 + pallets/smith-members/src/types.rs | 49 ++ pallets/smith-members/src/weights.rs | 38 ++ resources/gdev.yaml | 14 +- resources/metadata.scale | Bin 132253 -> 129512 bytes runtime/common/Cargo.toml | 2 + runtime/common/src/handlers.rs | 79 +-- runtime/common/src/pallets_config.rs | 62 +- runtime/common/src/providers.rs | 36 +- runtime/common/src/weights.rs | 3 +- .../pallet_certification_smith_cert.rs | 155 ----- .../pallet_membership_smith_membership.rs | 172 ------ .../src/weights/pallet_smith_members.rs | 105 ++++ runtime/g1/Cargo.toml | 3 + runtime/g1/src/lib.rs | 48 +- runtime/g1/src/parameters.rs | 17 +- runtime/gdev/Cargo.toml | 3 + runtime/gdev/src/lib.rs | 58 +- runtime/gdev/tests/common/mod.rs | 59 +- runtime/gdev/tests/fixme_tests.rs | 12 +- runtime/gdev/tests/integration_tests.rs | 251 ++++++-- runtime/gtest/Cargo.toml | 3 + runtime/gtest/src/lib.rs | 48 +- runtime/gtest/src/parameters.rs | 17 +- 57 files changed, 2390 insertions(+), 1431 deletions(-) create mode 100644 pallets/smith-members/Cargo.toml create mode 100644 pallets/smith-members/README.md create mode 100644 pallets/smith-members/src/benchmarking.rs create mode 100644 pallets/smith-members/src/impls.rs create mode 100644 pallets/smith-members/src/lib.rs create mode 100644 pallets/smith-members/src/mock.rs create mode 100644 pallets/smith-members/src/tests.rs create mode 100644 pallets/smith-members/src/traits.rs create mode 100644 pallets/smith-members/src/types.rs create mode 100644 pallets/smith-members/src/weights.rs delete mode 100644 runtime/common/src/weights/pallet_certification_smith_cert.rs delete mode 100644 runtime/common/src/weights/pallet_membership_smith_membership.rs create mode 100644 runtime/common/src/weights/pallet_smith_members.rs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ce5414b95..327707ff9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -94,6 +94,7 @@ run_benchmarks: tags: - podman +# FIXME: "gtest_build" gdev_build: stage: build image: rust:1-bullseye diff --git a/Cargo.lock b/Cargo.lock index 7c939dae9..d4e07f05f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,6 +1160,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", + "pallet-smith-members", "pallet-timestamp", "pallet-treasury", "pallet-universal-dividend", @@ -3171,6 +3172,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", + "pallet-smith-members", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -3241,6 +3243,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", + "pallet-smith-members", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -3572,6 +3575,7 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", + "pallet-smith-members", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -6348,6 +6352,27 @@ dependencies = [ "sp-std 5.0.0", ] +[[package]] +name = "pallet-smith-members" +version = "3.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "maplit", + "pallet-authority-members", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std 5.0.0", +] + [[package]] name = "pallet-sudo" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 5517414ea..362749c15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -156,6 +156,7 @@ members = [ 'pallets/membership', 'pallets/oneshot-account', 'pallets/authority-members', + 'pallets/smith-members', 'pallets/universal-dividend', 'pallets/upgrade-origin', 'primitives/membership', diff --git a/end2end-tests/cucumber-genesis/default.json b/end2end-tests/cucumber-genesis/default.json index fab39aad6..245e91e31 100644 --- a/end2end-tests/cucumber-genesis/default.json +++ b/end2end-tests/cucumber-genesis/default.json @@ -56,13 +56,8 @@ "pending_membership_period": 500, "ud_creation_period": 60000, "ud_reeval_period": 600000, - "smith_cert_period": 15, "smith_cert_max_by_issuer": 8, - "smith_cert_min_received_cert_to_issue_cert": 2, - "smith_cert_validity_period": 1000, - "smith_membership_period": 1000, - "smith_pending_membership_period": 500, - "smith_wot_first_cert_issuable_on": 20, + "smith_inactivity_max_duration": 48, "smith_wot_min_cert_for_membership": 2, "wot_first_cert_issuable_on": 20, "wot_min_cert_for_create_idty_right": 2, diff --git a/end2end-tests/cucumber-genesis/wot.json b/end2end-tests/cucumber-genesis/wot.json index 4c7183b2a..6b1fad670 100644 --- a/end2end-tests/cucumber-genesis/wot.json +++ b/end2end-tests/cucumber-genesis/wot.json @@ -65,13 +65,8 @@ "pending_membership_period": 500, "ud_creation_period": 60000, "ud_reeval_period": 600000, - "smith_cert_period": 15, "smith_cert_max_by_issuer": 8, - "smith_cert_min_received_cert_to_issue_cert": 2, - "smith_cert_validity_period": 1000, - "smith_membership_period": 1000, - "smith_pending_membership_period": 500, - "smith_wot_first_cert_issuable_on": 20, + "smith_inactivity_max_duration": 48, "smith_wot_min_cert_for_membership": 2, "wot_first_cert_issuable_on": 20, "wot_min_cert_for_create_idty_right": 2, diff --git a/node/src/chain_spec/gdev.rs b/node/src/chain_spec/gdev.rs index 0639cbfed..4d80232c6 100644 --- a/node/src/chain_spec/gdev.rs +++ b/node/src/chain_spec/gdev.rs @@ -24,9 +24,8 @@ use common_runtime::*; use gdev_runtime::{ opaque::SessionKeys, pallet_universal_dividend, parameters, AccountConfig, AuthorityMembersConfig, BabeConfig, BalancesConfig, CertConfig, GenesisConfig, IdentityConfig, - MembershipConfig, ParametersConfig, QuotaConfig, Runtime, SessionConfig, SmithCertConfig, - SmithMembershipConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, - UniversalDividendConfig, WASM_BINARY, + MembershipConfig, ParametersConfig, QuotaConfig, Runtime, SessionConfig, SmithMembersConfig, + SudoConfig, SystemConfig, TechnicalCommitteeConfig, UniversalDividendConfig, WASM_BINARY, }; use jsonrpsee::core::JsonValue; use sc_network::config::MultiaddrWithPeerId; @@ -39,7 +38,7 @@ use std::{env, fs}; pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>; -type GenesisParameters = gdev_runtime::GenesisParameters<u32, u32, u64>; +type GenesisParameters = gdev_runtime::GenesisParameters<u32, u32, u64, u32>; const TOKEN_DECIMALS: usize = 2; const TOKEN_SYMBOL: &str = "ĞD"; @@ -94,17 +93,10 @@ fn get_parameters(parameters_from_file: &Option<GenesisParameters>) -> CommonPar cert_validity_period: parameters_from_file.cert_validity_period, distance_min_accessible_referees: Perbill::from_percent(80), // TODO: generalize distance_max_depth: 5, // TODO: generalize - smith_sub_wot_first_issuable_on: parameters_from_file.smith_wot_first_cert_issuable_on, smith_sub_wot_min_cert_for_membership: parameters_from_file .smith_wot_min_cert_for_membership, - smith_membership_membership_period: parameters_from_file.smith_membership_period, - smith_membership_pending_membership_period: parameters_from_file - .smith_pending_membership_period, - smith_cert_cert_period: parameters_from_file.smith_cert_period, smith_cert_max_by_issuer: parameters_from_file.smith_cert_max_by_issuer, - smith_cert_min_received_cert_to_be_able_to_issue_cert: parameters_from_file - .smith_cert_min_received_cert_to_issue_cert, - smith_cert_validity_period: parameters_from_file.smith_cert_validity_period, + smith_inactivity_max_duration: parameters_from_file.smith_inactivity_max_duration, cert_cert_period: parameters_from_file.cert_period, treasury_spend_period: <Runtime as pallet_treasury::Config>::SpendPeriod::get(), } @@ -290,8 +282,7 @@ fn genesis_data_to_gdev_genesis_conf( parameters, common_parameters: _, session_keys_map, - smith_certs_by_receiver, - smith_memberships, + initial_smiths, sudo_key, technical_committee_members, ud, @@ -366,13 +357,7 @@ fn genesis_data_to_gdev_genesis_conf( certs_by_receiver, }, membership: MembershipConfig { memberships }, - smith_cert: SmithCertConfig { - apply_cert_period_at_genesis: true, - certs_by_receiver: smith_certs_by_receiver, - }, - smith_membership: SmithMembershipConfig { - memberships: smith_memberships, - }, + smith_members: SmithMembersConfig { initial_smiths }, universal_dividend: UniversalDividendConfig { first_reeval: first_ud_reeval, first_ud, @@ -387,8 +372,6 @@ fn get_local_chain_parameters() -> Option<GenesisParameters> { let babe_epoch_duration = get_env("DUNITER_BABE_EPOCH_DURATION", 30) as u64; let cert_validity_period = get_env("DUNITER_CERT_VALIDITY_PERIOD", 1_000); let membership_period = get_env("DUNITER_MEMBERSHIP_PERIOD", 1_000); - let smith_cert_validity_period = get_env("DUNITER_SMITH_CERT_VALIDITY_PERIOD", 1_000); - let smith_membership_period = get_env("DUNITER_SMITH_MEMBERSHIP_PERIOD", 1_000); let ud_creation_period = get_env("DUNITER_UD_CREATION_PERIOD", 60_000); let ud_reeval_period = get_env("DUNITER_UD_REEEVAL_PERIOD", 1_200_000); Some(GenesisParameters { @@ -403,13 +386,8 @@ fn get_local_chain_parameters() -> Option<GenesisParameters> { pending_membership_period: 500, ud_creation_period, ud_reeval_period, - smith_cert_period: 15, smith_cert_max_by_issuer: 8, - smith_cert_min_received_cert_to_issue_cert: 2, - smith_cert_validity_period, - smith_membership_period, - smith_pending_membership_period: 500, - smith_wot_first_cert_issuable_on: 20, + smith_inactivity_max_duration: 48, smith_wot_min_cert_for_membership: 2, wot_first_cert_issuable_on: 20, wot_min_cert_for_create_idty_right: 2, diff --git a/node/src/chain_spec/gen_genesis_data.rs b/node/src/chain_spec/gen_genesis_data.rs index 1813434b7..ab9856efe 100644 --- a/node/src/chain_spec/gen_genesis_data.rs +++ b/node/src/chain_spec/gen_genesis_data.rs @@ -74,8 +74,7 @@ pub struct GenesisData<Parameters: DeserializeOwned, SessionKeys: Decode> { pub parameters: Option<Parameters>, pub common_parameters: Option<CommonParameters>, pub session_keys_map: BTreeMap<AccountId, SessionKeys>, - pub smith_certs_by_receiver: BTreeMap<u32, BTreeMap<u32, Option<u32>>>, - pub smith_memberships: BTreeMap<u32, MembershipData>, + pub initial_smiths: BTreeMap<u32, (bool, Vec<u32>)>, pub sudo_key: Option<AccountId>, pub technical_committee_members: Vec<AccountId>, pub ud: u64, @@ -235,9 +234,8 @@ struct CliqueSmith { session_keys: Option<String>, } -struct SmithWoT<SK: Decode> { - smith_certs_by_receiver: BTreeMap<u32, BTreeMap<u32, Option<u32>>>, - smith_memberships: BTreeMap<u32, sp_membership::MembershipData<u32>>, +struct SmithMembers<SK: Decode> { + initial_smiths_wot: BTreeMap<u32, (bool, Vec<u32>)>, session_keys_map: BTreeMap<<<MultiSignature as Verify>::Signer as IdentifyAccount>::AccountId, SK>, } @@ -249,7 +247,7 @@ struct GenesisInfo<'a> { inactive_identities: &'a HashMap<u32, String>, identities: &'a Vec<GenesisIdentity>, identity_index: &'a HashMap<u32, String>, - smith_memberships: &'a BTreeMap<u32, MembershipData>, + initial_smiths: &'a BTreeMap<u32, (bool, Vec<u32>)>, counter_online_authorities: &'a u32, counter_cert: &'a u32, counter_smith_cert: &'a u32, @@ -395,16 +393,14 @@ where was_fatal, counter_online_authorities, counter_smith_cert, - SmithWoT { - smith_certs_by_receiver, - smith_memberships, + SmithMembers { + initial_smiths_wot, session_keys_map, }, ) = create_smith_wot( &mut initial_authorities, &identities_v2, &smiths, - &common_parameters, &clique_smiths, )?; if was_fatal { @@ -429,7 +425,7 @@ where } // Verify smith certifications coherence - for (idty_index, certs) in &smith_certs_by_receiver { + for (idty_index, (_online, certs)) in &initial_smiths_wot { if certs.len() < common_parameters.smith_sub_wot_min_cert_for_membership as usize { log::error!( "[{}] has received only {}/{} smith certifications", @@ -515,7 +511,7 @@ where identities: &identities, inactive_identities: &inactive_identities, identity_index: &identity_index, - smith_memberships: &smith_memberships, + initial_smiths: &initial_smiths_wot, counter_online_authorities: &counter_online_authorities, counter_cert: &counter_cert, counter_smith_cert: &counter_smith_cert, @@ -637,8 +633,8 @@ where identities.len() - inactive_identities.len(), memberships.len() ); - assert_eq!(smith_memberships.len(), initial_authorities.len()); - assert_eq!(smith_memberships.len(), session_keys_map.len()); + assert_eq!(initial_smiths_wot.len(), initial_authorities.len()); + assert_eq!(initial_smiths_wot.len(), session_keys_map.len()); assert_eq!(identity_index.len(), identities.len()); assert_eq!( accounts.len(), @@ -657,7 +653,6 @@ where // genesis_certs_min_received => min_cert // genesis_memberships_expire_on => membership_period // genesis_smith_certs_min_received => smith_min_cert - // genesis_smith_memberships_expire_on => smith_membership_period let export = GenesisIndexerExport { first_ud, first_ud_reeval, @@ -730,8 +725,7 @@ where parameters, common_parameters: Some(common_parameters), session_keys_map, - smith_certs_by_receiver, - smith_memberships, + initial_smiths: initial_smiths_wot, sudo_key, technical_committee_members, ud, @@ -759,7 +753,7 @@ fn dump_genesis_info(info: GenesisInfo) { info.identity_index.len(), info.identities.len() - info.inactive_identities.len(), info.inactive_identities.len(), - info.smith_memberships.len(), + info.initial_smiths.len(), info.counter_online_authorities, info.counter_cert, info.counter_smith_cert, @@ -829,28 +823,15 @@ fn dump_genesis_info(info: GenesisInfo) { get_best_unit_and_diviser_for_perbill(p.distance_min_accessible_referees); let (distance_max_depth, distance_max_depth_unit) = get_best_unit_and_diviser_for_depth(p.distance_max_depth); - let (smith_sub_wot_first_issuable_on, smith_sub_wot_first_issuable_on_unit) = - get_best_unit_and_diviser_for_blocks(p.smith_sub_wot_first_issuable_on); - let (smith_sub_wot_min_cert_for_membership, smith_sub_wot_min_cert_for_membership_unit) = + let (smith_members_min_cert_for_membership, smith_members_min_cert_for_membership_unit) = get_best_unit_and_diviser_for_certs(p.smith_sub_wot_min_cert_for_membership); - let (smith_membership_membership_period, smith_membership_membership_period_unit) = - get_best_unit_and_diviser_for_blocks(p.smith_membership_membership_period); - let ( - smith_membership_pending_membership_period, - smith_membership_pending_membership_period_unit, - ) = get_best_unit_and_diviser_for_blocks(p.smith_membership_pending_membership_period); - let (smith_cert_cert_period, smith_cert_cert_period_unit) = - get_best_unit_and_diviser_for_blocks(p.smith_cert_cert_period); - let (smith_cert_max_by_issuer, smith_cert_max_by_issuer_unit) = + let (smith_members_max_by_issuer, smith_members_max_by_issuer_unit) = get_best_unit_and_diviser_for_certs(p.smith_cert_max_by_issuer); - let ( - smith_cert_min_received_cert_to_be_able_to_issue_cert, - smith_cert_min_received_cert_to_be_able_to_issue_cert_unit, - ) = get_best_unit_and_diviser_for_certs( - p.smith_cert_min_received_cert_to_be_able_to_issue_cert, - ); - let (smith_cert_validity_period, smith_cert_validity_period_unit) = - get_best_unit_and_diviser_for_blocks(p.smith_cert_validity_period); + let (smith_members_inactivity_max_duration, smith_members_inactivity_max_duration_unit) = + get_best_unit_and_diviser_for_sessions( + p.smith_inactivity_max_duration, + p.babe_epoch_duration, + ); let (treasury_spend_period, treasury_spend_period_unit) = get_best_unit_and_diviser_for_blocks(p.treasury_spend_period); @@ -883,14 +864,9 @@ fn dump_genesis_info(info: GenesisInfo) { - cert.validity_period: {} {} - distance.min_accessible_referees: {} {} - distance.max_depth: {} {}, - - smith_sub_wot.first_issuable_on: {} {} - - smith_sub_wot.min_cert_for_membership: {} {} - - smith_membership.membership_period: {} {} - - smith_membership.pending_membership_period: {} {} - - smith_cert.cert_period: {} {} - - smith_cert.max_by_issuer: {} {} - - smith_cert.min_received_cert_to_be_able_to_issue_cert: {} {} - - smith_cert.validity_period: {} {} + - smith_members.min_cert_for_membership: {} {} + - smith_members.max_by_issuer: {} {} + - smith_members.smith_inactivity_max_duration: {} {} - treasury.spend_period: {} {} - currency decimals: {}", babe_epoch_duration, @@ -945,22 +921,12 @@ fn dump_genesis_info(info: GenesisInfo) { distance_min_accessible_referees_unit, distance_max_depth, distance_max_depth_unit, - smith_sub_wot_first_issuable_on, - smith_sub_wot_first_issuable_on_unit, - smith_sub_wot_min_cert_for_membership, - smith_sub_wot_min_cert_for_membership_unit, - smith_membership_membership_period, - smith_membership_membership_period_unit, - smith_membership_pending_membership_period, - smith_membership_pending_membership_period_unit, - smith_cert_cert_period, - smith_cert_cert_period_unit, - smith_cert_max_by_issuer, - smith_cert_max_by_issuer_unit, - smith_cert_min_received_cert_to_be_able_to_issue_cert, - smith_cert_min_received_cert_to_be_able_to_issue_cert_unit, - smith_cert_validity_period, - smith_cert_validity_period_unit, + smith_members_min_cert_for_membership, + smith_members_min_cert_for_membership_unit, + smith_members_max_by_issuer, + smith_members_max_by_issuer_unit, + smith_members_inactivity_max_duration, + smith_members_inactivity_max_duration_unit, treasury_spend_period, treasury_spend_period_unit, info.common_parameters.decimals, @@ -979,6 +945,16 @@ fn get_best_unit_and_diviser_for_blocks(duration_in_blocks: u32) -> (f32, String get_best_unit_and_diviser_for_ms(duration_in_ms) } +fn get_best_unit_and_diviser_for_sessions( + duration_in_sessions: u32, + babe_epoch_duration_in_blocks: u64, +) -> (f32, String) { + let duration_in_ms = duration_in_sessions as f32 + * babe_epoch_duration_in_blocks as f32 + * (MILLISECS_PER_BLOCK as u32) as f32; + get_best_unit_and_diviser_for_ms(duration_in_ms) +} + fn get_best_unit_and_diviser_for_perbill_square(qty: Perbill) -> (f32, String) { let qty = f32::sqrt(qty.deconstruct() as f32 / 1_000_000_000f32) * 100f32; (qty, "%".to_string()) @@ -1073,16 +1049,14 @@ fn create_smith_wot<SK: Decode>( initial_authorities: &mut BTreeMap<u32, (AccountId32, bool)>, identities_v2: &HashMap<String, IdentityV2>, smiths: &Vec<SmithData>, - common_parameters: &CommonParameters, clique_smiths: &Option<Vec<CliqueSmith>>, -) -> Result<(bool, u32, u32, SmithWoT<SK>), String> { +) -> Result<(bool, u32, u32, SmithMembers<SK>), String> { let mut fatal = false; let mut counter_online_authorities = 0; // counter for smith certifications let mut counter_smith_cert = 0; let mut smith_certs_by_receiver = BTreeMap::new(); // smith memberships - let mut smith_memberships = BTreeMap::new(); let mut session_keys_map = BTreeMap::new(); // Then create the smith WoT for smith in smiths { @@ -1103,16 +1077,7 @@ fn create_smith_wot<SK: Decode>( &smith, identity, &identities_v2_clone, - common_parameters, )?; - - // smith memberships - smith_memberships.insert( - identity.index, - MembershipData { - expire_on: common_parameters.smith_membership_membership_period, - }, - ); } else { log::error!( "Smith '{}' does not correspond to exising identity", @@ -1125,9 +1090,18 @@ fn create_smith_wot<SK: Decode>( fatal, counter_online_authorities, counter_smith_cert, - SmithWoT { - smith_certs_by_receiver, - smith_memberships, + SmithMembers { + initial_smiths_wot: smith_certs_by_receiver + .iter() + .map(|(k, v)| { + let is_online = initial_authorities + .iter() + .filter(|(k2, (_, online))| *k2 == k && *online) + .count() + > 0; + (*k, (is_online, v.clone())) + }) + .collect(), session_keys_map, }, )) @@ -1549,15 +1523,14 @@ where } fn feed_smith_certs_by_receiver( - smith_certs_by_receiver: &mut BTreeMap<u32, BTreeMap<u32, Option<u32>>>, + smith_certs_by_receiver: &mut BTreeMap<u32, Vec<u32>>, clique_smiths: &Option<Vec<CliqueSmith>>, smith: &&SmithData, identity: &IdentityV2, identities_v2: &HashMap<String, IdentityV2>, - common_parameters: &CommonParameters, ) -> Result<u32, String> { let mut counter_smith_cert = 0; - let mut certs = BTreeMap::new(); + let mut certs = Vec::<u32>::new(); if clique_smiths.is_some() { // All initial smiths are considered to be certifying all each other clique_smiths @@ -1572,7 +1545,7 @@ fn feed_smith_certs_by_receiver( panic!("Identity '{}' does not exist", other_smith.name.as_str()) }) .index; - certs.insert(*issuer_index, None); + certs.push(*issuer_index); counter_smith_cert += 1; }); } else { @@ -1581,10 +1554,7 @@ fn feed_smith_certs_by_receiver( .get(issuer) .ok_or(format!("Identity '{}' does not exist", issuer))? .index; - certs.insert( - *issuer_index, - Some(common_parameters.smith_cert_validity_period), - ); + certs.push(*issuer_index); counter_smith_cert += 1; } } @@ -1767,11 +1737,11 @@ where let genesis_data_wallets_count = 0; let inactive_identities = HashMap::new(); - let smith_memberships = (1..=initial_smiths_len) - .map(|i| (i as u32, MembershipData { expire_on: 0 })) - .collect(); - - let (smith_certs_by_receiver, counter_smith_cert) = clique_wot(initial_smiths_len); + let initial_smiths_wot: BTreeMap<u32, (bool, Vec<u32>)> = clique_smith_wot(initial_smiths_len); + let counter_smith_cert = initial_smiths_wot + .iter() + .map(|(_, (_, v))| v.len()) + .sum::<usize>() as u32; let initial_authorities: BTreeMap< u32, @@ -1808,7 +1778,7 @@ where identities: &identities, inactive_identities: &inactive_identities, identity_index: &identity_index, - smith_memberships: &smith_memberships, + initial_smiths: &initial_smiths_wot, counter_online_authorities: &counter_online_authorities, counter_cert: &counter_cert, counter_smith_cert: &counter_smith_cert, @@ -1834,8 +1804,7 @@ where parameters, common_parameters: None, session_keys_map, - smith_certs_by_receiver, - smith_memberships, + initial_smiths: initial_smiths_wot, sudo_key: Some(root_key), technical_committee_members, ud, @@ -1871,6 +1840,23 @@ fn clique_wot( (certs_by_issuer, count) } +#[cfg(feature = "gdev")] +fn clique_smith_wot(initial_identities_len: usize) -> BTreeMap<IdtyIndex, (bool, Vec<IdtyIndex>)> { + let mut certs_by_issuer = BTreeMap::new(); + for i in 1..=initial_identities_len { + certs_by_issuer.insert( + i as IdtyIndex, + ( + true, + (1..=initial_identities_len) + .filter_map(|j| if i != j { Some(j as IdtyIndex) } else { None }) + .collect(), + ), + ); + } + certs_by_issuer +} + fn check_parameters_consistency( wallets: &BTreeMap<PubkeyV1, u64>, first_ud: &Option<u64>, @@ -1999,14 +1985,9 @@ pub struct CommonParameters { pub cert_validity_period: u32, pub distance_min_accessible_referees: Perbill, pub distance_max_depth: u32, - pub smith_sub_wot_first_issuable_on: u32, pub smith_sub_wot_min_cert_for_membership: u32, - pub smith_membership_membership_period: u32, - pub smith_membership_pending_membership_period: u32, - pub smith_cert_cert_period: u32, pub smith_cert_max_by_issuer: u32, - pub smith_cert_min_received_cert_to_be_able_to_issue_cert: u32, - pub smith_cert_validity_period: u32, + pub smith_inactivity_max_duration: u32, pub treasury_spend_period: u32, // TODO: replace u32 by BlockNumber when appropriate pub currency_name: String, diff --git a/node/src/chain_spec/gtest.rs b/node/src/chain_spec/gtest.rs index 796b2c7de..4b1ee27f2 100644 --- a/node/src/chain_spec/gtest.rs +++ b/node/src/chain_spec/gtest.rs @@ -20,12 +20,12 @@ use common_runtime::constants::*; use common_runtime::entities::IdtyData; use common_runtime::*; use frame_benchmarking::frame_support::traits::Get; +use gtest_runtime::SmithMembersConfig; use gtest_runtime::{ opaque::SessionKeys, pallet_universal_dividend, parameters, AccountConfig, AccountId, AuthorityMembersConfig, BabeConfig, BalancesConfig, CertConfig, GenesisConfig, IdentityConfig, - ImOnlineId, MembershipConfig, Perbill, QuotaConfig, Runtime, SessionConfig, SmithCertConfig, - SmithMembershipConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, - UniversalDividendConfig, WASM_BINARY, + ImOnlineId, MembershipConfig, Perbill, QuotaConfig, Runtime, SessionConfig, SudoConfig, + SystemConfig, TechnicalCommitteeConfig, UniversalDividendConfig, WASM_BINARY, }; use jsonrpsee::core::JsonValue; use sc_consensus_grandpa::AuthorityId as GrandpaId; @@ -98,15 +98,9 @@ fn get_parameters(_: &Option<GenesisParameters>) -> CommonParameters { cert_validity_period: parameters::ValidityPeriod::get(), distance_min_accessible_referees: Perbill::from_percent(80), // TODO: generalize distance_max_depth: 5, // TODO: generalize - smith_sub_wot_first_issuable_on: parameters::SmithWotFirstCertIssuableOn::get(), smith_sub_wot_min_cert_for_membership: parameters::SmithWotMinCertForMembership::get(), - smith_membership_membership_period: parameters::SmithMembershipPeriod::get(), - smith_membership_pending_membership_period: parameters::SmithPendingMembershipPeriod::get(), - smith_cert_cert_period: parameters::SmithCertPeriod::get(), + smith_inactivity_max_duration: parameters::SmithInactivityMaxDuration::get(), smith_cert_max_by_issuer: parameters::SmithMaxByIssuer::get(), - smith_cert_min_received_cert_to_be_able_to_issue_cert: - parameters::SmithMinReceivedCertToBeAbleToIssueCert::get(), - smith_cert_validity_period: parameters::SmithValidityPeriod::get(), cert_cert_period: parameters::CertPeriod::get(), treasury_spend_period: <Runtime as pallet_treasury::Config>::SpendPeriod::get(), } @@ -239,8 +233,7 @@ fn genesis_data_to_gtest_genesis_conf( parameters: _, common_parameters: _, session_keys_map, - smith_certs_by_receiver, - smith_memberships, + initial_smiths, sudo_key, technical_committee_members, ud, @@ -313,13 +306,7 @@ fn genesis_data_to_gtest_genesis_conf( certs_by_receiver, }, membership: MembershipConfig { memberships }, - smith_cert: SmithCertConfig { - apply_cert_period_at_genesis: true, - certs_by_receiver: smith_certs_by_receiver, - }, - smith_membership: SmithMembershipConfig { - memberships: smith_memberships, - }, + smith_members: SmithMembersConfig { initial_smiths }, universal_dividend: UniversalDividendConfig { first_reeval: first_ud_reeval, first_ud, diff --git a/pallets/authority-members/src/impls.rs b/pallets/authority-members/src/impls.rs index ade9f7437..d656f01e6 100644 --- a/pallets/authority-members/src/impls.rs +++ b/pallets/authority-members/src/impls.rs @@ -20,7 +20,6 @@ //! The offences are executed here based. The offenders are disconnected and //! can be added to a blacklist to avoid futur connection. -#![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::type_complexity)] use super::pallet::*; @@ -54,9 +53,8 @@ where match strategy { SlashStrategy::Blacklist => { for offender in offenders { - Blacklist::<T>::mutate(|blacklist| { - if let Some(member_id) = T::MemberIdOf::convert(offender.offender.0.clone()) - { + if let Some(member_id) = T::MemberIdOf::convert(offender.offender.0.clone()) { + Blacklist::<T>::mutate(|blacklist| { if !blacklist.contains(&member_id) { blacklist.push(member_id); Self::deposit_event(Event::MemberAddedToBlacklist { @@ -66,8 +64,8 @@ where } Self::insert_out(member_id); add_db_reads_writes(2, 1); - } - }) + }); + } } } SlashStrategy::Disconnect => { diff --git a/pallets/authority-members/src/lib.rs b/pallets/authority-members/src/lib.rs index 29c4ecaab..d4ebf6b3f 100644 --- a/pallets/authority-members/src/lib.rs +++ b/pallets/authority-members/src/lib.rs @@ -51,6 +51,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use sp_runtime::traits::{Convert, IsMember}; use sp_std::collections::btree_map::BTreeMap; + use sp_std::vec; /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -68,7 +69,8 @@ pub mod pallet { { type IsMember: IsMember<Self::MemberId>; type OnNewSession: OnNewSession; - type OnRemovedMember: OnRemovedMember<Self::MemberId>; + type OnOutgoingMember: OnOutgoingMember<Self::MemberId>; + type OnIncomingMember: OnIncomingMember<Self::MemberId>; /// Max number of authorities allowed #[pallet::constant] type MaxAuthorities: Get<u32>; @@ -401,7 +403,6 @@ pub mod pallet { // Emit event Self::deposit_event(Event::MemberRemoved { member: member_id }); - T::OnRemovedMember::on_removed_member(member_id); } /// perform incoming authorities insertion fn insert_in(member_id: T::MemberId) -> bool { @@ -513,20 +514,23 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> { let members_ids_to_add = IncomingAuthorities::<T>::take(); let members_ids_to_del = OutgoingAuthorities::<T>::take(); - if members_ids_to_add.is_empty() { - if members_ids_to_del.is_empty() { - // when no change to the set of autorities, return None - return None; - } else { - Self::deposit_event(Event::OutgoingAuthorities { - members: members_ids_to_del.clone(), - }); - } - } else { + if members_ids_to_add.is_empty() && members_ids_to_del.is_empty() { + // when no change to the set of autorities, return None + return None; + } + + for member_id in members_ids_to_add.iter() { + T::OnIncomingMember::on_incoming_member(*member_id); Self::deposit_event(Event::IncomingAuthorities { members: members_ids_to_add.clone(), }); } + for member_id in members_ids_to_del.iter() { + T::OnOutgoingMember::on_outgoing_member(*member_id); + Self::deposit_event(Event::OutgoingAuthorities { + members: members_ids_to_del.clone(), + }); + } // updates the list of OnlineAuthorities and returns the list of their key Some( diff --git a/pallets/authority-members/src/mock.rs b/pallets/authority-members/src/mock.rs index d04f0f47f..4c818534a 100644 --- a/pallets/authority-members/src/mock.rs +++ b/pallets/authority-members/src/mock.rs @@ -156,10 +156,11 @@ impl pallet_authority_members::Config for Test { type MemberId = u64; type MemberIdOf = ConvertInto; type OnNewSession = (); - type OnRemovedMember = (); type RemoveMemberOrigin = system::EnsureRoot<u64>; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); + type OnIncomingMember = (); + type OnOutgoingMember = (); } // Build genesis storage according to the mock runtime. diff --git a/pallets/authority-members/src/traits.rs b/pallets/authority-members/src/traits.rs index 81f36396e..2bb98f77d 100644 --- a/pallets/authority-members/src/traits.rs +++ b/pallets/authority-members/src/traits.rs @@ -24,10 +24,22 @@ impl OnNewSession for () { fn on_new_session(_: SessionIndex) {} } -pub trait OnRemovedMember<MemberId> { - fn on_removed_member(member_id: MemberId); +/// Handle the consequences of going in the authority set for other pallets. +/// Typically, a smith won't expire as long as he is in the authority set. +pub trait OnIncomingMember<MemberId> { + fn on_incoming_member(member_id: MemberId); +} +/// By default: no consequences +impl<MemberId> OnIncomingMember<MemberId> for () { + fn on_incoming_member(_: MemberId) {} } -impl<MemberId> OnRemovedMember<MemberId> for () { - fn on_removed_member(_: MemberId) {} +/// Handle the consequences of going out of authority set for other pallets. +/// Typically, the smiths are not allowed to stay offline for a too long time. +pub trait OnOutgoingMember<MemberId> { + fn on_outgoing_member(member_id: MemberId); +} +/// By default: no consequences +impl<MemberId> OnOutgoingMember<MemberId> for () { + fn on_outgoing_member(_: MemberId) {} } diff --git a/pallets/certification/src/benchmarking.rs b/pallets/certification/src/benchmarking.rs index 4a4b61a8e..553e34846 100644 --- a/pallets/certification/src/benchmarking.rs +++ b/pallets/certification/src/benchmarking.rs @@ -18,7 +18,7 @@ use super::*; -use frame_benchmarking::benchmarks_instance_pallet; +use frame_benchmarking::benchmarks; use frame_benchmarking::Zero; use frame_system::RawOrigin; use sp_runtime::traits::Convert; @@ -28,23 +28,23 @@ use maplit::btreemap; use crate::Pallet; -fn assert_has_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) { +fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { frame_system::Pallet::<T>::assert_has_event(generic_event.into()); } -fn add_certs<T: Config<I>, I: 'static>(i: u32, receiver: T::IdtyIndex) -> Result<(), &'static str> { - Pallet::<T, I>::remove_all_certs_received_by(RawOrigin::Root.into(), receiver)?; +fn add_certs<T: Config>(i: u32, receiver: T::IdtyIndex) -> Result<(), &'static str> { + Pallet::<T>::remove_all_certs_received_by(RawOrigin::Root.into(), receiver)?; for j in 1..i { - Pallet::<T, I>::do_add_cert_checked(j.into(), receiver, false)?; + Pallet::<T>::do_add_cert_checked(j.into(), receiver, false)?; } assert!( - CertsByReceiver::<T, I>::get(receiver).len() as u32 == i - 1, + CertsByReceiver::<T>::get(receiver).len() as u32 == i - 1, "Certs not added", ); Ok(()) } -benchmarks_instance_pallet! { +benchmarks! { where_clause { where T::IdtyIndex: From<u32>, @@ -54,47 +54,47 @@ benchmarks_instance_pallet! { let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); let receiver: T::IdtyIndex = 2.into(); - Pallet::<T, I>::del_cert(RawOrigin::Root.into(), issuer, receiver)?; - let issuer_cert: u32 = StorageIdtyCertMeta::<T, I>::get(issuer).issued_count; - let receiver_cert: u32 = StorageIdtyCertMeta::<T, I>::get(receiver).received_count; + Pallet::<T>::del_cert(RawOrigin::Root.into(), issuer, receiver)?; + let issuer_cert: u32 = StorageIdtyCertMeta::<T>::get(issuer).issued_count; + let receiver_cert: u32 = StorageIdtyCertMeta::<T>::get(receiver).received_count; frame_system::pallet::Pallet::<T>::set_block_number(T::CertPeriod::get()); }: _<T::RuntimeOrigin>(caller_origin, issuer, receiver) verify { - assert_has_event::<T, I>(Event::<T, I>::CertAdded{ issuer, receiver }.into()); + assert_has_event::<T>(Event::<T>::CertAdded{ issuer, receiver }.into()); } del_cert { let issuer: T::IdtyIndex = 1.into(); let receiver: T::IdtyIndex = 0.into(); - Pallet::<T, I>::do_add_cert_checked(issuer, receiver, false)?; - let receiver_cert: u32 = StorageIdtyCertMeta::<T, I>::get(receiver).received_count; - let issuer_cert: u32 = StorageIdtyCertMeta::<T, I>::get(issuer).issued_count; + Pallet::<T>::do_add_cert_checked(issuer, receiver, false)?; + let receiver_cert: u32 = StorageIdtyCertMeta::<T>::get(receiver).received_count; + let issuer_cert: u32 = StorageIdtyCertMeta::<T>::get(issuer).issued_count; }: _<T::RuntimeOrigin>(RawOrigin::Root.into(), issuer, receiver) verify { - assert_has_event::<T, I>(Event::<T, I>::CertRemoved{ issuer, receiver, expiration: false }.into()); + assert_has_event::<T>(Event::<T>::CertRemoved{ issuer, receiver, expiration: false }.into()); } remove_all_certs_received_by { let receiver: T::IdtyIndex = 0.into(); - let i in 2..1000 => add_certs::<T, I>(i, receiver)?; + let i in 2..1000 => add_certs::<T>(i, receiver)?; }: _<T::RuntimeOrigin>(RawOrigin::Root.into(), receiver) verify { - assert!(CertsByReceiver::<T, I>::get(receiver).is_empty() ); + assert!(CertsByReceiver::<T>::get(receiver).is_empty() ); } on_initialize { - assert!(StorageCertsRemovableOn::<T, I>::try_get(T::BlockNumber::zero()).is_err()); - }: {Pallet::<T, I>::on_initialize(T::BlockNumber::zero());} + assert!(StorageCertsRemovableOn::<T>::try_get(T::BlockNumber::zero()).is_err()); + }: {Pallet::<T>::on_initialize(T::BlockNumber::zero());} do_remove_cert_noop { - }: {Pallet::<T, I>::do_remove_cert(100.into(), 101.into(), Some(T::BlockNumber::zero()));} + }: {Pallet::<T>::do_remove_cert(100.into(), 101.into(), Some(T::BlockNumber::zero()));} do_remove_cert { let issuer: T::IdtyIndex = 1.into(); let receiver: T::IdtyIndex = 0.into(); - Pallet::<T, I>::do_add_cert_checked(issuer, receiver, false)?; - let issuer_cert: u32 = StorageIdtyCertMeta::<T, I>::get(issuer).issued_count; - let receiver_cert: u32 = StorageIdtyCertMeta::<T, I>::get(receiver).received_count; + Pallet::<T>::do_add_cert_checked(issuer, receiver, false)?; + let issuer_cert: u32 = StorageIdtyCertMeta::<T>::get(issuer).issued_count; + let receiver_cert: u32 = StorageIdtyCertMeta::<T>::get(receiver).received_count; let block_number = T::ValidityPeriod::get(); frame_system::pallet::Pallet::<T>::set_block_number(block_number); - }: {Pallet::<T, I>::do_remove_cert(issuer, receiver, Some(block_number));} + }: {Pallet::<T>::do_remove_cert(issuer, receiver, Some(block_number));} verify { - assert_has_event::<T, I>(Event::<T, I>::CertRemoved{ issuer, receiver, expiration: true }.into()); + assert_has_event::<T>(Event::<T>::CertRemoved{ issuer, receiver, expiration: true }.into()); } impl_benchmark_test_suite!( diff --git a/pallets/certification/src/lib.rs b/pallets/certification/src/lib.rs index fd60d814e..aab81a264 100644 --- a/pallets/certification/src/lib.rs +++ b/pallets/certification/src/lib.rs @@ -53,10 +53,10 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] #[pallet::without_storage_info] - pub struct Pallet<T, I = ()>(PhantomData<(T, I)>); + pub struct Pallet<T>(PhantomData<T>); #[pallet::config] - pub trait Config<I: 'static = ()>: frame_system::Config { + pub trait Config: frame_system::Config { #[pallet::constant] /// Minimum duration between two certifications issued by the same issuer type CertPeriod: Get<Self::BlockNumber>; @@ -86,8 +86,7 @@ pub mod pallet { /// Handler for Removed event type OnRemovedCert: OnRemovedCert<Self::IdtyIndex>; /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From<Event<Self, I>> - + IsType<<Self as frame_system::Config>::RuntimeEvent>; + type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; /// Type representing the weight of this pallet type WeightInfo: WeightInfo; #[pallet::constant] @@ -99,14 +98,14 @@ pub mod pallet { #[pallet::genesis_config] #[allow(clippy::type_complexity)] - pub struct GenesisConfig<T: Config<I>, I: 'static = ()> { + pub struct GenesisConfig<T: Config> { pub apply_cert_period_at_genesis: bool, pub certs_by_receiver: BTreeMap<T::IdtyIndex, BTreeMap<T::IdtyIndex, Option<T::BlockNumber>>>, } #[cfg(feature = "std")] - impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> { + impl<T: Config> Default for GenesisConfig<T> { fn default() -> Self { Self { apply_cert_period_at_genesis: false, @@ -116,7 +115,7 @@ pub mod pallet { } #[pallet::genesis_build] - impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig<T, I> { + impl<T: Config> GenesisBuild<T> for GenesisConfig<T> { fn build(&self) { let mut cert_meta_by_issuer = BTreeMap::<T::IdtyIndex, IdtyCertMeta<T::BlockNumber>>::new(); @@ -175,7 +174,7 @@ pub mod pallet { // Write CertsByReceiver issuers_.sort(); - CertsByReceiver::<T, I>::insert(receiver, issuers_); + CertsByReceiver::<T>::insert(receiver, issuers_); } // Write StorageIdtyCertMeta @@ -190,11 +189,11 @@ pub mod pallet { "Identity n°{:?} not respect MinReceivedCertToBeAbleToIssueCert.", issuer ); - StorageIdtyCertMeta::<T, I>::insert(issuer, cert_meta); + StorageIdtyCertMeta::<T>::insert(issuer, cert_meta); } // Write storage StorageCertsRemovableOn for (removable_on, certs) in certs_removable_on { - StorageCertsRemovableOn::<T, I>::insert(removable_on, certs); + StorageCertsRemovableOn::<T>::insert(removable_on, certs); } } } @@ -204,26 +203,26 @@ pub mod pallet { /// Certifications metada by issuer #[pallet::storage] #[pallet::getter(fn idty_cert_meta)] - pub type StorageIdtyCertMeta<T: Config<I>, I: 'static = ()> = + pub type StorageIdtyCertMeta<T: Config> = StorageMap<_, Twox64Concat, T::IdtyIndex, IdtyCertMeta<T::BlockNumber>, ValueQuery>; /// Certifications by receiver #[pallet::storage] #[pallet::getter(fn certs_by_receiver)] - pub type CertsByReceiver<T: Config<I>, I: 'static = ()> = + pub type CertsByReceiver<T: Config> = StorageMap<_, Twox64Concat, T::IdtyIndex, Vec<(T::IdtyIndex, T::BlockNumber)>, ValueQuery>; /// Certifications removable on #[pallet::storage] #[pallet::getter(fn certs_removable_on)] - pub type StorageCertsRemovableOn<T: Config<I>, I: 'static = ()> = + pub type StorageCertsRemovableOn<T: Config> = StorageMap<_, Twox64Concat, T::BlockNumber, Vec<(T::IdtyIndex, T::IdtyIndex)>, OptionQuery>; // EVENTS // #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event<T: Config<I>, I: 'static = ()> { + pub enum Event<T: Config> { /// A new certification was added. CertAdded { issuer: T::IdtyIndex, @@ -245,7 +244,7 @@ pub mod pallet { // ERRORS // #[pallet::error] - pub enum Error<T, I = ()> { + pub enum Error<T> { /// Identity cannot certify itself CannotCertifySelf, /// Identity has already issued the maximum number of certifications @@ -259,7 +258,7 @@ pub mod pallet { } #[pallet::hooks] - impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> { + impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { fn on_initialize(n: T::BlockNumber) -> Weight { Self::prune_certifications(n).saturating_add(T::WeightInfo::on_initialize()) } @@ -268,7 +267,7 @@ pub mod pallet { // CALLS // #[pallet::call] - impl<T: Config<I>, I: 'static> Pallet<T, I> { + impl<T: Config> Pallet<T> { /// Add a new certification or renew an existing one /// /// - `receiver`: the account receiving the certification from the origin @@ -303,13 +302,13 @@ pub mod pallet { /// remove all certifications received by an identity (only root) #[pallet::call_index(2)] - #[pallet::weight(T::WeightInfo::remove_all_certs_received_by(CertsByReceiver::<T, I>::get(idty_index).len() as u32))] + #[pallet::weight(T::WeightInfo::remove_all_certs_received_by(CertsByReceiver::<T>::get(idty_index).len() as u32))] pub fn remove_all_certs_received_by( origin: OriginFor<T>, idty_index: T::IdtyIndex, ) -> DispatchResultWithPostInfo { ensure_root(origin)?; - for (issuer, _) in CertsByReceiver::<T, I>::get(idty_index) { + for (issuer, _) in CertsByReceiver::<T>::get(idty_index) { Self::do_remove_cert(issuer, idty_index, None); } Ok(().into()) @@ -318,7 +317,7 @@ pub mod pallet { // INTERNAL FUNCTIONS // - impl<T: Config<I>, I: 'static> Pallet<T, I> { + impl<T: Config> Pallet<T> { /// add a certification without checks pub fn do_add_cert_checked( issuer: T::IdtyIndex, @@ -326,29 +325,29 @@ pub mod pallet { verify_rules: bool, ) -> DispatchResultWithPostInfo { // Forbid self cert - ensure!(issuer != receiver, Error::<T, I>::CannotCertifySelf); + ensure!(issuer != receiver, Error::<T>::CannotCertifySelf); let block_number = frame_system::pallet::Pallet::<T>::block_number(); if verify_rules { // Verify rule MinReceivedCertToBeAbleToIssueCert - let issuer_idty_cert_meta = StorageIdtyCertMeta::<T, I>::get(issuer); + let issuer_idty_cert_meta = StorageIdtyCertMeta::<T>::get(issuer); ensure!( issuer_idty_cert_meta.received_count >= T::MinReceivedCertToBeAbleToIssueCert::get(), - Error::<T, I>::NotEnoughCertReceived + Error::<T>::NotEnoughCertReceived ); // Verify rule MaxByIssuer ensure!( issuer_idty_cert_meta.issued_count < T::MaxByIssuer::get(), - Error::<T, I>::IssuedTooManyCert + Error::<T>::IssuedTooManyCert ); // Verify rule CertPeriod ensure!( block_number >= issuer_idty_cert_meta.next_issuable_on, - Error::<T, I>::NotRespectCertPeriod + Error::<T>::NotRespectCertPeriod ); }; @@ -362,11 +361,11 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { // Write StorageCertsRemovableOn let removable_on = block_number + T::ValidityPeriod::get(); - <StorageCertsRemovableOn<T, I>>::append(removable_on, (issuer, receiver)); + <StorageCertsRemovableOn<T>>::append(removable_on, (issuer, receiver)); // Write CertsByReceiver let mut created = false; - CertsByReceiver::<T, I>::mutate_exists(receiver, |maybe_issuers| { + CertsByReceiver::<T>::mutate_exists(receiver, |maybe_issuers| { let issuers = maybe_issuers.get_or_insert(Vec::with_capacity(0)); match issuers.binary_search_by(|(issuer_, _)| issuer_.cmp(&issuer)) { // cert exists, must be renewed @@ -384,7 +383,7 @@ pub mod pallet { if created { // Write StorageIdtyCertMeta for issuer let issuer_issued_count = - StorageIdtyCertMeta::<T, I>::mutate(issuer, |issuer_idty_cert_meta| { + StorageIdtyCertMeta::<T>::mutate(issuer, |issuer_idty_cert_meta| { issuer_idty_cert_meta.issued_count = issuer_idty_cert_meta.issued_count.saturating_add(1); issuer_idty_cert_meta.next_issuable_on = @@ -394,7 +393,7 @@ pub mod pallet { // Write StorageIdtyCertMeta for receiver let receiver_received_count = - <StorageIdtyCertMeta<T, I>>::mutate_exists(receiver, |cert_meta_opt| { + <StorageIdtyCertMeta<T>>::mutate_exists(receiver, |cert_meta_opt| { let cert_meta = cert_meta_opt.get_or_insert(IdtyCertMeta::default()); cert_meta.received_count = cert_meta.received_count.saturating_add(1); cert_meta.received_count @@ -410,7 +409,7 @@ pub mod pallet { ); } else { // Update next_issuable_on in StorageIdtyCertMeta for issuer - StorageIdtyCertMeta::<T, I>::mutate(issuer, |issuer_idty_cert_meta| { + StorageIdtyCertMeta::<T>::mutate(issuer, |issuer_idty_cert_meta| { issuer_idty_cert_meta.next_issuable_on = block_number + T::CertPeriod::get(); }); // emit CertRenewed event @@ -425,7 +424,7 @@ pub mod pallet { // See on initialize for the overhead weight accounting let mut total_weight = Weight::zero(); - if let Some(certs) = StorageCertsRemovableOn::<T, I>::take(block_number) { + if let Some(certs) = StorageCertsRemovableOn::<T>::take(block_number) { for (issuer, receiver) in certs { total_weight += Self::do_remove_cert(issuer, receiver, Some(block_number)); } @@ -442,7 +441,7 @@ pub mod pallet { ) -> Weight { let mut total_weight = Weight::zero(); let mut removed = false; - CertsByReceiver::<T, I>::mutate_exists(receiver, |issuers_opt| { + CertsByReceiver::<T>::mutate_exists(receiver, |issuers_opt| { let issuers = issuers_opt.get_or_insert(Vec::with_capacity(0)); if let Ok(index) = issuers.binary_search_by(|(issuer_, _)| issuer_.cmp(&issuer)) { if let Some(block_number) = block_number_opt { @@ -463,13 +462,13 @@ pub mod pallet { }); if removed { let issuer_issued_count = - <StorageIdtyCertMeta<T, I>>::mutate_exists(issuer, |cert_meta_opt| { + <StorageIdtyCertMeta<T>>::mutate_exists(issuer, |cert_meta_opt| { let cert_meta = cert_meta_opt.get_or_insert(IdtyCertMeta::default()); cert_meta.issued_count = cert_meta.issued_count.saturating_sub(1); cert_meta.issued_count }); let receiver_received_count = - <StorageIdtyCertMeta<T, I>>::mutate_exists(receiver, |cert_meta_opt| { + <StorageIdtyCertMeta<T>>::mutate_exists(receiver, |cert_meta_opt| { let cert_meta = cert_meta_opt.get_or_insert(IdtyCertMeta::default()); cert_meta.received_count = cert_meta.received_count.saturating_sub(1); cert_meta.received_count @@ -506,32 +505,32 @@ pub mod pallet { ) -> DispatchResult { // --- first internal checks // 1. Forbid self cert - ensure!(issuer != receiver, Error::<T, I>::CannotCertifySelf); + ensure!(issuer != receiver, Error::<T>::CannotCertifySelf); // 2. Verify caller ownership let issuer_owner_key = - T::OwnerKeyOf::convert(issuer).ok_or(Error::<T, I>::IssuerNotFound)?; + T::OwnerKeyOf::convert(issuer).ok_or(Error::<T>::IssuerNotFound)?; ensure!(issuer_owner_key == caller_key, DispatchError::BadOrigin); // 3. Verify rule MinReceivedCertToBeAbleToIssueCert // (this number can differ from the one necessary to be member) - let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer); + let issuer_idty_cert_meta = <StorageIdtyCertMeta<T>>::get(issuer); ensure!( issuer_idty_cert_meta.received_count >= T::MinReceivedCertToBeAbleToIssueCert::get(), - Error::<T, I>::NotEnoughCertReceived + Error::<T>::NotEnoughCertReceived ); // 4. Verify rule MaxByIssuer ensure!( issuer_idty_cert_meta.issued_count < T::MaxByIssuer::get(), - Error::<T, I>::IssuedTooManyCert + Error::<T>::IssuedTooManyCert ); // 5. Verify rule CertPeriod ensure!( block_number >= issuer_idty_cert_meta.next_issuable_on, - Error::<T, I>::NotRespectCertPeriod + Error::<T>::NotRespectCertPeriod ); // --- then external checks @@ -546,9 +545,9 @@ pub mod pallet { } // implement setting next_issuable_on for certification period -impl<T: Config<I>, I: 'static> SetNextIssuableOn<T::BlockNumber, T::IdtyIndex> for Pallet<T, I> { +impl<T: Config> SetNextIssuableOn<T::BlockNumber, T::IdtyIndex> for Pallet<T> { fn set_next_issuable_on(idty_index: T::IdtyIndex, next_issuable_on: T::BlockNumber) { - <StorageIdtyCertMeta<T, I>>::mutate_exists(idty_index, |cert_meta_opt| { + <StorageIdtyCertMeta<T>>::mutate_exists(idty_index, |cert_meta_opt| { let cert_meta = cert_meta_opt.get_or_insert(IdtyCertMeta::default()); cert_meta.next_issuable_on = next_issuable_on; }); diff --git a/pallets/certification/src/tests.rs b/pallets/certification/src/tests.rs index cf09fa72d..c1abd06b9 100644 --- a/pallets/certification/src/tests.rs +++ b/pallets/certification/src/tests.rs @@ -29,7 +29,7 @@ fn test_must_receive_cert_before_can_issue() { .execute_with(|| { assert_eq!( DefaultCertification::add_cert(RuntimeOrigin::signed(0), 0, 1), - Err(Error::<Test, _>::NotEnoughCertReceived.into()) + Err(Error::<Test>::NotEnoughCertReceived.into()) ); }); } @@ -50,7 +50,7 @@ fn test_cannot_certify_self() { assert_eq!( DefaultCertification::add_cert(RuntimeOrigin::signed(0), 0, 0), - Err(Error::<Test, _>::CannotCertifySelf.into()) + Err(Error::<Test>::CannotCertifySelf.into()) ); }); } @@ -152,7 +152,7 @@ fn test_cert_period() { ); assert_eq!( DefaultCertification::add_cert(RuntimeOrigin::signed(0), 0, 3), - Err(Error::<Test, _>::NotRespectCertPeriod.into()) + Err(Error::<Test>::NotRespectCertPeriod.into()) ); run_to_block(CertPeriod::get()); assert_ok!(DefaultCertification::add_cert( @@ -163,7 +163,7 @@ fn test_cert_period() { run_to_block(CertPeriod::get() + 1); assert_eq!( DefaultCertification::add_cert(RuntimeOrigin::signed(0), 0, 4), - Err(Error::<Test, _>::NotRespectCertPeriod.into()) + Err(Error::<Test>::NotRespectCertPeriod.into()) ); run_to_block((2 * CertPeriod::get()) + 1); assert_ok!(DefaultCertification::add_cert( @@ -290,7 +290,7 @@ fn test_cert_renewal_cert_delay() { // try to renew again assert_noop!( DefaultCertification::add_cert(RuntimeOrigin::signed(1), 1, 0), - Error::<Test, _>::NotRespectCertPeriod, + Error::<Test>::NotRespectCertPeriod, ); // no renewal event should be emitted assert_eq!(System::events().last(), None); diff --git a/pallets/distance/src/mock.rs b/pallets/distance/src/mock.rs index bcdbd095d..ef477a8c8 100644 --- a/pallets/distance/src/mock.rs +++ b/pallets/distance/src/mock.rs @@ -185,10 +185,11 @@ impl pallet_authority_members::Config for Test { type MemberId = u32; type MemberIdOf = IdentityIndexOf<Self>; type OnNewSession = (); - type OnRemovedMember = (); type RemoveMemberOrigin = system::EnsureRoot<AccountId>; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); + type OnOutgoingMember = (); + type OnIncomingMember = (); } parameter_types! { diff --git a/pallets/duniter-test-parameters/src/lib.rs b/pallets/duniter-test-parameters/src/lib.rs index 0f75c3296..4da26974b 100644 --- a/pallets/duniter-test-parameters/src/lib.rs +++ b/pallets/duniter-test-parameters/src/lib.rs @@ -35,6 +35,7 @@ pub mod types { BlockNumber: Default + Parameter, CertCount: Default + Parameter, PeriodCount: Default + Parameter, + SessionCount: Default + Parameter, > { pub babe_epoch_duration: PeriodCount, pub cert_period: BlockNumber, @@ -47,14 +48,9 @@ pub mod types { pub pending_membership_period: BlockNumber, pub ud_creation_period: PeriodCount, pub ud_reeval_period: PeriodCount, - pub smith_cert_period: BlockNumber, pub smith_cert_max_by_issuer: CertCount, - pub smith_cert_min_received_cert_to_issue_cert: CertCount, - pub smith_cert_validity_period: BlockNumber, - pub smith_membership_period: BlockNumber, - pub smith_pending_membership_period: BlockNumber, - pub smith_wot_first_cert_issuable_on: BlockNumber, pub smith_wot_min_cert_for_membership: CertCount, + pub smith_inactivity_max_duration: SessionCount, pub wot_first_cert_issuable_on: BlockNumber, pub wot_min_cert_for_create_idty_right: CertCount, pub wot_min_cert_for_membership: CertCount, @@ -81,20 +77,24 @@ pub mod pallet { pub trait Config: frame_system::Config { type CertCount: Default + MaybeSerializeDeserialize + Parameter; type PeriodCount: Default + MaybeSerializeDeserialize + Parameter; + type SessionCount: Default + MaybeSerializeDeserialize + Parameter; } // STORAGE // #[pallet::storage] #[pallet::getter(fn parameters)] - pub type ParametersStorage<T: Config> = - StorageValue<_, Parameters<T::BlockNumber, T::CertCount, T::PeriodCount>, ValueQuery>; + pub type ParametersStorage<T: Config> = StorageValue< + _, + Parameters<T::BlockNumber, T::CertCount, T::PeriodCount, T::SessionCount>, + ValueQuery, + >; // GENESIS #[pallet::genesis_config] pub struct GenesisConfig<T: Config> { - pub parameters: Parameters<T::BlockNumber, T::CertCount, T::PeriodCount>, + pub parameters: Parameters<T::BlockNumber, T::CertCount, T::PeriodCount, T::SessionCount>, } #[cfg(feature = "std")] diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs index 41ad8db13..eb127c0cc 100644 --- a/pallets/duniter-wot/src/lib.rs +++ b/pallets/duniter-wot/src/lib.rs @@ -36,7 +36,6 @@ use frame_support::pallet_prelude::*; use pallet_certification::traits::SetNextIssuableOn; use pallet_identity::{IdtyEvent, IdtyStatus}; use pallet_membership::MembershipRemovalReason; -use sp_runtime::traits::IsMember; type IdtyIndex = u32; @@ -51,24 +50,22 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] #[pallet::without_storage_info] - pub struct Pallet<T, I = ()>(_); + pub struct Pallet<T>(_); // CONFIG // #[pallet::config] - pub trait Config<I: 'static = ()>: + pub trait Config: frame_system::Config - + pallet_certification::Config<I, IdtyIndex = IdtyIndex> + + pallet_certification::Config<IdtyIndex = IdtyIndex> + pallet_identity::Config<IdtyIndex = IdtyIndex> - + pallet_membership::Config<I, IdtyId = IdtyIndex> + + pallet_membership::Config<IdtyId = IdtyIndex> { /// Distance evaluation provider type IsDistanceOk: IsDistanceOk<IdtyIndex>; #[pallet::constant] type FirstIssuableOn: Get<Self::BlockNumber>; #[pallet::constant] - type IsSubWot: Get<bool>; - #[pallet::constant] type MinCertForMembership: Get<u32>; #[pallet::constant] type MinCertForCreateIdtyRight: Get<u32>; @@ -76,10 +73,10 @@ pub mod pallet { // INTERNAL FUNCTIONS // - impl<T: Config<I>, I: 'static> Pallet<T, I> { + impl<T: Config> Pallet<T> { pub(super) fn do_apply_first_issuable_on(idty_index: IdtyIndex) { let block_number = frame_system::pallet::Pallet::<T>::block_number(); - pallet_certification::Pallet::<T, I>::set_next_issuable_on( + pallet_certification::Pallet::<T>::set_next_issuable_on( idty_index, block_number + T::FirstIssuableOn::get(), ); @@ -89,7 +86,7 @@ pub mod pallet { // ERRORS // #[pallet::error] - pub enum Error<T, I = ()> { + pub enum Error<T> { /// Insufficient certifications received to claim membership. NotEnoughCertsToClaimMembership, /// Distance is invalid. @@ -126,61 +123,37 @@ pub mod pallet { } // implement identity call checks -impl<AccountId, T: Config<I>, I: 'static> pallet_identity::traits::CheckIdtyCallAllowed<T> - for Pallet<T, I> +impl<AccountId, T: Config> pallet_identity::traits::CheckIdtyCallAllowed<T> for Pallet<T> where - T: frame_system::Config<AccountId = AccountId> + pallet_membership::Config<I>, + T: frame_system::Config<AccountId = AccountId> + pallet_membership::Config, { // identity creation checks fn check_create_identity(creator: IdtyIndex) -> Result<(), DispatchError> { - // main WoT constraints - if !T::IsSubWot::get() { - let cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(creator); - // perform all checks - // 1. check that identity has the right to create an identity - // identity can be member with 5 certifications and still not reach identity creation threshold which could be higher (6, 7...) - ensure!( - cert_meta.received_count >= T::MinCertForCreateIdtyRight::get(), - Error::<T, I>::NotEnoughReceivedCertsToCreateIdty - ); - // 2. check that issuer can emit one more certification - // (this is only a partial check) - ensure!( - cert_meta.issued_count < T::MaxByIssuer::get(), - Error::<T, I>::MaxEmittedCertsReached - ); - // 3. check that issuer respects certification creation period - ensure!( - cert_meta.next_issuable_on <= frame_system::pallet::Pallet::<T>::block_number(), - Error::<T, I>::IdtyCreationPeriodNotRespected - ); - } - // TODO (#136) make these trait implementation work on instances rather than static to avoid checking IsSubWot - // smith subwot can never prevent from creating identity - Ok(()) - } - - // identity change owner key cheks - fn change_owner_key(idty_index: IdtyIndex) -> Result<(), DispatchError> { - // sub WoT prevents from changing identity - if T::IsSubWot::get() { - ensure!( - !pallet_membership::Pallet::<T, I>::is_member(&idty_index), - Error::<T, I>::NotAllowedToChangeIdtyAddress - ); - } - // no constraints for main wot + let cert_meta = pallet_certification::Pallet::<T>::idty_cert_meta(creator); + // perform all checks + // 1. check that identity has the right to create an identity + // identity can be member with 5 certifications and still not reach identity creation threshold which could be higher (6, 7...) + ensure!( + cert_meta.received_count >= T::MinCertForCreateIdtyRight::get(), + Error::<T>::NotEnoughReceivedCertsToCreateIdty + ); + // 2. check that issuer can emit one more certification + // (this is only a partial check) + ensure!( + cert_meta.issued_count < T::MaxByIssuer::get(), + Error::<T>::MaxEmittedCertsReached + ); + // 3. check that issuer respects certification creation period + ensure!( + cert_meta.next_issuable_on <= frame_system::pallet::Pallet::<T>::block_number(), + Error::<T>::IdtyCreationPeriodNotRespected + ); Ok(()) } } // implement cert call checks -impl<T: Config<I>, I: 'static> pallet_certification::traits::CheckCertAllowed<IdtyIndex> - for Pallet<T, I> -// TODO (#136) add the following where clause once checks can be done on pallet instance -// where -// T: pallet_membership::Config<I>, -{ +impl<T: Config> pallet_certification::traits::CheckCertAllowed<IdtyIndex> for Pallet<T> { // check the following: // - issuer has identity // - issuer identity is member @@ -192,10 +165,10 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::CheckCertAllowed<Id if let Some(issuer_data) = pallet_identity::Pallet::<T>::identity(issuer) { ensure!( issuer_data.status == IdtyStatus::Member, - Error::<T, I>::IssuerNotMember + Error::<T>::IssuerNotMember ); } else { - return Err(Error::<T, I>::IdtyNotFound.into()); + return Err(Error::<T>::IdtyNotFound.into()); } // receiver checks @@ -204,26 +177,24 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::CheckCertAllowed<Id match receiver_data.status { // able to receive cert IdtyStatus::Unvalidated | IdtyStatus::Member | IdtyStatus::NotMember => {} - IdtyStatus::Unconfirmed => return Err(Error::<T, I>::CertToUnconfirmed.into()), - IdtyStatus::Revoked => return Err(Error::<T, I>::CertToRevoked.into()), + IdtyStatus::Unconfirmed => return Err(Error::<T>::CertToUnconfirmed.into()), + IdtyStatus::Revoked => return Err(Error::<T>::CertToRevoked.into()), }; } else { - return Err(Error::<T, I>::IdtyNotFound.into()); + return Err(Error::<T>::IdtyNotFound.into()); } Ok(()) } } // implement membership call checks -impl<T: Config<I>, I: 'static> sp_membership::traits::CheckMembershipCallAllowed<IdtyIndex> - for Pallet<T, I> -{ +impl<T: Config> sp_membership::traits::CheckMembershipCallAllowed<IdtyIndex> for Pallet<T> { // membership claim is only possible when enough certs are received (both wots) and distance is ok fn check_idty_allowed_to_claim_membership(idty_index: &IdtyIndex) -> Result<(), DispatchError> { - let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index); + let idty_cert_meta = pallet_certification::Pallet::<T>::idty_cert_meta(idty_index); ensure!( idty_cert_meta.received_count >= T::MinCertForMembership::get(), - Error::<T, I>::NotEnoughCertsToClaimMembership + Error::<T>::NotEnoughCertsToClaimMembership ); T::IsDistanceOk::is_distance_ok(idty_index)?; Ok(()) @@ -234,35 +205,31 @@ impl<T: Config<I>, I: 'static> sp_membership::traits::CheckMembershipCallAllowed if let Some(idty_value) = pallet_identity::Pallet::<T>::identity(idty_index) { ensure!( idty_value.status == IdtyStatus::Member, - Error::<T, I>::IdtyNotAllowedToRenewMembership + Error::<T>::IdtyNotAllowedToRenewMembership ); T::IsDistanceOk::is_distance_ok(idty_index)?; } else { - return Err(Error::<T, I>::IdtyNotFound.into()); + return Err(Error::<T>::IdtyNotFound.into()); } Ok(()) } } // implement membership event handler -impl<T: Config<I>, I: 'static> sp_membership::traits::OnEvent<IdtyIndex> for Pallet<T, I> +impl<T: Config> sp_membership::traits::OnEvent<IdtyIndex> for Pallet<T> where - T: pallet_membership::Config<I>, + T: pallet_membership::Config, { fn on_event(membership_event: &sp_membership::Event<IdtyIndex>) { match membership_event { sp_membership::Event::<IdtyIndex>::MembershipAdded(idty_index) => { - if !T::IsSubWot::get() { - // when main membership is acquired, tell identity - // (only used on first membership acquiry) - pallet_identity::Pallet::<T>::membership_added(*idty_index); - } + // when main membership is acquired, tell identity + // (only used on first membership acquiry) + pallet_identity::Pallet::<T>::membership_added(*idty_index); } sp_membership::Event::<IdtyIndex>::MembershipRemoved(idty_index) => { - if !T::IsSubWot::get() { - // when main membership is lost, tell identity - pallet_identity::Pallet::<T>::membership_removed(*idty_index); - } + // when main membership is lost, tell identity + pallet_identity::Pallet::<T>::membership_removed(*idty_index); } sp_membership::Event::<IdtyIndex>::MembershipRenewed(_) => {} } @@ -270,12 +237,12 @@ where } // implement identity event handler -impl<T: Config<I>, I: 'static> pallet_identity::traits::OnIdtyChange<T> for Pallet<T, I> { +impl<T: Config> pallet_identity::traits::OnIdtyChange<T> for Pallet<T> { fn on_idty_change(idty_index: IdtyIndex, idty_event: &IdtyEvent<T>) { match idty_event { // identity just has been created, a cert must be added IdtyEvent::Created { creator, .. } => { - if let Err(e) = <pallet_certification::Pallet<T, I>>::do_add_cert_checked( + if let Err(e) = <pallet_certification::Pallet<T>>::do_add_cert_checked( *creator, idty_index, true, ) { sp_std::if_std! { @@ -288,7 +255,7 @@ impl<T: Config<I>, I: 'static> pallet_identity::traits::OnIdtyChange<T> for Pall // if identity is removed also remove certs IdtyEvent::Removed { status } => { // try remove membership in any case - <pallet_membership::Pallet<T, I>>::do_remove_membership( + <pallet_membership::Pallet<T>>::do_remove_membership( idty_index, MembershipRemovalReason::Revoked, ); @@ -297,7 +264,7 @@ impl<T: Config<I>, I: 'static> pallet_identity::traits::OnIdtyChange<T> for Pall match status { IdtyStatus::Unconfirmed | IdtyStatus::Unvalidated => { if let Err(e) = - <pallet_certification::Pallet<T, I>>::remove_all_certs_received_by( + <pallet_certification::Pallet<T>>::remove_all_certs_received_by( frame_system::Origin::<T>::Root.into(), idty_index, ) @@ -321,7 +288,7 @@ impl<T: Config<I>, I: 'static> pallet_identity::traits::OnIdtyChange<T> for Pall // implement certification event handlers // new cert handler -impl<T: Config<I>, I: 'static> pallet_certification::traits::OnNewcert<IdtyIndex> for Pallet<T, I> { +impl<T: Config> pallet_certification::traits::OnNewcert<IdtyIndex> for Pallet<T> { fn on_new_cert( _issuer: IdtyIndex, _issuer_issued_count: u32, @@ -335,9 +302,7 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::OnNewcert<IdtyIndex } // remove cert handler -impl<T: Config<I>, I: 'static> pallet_certification::traits::OnRemovedCert<IdtyIndex> - for Pallet<T, I> -{ +impl<T: Config> pallet_certification::traits::OnRemovedCert<IdtyIndex> for Pallet<T> { fn on_removed_cert( _issuer: IdtyIndex, _issuer_issued_count: u32, @@ -346,10 +311,10 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::OnRemovedCert<IdtyI _expiration: bool, ) { if receiver_received_count < T::MinCertForMembership::get() - && pallet_membership::Pallet::<T, I>::is_member(&receiver) + && pallet_membership::Pallet::<T>::is_member(&receiver) { // expire receiver membership - <pallet_membership::Pallet<T, I>>::do_remove_membership( + <pallet_membership::Pallet<T>>::do_remove_membership( receiver, MembershipRemovalReason::NotEnoughCerts, ) diff --git a/pallets/duniter-wot/src/mock.rs b/pallets/duniter-wot/src/mock.rs index 268a6bf01..c043ef764 100644 --- a/pallets/duniter-wot/src/mock.rs +++ b/pallets/duniter-wot/src/mock.rs @@ -46,13 +46,10 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, - DuniterWot: pallet_duniter_wot::<Instance1>::{Pallet}, + DuniterWot: pallet_duniter_wot::{Pallet}, Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>}, - Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>}, - Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>}, - SmithSubWot: pallet_duniter_wot::<Instance2>::{Pallet}, - SmithMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>}, - SmithCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>}, + Membership: pallet_membership::{Pallet, Call, Config<T>, Storage, Event<T>}, + Cert: pallet_certification::{Pallet, Call, Config<T>, Storage, Event<T>}, } ); @@ -96,8 +93,7 @@ parameter_types! { pub const FirstIssuableOn: u64 = 2; } -impl pallet_duniter_wot::Config<Instance1> for Test { - type IsSubWot = frame_support::traits::ConstBool<false>; +impl pallet_duniter_wot::Config for Test { type MinCertForMembership = MinCertForMembership; type MinCertForCreateIdtyRight = MinCertForCreateIdtyRight; type FirstIssuableOn = FirstIssuableOn; @@ -124,7 +120,7 @@ impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl { impl pallet_identity::Config for Test { type ChangeOwnerKeyPeriod = ChangeOwnerKeyPeriod; type ConfirmPeriod = ConfirmPeriod; - type CheckIdtyCallAllowed = (DuniterWot, SmithSubWot); + type CheckIdtyCallAllowed = DuniterWot; type IdtyCreationPeriod = IdtyCreationPeriod; type ValidationPeriod = ValidationPeriod; type AutorevocationPeriod = AutorevocationPeriod; @@ -135,7 +131,7 @@ impl pallet_identity::Config for Test { type AccountLinker = (); type Signer = UintAuthorityId; type Signature = TestSignature; - type OnIdtyChange = (DuniterWot, SmithSubWot); + type OnIdtyChange = DuniterWot; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -145,7 +141,7 @@ parameter_types! { pub const MembershipPeriod: u64 = 8; } -impl pallet_membership::Config<Instance1> for Test { +impl pallet_membership::Config for Test { type CheckMembershipCallAllowed = DuniterWot; type IdtyId = IdtyIndex; type IdtyIdOf = IdentityIndexOf<Self>; @@ -166,7 +162,7 @@ parameter_types! { pub const ValidityPeriod: u64 = 20; } -impl pallet_certification::Config<Instance1> for Test { +impl pallet_certification::Config for Test { type CertPeriod = CertPeriod; type IdtyIndex = IdtyIndex; type OwnerKeyOf = Identity; @@ -180,68 +176,10 @@ impl pallet_certification::Config<Instance1> for Test { type ValidityPeriod = ValidityPeriod; } -// SMITHS SUB-WOT // - -parameter_types! { - pub const SmithMinCertForMembership: u32 = 2; - pub const SmithFirstIssuableOn: u64 = 2; -} - -impl pallet_duniter_wot::Config<Instance2> for Test { - type IsSubWot = frame_support::traits::ConstBool<true>; - type MinCertForMembership = SmithMinCertForMembership; - type MinCertForCreateIdtyRight = frame_support::traits::ConstU32<0>; - type FirstIssuableOn = SmithFirstIssuableOn; - type IsDistanceOk = crate::traits::DistanceAlwaysOk; -} - -// SmithMembership -parameter_types! { - pub const SmithMembershipPeriod: u64 = 20; -} - -impl pallet_membership::Config<Instance2> for Test { - type CheckMembershipCallAllowed = SmithSubWot; - type IdtyId = IdtyIndex; - type IdtyIdOf = IdentityIndexOf<Self>; - type AccountIdOf = (); - type MembershipPeriod = SmithMembershipPeriod; - type OnEvent = SmithSubWot; - type WeightInfo = (); - type RuntimeEvent = RuntimeEvent; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkSetupHandler = (); -} - -// SmithCert -parameter_types! { - pub const SmithMaxByIssuer: u8 = 8; - pub const SmithMinReceivedCertToBeAbleToIssueCert: u32 = 2; - pub const SmithCertPeriod: u64 = 2; - pub const SmithValidityPeriod: u64 = 10; -} - -impl pallet_certification::Config<Instance2> for Test { - type CertPeriod = SmithCertPeriod; - type IdtyIndex = IdtyIndex; - type OwnerKeyOf = Identity; - type CheckCertAllowed = SmithSubWot; - type MaxByIssuer = SmithMaxByIssuer; - type MinReceivedCertToBeAbleToIssueCert = SmithMinReceivedCertToBeAbleToIssueCert; - type OnNewcert = SmithSubWot; - type OnRemovedCert = SmithSubWot; - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type ValidityPeriod = SmithValidityPeriod; -} - pub const NAMES: [&str; 6] = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"]; // Build genesis storage according to the mock runtime. -pub fn new_test_ext( - initial_identities_len: usize, - initial_smiths_len: usize, -) -> sp_io::TestExternalities { +pub fn new_test_ext(initial_identities_len: usize) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default() .build_storage::<Test>() .unwrap(); @@ -265,7 +203,7 @@ pub fn new_test_ext( .assimilate_storage(&mut t) .unwrap(); - pallet_membership::GenesisConfig::<Test, Instance1> { + pallet_membership::GenesisConfig::<Test> { memberships: (1..=initial_identities_len) .map(|i| { ( @@ -280,35 +218,13 @@ pub fn new_test_ext( .assimilate_storage(&mut t) .unwrap(); - pallet_certification::GenesisConfig::<Test, Instance1> { + pallet_certification::GenesisConfig::<Test> { apply_cert_period_at_genesis: true, certs_by_receiver: clique_wot(initial_identities_len, ValidityPeriod::get()), } .assimilate_storage(&mut t) .unwrap(); - pallet_membership::GenesisConfig::<Test, Instance2> { - memberships: (1..=initial_smiths_len) - .map(|i| { - ( - i as u32, - sp_membership::MembershipData { - expire_on: SmithMembershipPeriod::get(), - }, - ) - }) - .collect(), - } - .assimilate_storage(&mut t) - .unwrap(); - - pallet_certification::GenesisConfig::<Test, Instance2> { - apply_cert_period_at_genesis: true, - certs_by_receiver: clique_wot(initial_smiths_len, SmithValidityPeriod::get()), - } - .assimilate_storage(&mut t) - .unwrap(); - frame_support::BasicExternalities::execute_with_storage(&mut t, || { // manually increment genesis identities sufficient counter // In real world, this is done by pallet-identity @@ -330,9 +246,6 @@ pub fn run_to_block(n: u64) { Identity::on_finalize(System::block_number()); Membership::on_finalize(System::block_number()); Cert::on_finalize(System::block_number()); - SmithSubWot::on_finalize(System::block_number()); - SmithMembership::on_finalize(System::block_number()); - SmithCert::on_finalize(System::block_number()); System::on_finalize(System::block_number()); // reset events and change block number System::reset_events(); @@ -343,9 +256,6 @@ pub fn run_to_block(n: u64) { Identity::on_initialize(System::block_number()); Membership::on_initialize(System::block_number()); Cert::on_initialize(System::block_number()); - SmithSubWot::on_initialize(System::block_number()); - SmithMembership::on_initialize(System::block_number()); - SmithCert::on_initialize(System::block_number()); } } diff --git a/pallets/duniter-wot/src/tests.rs b/pallets/duniter-wot/src/tests.rs index 3645f1979..2b86ee97f 100644 --- a/pallets/duniter-wot/src/tests.rs +++ b/pallets/duniter-wot/src/tests.rs @@ -17,11 +17,9 @@ use crate::mock::*; use crate::pallet as pallet_duniter_wot; use codec::Encode; -use frame_support::instances::{Instance1, Instance2}; use frame_support::{assert_noop, assert_ok}; use pallet_identity::{ - IdtyIndexAccountIdPayload, IdtyName, IdtyStatus, RevocationPayload, RevocationReason, - NEW_OWNER_KEY_PAYLOAD_PREFIX, REVOCATION_PAYLOAD_PREFIX, + IdtyName, IdtyStatus, RevocationPayload, RevocationReason, REVOCATION_PAYLOAD_PREFIX, }; use pallet_membership::MembershipRemovalReason; use sp_runtime::testing::TestSignature; @@ -30,13 +28,13 @@ use sp_runtime::testing::TestSignature; /// and good identity and certification metadate #[test] fn test_genesis_build() { - new_test_ext(3, 2).execute_with(|| { + new_test_ext(3).execute_with(|| { run_to_block(1); // Verify state assert_eq!(Identity::identities_count(), 3); assert_eq!(Identity::identity(1).unwrap().next_creatable_identity_on, 0); assert_eq!( - pallet_certification::Pallet::<Test, Instance1>::idty_cert_meta(1).next_issuable_on, + pallet_certification::Pallet::<Test>::idty_cert_meta(1).next_issuable_on, 2 ); }); @@ -45,7 +43,7 @@ fn test_genesis_build() { /// test that Alice is not able to create an identity when she received too few certs (2 of 4) #[test] fn test_creator_not_allowed_to_create_idty() { - new_test_ext(3, 2).execute_with(|| { + new_test_ext(3).execute_with(|| { run_to_block(1); // Alice did not receive enough certs @@ -53,7 +51,7 @@ fn test_creator_not_allowed_to_create_idty() { // because Alice.next_issuable_on = 2) assert_noop!( Identity::create_identity(RuntimeOrigin::signed(1), 4), - pallet_duniter_wot::Error::<Test, Instance1>::NotEnoughReceivedCertsToCreateIdty + pallet_duniter_wot::Error::<Test>::NotEnoughReceivedCertsToCreateIdty ); }); } @@ -61,123 +59,21 @@ fn test_creator_not_allowed_to_create_idty() { /// test that Alice is able to create an identity when she received enough certs (4) #[test] fn test_creator_allowed_to_create_idty() { - new_test_ext(5, 2).execute_with(|| { + new_test_ext(5).execute_with(|| { run_to_block(2); // Alice should be able to create an identity assert_ok!( Identity::create_identity(RuntimeOrigin::signed(1), 6), - // pallet_duniter_wot::Error::<Test, Instance1>::NotEnoughReceivedCertsToCreateIdty + // pallet_duniter_wot::Error::<Test>::NotEnoughReceivedCertsToCreateIdty ); }); } -/// test smith joining workflow -#[test] -fn test_join_smiths() { - new_test_ext(5, 3).execute_with(|| { - run_to_block(2); - - // Alice should be able to send a smith cert to Dave - run_to_block(3); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 4)); - - // Bob should be able to send a smith cert to Dave - run_to_block(4); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(2), 2, 4)); - - // Dave should be able to claim his membership - run_to_block(4); - assert_ok!(SmithMembership::claim_membership(RuntimeOrigin::signed(4),)); - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipAdded { - member: 4, - expire_on: 4 - + <Test as pallet_membership::Config<Instance2>>::MembershipPeriod::get(), - }, - )); - }); -} - -/// test smith membership expiry after cert expiration -#[test] -fn test_smith_certs_expirations_should_expire_smith_membership() { - new_test_ext(5, 3).execute_with(|| { - // After block #10, alice membership should be revoked due to smith certs expiration - run_to_block(10); - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipRemoved { - member: 1, - reason: MembershipRemovalReason::NotEnoughCerts, - }, - )); - }); -} - -/// test that smith can not change owner key -#[test] -fn test_smith_member_cant_change_its_idty_address() { - new_test_ext(5, 3).execute_with(|| { - run_to_block(2); - - let genesis_hash = System::block_hash(0); - let new_key_payload = IdtyIndexAccountIdPayload { - genesis_hash: &genesis_hash, - idty_index: 3u32, - old_owner_key: &3u64, - }; - - // Identity 3 can't change it's address - assert_noop!( - Identity::change_owner_key( - RuntimeOrigin::signed(3), - 13, - TestSignature(13, (NEW_OWNER_KEY_PAYLOAD_PREFIX, new_key_payload).encode()) - ), - pallet_duniter_wot::Error::<Test, Instance2>::NotAllowedToChangeIdtyAddress - ); - }); -} - -/// members of the smith subwot can revoke their identity -#[test] -fn test_smith_member_can_revoke_its_idty() { - new_test_ext(5, 3).execute_with(|| { - run_to_block(2); - - let revocation_payload = RevocationPayload { - idty_index: 3u32, - genesis_hash: System::block_hash(0), - }; - - // Identity 3 can't change it's address - assert_ok!(Identity::revoke_identity( - RuntimeOrigin::signed(3), - 3, - 3, - TestSignature(3, (REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode()) - )); - // membership should be removed - System::assert_has_event(RuntimeEvent::Membership( - pallet_membership::Event::MembershipRemoved { - member: 3, - reason: pallet_membership::MembershipRemovalReason::Revoked, - }, - )); - // smith membership should be removed as well - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipRemoved { - member: 3, - reason: pallet_membership::MembershipRemovalReason::Revoked, - }, - )); - }); -} - /// test identity creation and that a first cert is emitted #[test] fn test_create_idty_ok() { - new_test_ext(5, 2).execute_with(|| { + new_test_ext(5).execute_with(|| { run_to_block(2); // Alice should be able to create an identity at block #2 @@ -205,7 +101,7 @@ fn test_create_idty_ok() { /// test identity validation #[test] fn test_new_idty_validation() { - new_test_ext(5, 2).execute_with(|| { + new_test_ext(5).execute_with(|| { // Alice creates Ferdie identity run_to_block(2); assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 6)); @@ -231,8 +127,7 @@ fn test_new_idty_validation() { System::assert_has_event(RuntimeEvent::Membership( pallet_membership::Event::MembershipAdded { member: 6, - expire_on: 5 - + <Test as pallet_membership::Config<Instance1>>::MembershipPeriod::get(), + expire_on: 5 + <Test as pallet_membership::Config>::MembershipPeriod::get(), }, )); System::assert_has_event(RuntimeEvent::Identity( @@ -258,7 +153,7 @@ fn test_new_idty_validation() { /// test that Ferdie can confirm an identity created for him by Alice #[test] fn test_confirm_idty_ok() { - new_test_ext(5, 2).execute_with(|| { + new_test_ext(5).execute_with(|| { run_to_block(2); // Alice creates Ferdie identity @@ -282,11 +177,10 @@ fn test_confirm_idty_ok() { } /// test identity revocation -/// - a smith ca not revoke his identity /// - anyone can submit a revocation certificate signed by bob #[test] fn test_revoke_idty() { - new_test_ext(5, 1).execute_with(|| { + new_test_ext(5).execute_with(|| { run_to_block(2); // Alice identity can be revoked @@ -313,13 +207,6 @@ fn test_revoke_idty() { reason: pallet_membership::MembershipRemovalReason::Revoked, }, )); - // and her smith membership should be removed as well - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipRemoved { - member: 1, - reason: pallet_membership::MembershipRemovalReason::Revoked, - }, - )); // Anyone should be able to submit Bob revocation certificate assert_ok!(Identity::revoke_identity( @@ -351,7 +238,7 @@ fn test_revoke_idty() { /// test that expired membership lose the identity after a delay #[test] fn test_idty_membership_expire() { - new_test_ext(3, 2).execute_with(|| { + new_test_ext(3).execute_with(|| { run_to_block(4); // Alice renews her membership @@ -411,7 +298,7 @@ fn test_idty_membership_expire() { // Alice can't certify revoked identity assert_noop!( Cert::add_cert(RuntimeOrigin::signed(1), 1, 3), - pallet_duniter_wot::Error::<Test, Instance1>::CertToRevoked + pallet_duniter_wot::Error::<Test>::CertToRevoked ); run_to_block(21); @@ -424,7 +311,7 @@ fn test_idty_membership_expire() { // Alice can't certify removed identity assert_noop!( Cert::add_cert(RuntimeOrigin::signed(1), 1, 3), - pallet_duniter_wot::Error::<Test, Instance1>::IdtyNotFound + pallet_duniter_wot::Error::<Test>::IdtyNotFound ); }); } @@ -432,7 +319,7 @@ fn test_idty_membership_expire() { /// when an identity is confirmed and not validated, the certification received should be removed #[test] fn test_unvalidated_idty_certs_removal() { - new_test_ext(5, 2).execute_with(|| { + new_test_ext(5).execute_with(|| { // Alice creates Ferdie identity run_to_block(2); assert_ok!(Identity::create_identity(RuntimeOrigin::signed(1), 6)); @@ -455,50 +342,24 @@ fn test_unvalidated_idty_certs_removal() { /// test what happens when certification expire #[test] fn test_certification_expire() { - new_test_ext(3, 3).execute_with(|| { + new_test_ext(3).execute_with(|| { // smith cert Bob → Alice not renewed // cert Bob → Alice not renewed // --- BLOCK 2 --- run_to_block(2); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 2)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(2), 2, 3)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 1)); assert_ok!(Cert::add_cert(RuntimeOrigin::signed(1), 1, 2)); assert_ok!(Cert::add_cert(RuntimeOrigin::signed(2), 2, 3)); assert_ok!(Cert::add_cert(RuntimeOrigin::signed(3), 3, 1)); // --- BLOCK 4 --- run_to_block(4); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 3)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 2)); assert_ok!(Cert::add_cert(RuntimeOrigin::signed(1), 1, 3)); assert_ok!(Cert::add_cert(RuntimeOrigin::signed(3), 3, 2)); // --- BLOCK 7 --- run_to_block(7); - assert_ok!(SmithMembership::renew_membership(RuntimeOrigin::signed(1))); - assert_ok!(SmithMembership::renew_membership(RuntimeOrigin::signed(2))); - assert_ok!(SmithMembership::renew_membership(RuntimeOrigin::signed(3))); assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(1))); assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(2))); assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(3))); - // smith cert Bob → Alice expires at block 10 - run_to_block(10); - // println!("{:?}", System::events()); - System::assert_has_event(RuntimeEvent::SmithCert( - pallet_certification::Event::CertRemoved { - issuer: 2, // Bob - receiver: 1, // Alice - expiration: true, - }, - )); - // in consequence, since Alice has only 1/2 smith certification remaining, she looses smith membership - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipRemoved { - member: 1, - reason: MembershipRemovalReason::NotEnoughCerts, - }, - )); - // --- BLOCK 14 --- run_to_block(14); assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(1))); @@ -532,13 +393,13 @@ fn test_certification_expire() { // Alice can not renew her membership which does not exist assert_noop!( Membership::renew_membership(RuntimeOrigin::signed(1)), - pallet_membership::Error::<Test, Instance1>::MembershipNotFound + pallet_membership::Error::<Test>::MembershipNotFound ); // Alice can not claim her membership because she does not have enough certifications assert_noop!( Membership::claim_membership(RuntimeOrigin::signed(1)), - pallet_duniter_wot::Error::<Test, Instance1>::NotEnoughCertsToClaimMembership + pallet_duniter_wot::Error::<Test>::NotEnoughCertsToClaimMembership ); // --- BLOCK 23 --- @@ -559,78 +420,27 @@ fn test_certification_expire() { // - when source or target membership is pending (both wot) #[test] fn test_cert_can_not_be_issued() { - new_test_ext(4, 3).execute_with(|| { + new_test_ext(4).execute_with(|| { // smith cert Bob → Alice not renewed // cert Bob → Alice not renewed // --- BLOCK 2 --- run_to_block(2); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 2)); // +10 - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(2), 2, 3)); // +10 - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 1)); // +10 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(1), 1, 2)); // +20 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(2), 2, 3)); // +20 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(3), 3, 4)); // +20 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(4), 4, 1)); // +20 // --- BLOCK 4 --- run_to_block(4); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 3)); // +10 - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 2)); // +10 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(2), 2, 4)); // +20 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(3), 3, 2)); // +20 assert_ok!(Cert::add_cert(RuntimeOrigin::signed(4), 4, 3)); // +20 // --- BLOCK 7 --- run_to_block(7); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 1)); // +10 - assert_ok!(SmithMembership::renew_membership(RuntimeOrigin::signed(1))); // +20 - assert_ok!(SmithMembership::renew_membership(RuntimeOrigin::signed(2))); // +20 - assert_ok!(SmithMembership::renew_membership(RuntimeOrigin::signed(3))); // +20 assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(1))); // + 8 assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(2))); // + 8 assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(3))); // + 8 assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(4))); // + 8 - // smith cert Bob → Alice expires at block 10 - run_to_block(10); - // println!("{:?}", System::events()); - System::assert_has_event(RuntimeEvent::SmithCert( - pallet_certification::Event::CertRemoved { - issuer: 2, // Bob - receiver: 1, // Alice - expiration: true, - }, - )); - // in consequence, since Alice has only 1/2 smith certification remaining, she looses smith membership - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipRemoved { - member: 1, - reason: MembershipRemovalReason::NotEnoughCerts, - }, - )); - - run_to_block(11); - // Dave should be able to receive a smith cert since - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 4)); - // Bob renews his smith certification towards Alice - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(2), 2, 1)); - // now Alice has enough certs - assert_eq!( - SmithCert::idty_cert_meta(1), - pallet_certification::IdtyCertMeta { - issued_count: 2, // → Bob, → Charlie - // since Alice got back to min number of received certs to be able to issue cert - // her next_issuable_on was updated to block_number (11) + cert_period (2) - next_issuable_on: 13, // 11 + 2 - received_count: 2 // ↠Bob, ↠Charlie - } - ); - - // because Alice did not claim membership, she is not member at this point - assert_eq!(SmithMembership::membership(1), None); - run_to_block(13); - // /!\ COUNTERINTUITIVE BEHAVIOR - // Alice is not smith member, she should not be able to issue cert - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 2)); - run_to_block(14); assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(1))); // + 8 assert_ok!(Membership::renew_membership(RuntimeOrigin::signed(2))); // + 8 @@ -669,54 +479,3 @@ fn test_cert_can_not_be_issued() { // she would have been able to emit a cert without being member }) } - -/// test non smith identity can not emit smith cert -#[test] -fn test_non_smith_can_not_issue_smith_cert() { - new_test_ext(4, 3).execute_with(|| { - assert_noop!( - SmithCert::add_cert(RuntimeOrigin::signed(4), 4, 1), - pallet_certification::Error::<Test, Instance2>::NotEnoughCertReceived - ); - }) -} - -/// FIXME this test should not fail with NotRespectCertPeriod but NotSmith or somthing like that -/// test non smith identity can not emit smith cert -#[test] -fn test_non_smith_with_certs_can_not_issue_smith_cert() { - new_test_ext(4, 3).execute_with(|| { - run_to_block(2); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 4)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(2), 2, 4)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 4)); - assert_noop!( - SmithCert::add_cert(RuntimeOrigin::signed(4), 4, 1), - pallet_certification::Error::<Test, Instance2>::NotRespectCertPeriod - ); - }) -} - -/// FIXME this test should not succeed because Dave should not be able to issue cert -/// after revocation of his smith membership -/// test non smith identity can not emit smith cert -#[test] -fn test_revoked_smith_with_certs_can_not_issue_smith_cert() { - new_test_ext(4, 3).execute_with(|| { - run_to_block(2); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(1), 1, 4)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(2), 2, 4)); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(3), 3, 4)); - assert_ok!(SmithMembership::claim_membership(RuntimeOrigin::signed(4))); - assert_noop!( - SmithCert::add_cert(RuntimeOrigin::signed(4), 4, 1), - pallet_certification::Error::<Test, Instance2>::NotRespectCertPeriod - ); - run_to_block(4); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(4), 4, 1),); - run_to_block(5); - assert_ok!(SmithMembership::revoke_membership(RuntimeOrigin::signed(4))); - run_to_block(6); - assert_ok!(SmithCert::add_cert(RuntimeOrigin::signed(4), 4, 1),); - }) -} diff --git a/pallets/identity/src/lib.rs b/pallets/identity/src/lib.rs index c9656a498..01998e0c5 100644 --- a/pallets/identity/src/lib.rs +++ b/pallets/identity/src/lib.rs @@ -410,8 +410,6 @@ pub mod pallet { Error::<T>::OwnerKeyAlreadyUsed ); - T::CheckIdtyCallAllowed::change_owner_key(idty_index)?; - let block_number = frame_system::Pallet::<T>::block_number(); let maybe_old_old_owner_key = if let Some((old_owner_key, last_change)) = idty_value.old_owner_key { diff --git a/pallets/identity/src/traits.rs b/pallets/identity/src/traits.rs index 925714813..6a1b457c1 100644 --- a/pallets/identity/src/traits.rs +++ b/pallets/identity/src/traits.rs @@ -20,7 +20,6 @@ use impl_trait_for_tuples::impl_for_tuples; pub trait CheckIdtyCallAllowed<T: Config> { fn check_create_identity(creator: T::IdtyIndex) -> Result<(), DispatchError>; - fn change_owner_key(idty_index: T::IdtyIndex) -> Result<(), DispatchError>; } #[impl_for_tuples(5)] @@ -29,10 +28,6 @@ impl<T: Config> CheckIdtyCallAllowed<T> for Tuple { for_tuples!( #( Tuple::check_create_identity(creator)?; )* ); Ok(()) } - fn change_owner_key(idty_index: T::IdtyIndex) -> Result<(), DispatchError> { - for_tuples!( #( Tuple::change_owner_key(idty_index)?; )* ); - Ok(()) - } } pub trait IdtyNameValidator { diff --git a/pallets/identity/src/types.rs b/pallets/identity/src/types.rs index 20120f25c..f8bff333c 100644 --- a/pallets/identity/src/types.rs +++ b/pallets/identity/src/types.rs @@ -38,6 +38,7 @@ pub enum IdtyEvent<T: crate::Config> { /// 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 }, // TODO add a way to unlink accounts corresponding to revoked or removed identities } diff --git a/pallets/membership/src/benchmarking.rs b/pallets/membership/src/benchmarking.rs index d07f4661b..1bdf5edf6 100644 --- a/pallets/membership/src/benchmarking.rs +++ b/pallets/membership/src/benchmarking.rs @@ -18,7 +18,7 @@ use super::*; -use frame_benchmarking::benchmarks_instance_pallet; +use frame_benchmarking::benchmarks; use frame_system::pallet_prelude::BlockNumberFor; use frame_system::RawOrigin; use sp_runtime::traits::{Convert, One}; @@ -28,11 +28,11 @@ use maplit::btreemap; use crate::Pallet; -fn assert_has_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) { +fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { frame_system::Pallet::<T>::assert_has_event(generic_event.into()); } -benchmarks_instance_pallet! { +benchmarks! { where_clause { where T::IdtyId: From<u32>, @@ -42,13 +42,13 @@ benchmarks_instance_pallet! { // claim membership claim_membership { let idty: T::IdtyId = 3.into(); - Membership::<T, I>::take(idty); + Membership::<T>::take(idty); let caller: T::AccountId = T::AccountIdOf::convert(idty).unwrap(); let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); T::BenchmarkSetupHandler::force_status_ok(&idty, &caller); }: _<T::RuntimeOrigin>(caller_origin) verify { - assert_has_event::<T, I>(Event::<T, I>::MembershipAdded{member: idty, expire_on: BlockNumberFor::<T>::one() + T::MembershipPeriod::get()}.into()); + assert_has_event::<T>(Event::<T>::MembershipAdded{member: idty, expire_on: BlockNumberFor::<T>::one() + T::MembershipPeriod::get()}.into()); } // renew membership @@ -59,7 +59,7 @@ benchmarks_instance_pallet! { T::BenchmarkSetupHandler::force_status_ok(&idty, &caller); }: _<T::RuntimeOrigin>(caller_origin) verify { - assert_has_event::<T, I>(Event::<T, I>::MembershipAdded{member: idty, expire_on: BlockNumberFor::<T>::one() + T::MembershipPeriod::get()}.into()); + assert_has_event::<T>(Event::<T>::MembershipAdded{member: idty, expire_on: BlockNumberFor::<T>::one() + T::MembershipPeriod::get()}.into()); } // revoke membership @@ -70,12 +70,12 @@ benchmarks_instance_pallet! { frame_system::pallet::Pallet::<T>::set_block_number(10_000_000.into()); // Arbitrarily high, to be in the worst case of wot instance. }: _<T::RuntimeOrigin>(caller_origin) verify { - assert_has_event::<T, I>(Event::<T, I>::MembershipRemoved{member: idty, reason: MembershipRemovalReason::Revoked}.into()); + assert_has_event::<T>(Event::<T>::MembershipRemoved{member: idty, reason: MembershipRemovalReason::Revoked}.into()); } // Base weight of an empty initialize on_initialize { - }: {Pallet::<T, I>::on_initialize(BlockNumberFor::<T>::zero());} + }: {Pallet::<T>::on_initialize(BlockNumberFor::<T>::zero());} expire_memberships { let i in 0..3; // Limited by the number of validators @@ -86,14 +86,14 @@ benchmarks_instance_pallet! { let mut idties: Vec<T::IdtyId> = Vec::new(); for j in 1..i+1 { let j: T::IdtyId = j.into(); - Membership::<T, I>::insert(j, MembershipData::<T::BlockNumber>::default()); + Membership::<T>::insert(j, MembershipData::<T::BlockNumber>::default()); idties.push(j); } - MembershipsExpireOn::<T, I>::insert(block_number, idties); - assert_eq!(MembershipsExpireOn::<T, I>::get(block_number).len(), i as usize); - }: {Pallet::<T, I>::expire_memberships(block_number);} + MembershipsExpireOn::<T>::insert(block_number, idties); + assert_eq!(MembershipsExpireOn::<T>::get(block_number).len(), i as usize); + }: {Pallet::<T>::expire_memberships(block_number);} verify { - assert_eq!(MembershipsExpireOn::<T, I>::get(block_number).len(), 0_usize); + assert_eq!(MembershipsExpireOn::<T>::get(block_number).len(), 0_usize); } impl_benchmark_test_suite!( diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs index 08bbb81ad..cba39e37e 100644 --- a/pallets/membership/src/lib.rs +++ b/pallets/membership/src/lib.rs @@ -79,12 +79,12 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] #[pallet::without_storage_info] - pub struct Pallet<T, I = ()>(_); + pub struct Pallet<T>(_); // CONFIG // #[pallet::config] - pub trait Config<I: 'static = ()>: frame_system::Config { + pub trait Config: frame_system::Config { /// Ask the runtime whether the identity can perform membership operations type CheckMembershipCallAllowed: CheckMembershipCallAllowed<Self::IdtyId>; /// Something that identifies an identity @@ -99,8 +99,7 @@ pub mod pallet { /// On event handler type OnEvent: OnEvent<Self::IdtyId>; /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From<Event<Self, I>> - + IsType<<Self as frame_system::Config>::RuntimeEvent>; + type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; type WeightInfo: WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkSetupHandler: SetupBenchmark<Self::IdtyId, Self::AccountId>; @@ -109,12 +108,12 @@ pub mod pallet { // GENESIS STUFF // #[pallet::genesis_config] - pub struct GenesisConfig<T: Config<I>, I: 'static = ()> { + pub struct GenesisConfig<T: Config> { pub memberships: BTreeMap<T::IdtyId, MembershipData<T::BlockNumber>>, } #[cfg(feature = "std")] - impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> { + impl<T: Config> Default for GenesisConfig<T> { fn default() -> Self { Self { memberships: Default::default(), @@ -123,11 +122,11 @@ pub mod pallet { } #[pallet::genesis_build] - impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig<T, I> { + impl<T: Config> GenesisBuild<T> for GenesisConfig<T> { fn build(&self) { for (idty_id, membership_data) in &self.memberships { - MembershipsExpireOn::<T, I>::append(membership_data.expire_on, idty_id); - Membership::<T, I>::insert(idty_id, membership_data); + MembershipsExpireOn::<T>::append(membership_data.expire_on, idty_id); + Membership::<T>::insert(idty_id, membership_data); } } } @@ -138,20 +137,20 @@ pub mod pallet { // (expiration block for instance) #[pallet::storage] #[pallet::getter(fn membership)] - pub type Membership<T: Config<I>, I: 'static = ()> = + pub type Membership<T: Config> = CountedStorageMap<_, Twox64Concat, T::IdtyId, MembershipData<T::BlockNumber>, OptionQuery>; /// maps block number to the list of identity id set to expire at this block #[pallet::storage] #[pallet::getter(fn memberships_expire_on)] - pub type MembershipsExpireOn<T: Config<I>, I: 'static = ()> = + pub type MembershipsExpireOn<T: Config> = StorageMap<_, Twox64Concat, T::BlockNumber, Vec<T::IdtyId>, ValueQuery>; // EVENTS // #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event<T: Config<I>, I: 'static = ()> { + pub enum Event<T: Config> { /// A membership was added. MembershipAdded { member: T::IdtyId, @@ -167,7 +166,7 @@ pub mod pallet { // ERRORS// #[pallet::error] - pub enum Error<T, I = ()> { + pub enum Error<T> { /// Identity ID not found. IdtyIdNotFound, /// Membership already acquired. @@ -179,7 +178,7 @@ pub mod pallet { // HOOKS // #[pallet::hooks] - impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> { + impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { fn on_initialize(n: T::BlockNumber) -> Weight { if n > T::BlockNumber::zero() { T::WeightInfo::on_initialize().saturating_add(Self::expire_memberships(n)) @@ -192,7 +191,7 @@ pub mod pallet { // CALLS // #[pallet::call] - impl<T: Config<I>, I: 'static> Pallet<T, I> { + impl<T: Config> Pallet<T> { /// claim membership /// it must fullfill the requirements (certs, distance) /// TODO #159 for main wot claim_membership is called automatically when distance is evaluated positively @@ -215,7 +214,7 @@ pub mod pallet { // Verify phase let idty_id = Self::get_idty_id(origin)?; let membership_data = - Membership::<T, I>::get(idty_id).ok_or(Error::<T, I>::MembershipNotFound)?; + Membership::<T>::get(idty_id).ok_or(Error::<T>::MembershipNotFound)?; T::CheckMembershipCallAllowed::check_idty_allowed_to_renew_membership(&idty_id)?; @@ -244,14 +243,14 @@ pub mod pallet { // INTERNAL FUNCTIONS // - impl<T: Config<I>, I: 'static> Pallet<T, I> { + impl<T: Config> Pallet<T> { /// unschedule membership expiry fn unschedule_membership_expiry(idty_id: T::IdtyId, block_number: T::BlockNumber) { - let mut scheduled = MembershipsExpireOn::<T, I>::get(block_number); + let mut scheduled = MembershipsExpireOn::<T>::get(block_number); if let Some(pos) = scheduled.iter().position(|x| *x == idty_id) { scheduled.swap_remove(pos); - MembershipsExpireOn::<T, I>::set(block_number, scheduled); + MembershipsExpireOn::<T>::set(block_number, scheduled); } } /// schedule membership expiry @@ -259,8 +258,8 @@ pub mod pallet { let block_number = frame_system::pallet::Pallet::<T>::block_number(); let expire_on = block_number + T::MembershipPeriod::get(); - Membership::<T, I>::insert(idty_id, MembershipData { expire_on }); - MembershipsExpireOn::<T, I>::append(expire_on, idty_id); + Membership::<T>::insert(idty_id, MembershipData { expire_on }); + MembershipsExpireOn::<T>::append(expire_on, idty_id); Self::deposit_event(Event::MembershipAdded { member: idty_id, expire_on, @@ -282,7 +281,7 @@ pub mod pallet { /// perform membership removal pub fn do_remove_membership(idty_id: T::IdtyId, reason: MembershipRemovalReason) { - if let Some(membership_data) = Membership::<T, I>::take(idty_id) { + if let Some(membership_data) = Membership::<T>::take(idty_id) { Self::unschedule_membership_expiry(idty_id, membership_data.expire_on); Self::deposit_event(Event::MembershipRemoved { member: idty_id, @@ -295,7 +294,7 @@ pub mod pallet { /// check the origin and get identity id if valid fn get_idty_id(origin: OriginFor<T>) -> Result<T::IdtyId, DispatchError> { if let Ok(RawOrigin::Signed(account_id)) = origin.into() { - T::IdtyIdOf::convert(account_id).ok_or_else(|| Error::<T, I>::IdtyIdNotFound.into()) + T::IdtyIdOf::convert(account_id).ok_or_else(|| Error::<T>::IdtyIdNotFound.into()) } else { Err(BadOrigin.into()) } @@ -305,7 +304,7 @@ pub mod pallet { pub fn expire_memberships(block_number: T::BlockNumber) -> Weight { let mut expired_idty_count = 0u32; - for idty_id in MembershipsExpireOn::<T, I>::take(block_number) { + for idty_id in MembershipsExpireOn::<T>::take(block_number) { // remove membership (take) Self::do_remove_membership(idty_id, MembershipRemovalReason::Expired); expired_idty_count += 1; @@ -314,22 +313,22 @@ pub mod pallet { } /// check if identity is member - pub(super) fn is_member(idty_id: &T::IdtyId) -> bool { - Membership::<T, I>::contains_key(idty_id) + pub fn is_member(idty_id: &T::IdtyId) -> bool { + Membership::<T>::contains_key(idty_id) } } } // implement traits -impl<T: Config<I>, I: 'static> sp_runtime::traits::IsMember<T::IdtyId> for Pallet<T, I> { +impl<T: Config> sp_runtime::traits::IsMember<T::IdtyId> for Pallet<T> { fn is_member(idty_id: &T::IdtyId) -> bool { Self::is_member(idty_id) } } -impl<T: Config<I>, I: 'static> MembersCount for Pallet<T, I> { +impl<T: Config> MembersCount for Pallet<T> { fn members_count() -> u32 { - Membership::<T, I>::count() + Membership::<T>::count() } } diff --git a/pallets/membership/src/tests.rs b/pallets/membership/src/tests.rs index d3ea56167..53da60336 100644 --- a/pallets/membership/src/tests.rs +++ b/pallets/membership/src/tests.rs @@ -106,7 +106,7 @@ fn test_membership_renewal_nope() { // Membership 1 can not be renewed assert_noop!( DefaultMembership::renew_membership(RuntimeOrigin::signed(1)), - Error::<Test, _>::MembershipNotFound, + Error::<Test>::MembershipNotFound, ); run_to_block(3); assert!(!DefaultMembership::is_member(&1)); diff --git a/pallets/smith-members/Cargo.toml b/pallets/smith-members/Cargo.toml new file mode 100644 index 000000000..5ced90e2c --- /dev/null +++ b/pallets/smith-members/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-smith-members" +authors = ["c-geek <https://forum.duniter.org/u/cgeek>"] +description = 'duniter pallet to handle offences.' +edition = "2021" +homepage = 'https://duniter.org' +license = 'AGPL-3.0' +repository = 'https://git.duniter.org/nodes/rust/duniter-v2s' +version = '3.0.0' +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"], default-features = false } +log = { version = "0.4.17", default-features = false } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", default-features = false, optional = true } +pallet-authority-members = { path = "../authority-members", default-features = false } +frame-support = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } +frame-system = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } +pallet-balances = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } +sp-runtime = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } +sp-staking = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } +sp-std = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } + +[dev-dependencies] +maplit = "1.0.2" +sp-core = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } +sp-io = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42' } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + 'frame-benchmarking/std', + "log/std", + "pallet-balances/std", + "pallet-authority-members/std", + "scale-info/std", + "serde", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] + +[dependencies.frame-benchmarking] +default-features = false +git = 'https://github.com/duniter/substrate' +optional = true +branch = 'duniter-substrate-v0.9.42' \ No newline at end of file diff --git a/pallets/smith-members/README.md b/pallets/smith-members/README.md new file mode 100644 index 000000000..655534a2a --- /dev/null +++ b/pallets/smith-members/README.md @@ -0,0 +1,3 @@ +# Duniter smith pallet + +The bridge between `identity` and `authority-members` pallet. \ No newline at end of file diff --git a/pallets/smith-members/src/benchmarking.rs b/pallets/smith-members/src/benchmarking.rs new file mode 100644 index 000000000..071d73905 --- /dev/null +++ b/pallets/smith-members/src/benchmarking.rs @@ -0,0 +1,105 @@ +// Copyright 2021-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/>. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_benchmarking::benchmarks; +use frame_system::RawOrigin; +use sp_runtime::traits::Convert; + +#[cfg(test)] +use maplit::btreemap; + +use crate::Pallet; + +fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { + frame_system::Pallet::<T>::assert_has_event(generic_event.into()); +} + +benchmarks! { + where_clause { + where + T::IdtyIndex: From<u32> + } + invite_smith { + let issuer: T::IdtyIndex = 1.into(); + let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); + Pallet::<T>::on_smith_goes_online(1.into()); + let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + let receiver: T::IdtyIndex = 4.into(); + }: _<T::RuntimeOrigin>(caller_origin, receiver) + verify { + assert_has_event::<T>(Event::<T>::InvitationSent{ + idty_index: receiver, + invited_by: issuer, + }.into()); + } + accept_invitation { + // Worst case preparation + let issuer: T::IdtyIndex = 1.into(); + let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); + Pallet::<T>::on_smith_goes_online(1.into()); + let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + let receiver: T::IdtyIndex = 4.into(); + Pallet::<T>::invite_smith(caller_origin, receiver)?; + // test + let issuer: T::IdtyIndex = 4.into(); + let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); + let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + }: _<T::RuntimeOrigin>(caller_origin) + verify { + assert_has_event::<T>(Event::<T>::InvitationAccepted{ + idty_index: receiver, + }.into()); + } + certify_smith { + // Worst case preparation + let issuer: T::IdtyIndex = 1.into(); + let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); + Pallet::<T>::on_smith_goes_online(1.into()); + let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + let receiver: T::IdtyIndex = 4.into(); + Pallet::<T>::invite_smith(caller_origin, receiver)?; + let issuer: T::IdtyIndex = receiver; + let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); + let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + Pallet::<T>::accept_invitation(caller_origin)?; + // test + let issuer: T::IdtyIndex = 1.into(); + let caller: T::AccountId = T::OwnerKeyOf::convert(issuer).unwrap(); + let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + }: _<T::RuntimeOrigin>(caller_origin, receiver) + verify { + assert_has_event::<T>(Event::<T>::CertificationReceived{ + idty_index: receiver, + issued_by: issuer, + }.into()); + } + + impl_benchmark_test_suite!( + Pallet, + crate::mock::new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3]), + 2 => (false, vec![1, 3]), + 3 => (false, vec![1, 2]), + ], + }), + crate::mock::Runtime + ); +} diff --git a/pallets/smith-members/src/impls.rs b/pallets/smith-members/src/impls.rs new file mode 100644 index 000000000..95a1e49df --- /dev/null +++ b/pallets/smith-members/src/impls.rs @@ -0,0 +1,28 @@ +use crate::{Config, CurrentSession, Pallet}; +use pallet_authority_members::SessionIndex; +use sp_runtime::traits::Convert; + +impl<T: Config> pallet_authority_members::OnOutgoingMember<T::MemberId> for Pallet<T> { + fn on_outgoing_member(member_id: T::MemberId) { + if let Some(member_id) = T::IdtyIdOfAuthorityId::convert(member_id) { + Pallet::<T>::on_smith_goes_offline(member_id); + } + } +} + +/// As long as a Smith is in the authority set, he will not expire. +impl<T: Config> pallet_authority_members::OnIncomingMember<T::MemberId> for Pallet<T> { + fn on_incoming_member(member_id: T::MemberId) { + if let Some(member_id) = T::IdtyIdOfAuthorityId::convert(member_id) { + Pallet::<T>::on_smith_goes_online(member_id); + } + } +} + +/// +impl<T: Config> pallet_authority_members::OnNewSession for Pallet<T> { + fn on_new_session(index: SessionIndex) { + CurrentSession::<T>::put(index); + Pallet::<T>::on_exclude_expired_smiths(index); + } +} diff --git a/pallets/smith-members/src/lib.rs b/pallets/smith-members/src/lib.rs new file mode 100644 index 000000000..95dd31177 --- /dev/null +++ b/pallets/smith-members/src/lib.rs @@ -0,0 +1,552 @@ +// Copyright 2021-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/>. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +mod impls; +pub mod traits; +mod types; +pub mod weights; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +use codec::{Codec, Decode, Encode}; +use frame_support::dispatch::{DispatchResultWithPostInfo, TypeInfo}; +use frame_support::pallet_prelude::Get; +use frame_support::{ensure, RuntimeDebug}; +use frame_system::ensure_signed; +use frame_system::pallet_prelude::OriginFor; +use sp_runtime::traits::AtLeast32BitUnsigned; +use sp_runtime::traits::IsMember; +use sp_std::fmt::Debug; +use sp_std::prelude::*; + +use crate::traits::OnSmithDelete; +pub use crate::weights::WeightInfo; +pub use pallet::*; +use pallet_authority_members::SessionIndex; +pub use types::*; + +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum SmithRemovalReason { + LostMembership, + OfflineTooLong, + Blacklisted, +} + +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum SmithStatus { + /// The identity has been invited by a smith but has not accepted yet + Invited, + /// 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 + Smith, + /// The identity has been removed from the smiths set but is kept to keep track of its certifications + Excluded, +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_support::traits::StorageVersion; + use pallet_authority_members::SessionIndex; + use sp_runtime::traits::{Convert, IsMember}; + use sp_std::collections::btree_map::BTreeMap; + use sp_std::vec; + use sp_std::vec::Vec; + + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + + #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] + pub struct Pallet<T>(_); + + /// The pallet's config trait. + #[pallet::config] + pub trait Config: frame_system::Config { + /// To only allow WoT members to be invited + type IsWoTMember: IsMember<Self::IdtyIndex>; + /// Notify when a smith is removed (for authority-members to react) + type OnSmithDelete: traits::OnSmithDelete<Self::IdtyIndex>; + /// The overarching event type. + type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; + /// A short identity index. + type IdtyIndex: Parameter + + Member + + AtLeast32BitUnsigned + + Codec + + Default + + Copy + + MaybeSerializeDeserialize + + Debug + + MaxEncodedLen; + /// Identifier for an authority-member + type MemberId: Copy + Ord + MaybeSerializeDeserialize + Parameter; + /// Something that gives the IdtyId of an AccountId + type IdtyIdOf: Convert<Self::AccountId, Option<Self::IdtyIndex>>; + /// Something that give the owner key of an identity + type OwnerKeyOf: Convert<Self::IdtyIndex, Option<Self::AccountId>>; + /// Something that gives the IdtyId of an AccountId + type IdtyIdOfAuthorityId: Convert<Self::MemberId, Option<Self::IdtyIndex>>; + /// Maximum number of active certifications by issuer + #[pallet::constant] + type MaxByIssuer: Get<u32>; + /// Minimum number of certifications to become a Smith + #[pallet::constant] + type MinCertForMembership: Get<u32>; + /// Maximum duration of inactivity before a smith is removed + #[pallet::constant] + type SmithInactivityMaxDuration: Get<u32>; + /// Type representing the weight of this pallet + type WeightInfo: WeightInfo; + } + + /// Events type. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event<T: Config> { + /// An identity is being inivited to become a smith + InvitationSent { + idty_index: T::IdtyIndex, + invited_by: T::IdtyIndex, + }, + /// The invitation has been accepted + InvitationAccepted { idty_index: T::IdtyIndex }, + /// Certification received + CertificationReceived { + idty_index: T::IdtyIndex, + issued_by: T::IdtyIndex, + }, + /// A smith gathered enough certifications to become an authority (can call `go_online()`). + PromotedToSmith { idty_index: T::IdtyIndex }, + /// A smith has been removed from the smiths set + SmithExcluded { idty_index: T::IdtyIndex }, + } + + #[pallet::genesis_config] + pub struct GenesisConfig<T: Config> { + pub initial_smiths: BTreeMap<T::IdtyIndex, (bool, Vec<T::IdtyIndex>)>, + } + + #[cfg(feature = "std")] + impl<T: Config> Default for GenesisConfig<T> { + fn default() -> Self { + Self { + initial_smiths: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl<T: Config> GenesisBuild<T> for GenesisConfig<T> { + fn build(&self) { + CurrentSession::<T>::put(0); + let mut cert_meta_by_issuer = BTreeMap::<T::IdtyIndex, Vec<T::IdtyIndex>>::new(); + for (receiver, (is_online, issuers)) in &self.initial_smiths { + // Forbid self-cert + assert!( + !issuers.contains(receiver), + "Identity cannot certify it-self." + ); + + let mut issuers_: Vec<_> = Vec::with_capacity(issuers.len()); + for issuer in issuers { + // Count issued certs + cert_meta_by_issuer + .entry(*issuer) + .or_insert(vec![]) + .push(*receiver); + issuers_.push(*issuer); + } + + // Write CertsByReceiver + issuers_.sort(); + let issuers_count = issuers_.len(); + let smith_status = if issuers_count >= T::MinCertForMembership::get() as usize { + SmithStatus::Smith + } else { + SmithStatus::Pending + }; + Smiths::<T>::insert( + receiver, + SmithMeta { + status: smith_status, + expires_on: if *is_online { + None + } else { + Some(CurrentSession::<T>::get() + T::SmithInactivityMaxDuration::get()) + }, + issued_certs: vec![], + received_certs: issuers_, + }, + ); + ExpiresOn::<T>::append( + CurrentSession::<T>::get() + T::SmithInactivityMaxDuration::get(), + receiver, + ); + } + + for (issuer, issued_certs) in cert_meta_by_issuer { + // Write CertsByIssuer + Smiths::<T>::mutate(issuer, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + smith_meta.issued_certs = issued_certs; + } + }); + } + } + } + + /// maps identity index to smith status + #[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 + #[pallet::storage] + #[pallet::getter(fn expires_on)] + pub type ExpiresOn<T: Config> = + StorageMap<_, Twox64Concat, SessionIndex, Vec<T::IdtyIndex>, OptionQuery>; + + /// stores the current session index + #[pallet::storage] + #[pallet::getter(fn current_session)] + pub type CurrentSession<T: Config> = StorageValue<_, SessionIndex, ValueQuery>; + + // ERRORS // + + #[pallet::error] + pub enum Error<T> { + /// Issuer of anything (invitation, acceptance, certification) must have an identity ID + OriginMustHaveAnIdentity, + /// Issuer must be known as a potential smith + OriginHasNeverBeenInvited, + /// Invitation is reseverd to smiths + InvitationIsASmithPrivilege, + /// Invitation is reseverd to online smiths + InvitationIsAOnlineSmithPrivilege, + /// Invitation must not have been accepted yet + InvitationAlreadyAccepted, + /// Invitation of an already known smith is forbidden except if it has been excluded + InvitationOfExistingNonExcluded, + /// Invitation of a non-member (of the WoT) is forbidden + InvitationOfNonMember, + /// Certification cannot be made on someone who has not accepted an invitation + CertificationMustBeAgreed, + /// Certification cannot be made on excluded + CertificationOnExcludedIsForbidden, + /// Issuer must be a smith + CertificationIsASmithPrivilege, + /// Only online smiths can certify + CertificationIsAOnlineSmithPrivilege, + /// Smith cannot certify itself + CertificationOfSelfIsForbidden, + /// Receiver must be invited by another smith + CertificationReceiverMustHaveBeenInvited, + /// Receiver must not already have this certification + CertificationAlreadyExists, + /// A smith has a limited stock of certifications + CertificationStockFullyConsumed, + } + + #[pallet::call] + impl<T: Config> Pallet<T> { + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::invite_smith())] + pub fn invite_smith( + origin: OriginFor<T>, + receiver: T::IdtyIndex, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin.clone())?; + let issuer = + T::IdtyIdOf::convert(who.clone()).ok_or(Error::<T>::OriginMustHaveAnIdentity)?; + Self::check_invite_smith(issuer, receiver)?; + Self::do_invite_smith(issuer, receiver); + Ok(().into()) + } + + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::accept_invitation())] + pub fn accept_invitation(origin: OriginFor<T>) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin.clone())?; + let receiver = + T::IdtyIdOf::convert(who.clone()).ok_or(Error::<T>::OriginMustHaveAnIdentity)?; + Self::check_accept_invitation(receiver)?; + Self::do_accept_invitation(receiver)?; + Ok(().into()) + } + + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::certify_smith())] + pub fn certify_smith( + origin: OriginFor<T>, + receiver: T::IdtyIndex, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let issuer = + T::IdtyIdOf::convert(who.clone()).ok_or(Error::<T>::OriginMustHaveAnIdentity)?; + Self::check_certify_smith(issuer, receiver)?; + Self::do_certify_smith(receiver, issuer); + Ok(().into()) + } + } +} + +impl<T: Config> Pallet<T> { + fn check_invite_smith( + issuer: T::IdtyIndex, + receiver: T::IdtyIndex, + ) -> DispatchResultWithPostInfo { + let issuer = Smiths::<T>::get(issuer).ok_or(Error::<T>::OriginHasNeverBeenInvited)?; + ensure!( + issuer.status == SmithStatus::Smith, + Error::<T>::InvitationIsASmithPrivilege + ); + ensure!( + issuer.expires_on.is_none(), + Error::<T>::InvitationIsAOnlineSmithPrivilege + ); + if let Some(receiver_meta) = Smiths::<T>::get(receiver) { + ensure!( + receiver_meta.status == SmithStatus::Excluded, + Error::<T>::InvitationOfExistingNonExcluded + ); + } + ensure!( + T::IsWoTMember::is_member(&receiver), + Error::<T>::InvitationOfNonMember + ); + + Ok(().into()) + } + + 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(); + existing.status = SmithStatus::Invited; + existing.expires_on = Some(new_expires_on); + existing.received_certs = vec![]; + Smiths::<T>::insert(receiver, existing); + ExpiresOn::<T>::append(new_expires_on, receiver); + Self::deposit_event(Event::<T>::InvitationSent { + idty_index: receiver, + invited_by: issuer, + }); + } + + fn check_accept_invitation(receiver: T::IdtyIndex) -> DispatchResultWithPostInfo { + let pretender_status = Smiths::<T>::get(receiver) + .ok_or(Error::<T>::OriginHasNeverBeenInvited)? + .status; + ensure!( + pretender_status == SmithStatus::Invited, + Error::<T>::InvitationAlreadyAccepted + ); + Ok(().into()) + } + + fn do_accept_invitation(receiver: T::IdtyIndex) -> DispatchResultWithPostInfo { + Smiths::<T>::mutate(receiver, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + smith_meta.status = SmithStatus::Pending; + } + }); + Self::deposit_event(Event::<T>::InvitationAccepted { + idty_index: receiver, + }); + Ok(().into()) + } + + fn check_certify_smith( + issuer_index: T::IdtyIndex, + receiver_index: T::IdtyIndex, + ) -> DispatchResultWithPostInfo { + ensure!( + issuer_index != receiver_index, + Error::<T>::CertificationOfSelfIsForbidden + ); + let issuer = Smiths::<T>::get(issuer_index).ok_or(Error::<T>::OriginHasNeverBeenInvited)?; + ensure!( + issuer.status == SmithStatus::Smith, + Error::<T>::CertificationIsASmithPrivilege + ); + ensure!( + issuer.expires_on.is_none(), + Error::<T>::CertificationIsAOnlineSmithPrivilege + ); + let issued_certs = issuer.issued_certs.len(); + ensure!( + issued_certs < T::MaxByIssuer::get() as usize, + Error::<T>::CertificationStockFullyConsumed + ); + let receiver = Smiths::<T>::get(receiver_index) + .ok_or(Error::<T>::CertificationReceiverMustHaveBeenInvited)?; + ensure!( + receiver.status != SmithStatus::Invited, + Error::<T>::CertificationMustBeAgreed + ); + ensure!( + receiver.status != SmithStatus::Excluded, + Error::<T>::CertificationOnExcludedIsForbidden + ); + ensure!( + receiver + .received_certs + .binary_search(&issuer_index) + .is_err(), + Error::<T>::CertificationAlreadyExists + ); + + Ok(().into()) + } + + fn do_certify_smith(receiver: T::IdtyIndex, issuer: T::IdtyIndex) { + Smiths::<T>::mutate(issuer, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + smith_meta.issued_certs.push(receiver); + smith_meta.issued_certs.sort(); + } + }); + Smiths::<T>::mutate(receiver, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + smith_meta.received_certs.push(issuer); + smith_meta.received_certs.sort(); + smith_meta.status = + if smith_meta.received_certs.len() >= T::MinCertForMembership::get() as usize { + SmithStatus::Smith + } else { + SmithStatus::Pending + }; + // expiry postponed + let new_expires_on = + CurrentSession::<T>::get() + T::SmithInactivityMaxDuration::get(); + smith_meta.expires_on = Some(new_expires_on); + Self::deposit_event(Event::<T>::CertificationReceived { + idty_index: receiver, + issued_by: issuer, + }); + if smith_meta.status == SmithStatus::Smith { + Self::deposit_event(Event::<T>::PromotedToSmith { + idty_index: receiver, + }); + } + // TODO: unschedule old expiry + } + }); + } + + fn on_exclude_expired_smiths(at: SessionIndex) { + if let Some(smiths_to_remove) = ExpiresOn::<T>::get(at) { + for smith in smiths_to_remove { + if let Some(smith_meta) = Smiths::<T>::get(smith) { + if let Some(expires_on) = smith_meta.expires_on { + if expires_on == at { + Self::_do_exclude_smith(smith, SmithRemovalReason::OfflineTooLong); + } + } + } + } + } + } + + pub fn on_removed_wot_member(idty_index: T::IdtyIndex) { + if Smiths::<T>::get(idty_index).is_some() { + Self::_do_exclude_smith(idty_index, SmithRemovalReason::LostMembership); + } + } + + fn _do_exclude_smith(idty_index: T::IdtyIndex, reason: SmithRemovalReason) { + let mut lost_certs = vec![]; + Smiths::<T>::mutate(idty_index, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + smith_meta.expires_on = None; + smith_meta.status = SmithStatus::Excluded; + for cert in &smith_meta.received_certs { + lost_certs.push(*cert); + } + smith_meta.received_certs = vec![]; + // N.B.: the issued certs are kept in case the smith joins back + } + }); + // We remove the lost certs from their issuer's stock + for lost_cert in lost_certs { + Smiths::<T>::mutate(lost_cert, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + if let Ok(index) = smith_meta.issued_certs.binary_search(&idty_index) { + smith_meta.issued_certs.remove(index); + } + } + }); + } + // Deletion done: notify (authority-members) for cascading + T::OnSmithDelete::on_smith_delete(idty_index, reason); + Self::deposit_event(Event::<T>::SmithExcluded { idty_index }); + } + + 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() { + Smiths::<T>::mutate(idty_index, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + // As long as the smith is online, it cannot expire + smith_meta.expires_on = None; + // FIXME: unschedule old expiry + } + }); + } + } + } + + 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() { + Smiths::<T>::mutate(idty_index, |maybe_smith_meta| { + if let Some(smith_meta) = maybe_smith_meta { + // As long as the smith is online, it cannot expire + let new_expires_on = + CurrentSession::<T>::get() + T::SmithInactivityMaxDuration::get(); + smith_meta.expires_on = Some(new_expires_on); + ExpiresOn::<T>::append(new_expires_on, idty_index); + } + }); + } + } + } + + fn provide_is_member(idty_id: &T::IdtyIndex) -> bool { + let Some(smith) = Smiths::<T>::get(idty_id) else { + return false; + }; + smith.status == SmithStatus::Smith + } +} + +impl<T: Config> sp_runtime::traits::IsMember<T::IdtyIndex> for Pallet<T> { + fn is_member(idty_id: &T::IdtyIndex) -> bool { + Self::provide_is_member(idty_id) + } +} diff --git a/pallets/smith-members/src/mock.rs b/pallets/smith-members/src/mock.rs new file mode 100644 index 000000000..cd2398e4d --- /dev/null +++ b/pallets/smith-members/src/mock.rs @@ -0,0 +1,123 @@ +// Copyright 2021-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/>. + +#![cfg(test)] + +use crate::{self as pallet_smith_members}; +use frame_support::pallet_prelude::Hooks; +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64}, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_core::H256; +use sp_runtime::traits::{ConvertInto, IsMember}; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, Perbill, +}; + +parameter_types! { + pub static OnOffencePerbill: Vec<Perbill> = Default::default(); + pub static OffenceWeight: Weight = Default::default(); +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>; +type Block = frame_system::mocking::MockBlock<Runtime>; + +frame_support::construct_runtime!( + pub struct Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, + Smith: pallet_smith_members::{Pallet, Config<T>, Storage, Event<T>}, + } +); + +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = u64; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup<Self::AccountId>; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +pub struct EveryoneExceptIdZero; +impl IsMember<u64> for EveryoneExceptIdZero { + fn is_member(member_id: &u64) -> bool { + member_id != &0 && member_id != &10 + } +} + +impl pallet_smith_members::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type IdtyIndex = u64; + type IsWoTMember = EveryoneExceptIdZero; + type IdtyIdOf = ConvertInto; + type MinCertForMembership = ConstU32<2>; + type MaxByIssuer = ConstU32<3>; + type SmithInactivityMaxDuration = ConstU32<5>; + type OnSmithDelete = (); + type IdtyIdOfAuthorityId = ConvertInto; + type MemberId = u64; + type OwnerKeyOf = ConvertInto; + type WeightInfo = (); +} + +pub fn new_test_ext( + genesis_config: crate::pallet::GenesisConfig<Runtime>, +) -> sp_io::TestExternalities { + GenesisConfig { + system: SystemConfig::default(), + smith: genesis_config, + } + .build_storage() + .unwrap() + .into() +} + +pub fn run_to_block(n: u64) { + while System::block_number() < n { + Smith::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::reset_events(); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Smith::on_initialize(System::block_number()); + } +} diff --git a/pallets/smith-members/src/tests.rs b/pallets/smith-members/src/tests.rs new file mode 100644 index 000000000..a843a17a9 --- /dev/null +++ b/pallets/smith-members/src/tests.rs @@ -0,0 +1,577 @@ +// Copyright 2021-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/>. + +#![cfg(test)] + +use super::*; +use crate::mock::{new_test_ext, run_to_block, Runtime, RuntimeEvent, RuntimeOrigin, System}; +use frame_support::{assert_err, assert_ok}; + +use crate::SmithStatus::{Excluded, Invited, Pending, Smith}; +#[cfg(test)] +use maplit::btreemap; +use pallet_authority_members::OnNewSession; + +#[test] +fn process_to_become_a_smith_and_lose_it() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![]), + 4 => (false, vec![]), + ], + }) + .execute_with(|| { + // Go online to be able to invite+certify + Pallet::<Runtime>::on_smith_goes_online(1); + Pallet::<Runtime>::on_smith_goes_online(2); + // Events cannot be recorded on genesis + run_to_block(1); + // State before + assert_eq!(Smiths::<Runtime>::get(5), None); + // Try to invite + assert_ok!(Pallet::<Runtime>::invite_smith(RuntimeOrigin::signed(1), 5)); + System::assert_has_event(RuntimeEvent::Smith(Event::<Runtime>::InvitationSent { + idty_index: 5, + invited_by: 1, + })); + // Accept invitation + assert_ok!(Pallet::<Runtime>::accept_invitation(RuntimeOrigin::signed( + 5 + ))); + System::assert_has_event(RuntimeEvent::Smith(Event::<Runtime>::InvitationAccepted { + idty_index: 5, + })); + // State after + assert_eq!( + Smiths::<Runtime>::get(5).unwrap(), + SmithMeta { + status: SmithStatus::Pending, + expires_on: Some(5), + issued_certs: vec![], + received_certs: vec![], + } + ); + // Then certification 1/2 + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(1), + 5 + )); + System::assert_has_event(RuntimeEvent::Smith( + Event::<Runtime>::CertificationReceived { + idty_index: 5, + issued_by: 1, + }, + )); + assert_eq!( + Smiths::<Runtime>::get(5).unwrap(), + SmithMeta { + status: SmithStatus::Pending, + expires_on: Some(5), + issued_certs: vec![], + received_certs: vec![1], + } + ); + // Then certification 2/2 + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(2), + 5 + )); + System::assert_has_event(RuntimeEvent::Smith( + Event::<Runtime>::CertificationReceived { + idty_index: 5, + issued_by: 1, + }, + )); + System::assert_has_event(RuntimeEvent::Smith(Event::<Runtime>::PromotedToSmith { + idty_index: 5, + })); + assert_eq!( + Smiths::<Runtime>::get(5).unwrap(), + SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(5), + issued_certs: vec![], + received_certs: vec![1, 2], + } + ); + // Go online to be able to invite+certify + Pallet::<Runtime>::on_smith_goes_offline(1); + Pallet::<Runtime>::on_smith_goes_offline(2); + + // On session 4 everything if fine + Pallet::<Runtime>::on_new_session(4); + assert!(Smiths::<Runtime>::get(1).is_some()); + assert!(Smiths::<Runtime>::get(2).is_some()); + assert!(Smiths::<Runtime>::get(5).is_some()); + // On session 5 no more smiths because of lack of activity + Pallet::<Runtime>::on_new_session(5); + System::assert_has_event(RuntimeEvent::Smith(Event::<Runtime>::SmithExcluded { + idty_index: 1, + })); + System::assert_has_event(RuntimeEvent::Smith(Event::<Runtime>::SmithExcluded { + idty_index: 2, + })); + System::assert_has_event(RuntimeEvent::Smith(Event::<Runtime>::SmithExcluded { + idty_index: 5, + })); + assert_eq!( + Smiths::<Runtime>::get(1), + Some(SmithMeta { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: vec![], + received_certs: vec![] + }) + ); + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: vec![], + received_certs: vec![] + }) + ); + assert_eq!( + Smiths::<Runtime>::get(5), + Some(SmithMeta { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: vec![], + received_certs: vec![] + }) + ); + }); +} + +#[test] +fn should_have_checks_on_certify() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![4]), + 4 => (false, vec![1, 2]), + ], + }) + .execute_with(|| { + // Go online to be able to invite+certify + Pallet::<Runtime>::on_smith_goes_online(1); + // Initially + assert_eq!( + Smiths::<Runtime>::get(1).unwrap(), + SmithMeta { + status: Smith, + expires_on: None, + issued_certs: vec![4], + received_certs: vec![2, 3, 4], + } + ); + assert_eq!( + Smiths::<Runtime>::get(2).unwrap(), + SmithMeta { + status: Smith, + expires_on: Some(5), + issued_certs: vec![1, 4], + received_certs: vec![3, 4], + } + ); + assert_eq!( + Smiths::<Runtime>::get(3).unwrap(), + SmithMeta { + status: Pending, + expires_on: Some(5), + issued_certs: vec![1, 2], + received_certs: vec![4], + } + ); + assert_eq!( + Smiths::<Runtime>::get(4).unwrap(), + SmithMeta { + status: Smith, + expires_on: Some(5), + issued_certs: vec![1, 2, 3], + received_certs: vec![1, 2], + } + ); + + // Tries all possible errors + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(0), 1), + Error::<Runtime>::OriginHasNeverBeenInvited + ); + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(1), 1), + Error::<Runtime>::CertificationOfSelfIsForbidden + ); + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(3), 5), + Error::<Runtime>::CertificationIsASmithPrivilege + ); + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(1), 6), + Error::<Runtime>::CertificationReceiverMustHaveBeenInvited + ); + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(1), 4), + Error::<Runtime>::CertificationAlreadyExists + ); + + // #3: state before + assert_eq!( + Smiths::<Runtime>::get(3).unwrap(), + SmithMeta { + status: Pending, + expires_on: Some(5), + issued_certs: vec![1, 2], + received_certs: vec![4], + } + ); + // Try to certify #3 + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(1), + 3 + )); + // #3: state after + assert_eq!( + Smiths::<Runtime>::get(3).unwrap(), + SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(5), + issued_certs: vec![1, 2], + received_certs: vec![1, 4], + } + ); + }); +} + +#[test] +fn smith_activity_postpones_expiration() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![]), + 4 => (false, vec![]) + ], + }) + .execute_with(|| { + // On session 4 everything is fine + Pallet::<Runtime>::on_new_session(4); + assert!(Smiths::<Runtime>::get(1).is_some()); + assert!(Smiths::<Runtime>::get(2).is_some()); + + // Smith #2 is online but not #1 + Pallet::<Runtime>::on_smith_goes_online(2); + + // On session 5: exclusion for lack of activity + Pallet::<Runtime>::on_new_session(5); + assert_eq!( + Smiths::<Runtime>::get(1), + Some(SmithMeta { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: vec![], + received_certs: vec![] + }) + ); + // issued_certs is empty because #1 was excluded + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: None, + issued_certs: vec![], + received_certs: vec![3, 4], + }) + ); + + // Smith #2 goes offline + Pallet::<Runtime>::on_new_session(6); + Pallet::<Runtime>::on_smith_goes_offline(2); + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(11), + issued_certs: vec![], + received_certs: vec![3, 4], + }) + ); + // Still not expired on session 10 + Pallet::<Runtime>::on_new_session(10); + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(11), + issued_certs: vec![], + received_certs: vec![3, 4], + }) + ); + // But expired on session 11 + Pallet::<Runtime>::on_new_session(11); + assert_eq!( + Smiths::<Runtime>::get(1), + Some(SmithMeta { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: vec![], + received_certs: vec![] + }) + ); + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: vec![], + received_certs: vec![] + }) + ); + }); +} + +#[test] +fn smith_coming_back_recovers_its_issued_certs() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![1, 4]), + 4 => (false, vec![]), + ], + }) + .execute_with(|| { + // Not activity for Smith #2 + Pallet::<Runtime>::on_smith_goes_online(1); + Pallet::<Runtime>::on_smith_goes_online(3); + Pallet::<Runtime>::on_smith_goes_online(4); + // Smith #2 gets excluded + Pallet::<Runtime>::on_new_session(5); + // The issued certs are preserved + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: Excluded, + expires_on: None, + issued_certs: vec![1], + received_certs: vec![] + }) + ); + // Smith #2 comes back + assert_ok!(Pallet::<Runtime>::invite_smith(RuntimeOrigin::signed(1), 2)); + assert_ok!(Pallet::<Runtime>::accept_invitation(RuntimeOrigin::signed( + 2 + ))); + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(1), + 2 + )); + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(3), + 2 + )); + // Smith #2 is back with its issued certs recovered, but not its received certs + assert_eq!( + Smiths::<Runtime>::get(2), + Some(SmithMeta { + status: Smith, + expires_on: Some(10), + issued_certs: vec![1], + received_certs: vec![1, 3] + }) + ); + Pallet::<Runtime>::on_smith_goes_online(2); + // We can verify it with the stock rule + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(2), + 3 + )); + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(2), + 4 + )); + // Max stock is reached (3 = 1 recovered + 2 new) + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(2), 5), + Error::<Runtime>::CertificationStockFullyConsumed + ); + }); +} + +#[test] +fn certifying_on_different_status() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![1, 2]), + 4 => (false, vec![]), + ], + }) + .execute_with(|| { + // Go online to be able to invite+certify + Pallet::<Runtime>::on_smith_goes_online(1); + Pallet::<Runtime>::on_smith_goes_online(2); + Pallet::<Runtime>::on_smith_goes_online(3); + // State before + assert_eq!(Smiths::<Runtime>::get(5), None); + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(1), 5), + Error::<Runtime>::CertificationReceiverMustHaveBeenInvited + ); + + // After invitation + assert_ok!(Pallet::<Runtime>::invite_smith(RuntimeOrigin::signed(1), 5)); + assert_eq!(Smiths::<Runtime>::get(5).unwrap().status, Invited); + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(1), 5), + Error::<Runtime>::CertificationMustBeAgreed + ); + + // After acceptation + assert_ok!(Pallet::<Runtime>::accept_invitation(RuntimeOrigin::signed( + 5 + ))); + assert_eq!(Smiths::<Runtime>::get(5).unwrap().status, Pending); + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(1), + 5 + )); + assert_eq!(Smiths::<Runtime>::get(5).unwrap().status, Pending); + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(2), + 5 + )); + assert_eq!(Smiths::<Runtime>::get(5).unwrap().status, Smith); + + // After being a smith + assert_ok!(Pallet::<Runtime>::certify_smith( + RuntimeOrigin::signed(3), + 5 + )); + + Pallet::<Runtime>::on_smith_goes_online(1); + Pallet::<Runtime>::on_smith_goes_online(2); + Pallet::<Runtime>::on_new_session(5); + assert_eq!(Smiths::<Runtime>::get(1).unwrap().status, Smith); + assert_eq!(Smiths::<Runtime>::get(2).unwrap().status, Smith); + assert_eq!(Smiths::<Runtime>::get(5).unwrap().status, Excluded); + + // After being excluded + assert_err!( + Pallet::<Runtime>::certify_smith(RuntimeOrigin::signed(1), 5), + Error::<Runtime>::CertificationOnExcludedIsForbidden + ); + }); +} + +#[test] +fn invitation_on_non_wot_member() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![1, 2]), + 4 => (false, vec![]), + ], + }) + .execute_with(|| { + // Go online to be able to invite+certify + Pallet::<Runtime>::on_smith_goes_online(1); + // State before + assert_eq!(Smiths::<Runtime>::get(10), None); + + // After invitation + assert_err!( + Pallet::<Runtime>::invite_smith(RuntimeOrigin::signed(1), 10), + Error::<Runtime>::InvitationOfNonMember + ); + }); +} + +#[test] +fn losing_wot_membership_cascades_to_smith_members() { + new_test_ext(GenesisConfig { + initial_smiths: btreemap![ + 1 => (false, vec![2, 3, 4]), + 2 => (false, vec![3, 4]), + 3 => (false, vec![1, 2]), + 4 => (false, vec![]), + ], + }) + .execute_with(|| { + // State before + assert_eq!( + Smiths::<Runtime>::get(1), + Some(SmithMeta { + status: Smith, + expires_on: Some(5), + issued_certs: vec![3], + received_certs: vec![2, 3, 4], + }) + ); + assert_eq!( + Smiths::<Runtime>::get(1).unwrap().issued_certs, + Vec::<u64>::from([3]) + ); + assert_eq!( + Smiths::<Runtime>::get(2).unwrap().issued_certs, + Vec::<u64>::from([1, 3]) + ); + assert_eq!( + Smiths::<Runtime>::get(3).unwrap().issued_certs, + Vec::<u64>::from([1, 2]) + ); + assert_eq!( + Smiths::<Runtime>::get(4).unwrap().issued_certs, + Vec::<u64>::from([1, 2]) + ); + + Pallet::<Runtime>::on_removed_wot_member(1); + + // Excluded + assert_eq!( + Smiths::<Runtime>::get(1), + Some(SmithMeta { + status: Excluded, + expires_on: None, + issued_certs: vec![3], + received_certs: vec![], + }) + ); + // Issued certifications updated for certifiers of 1 + assert_eq!( + Smiths::<Runtime>::get(1).unwrap().issued_certs, + Vec::<u64>::from([3]) + ); + assert_eq!( + Smiths::<Runtime>::get(2).unwrap().issued_certs, + Vec::<u64>::from([3]) + ); + assert_eq!( + Smiths::<Runtime>::get(3).unwrap().issued_certs, + Vec::<u64>::from([2]) + ); + assert_eq!( + Smiths::<Runtime>::get(4).unwrap().issued_certs, + Vec::<u64>::from([2]) + ); + }); +} diff --git a/pallets/smith-members/src/traits.rs b/pallets/smith-members/src/traits.rs new file mode 100644 index 000000000..f59b6fc1c --- /dev/null +++ b/pallets/smith-members/src/traits.rs @@ -0,0 +1,8 @@ +use crate::SmithRemovalReason; + +pub trait OnSmithDelete<IdtyIndex> { + 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 new file mode 100644 index 000000000..fcccd3468 --- /dev/null +++ b/pallets/smith-members/src/types.rs @@ -0,0 +1,49 @@ +// Copyright 2021 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/>. + +//! Various basic types for use in the identity pallet. + +use crate::SmithStatus; +use codec::{Decode, Encode}; +use frame_support::pallet_prelude::*; +use scale_info::TypeInfo; +use sp_staking::SessionIndex; +use sp_std::vec::Vec; + +/// certification metadata attached to an identity +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct SmithMeta<IdtyIndex> { + /// current status of the smith + pub status: SmithStatus, + /// the session at which the smith will expire (for lack of validation activity) + pub expires_on: Option<SessionIndex>, + /// the certifications issued to other smiths + pub issued_certs: Vec<IdtyIndex>, + /// the certifications received from other smiths + pub received_certs: Vec<IdtyIndex>, +} + +/// By default, a smith has the least possible privileges +impl<IdtyIndex> Default for SmithMeta<IdtyIndex> { + fn default() -> Self { + Self { + status: SmithStatus::Excluded, + expires_on: None, + issued_certs: Vec::<IdtyIndex>::new(), + received_certs: Vec::<IdtyIndex>::new(), + } + } +} diff --git a/pallets/smith-members/src/weights.rs b/pallets/smith-members/src/weights.rs new file mode 100644 index 000000000..b18e0cef9 --- /dev/null +++ b/pallets/smith-members/src/weights.rs @@ -0,0 +1,38 @@ +// Copyright 2021-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/>. + +#![allow(clippy::unnecessary_cast)] + +use frame_support::weights::Weight; + +/// Weight functions needed for pallet. +pub trait WeightInfo { + fn invite_smith() -> Weight; + fn accept_invitation() -> Weight; + fn certify_smith() -> Weight; +} + +impl WeightInfo for () { + fn invite_smith() -> Weight { + Weight::zero() + } + fn accept_invitation() -> Weight { + Weight::zero() + } + fn certify_smith() -> Weight { + Weight::zero() + } +} diff --git a/resources/gdev.yaml b/resources/gdev.yaml index 80296c969..a90145753 100644 --- a/resources/gdev.yaml +++ b/resources/gdev.yaml @@ -41,20 +41,10 @@ parameters: wot_min_cert_for_create_idty_right: 3 # ----- SMITH WOT ----- - # Duration to wait between two emitted certifications, in blocks. 14400 blocks = 24h = 1 day. - smith_cert_period: 14400 # Maximum quantity of currently valid certifications emitted by a same issuer. 15 certs. smith_cert_max_by_issuer: 15 - # Minimum quantity of smith certifications received to be able to smith certify someone else. - smith_cert_min_received_cert_to_issue_cert: 3 - # Validity duration of a certification, in blocks. 2102400 blocks = 146 days. - smith_cert_validity_period: 2102400 - # Validity duration of a membership. 1051200 blocks = 73 days. - smith_membership_period: 1051200 - # Validity duration of a pending membership. 172800 blocks = 12 days. - smith_pending_membership_period: 172800 - # Delay a new smith member must observe before being able to emit a smith certification. 14400 blocks = 24h = 1 day. - smith_wot_first_cert_issuable_on: 14400 + # Maximum duration a smith can be offline without being excluded + smith_inactivity_max_duration: 48 # Number of required received smith certs to become a smith member smith_wot_min_cert_for_membership: 3 diff --git a/resources/metadata.scale b/resources/metadata.scale index 86dc5fa76adcc7628a8dd62903866e06603f0719..d9b927842841c74ddf26cd400b3b4a304a3c6eeb 100644 GIT binary patch delta 9601 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 V%+lWUXpt&9WN8e=&W%aN{|AOe^lktE delta 7846 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 Z9Qp(7uvBWlm`W^-we<5i#jrls@P8I#l8yiX diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 620eb3c8c..04ca8dd0c 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -35,6 +35,7 @@ std = [ 'frame-system/std', 'log/std', 'pallet-authority-members/std', + 'pallet-smith-members/std', 'pallet-babe/std', 'pallet-balances/std', 'pallet-certification/std', @@ -73,6 +74,7 @@ try-runtime = [ [dependencies] duniter-primitives = { path = '../../primitives/duniter', default-features = false } pallet-authority-members = { path = '../../pallets/authority-members', default-features = false } +pallet-smith-members = { path = '../../pallets/smith-members', default-features = false } pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-distance = { path = "../../pallets/distance", default-features = false } pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false } diff --git a/runtime/common/src/handlers.rs b/runtime/common/src/handlers.rs index 8cb679c66..c52925272 100644 --- a/runtime/common/src/handlers.rs +++ b/runtime/common/src/handlers.rs @@ -17,9 +17,8 @@ use super::entities::*; use super::{AccountId, IdtyIndex}; use frame_support::dispatch::UnfilteredDispatchable; -use frame_support::instances::{Instance1, Instance2}; use frame_support::pallet_prelude::Weight; -use frame_support::Parameter; +use pallet_smith_members::SmithRemovalReason; // new session handler pub struct OnNewSessionHandler<Runtime>(core::marker::PhantomData<Runtime>); @@ -39,7 +38,8 @@ impl< Inner: sp_membership::traits::OnEvent<IdtyIndex>, Runtime: frame_system::Config<AccountId = AccountId> + pallet_identity::Config<IdtyData = IdtyData, IdtyIndex = IdtyIndex> - + pallet_membership::Config<Instance1> + + pallet_membership::Config + + pallet_smith_members::Config<IdtyIndex = IdtyIndex> + pallet_universal_dividend::Config, > sp_membership::traits::OnEvent<IdtyIndex> for OnMembershipEventHandler<Inner, Runtime> { @@ -55,6 +55,7 @@ impl< ); } } + pallet_smith_members::Pallet::<Runtime>::on_removed_wot_member(*idty_index); } // when main membership is acquired, it starts getting right to UD sp_membership::Event::MembershipAdded(idty_index) => { @@ -75,60 +76,6 @@ impl< } } -// smith membership event handler -pub struct OnSmithMembershipEventHandler<Inner, Runtime>( - core::marker::PhantomData<(Inner, Runtime)>, -); -impl< - IdtyIndex: Copy + Parameter, - Inner: sp_membership::traits::OnEvent<IdtyIndex>, - Runtime: frame_system::Config<AccountId = AccountId> - + pallet_identity::Config<IdtyIndex = IdtyIndex> - + pallet_authority_members::Config<MemberId = IdtyIndex> - + pallet_membership::Config<Instance2>, - > sp_membership::traits::OnEvent<IdtyIndex> for OnSmithMembershipEventHandler<Inner, Runtime> -{ - fn on_event(membership_event: &sp_membership::Event<IdtyIndex>) { - (match membership_event { - sp_membership::Event::MembershipAdded(_idty_index) => { - // nothing when smith membership acquired - // user will have to claim authority membership - } - sp_membership::Event::MembershipRemoved(idty_index) => { - let call = pallet_authority_members::Call::<Runtime>::remove_member { - member_id: *idty_index, - }; - if let Err(e) = - call.dispatch_bypass_filter(frame_system::Origin::<Runtime>::Root.into()) - { - sp_std::if_std! { - println!("faid to remove member: {:?}", e) - } - } - } - _ => (), - }); - Inner::on_event(membership_event) - } -} - -// authority member removal handler -// TODO refac smith wot -// or document the link between smith membership and authority member -pub struct OnRemovedAuthorityMemberHandler<Runtime>(core::marker::PhantomData<Runtime>); -impl<Runtime> pallet_authority_members::traits::OnRemovedMember<IdtyIndex> - for OnRemovedAuthorityMemberHandler<Runtime> -where - Runtime: frame_system::Config + pallet_membership::Config<Instance2, IdtyId = IdtyIndex>, -{ - fn on_removed_member(idty_index: IdtyIndex) { - pallet_membership::Pallet::<Runtime, Instance2>::do_remove_membership( - idty_index, - pallet_membership::MembershipRemovalReason::System, - ); - } -} - // spend treasury handler pub struct TreasurySpendFunds<Runtime>(core::marker::PhantomData<Runtime>); impl<Runtime> pallet_treasury::SpendFunds<Runtime> for TreasurySpendFunds<Runtime> @@ -144,3 +91,21 @@ where *missed_any = true; } } + +pub struct OnSmithDeletedHandler<Runtime>(core::marker::PhantomData<Runtime>); +impl<Runtime> pallet_smith_members::traits::OnSmithDelete<Runtime::MemberId> + for OnSmithDeletedHandler<Runtime> +where + Runtime: pallet_authority_members::Config, +{ + fn on_smith_delete(idty_index: Runtime::MemberId, _reason: SmithRemovalReason) { + let call = pallet_authority_members::Call::<Runtime>::remove_member { + member_id: idty_index, + }; + if let Err(e) = call.dispatch_bypass_filter(frame_system::Origin::<Runtime>::Root.into()) { + sp_std::if_std! { + println!("faid to remove member: {:?}", e) + } + } + } +} diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs index e61c1996d..f1cfbf299 100644 --- a/runtime/common/src/pallets_config.rs +++ b/runtime/common/src/pallets_config.rs @@ -236,14 +236,15 @@ macro_rules! pallets_config { } impl pallet_authority_members::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type IsMember = SmithMembership; + type IsMember = SmithMembers; type OnNewSession = OnNewSessionHandler<Runtime>; - type OnRemovedMember = OnRemovedAuthorityMemberHandler<Runtime>; type MemberId = IdtyIndex; type MemberIdOf = common_runtime::providers::IdentityIndexOf<Self>; type MaxAuthorities = MaxAuthorities; type RemoveMemberOrigin = EnsureRoot<Self::AccountId>; type WeightInfo = common_runtime::weights::pallet_authority_members::WeightInfo<Runtime>; + type OnIncomingMember = SmithMembers; + type OnOutgoingMember = SmithMembers; } impl pallet_authorship::Config for Runtime { type EventHandler = ImOnline; @@ -453,11 +454,9 @@ macro_rules! pallets_config { // WEB OF TRUST // - use frame_support::instances::Instance1; - impl pallet_duniter_wot::Config<Instance1> for Runtime { + impl pallet_duniter_wot::Config for Runtime { type FirstIssuableOn = WotFirstCertIssuableOn; type IsDistanceOk = common_runtime::providers::MainWotIsDistanceOk<Runtime>; - type IsSubWot = frame_support::traits::ConstBool<false>; type MinCertForMembership = WotMinCertForMembership; type MinCertForCreateIdtyRight = WotMinCertForCreateIdtyRight; } @@ -473,7 +472,7 @@ macro_rules! pallets_config { type ValidationPeriod = ValidationPeriod; type AutorevocationPeriod = AutorevocationPeriod; type DeletionPeriod = DeletionPeriod; - type CheckIdtyCallAllowed = (Wot, SmithSubWot); + type CheckIdtyCallAllowed = Wot; type IdtyCreationPeriod = IdtyCreationPeriod; type IdtyData = IdtyData; type IdtyIndex = IdtyIndex; @@ -481,12 +480,12 @@ macro_rules! pallets_config { type IdtyNameValidator = IdtyNameValidatorImpl; type Signer = <Signature as sp_runtime::traits::Verify>::Signer; type Signature = Signature; - type OnIdtyChange = (Wot, SmithSubWot, Quota); + type OnIdtyChange = (Wot, Quota); type RuntimeEvent = RuntimeEvent; type WeightInfo = common_runtime::weights::pallet_identity::WeightInfo<Runtime>; } - impl pallet_membership::Config<frame_support::instances::Instance1> for Runtime { + impl pallet_membership::Config for Runtime { type CheckMembershipCallAllowed = Wot; type IdtyId = IdtyIndex; type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>; @@ -499,7 +498,7 @@ macro_rules! pallets_config { type BenchmarkSetupHandler = common_runtime::providers::BenchmarkSetupHandler<Runtime>; } - impl pallet_certification::Config<Instance1> for Runtime { + impl pallet_certification::Config for Runtime { type CertPeriod = CertPeriod; type IdtyIndex = IdtyIndex; type OwnerKeyOf = Identity; @@ -525,42 +524,21 @@ macro_rules! pallets_config { type WeightInfo = common_runtime::weights::pallet_distance::WeightInfo<Runtime>; } - // SMITHS SUB-WOT // - - use frame_support::instances::Instance2; - impl pallet_duniter_wot::Config<Instance2> for Runtime { - type FirstIssuableOn = SmithWotFirstCertIssuableOn; - type IsDistanceOk = pallet_duniter_wot::traits::DistanceAlwaysOk; - type IsSubWot = frame_support::traits::ConstBool<true>; - type MinCertForMembership = SmithWotMinCertForMembership; - type MinCertForCreateIdtyRight = frame_support::traits::ConstU32<0>; - } - - impl pallet_membership::Config<Instance2> for Runtime { - type CheckMembershipCallAllowed = SmithSubWot; - type IdtyId = IdtyIndex; - type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>; - type AccountIdOf = common_runtime::providers::IdentityAccountIdProvider<Self>; - type MembershipPeriod = SmithMembershipPeriod; - type OnEvent = OnSmithMembershipEventHandler<SmithSubWot, Runtime>; + // SMITH-MEMBERS + impl pallet_smith_members::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = common_runtime::weights::pallet_membership_smith_membership::WeightInfo<Runtime>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkSetupHandler = common_runtime::providers::BenchmarkSetupHandler<Runtime>; - } - - impl pallet_certification::Config<Instance2> for Runtime { - type CertPeriod = SmithCertPeriod; type IdtyIndex = IdtyIndex; - type OwnerKeyOf = Identity; - type CheckCertAllowed = SmithSubWot; + type IsWoTMember = common_runtime::providers::IsWoTMemberProvider<Runtime>; + type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>; + type MinCertForMembership = SmithWotMinCertForMembership; type MaxByIssuer = SmithMaxByIssuer; - type MinReceivedCertToBeAbleToIssueCert = SmithMinReceivedCertToBeAbleToIssueCert; - type OnNewcert = SmithSubWot; - type OnRemovedCert = SmithSubWot; - type RuntimeEvent = RuntimeEvent; - type WeightInfo = common_runtime::weights::pallet_certification_smith_cert::WeightInfo<Runtime>; - type ValidityPeriod = SmithValidityPeriod; + type SmithInactivityMaxDuration = SmithInactivityMaxDuration; + type OnSmithDelete = OnSmithDeletedHandler<Runtime>; + type IdtyIdOfAuthorityId = sp_runtime::traits::ConvertInto; + type MemberId = IdtyIndex; + type WeightInfo = common_runtime::weights::pallet_smith_members::WeightInfo<Runtime>; + // TODO: remove as it is only used for benchmarking + type OwnerKeyOf = Identity; } pub struct TechnicalCommitteeDefaultVote; diff --git a/runtime/common/src/providers.rs b/runtime/common/src/providers.rs index 1518c1060..ca631988e 100644 --- a/runtime/common/src/providers.rs +++ b/runtime/common/src/providers.rs @@ -76,7 +76,7 @@ pub struct MainWotIsDistanceOk<T>(PhantomData<T>); impl<T> pallet_duniter_wot::traits::IsDistanceOk<<T as pallet_identity::Config>::IdtyIndex> for MainWotIsDistanceOk<T> where - T: pallet_distance::Config + pallet_duniter_wot::Config<frame_support::instances::Instance1>, + T: pallet_distance::Config + pallet_duniter_wot::Config, { fn is_distance_ok( idty_id: &<T as pallet_identity::Config>::IdtyIndex, @@ -84,11 +84,27 @@ where match pallet_distance::Pallet::<T>::identity_distance_status(idty_id) { Some((_, status)) => match status { pallet_distance::DistanceStatus::Valid => Ok(()), - pallet_distance::DistanceStatus::Invalid => Err(pallet_duniter_wot::Error::<T, frame_support::instances::Instance1>::DistanceIsInvalid.into()), - pallet_distance::DistanceStatus::Pending => Err(pallet_duniter_wot::Error::<T, frame_support::instances::Instance1>::DistanceEvaluationPending.into()), + pallet_distance::DistanceStatus::Invalid => { + Err(pallet_duniter_wot::Error::<T>::DistanceIsInvalid.into()) + } + pallet_distance::DistanceStatus::Pending => { + Err(pallet_duniter_wot::Error::<T>::DistanceEvaluationPending.into()) + } }, - None => Err(pallet_duniter_wot::Error::<T, frame_support::instances::Instance1>::DistanceEvaluationNotRequested.into()), - } + None => Err(pallet_duniter_wot::Error::<T>::DistanceEvaluationNotRequested.into()), + } + } +} + +pub struct IsWoTMemberProvider<T>(PhantomData<T>); +impl<T: pallet_smith_members::Config> + sp_runtime::traits::IsMember<<T as pallet_membership::Config>::IdtyId> + for IsWoTMemberProvider<T> +where + T: pallet_distance::Config + pallet_membership::Config, +{ + fn is_member(idty_id: &T::IdtyId) -> bool { + pallet_membership::Pallet::<T>::is_member(idty_id) } } @@ -102,8 +118,8 @@ macro_rules! impl_benchmark_setup_handler { impl<T> $t for BenchmarkSetupHandler<T> where T: pallet_distance::Config, - T: pallet_certification::Config<frame_support::instances::Instance1>, - <T as pallet_certification::Config<frame_support::instances::Instance1>>::IdtyIndex: From<u32>, + T: pallet_certification::Config, + <T as pallet_certification::Config>::IdtyIndex: From<u32>, { fn force_status_ok( idty_id: &IdtyIndex, @@ -115,7 +131,11 @@ macro_rules! impl_benchmark_setup_handler { ); } fn add_cert(issuer: &IdtyIndex, receiver: &IdtyIndex) { - let _ = pallet_certification::Pallet::<T, frame_support::instances::Instance1>::do_add_cert_checked((*issuer).into(), (*receiver).into(), false); + let _ = pallet_certification::Pallet::<T>::do_add_cert_checked( + (*issuer).into(), + (*receiver).into(), + false, + ); } } }; diff --git a/runtime/common/src/weights.rs b/runtime/common/src/weights.rs index 60201d11e..bf1e188a9 100644 --- a/runtime/common/src/weights.rs +++ b/runtime/common/src/weights.rs @@ -44,8 +44,7 @@ pub mod pallet_duniter_account; pub mod pallet_quota; pub mod pallet_oneshot_account; pub mod pallet_certification_cert; -pub mod pallet_certification_smith_cert; pub mod pallet_membership_membership; -pub mod pallet_membership_smith_membership; +pub mod pallet_smith_members; pub mod pallet_authority_members; pub mod paritydb_weights; diff --git a/runtime/common/src/weights/pallet_certification_smith_cert.rs b/runtime/common/src/weights/pallet_certification_smith_cert.rs deleted file mode 100644 index 7403ec2d9..000000000 --- a/runtime/common/src/weights/pallet_certification_smith_cert.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2021-2022 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/>. - -//! Autogenerated weights for `pallet_certification` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bgallois-ms7d43`, CPU: `12th Gen Intel(R) Core(TM) i3-12100F` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// target/release/duniter -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=* -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --header=file_header.txt -// --output=runtime/common/src/weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_certification`. -pub struct WeightInfo<T>(PhantomData<T>); -impl<T: frame_system::Config> pallet_certification::WeightInfo for WeightInfo<T> { - /// Storage: Identity Identities (r:2 w:0) - /// Proof Skipped: Identity Identities (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2) - /// Proof Skipped: SmithCert StorageIdtyCertMeta (max_values: None, max_size: None, mode: Measured) - /// Storage: Parameters ParametersStorage (r:1 w:0) - /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: SmithCert StorageCertsRemovableOn (r:1 w:1) - /// Proof Skipped: SmithCert StorageCertsRemovableOn (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithCert CertsByReceiver (r:1 w:1) - /// Proof Skipped: SmithCert CertsByReceiver (max_values: None, max_size: None, mode: Measured) - fn add_cert() -> Weight { - // Proof Size summary in bytes: - // Measured: `769` - // Estimated: `6709` - // Minimum execution time: 38_312_000 picoseconds. - Weight::from_parts(39_872_000, 0) - .saturating_add(Weight::from_parts(0, 6709)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: SmithCert CertsByReceiver (r:1 w:1) - /// Proof Skipped: SmithCert CertsByReceiver (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2) - /// Proof Skipped: SmithCert StorageIdtyCertMeta (max_values: None, max_size: None, mode: Measured) - /// Storage: Parameters ParametersStorage (r:1 w:0) - /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:1 w:0) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - fn del_cert() -> Weight { - // Proof Size summary in bytes: - // Measured: `638` - // Estimated: `6578` - // Minimum execution time: 25_005_000 picoseconds. - Weight::from_parts(26_178_000, 0) - .saturating_add(Weight::from_parts(0, 6578)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: SmithCert CertsByReceiver (r:1 w:1) - /// Proof Skipped: SmithCert CertsByReceiver (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithCert StorageIdtyCertMeta (r:1000 w:1000) - /// Proof Skipped: SmithCert StorageIdtyCertMeta (max_values: None, max_size: None, mode: Measured) - /// Storage: Parameters ParametersStorage (r:1 w:0) - /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:1 w:0) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - /// The range of component `i` is `[2, 1000]`. - /// The range of component `i` is `[2, 1000]`. - fn remove_all_certs_received_by(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `546 + i * (35 ±0)` - // Estimated: `4020 + i * (2511 ±0)` - // Minimum execution time: 26_616_000 picoseconds. - Weight::from_parts(27_240_000, 0) - .saturating_add(Weight::from_parts(0, 4020)) - // Standard Error: 15_842 - .saturating_add(Weight::from_parts(10_835_042, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) - .saturating_add(Weight::from_parts(0, 2511).saturating_mul(i.into())) - } - /// Storage: SmithCert StorageCertsRemovableOn (r:1 w:0) - /// Proof Skipped: SmithCert StorageCertsRemovableOn (max_values: None, max_size: None, mode: Measured) - fn on_initialize() -> Weight { - // Proof Size summary in bytes: - // Measured: `181` - // Estimated: `3646` - // Minimum execution time: 4_084_000 picoseconds. - Weight::from_parts(4_316_000, 0) - .saturating_add(Weight::from_parts(0, 3646)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: SmithCert CertsByReceiver (r:1 w:1) - /// Proof Skipped: SmithCert CertsByReceiver (max_values: None, max_size: None, mode: Measured) - fn do_remove_cert_noop() -> Weight { - // Proof Size summary in bytes: - // Measured: `235` - // Estimated: `3700` - // Minimum execution time: 5_261_000 picoseconds. - Weight::from_parts(5_742_000, 0) - .saturating_add(Weight::from_parts(0, 3700)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: SmithCert CertsByReceiver (r:1 w:1) - /// Proof Skipped: SmithCert CertsByReceiver (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2) - /// Proof Skipped: SmithCert StorageIdtyCertMeta (max_values: None, max_size: None, mode: Measured) - /// Storage: Parameters ParametersStorage (r:1 w:0) - /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:1 w:0) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - fn do_remove_cert() -> Weight { - // Proof Size summary in bytes: - // Measured: `638` - // Estimated: `6578` - // Minimum execution time: 22_342_000 picoseconds. - Weight::from_parts(23_355_000, 0) - .saturating_add(Weight::from_parts(0, 6578)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } -} diff --git a/runtime/common/src/weights/pallet_membership_smith_membership.rs b/runtime/common/src/weights/pallet_membership_smith_membership.rs deleted file mode 100644 index d0bd9f668..000000000 --- a/runtime/common/src/weights/pallet_membership_smith_membership.rs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2021-2022 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/>. - -//! Autogenerated weights for `pallet_membership` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bgallois-ms7d43`, CPU: `12th Gen Intel(R) Core(TM) i3-12100F` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// target/release/duniter -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=* -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --header=file_header.txt -// --output=runtime/common/src/weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_membership`. -pub struct WeightInfo<T>(PhantomData<T>); -impl<T: frame_system::Config> pallet_membership::WeightInfo for WeightInfo<T> { - /// Storage: Identity IdentityIndexOf (r:1 w:0) - /// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithCert StorageIdtyCertMeta (r:1 w:0) - /// Proof Skipped: SmithCert StorageIdtyCertMeta (max_values: None, max_size: None, mode: Measured) - /// Storage: Parameters ParametersStorage (r:1 w:0) - /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:1 w:1) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership CounterForMembership (r:1 w:1) - /// Proof: SmithMembership CounterForMembership (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: SmithMembership MembershipsExpireOn (r:1 w:1) - /// Proof Skipped: SmithMembership MembershipsExpireOn (max_values: None, max_size: None, mode: Measured) - fn claim_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `704` - // Estimated: `4169` - // Minimum execution time: 27_429_000 picoseconds. - Weight::from_parts(28_797_000, 0) - .saturating_add(Weight::from_parts(0, 4169)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: Identity IdentityIndexOf (r:1 w:0) - /// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:1 w:1) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - /// Storage: Identity Identities (r:1 w:0) - /// Proof Skipped: Identity Identities (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership MembershipsExpireOn (r:2 w:2) - /// Proof Skipped: SmithMembership MembershipsExpireOn (max_values: None, max_size: None, mode: Measured) - /// Storage: Parameters ParametersStorage (r:1 w:0) - /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) - fn renew_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `717` - // Estimated: `6657` - // Minimum execution time: 28_139_000 picoseconds. - Weight::from_parts(28_982_000, 0) - .saturating_add(Weight::from_parts(0, 6657)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: Identity IdentityIndexOf (r:1 w:0) - /// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:1 w:1) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership CounterForMembership (r:1 w:1) - /// Proof: SmithMembership CounterForMembership (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: SmithMembership MembershipsExpireOn (r:1 w:1) - /// Proof Skipped: SmithMembership MembershipsExpireOn (max_values: None, max_size: None, mode: Measured) - /// Storage: AuthorityMembers Members (r:1 w:1) - /// Proof Skipped: AuthorityMembers Members (max_values: None, max_size: None, mode: Measured) - /// Storage: AuthorityMembers OnlineAuthorities (r:1 w:1) - /// Proof Skipped: AuthorityMembers OnlineAuthorities (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AuthorityMembers AuthoritiesCounter (r:1 w:1) - /// Proof Skipped: AuthorityMembers AuthoritiesCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AuthorityMembers IncomingAuthorities (r:1 w:1) - /// Proof Skipped: AuthorityMembers IncomingAuthorities (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Session NextKeys (r:1 w:1) - /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(126), added: 2601, mode: MaxEncodedLen) - /// Storage: Session KeyOwner (r:0 w:4) - /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) - fn revoke_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `1183` - // Estimated: `4648` - // Minimum execution time: 60_153_000 picoseconds. - Weight::from_parts(62_834_000, 0) - .saturating_add(Weight::from_parts(0, 4648)) - .saturating_add(T::DbWeight::get().reads(10)) - .saturating_add(T::DbWeight::get().writes(13)) - } - fn on_initialize() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 133_000 picoseconds. - Weight::from_parts(157_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: SmithMembership MembershipsExpireOn (r:2 w:2) - /// Proof Skipped: SmithMembership MembershipsExpireOn (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership Membership (r:3 w:3) - /// Proof Skipped: SmithMembership Membership (max_values: None, max_size: None, mode: Measured) - /// Storage: SmithMembership CounterForMembership (r:1 w:1) - /// Proof: SmithMembership CounterForMembership (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: AuthorityMembers Members (r:3 w:3) - /// Proof Skipped: AuthorityMembers Members (max_values: None, max_size: None, mode: Measured) - /// Storage: AuthorityMembers OnlineAuthorities (r:1 w:1) - /// Proof Skipped: AuthorityMembers OnlineAuthorities (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AuthorityMembers OutgoingAuthorities (r:1 w:1) - /// Proof Skipped: AuthorityMembers OutgoingAuthorities (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AuthorityMembers AuthoritiesCounter (r:1 w:1) - /// Proof Skipped: AuthorityMembers AuthoritiesCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AuthorityMembers IncomingAuthorities (r:1 w:1) - /// Proof Skipped: AuthorityMembers IncomingAuthorities (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Session NextKeys (r:3 w:3) - /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(126), added: 2601, mode: MaxEncodedLen) - /// Storage: Session KeyOwner (r:0 w:12) - /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) - /// The range of component `i` is `[0, 3]`. - /// The range of component `i` is `[0, 3]`. - fn expire_memberships(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `133 + i * (515 ±0)` - // Estimated: `4157 + i * (2692 ±0)` - // Minimum execution time: 4_794_000 picoseconds. - Weight::from_parts(9_091_363, 0) - .saturating_add(Weight::from_parts(0, 4157)) - // Standard Error: 191_583 - .saturating_add(Weight::from_parts(46_909_320, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(i.into()))) - .saturating_add(T::DbWeight::get().writes(2)) - .saturating_add(T::DbWeight::get().writes((11_u64).saturating_mul(i.into()))) - .saturating_add(Weight::from_parts(0, 2692).saturating_mul(i.into())) - } -} diff --git a/runtime/common/src/weights/pallet_smith_members.rs b/runtime/common/src/weights/pallet_smith_members.rs new file mode 100644 index 000000000..a0c5d8bda --- /dev/null +++ b/runtime/common/src/weights/pallet_smith_members.rs @@ -0,0 +1,105 @@ +// Copyright 2021-2022 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/>. + +//! Autogenerated weights for `pallet_smith_members` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `MacBook-Pro-de-Cedric.local`, CPU: `<UNKNOWN>` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/duniter +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet-smith-members +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_smith_members`. +pub struct WeightInfo<T>(PhantomData<T>); +impl<T: frame_system::Config> pallet_smith_members::WeightInfo for WeightInfo<T> { + /// Storage: Identity IdentityIndexOf (r:1 w:0) + /// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured) + /// Storage: SmithMembers Smiths (r:2 w:1) + /// Proof Skipped: SmithMembers Smiths (max_values: None, max_size: None, mode: Measured) + /// Storage: Membership Membership (r:1 w:0) + /// Proof Skipped: Membership Membership (max_values: None, max_size: None, mode: Measured) + /// Storage: SmithMembers CurrentSession (r:1 w:0) + /// Proof Skipped: SmithMembers CurrentSession (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Parameters ParametersStorage (r:1 w:0) + /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: SmithMembers ExpiresOn (r:1 w:1) + /// Proof Skipped: SmithMembers ExpiresOn (max_values: None, max_size: None, mode: Measured) + fn invite_smith() -> Weight { + // Proof Size summary in bytes: + // Measured: `731` + // Estimated: `6671` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(28_000_000, 0) + .saturating_add(Weight::from_parts(0, 6671)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Identity IdentityIndexOf (r:1 w:0) + /// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured) + /// Storage: SmithMembers Smiths (r:1 w:1) + /// Proof Skipped: SmithMembers Smiths (max_values: None, max_size: None, mode: Measured) + fn accept_invitation() -> Weight { + // Proof Size summary in bytes: + // Measured: `463` + // Estimated: `3928` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 0) + .saturating_add(Weight::from_parts(0, 3928)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity IdentityIndexOf (r:1 w:0) + /// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured) + /// Storage: SmithMembers Smiths (r:2 w:2) + /// Proof Skipped: SmithMembers Smiths (max_values: None, max_size: None, mode: Measured) + /// Storage: Parameters ParametersStorage (r:1 w:0) + /// Proof Skipped: Parameters ParametersStorage (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: SmithMembers CurrentSession (r:1 w:0) + /// Proof Skipped: SmithMembers CurrentSession (max_values: Some(1), max_size: None, mode: Measured) + fn certify_smith() -> Weight { + // Proof Size summary in bytes: + // Measured: `576` + // Estimated: `6516` + // Minimum execution time: 24_000_000 picoseconds. + Weight::from_parts(26_000_000, 0) + .saturating_add(Weight::from_parts(0, 6516)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/runtime/g1/Cargo.toml b/runtime/g1/Cargo.toml index e96b7a084..65207b28d 100644 --- a/runtime/g1/Cargo.toml +++ b/runtime/g1/Cargo.toml @@ -23,6 +23,7 @@ runtime-benchmarks = [ 'frame-system/runtime-benchmarks', 'hex-literal', 'pallet-authority-members/runtime-benchmarks', + 'pallet-smith-members/runtime-benchmarks', 'pallet-babe/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', 'pallet-certification/runtime-benchmarks', @@ -61,6 +62,7 @@ std = [ 'log/std', 'pallet-authority-discovery/std', 'pallet-authority-members/std', + 'pallet-smith-members/std', 'pallet-babe/std', 'pallet-balances/std', 'pallet-certification/std', @@ -134,6 +136,7 @@ sp-keyring = { git = 'https://github.com/duniter/substrate', branch = 'duniter-s # local common-runtime = { path = "../common", default-features = false } pallet-authority-members = { path = '../../pallets/authority-members', default-features = false } +pallet-smith-members = { path = '../../pallets/smith-members', default-features = false } pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-distance = { path = "../../pallets/distance", default-features = false } pallet-duniter-test-parameters = { path = '../../pallets/duniter-test-parameters', default-features = false } diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs index 8cef6bfcb..695fb3d39 100644 --- a/runtime/g1/src/lib.rs +++ b/runtime/g1/src/lib.rs @@ -66,6 +66,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. +use frame_support::instances::Instance2; pub use frame_support::{ construct_runtime, parameter_types, traits::{EqualPrivilegeOnly, KeyOwnerProofSystem, Randomness}, @@ -139,7 +140,6 @@ pub type TechnicalCommitteeInstance = Instance2; mod benches { define_benchmarks!( [pallet_certification, Cert] - [pallet_certification, SmithCert] [pallet_distance, Distance] [pallet_oneshot_account, OneshotAccount] [pallet_universal_dividend, UniversalDividend] @@ -148,7 +148,7 @@ mod benches { [pallet_duniter_account, Account] [pallet_identity, Identity] [pallet_membership, Membership] - [pallet_membership, SmithMembership] + [pallet_smith_members, SmithMembers] [pallet_authority_members, AuthorityMembers] // Substrate [pallet_balances, Balances] @@ -214,7 +214,9 @@ impl frame_support::traits::InstanceFilter<RuntimeCall> for ProxyType { // Some calls are never authorized from a proxied account !matches!( c, - RuntimeCall::Cert(..) | RuntimeCall::Identity(..) | RuntimeCall::SmithCert(..) + RuntimeCall::Cert(..) + | RuntimeCall::Identity(..) + | RuntimeCall::SmithMembers(..) ) } ProxyType::TransferOnly => { @@ -263,14 +265,15 @@ construct_runtime!( Quota: pallet_quota::{Pallet, Storage, Config<T>, Event<T>} = 66, // Consensus support. - AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, - Authorship: pallet_authorship::{Pallet, Storage} = 11, - Offences: pallet_offences::{Pallet, Storage, Event} = 12, - Historical: session_historical::{Pallet} = 13, - Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 14, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 15, - ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 16, - AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 17, + SmithMembers: pallet_smith_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, + AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 11, + Authorship: pallet_authorship::{Pallet, Storage} = 12, + Offences: pallet_offences::{Pallet, Storage, Event} = 13, + Historical: session_historical::{Pallet} = 14, + Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 15, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 16, + ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 17, + AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 18, // Governance stuff. Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20, @@ -282,24 +285,19 @@ construct_runtime!( UniversalDividend: pallet_universal_dividend::{Pallet, Call, Config<T>, Storage, Event<T>} = 30, // Web Of Trust - Wot: pallet_duniter_wot::<Instance1>::{Pallet} = 40, + Wot: pallet_duniter_wot::{Pallet} = 40, Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 41, - Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 42, - Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 43, + Membership: pallet_membership::{Pallet, Call, Config<T>, Storage, Event<T>} = 42, + Cert: pallet_certification::{Pallet, Call, Config<T>, Storage, Event<T>} = 43, Distance: pallet_distance::{Pallet, Call, Storage, Inherent, Event<T>} = 44, - // Smith Sub-Wot - SmithSubWot: pallet_duniter_wot::<Instance2>::{Pallet} = 50, - SmithMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52, - SmithCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 53, - // Utilities - AtomicSwap: pallet_atomic_swap::{Pallet, Call, Storage, Event<T>} = 60, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 61, - ProvideRandomness: pallet_provide_randomness::{Pallet, Call, Storage, Event} = 62, - Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 63, - Utility: pallet_utility::{Pallet, Call, Event} = 64, - Treasury: pallet_treasury::{Pallet, Call, Config, Storage, Event<T>} = 65, + AtomicSwap: pallet_atomic_swap::{Pallet, Call, Storage, Event<T>} = 50, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 51, + ProvideRandomness: pallet_provide_randomness::{Pallet, Call, Storage, Event} = 52, + Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 53, + Utility: pallet_utility::{Pallet, Call, Event} = 54, + Treasury: pallet_treasury::{Pallet, Call, Config, Storage, Event<T>} = 55, } ); diff --git a/runtime/g1/src/parameters.rs b/runtime/g1/src/parameters.rs index 11315f7fc..22ef4efa4 100644 --- a/runtime/g1/src/parameters.rs +++ b/runtime/g1/src/parameters.rs @@ -117,26 +117,13 @@ parameter_types! { } /******************/ -/* SMITHS SUB-WOT */ +/* SMITH-MEMBERS */ /******************/ parameter_types! { - pub const SmithWotFirstCertIssuableOn: BlockNumber = 30 * DAYS; pub const SmithWotMinCertForMembership: u32 = 3; -} - -// Membership -parameter_types! { - pub const SmithMembershipPeriod: BlockNumber = 73 * DAYS; - pub const SmithPendingMembershipPeriod: BlockNumber = 12 * DAYS; -} - -// Certification -parameter_types! { - pub const SmithCertPeriod: BlockNumber = 5 * DAYS; pub const SmithMaxByIssuer: u32 = 12; - pub const SmithMinReceivedCertToBeAbleToIssueCert: u32 = 5; - pub const SmithValidityPeriod: BlockNumber = 146 * DAYS; + pub const SmithInactivityMaxDuration: u32 = 48; } /*************/ diff --git a/runtime/gdev/Cargo.toml b/runtime/gdev/Cargo.toml index 976999d23..716482251 100644 --- a/runtime/gdev/Cargo.toml +++ b/runtime/gdev/Cargo.toml @@ -23,6 +23,7 @@ runtime-benchmarks = [ 'frame-system/runtime-benchmarks', 'hex-literal', 'pallet-authority-members/runtime-benchmarks', + 'pallet-smith-members/runtime-benchmarks', 'pallet-babe/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', 'pallet-certification/runtime-benchmarks', @@ -62,6 +63,7 @@ std = [ 'pallet-atomic-swap/std', 'pallet-authority-discovery/std', 'pallet-authority-members/std', + 'pallet-smith-members/std', 'pallet-babe/std', 'pallet-balances/std', 'pallet-certification/std', @@ -141,6 +143,7 @@ sp-staking = { git = 'https://github.com/duniter/substrate', branch = 'duniter-s # local common-runtime = { path = "../common", default-features = false } pallet-authority-members = { path = '../../pallets/authority-members', default-features = false } +pallet-smith-members = { path = '../../pallets/smith-members', default-features = false } pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-distance = { path = "../../pallets/distance", default-features = false } pallet-duniter-test-parameters = { path = '../../pallets/duniter-test-parameters', default-features = false } diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs index 5b13dec43..544ae962d 100644 --- a/runtime/gdev/src/lib.rs +++ b/runtime/gdev/src/lib.rs @@ -67,6 +67,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. +use frame_support::instances::Instance2; pub use frame_support::{ construct_runtime, parameter_types, traits::{EqualPrivilegeOnly, KeyOwnerProofSystem, Randomness}, @@ -141,7 +142,6 @@ pub type TechnicalCommitteeInstance = Instance2; mod benches { define_benchmarks!( [pallet_certification, Cert] - [pallet_certification, SmithCert] [pallet_distance, Distance] [pallet_oneshot_account, OneshotAccount] [pallet_universal_dividend, UniversalDividend] @@ -151,7 +151,7 @@ mod benches { [pallet_quota, Quota] [pallet_identity, Identity] [pallet_membership, Membership] - [pallet_membership, SmithMembership] + [pallet_smith_members, SmithMembers] [pallet_authority_members, AuthorityMembers] // Substrate [pallet_balances, Balances] @@ -218,7 +218,9 @@ impl frame_support::traits::InstanceFilter<RuntimeCall> for ProxyType { // Some calls are never authorized from a proxied account !matches!( c, - RuntimeCall::Cert(..) | RuntimeCall::Identity(..) | RuntimeCall::SmithCert(..) + RuntimeCall::Cert(..) + | RuntimeCall::Identity(..) + | RuntimeCall::SmithMembers(..) ) } ProxyType::TransferOnly => { @@ -261,20 +263,16 @@ common_runtime::pallets_config! { pub type WotMinCertForMembership = pallet_duniter_test_parameters::WotMinCertForMembership<Runtime>; pub type WotMinCertForCreateIdtyRight = pallet_duniter_test_parameters::WotMinCertForCreateIdtyRight<Runtime>; - pub type SmithCertPeriod = pallet_duniter_test_parameters::SmithCertPeriod<Runtime>; pub type SmithMaxByIssuer = pallet_duniter_test_parameters::SmithCertMaxByIssuer<Runtime>; - pub type SmithMinReceivedCertToBeAbleToIssueCert = - pallet_duniter_test_parameters::SmithCertMinReceivedCertToIssueCert<Runtime>; - pub type SmithValidityPeriod = pallet_duniter_test_parameters::SmithCertValidityPeriod<Runtime>; - pub type SmithMembershipPeriod = pallet_duniter_test_parameters::SmithMembershipPeriod<Runtime>; - pub type SmithWotFirstCertIssuableOn = - pallet_duniter_test_parameters::SmithWotFirstCertIssuableOn<Runtime>; pub type SmithWotMinCertForMembership = pallet_duniter_test_parameters::SmithWotMinCertForMembership<Runtime>; + pub type SmithInactivityMaxDuration = + pallet_duniter_test_parameters::SmithInactivityMaxDuration<Runtime>; impl pallet_duniter_test_parameters::Config for Runtime { type CertCount = u32; type PeriodCount = Balance; + type SessionCount = u32; } impl pallet_sudo::Config for Runtime { @@ -309,14 +307,15 @@ construct_runtime!( Quota: pallet_quota::{Pallet, Storage, Config<T>, Event<T>} = 66, // Consensus support - AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, - Authorship: pallet_authorship::{Pallet, Storage} = 11, - Offences: pallet_offences::{Pallet, Storage, Event} = 12, - Historical: session_historical::{Pallet} = 13, - Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 14, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 15, - ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 16, - AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 17, + SmithMembers: pallet_smith_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, + AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 11, + Authorship: pallet_authorship::{Pallet, Storage} = 12, + Offences: pallet_offences::{Pallet, Storage, Event} = 13, + Historical: session_historical::{Pallet} = 14, + Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 15, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 16, + ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 17, + AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 18, // Governance stuff Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20, @@ -328,24 +327,19 @@ construct_runtime!( UniversalDividend: pallet_universal_dividend::{Pallet, Call, Config<T>, Storage, Event<T>} = 30, // Web Of Trust - Wot: pallet_duniter_wot::<Instance1>::{Pallet} = 40, + Wot: pallet_duniter_wot::{Pallet} = 40, Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 41, - Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 42, - Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 43, + Membership: pallet_membership::{Pallet, Call, Config<T>, Storage, Event<T>} = 42, + Cert: pallet_certification::{Pallet, Call, Config<T>, Storage, Event<T>} = 43, Distance: pallet_distance::{Pallet, Call, Storage, Inherent, Event<T>} = 44, - // Smith Sub-Wot - SmithSubWot: pallet_duniter_wot::<Instance2>::{Pallet} = 50, - SmithMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52, - SmithCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 53, - // Utilities - AtomicSwap: pallet_atomic_swap::{Pallet, Call, Storage, Event<T>} = 60, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 61, - ProvideRandomness: pallet_provide_randomness::{Pallet, Call, Storage, Event} = 62, - Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 63, - Utility: pallet_utility::{Pallet, Call, Event} = 64, - Treasury: pallet_treasury::{Pallet, Call, Config, Storage, Event<T>} = 65, + AtomicSwap: pallet_atomic_swap::{Pallet, Call, Storage, Event<T>} = 50, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 51, + ProvideRandomness: pallet_provide_randomness::{Pallet, Call, Storage, Event} = 52, + Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 53, + Utility: pallet_utility::{Pallet, Call, Event} = 54, + Treasury: pallet_treasury::{Pallet, Call, Config, Storage, Event<T>} = 55, } ); diff --git a/runtime/gdev/tests/common/mod.rs b/runtime/gdev/tests/common/mod.rs index 5c20cd6ab..a74493b34 100644 --- a/runtime/gdev/tests/common/mod.rs +++ b/runtime/gdev/tests/common/mod.rs @@ -18,11 +18,11 @@ use common_runtime::constants::*; use common_runtime::*; -use frame_support::instances::{Instance1, Instance2}; use frame_support::traits::{GenesisBuild, OnFinalize, OnInitialize}; use gdev_runtime::opaque::SessionKeys; use gdev_runtime::*; use pallet_authority_members::OnNewSession; +use pallet_smith_members::SmithMeta; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::{AuthorityId as BabeId, Slot}; use sp_consensus_babe::{VrfOutput, VrfProof}; @@ -54,7 +54,7 @@ pub struct ExtBuilder { initial_authorities_len: usize, initial_identities: BTreeMap<IdtyName, AccountId>, initial_smiths: Vec<AuthorityKeys>, - parameters: GenesisParameters<u32, u32, Balance>, + parameters: GenesisParameters<u32, u32, Balance, u32>, } impl ExtBuilder { @@ -108,14 +108,9 @@ impl ExtBuilder { pending_membership_period: 500, ud_creation_period: 60_000, ud_reeval_period: 60_000 * 20, - smith_cert_period: 15, smith_cert_max_by_issuer: 8, - smith_cert_min_received_cert_to_issue_cert: 2, - smith_cert_validity_period: 1_000, - smith_membership_period: 1_000, - smith_pending_membership_period: 500, - smith_wot_first_cert_issuable_on: 20, smith_wot_min_cert_for_membership: 2, + smith_inactivity_max_duration: 48, wot_first_cert_issuable_on: 20, wot_min_cert_for_create_idty_right: 2, wot_min_cert_for_membership: 2, @@ -142,7 +137,7 @@ impl ExtBuilder { }*/ pub fn change_parameters< - F: Fn(&mut pallet_duniter_test_parameters::Parameters<u32, u32, Balance>), + F: Fn(&mut pallet_duniter_test_parameters::Parameters<u32, u32, Balance, u32>), >( mut self, f: F, @@ -251,7 +246,7 @@ impl ExtBuilder { .assimilate_storage(&mut t) .unwrap(); - pallet_membership::GenesisConfig::<Runtime, Instance1> { + pallet_membership::GenesisConfig::<Runtime> { memberships: (1..=initial_identities.len()) .map(|i| { ( @@ -266,7 +261,7 @@ impl ExtBuilder { .assimilate_storage(&mut t) .unwrap(); - pallet_certification::GenesisConfig::<Runtime, Instance1> { + pallet_certification::GenesisConfig::<Runtime> { certs_by_receiver: clique_wot( initial_identities.len(), parameters.cert_validity_period, @@ -276,27 +271,8 @@ impl ExtBuilder { .assimilate_storage(&mut t) .unwrap(); - pallet_membership::GenesisConfig::<Runtime, Instance2> { - memberships: (1..=initial_smiths.len()) - .map(|i| { - ( - i as u32, - MembershipData { - expire_on: parameters.smith_membership_period, - }, - ) - }) - .collect(), - } - .assimilate_storage(&mut t) - .unwrap(); - - pallet_certification::GenesisConfig::<Runtime, Instance2> { - apply_cert_period_at_genesis: false, - certs_by_receiver: clique_wot( - initial_smiths.len(), - parameters.smith_cert_validity_period, - ), + pallet_smith_members::GenesisConfig::<Runtime> { + initial_smiths: clique_smith_wot(initial_smiths.len()), } .assimilate_storage(&mut t) .unwrap(); @@ -393,9 +369,6 @@ pub fn run_to_block(n: u32) { Identity::on_initialize(System::block_number()); Membership::on_initialize(System::block_number()); Cert::on_initialize(System::block_number()); - SmithSubWot::on_initialize(System::block_number()); - SmithMembership::on_initialize(System::block_number()); - SmithCert::on_initialize(System::block_number()); Timestamp::set_timestamp(System::block_number() as u64 * BLOCK_TIME); Distance::on_initialize(System::block_number()); @@ -476,6 +449,22 @@ fn clique_wot( certs_by_issuer } +fn clique_smith_wot(initial_identities_len: usize) -> BTreeMap<IdtyIndex, (bool, Vec<IdtyIndex>)> { + let mut certs_by_issuer = BTreeMap::new(); + for i in 1..=initial_identities_len { + certs_by_issuer.insert( + i as IdtyIndex, + ( + true, + (1..=initial_identities_len) + .filter_map(|j| if i != j { Some(j as IdtyIndex) } else { None }) + .collect(), + ), + ); + } + certs_by_issuer +} + fn session_keys( babe: BabeId, grandpa: GrandpaId, diff --git a/runtime/gdev/tests/fixme_tests.rs b/runtime/gdev/tests/fixme_tests.rs index 028f23600..1ab0bd7a7 100644 --- a/runtime/gdev/tests/fixme_tests.rs +++ b/runtime/gdev/tests/fixme_tests.rs @@ -43,10 +43,7 @@ fn can_still_issue_cert_when_membership_lost() { run_to_block(1); // expire Bob membership - Membership::do_remove_membership( - 2, - MembershipRemovalReason::System - ); + Membership::do_remove_membership(2, MembershipRemovalReason::System); System::assert_has_event(RuntimeEvent::Membership( pallet_membership::Event::MembershipRemoved { member: 2, @@ -55,12 +52,13 @@ fn can_still_issue_cert_when_membership_lost() { )); // fixed :) - assert_noop!(Cert::add_cert( - frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(), + assert_noop!( + Cert::add_cert( + frame_system::RawOrigin::Signed(AccountKeyring::Bob.to_account_id()).into(), 2, // Bob 3, // Charlie ), - pallet_duniter_wot::Error::<gdev_runtime::Runtime, pallet_certification::Instance1>::IssuerNotMember + pallet_duniter_wot::Error::<gdev_runtime::Runtime>::IssuerNotMember ); // // not anymore // System::assert_has_event(RuntimeEvent::Cert( diff --git a/runtime/gdev/tests/integration_tests.rs b/runtime/gdev/tests/integration_tests.rs index ef4dce191..ca90f9925 100644 --- a/runtime/gdev/tests/integration_tests.rs +++ b/runtime/gdev/tests/integration_tests.rs @@ -17,13 +17,14 @@ mod common; use common::*; -use frame_support::instances::Instance1; use frame_support::traits::StoredMap; use frame_support::traits::{Get, PalletInfo, StorageInfo, StorageInfoTrait}; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_err, assert_noop, assert_ok}; use frame_support::{StorageHasher, Twox128}; use gdev_runtime::*; +use pallet_identity::{RevocationPayload, REVOCATION_PAYLOAD_PREFIX}; use pallet_membership::MembershipRemovalReason; +use pallet_smith_members::{SmithMeta, SmithStatus}; use sp_core::Encode; use sp_keyring::AccountKeyring; use sp_runtime::MultiAddress; @@ -367,9 +368,7 @@ fn test_validate_identity_when_claim() { System::assert_has_event(RuntimeEvent::Membership( pallet_membership::Event::MembershipAdded { member: 5, - expire_on: 76 - + <Runtime as pallet_membership::Config<Instance1>>::MembershipPeriod::get( - ), + expire_on: 76 + <Runtime as pallet_membership::Config>::MembershipPeriod::get(), }, )); // not possible anymore to validate identity of someone else @@ -392,6 +391,7 @@ fn test_membership_expiry() { }); } +// TODO: use change_parameter to change autorevocation period #[test] #[ignore = "long to go to autorevocation period"] fn test_membership_expiry_with_identity_removal() { @@ -445,9 +445,7 @@ fn test_membership_renewal() { System::assert_has_event(RuntimeEvent::Membership( pallet_membership::Event::MembershipAdded { member: 1, - expire_on: 76 - + <Runtime as pallet_membership::Config<Instance1>>::MembershipPeriod::get( - ), + expire_on: 76 + <Runtime as pallet_membership::Config>::MembershipPeriod::get(), }, )); @@ -459,9 +457,7 @@ fn test_membership_renewal() { System::assert_has_event(RuntimeEvent::Membership( pallet_membership::Event::MembershipAdded { member: 1, - expire_on: 77 - + <Runtime as pallet_membership::Config<Instance1>>::MembershipPeriod::get( - ), + expire_on: 77 + <Runtime as pallet_membership::Config>::MembershipPeriod::get(), }, )); @@ -602,8 +598,7 @@ fn test_ud_claimed_membership_on_and_off() { System::assert_has_event(RuntimeEvent::Membership( pallet_membership::Event::MembershipAdded { member: 1, - expire_on: 14 - + <Runtime as pallet_membership::Config<Instance1>>::MembershipPeriod::get(), + expire_on: 14 + <Runtime as pallet_membership::Config>::MembershipPeriod::get(), }, )); @@ -647,12 +642,6 @@ fn test_revoke_smith_identity() { Identity::do_revoke_identity(3, pallet_identity::RevocationReason::Root); // Verify events - System::assert_has_event(RuntimeEvent::SmithMembership( - pallet_membership::Event::MembershipRemoved { - member: 3, - reason: MembershipRemovalReason::Revoked, - }, - )); System::assert_has_event(RuntimeEvent::AuthorityMembers( pallet_authority_members::Event::MemberRemoved { member: 3 }, )); @@ -679,26 +668,33 @@ fn test_smith_certification() { ExtBuilder::new(1, 3, 4).build().execute_with(|| { run_to_block(1); - // alice can renew smith cert to bob - assert_ok!(SmithCert::add_cert( - frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(), - 1, // alice - 2 // bob - )); + assert_noop!( + SmithMembers::certify_smith( + frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(), + 2 + ), + pallet_smith_members::Error::<Runtime>::CertificationAlreadyExists + ); - // charlie can not add new cert to eve (no identity) assert_noop!( - SmithCert::add_cert( - frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into(), - 3, // charlie - 5 // eve + SmithMembers::certify_smith( + frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(), + 4 ), - // SmithSubWot::Error::IdtyNotFound, - pallet_duniter_wot::Error::<gdev_runtime::Runtime, pallet_certification::Instance2>::IdtyNotFound, + pallet_smith_members::Error::<Runtime>::CertificationReceiverMustHaveBeenInvited ); }); } +fn create_dummy_session_keys() -> gdev_runtime::opaque::SessionKeys { + gdev_runtime::opaque::SessionKeys { + grandpa: sp_core::ed25519::Public([0u8; 32]).into(), + babe: sp_core::sr25519::Public([0u8; 32]).into(), + im_online: sp_core::sr25519::Public([0u8; 32]).into(), + authority_discovery: sp_core::sr25519::Public([0u8; 32]).into(), + } +} + /// test the full process to join smith from main wot member to authority member #[test] fn test_smith_process() { @@ -711,6 +707,8 @@ fn test_smith_process() { let alice = AccountKeyring::Alice.to_account_id(); let bob = AccountKeyring::Bob.to_account_id(); let charlie = AccountKeyring::Charlie.to_account_id(); + let dave = AccountKeyring::Dave.to_account_id(); + let dummy_session_keys = create_dummy_session_keys(); // Eve can not request smith membership because not member of the smith wot // no more membership request @@ -718,45 +716,53 @@ fn test_smith_process() { // Dave can request smith membership (currently optional) // no more membership request - // Alice Bob and Charlie can certify Dave - assert_ok!(SmithCert::add_cert( - frame_system::RawOrigin::Signed(alice).into(), - 1, + assert_ok!(SmithMembers::invite_smith( + frame_system::RawOrigin::Signed(alice.clone()).into(), 4 )); - assert_ok!(SmithCert::add_cert( - frame_system::RawOrigin::Signed(bob).into(), - 2, + assert_ok!(SmithMembers::accept_invitation( + frame_system::RawOrigin::Signed(dave).into(), + )); + + // Dave cannot (yet) set his session keys + assert_err!( + AuthorityMembers::set_session_keys( + frame_system::RawOrigin::Signed(AccountKeyring::Dave.to_account_id()).into(), + dummy_session_keys.clone() + ), + pallet_authority_members::Error::<Runtime>::NotMember + ); + + // Alice Bob and Charlie can certify Dave + assert_ok!(SmithMembers::certify_smith( + frame_system::RawOrigin::Signed(alice.clone()).into(), 4 )); - assert_ok!(SmithCert::add_cert( - frame_system::RawOrigin::Signed(charlie).into(), - 3, + assert_ok!(SmithMembers::certify_smith( + frame_system::RawOrigin::Signed(bob.clone()).into(), 4 )); - - // with these three smith certs, Dave can claim membership - assert_ok!(SmithMembership::claim_membership( - frame_system::RawOrigin::Signed(AccountKeyring::Dave.to_account_id()).into(), + assert_ok!(SmithMembers::certify_smith( + frame_system::RawOrigin::Signed(charlie.clone()).into(), + 4 )); + // with these three smith certs, Dave has become smith // Dave is then member of the smith wot assert_eq!( - SmithMembership::membership(4), - Some(sp_membership::MembershipData { - expire_on: 1001, // 1 + 1000 + SmithMembers::smiths(4), + Some(pallet_smith_members::SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(48), + issued_certs: vec![], + received_certs: vec![1, 2, 3], }) ); // Dave can set his (dummy) session keys assert_ok!(AuthorityMembers::set_session_keys( frame_system::RawOrigin::Signed(AccountKeyring::Dave.to_account_id()).into(), - gdev_runtime::opaque::SessionKeys { - grandpa: sp_core::ed25519::Public([0u8; 32]).into(), - babe: sp_core::sr25519::Public([0u8; 32]).into(), - im_online: sp_core::sr25519::Public([0u8; 32]).into(), - authority_discovery: sp_core::sr25519::Public([0u8; 32]).into(), - } + dummy_session_keys )); // Dave can go online @@ -1235,14 +1241,26 @@ fn test_link_account() { fn test_change_owner_key() { ExtBuilder::new(1, 3, 4).build().execute_with(|| { let genesis_hash = System::block_hash(0); - let dave = AccountKeyring::Dave.to_account_id(); + let charlie = AccountKeyring::Charlie.to_account_id(); let ferdie = AccountKeyring::Ferdie.to_account_id(); - let payload = (b"icok", genesis_hash, 4u32, dave.clone()).encode(); + let payload = (b"icok", genesis_hash, 3u32, charlie.clone()).encode(); let signature = AccountKeyring::Ferdie.sign(&payload); + SmithMembers::on_smith_goes_offline(3); + // Charlie is now offline smith + assert_eq!( + SmithMembers::smiths(3), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(48), + issued_certs: vec![1, 2], + received_certs: vec![1, 2] + }) + ); + assert_eq!( - frame_system::Pallet::<Runtime>::get(&dave).linked_idty, - Some(4) + frame_system::Pallet::<Runtime>::get(&charlie).linked_idty, + Some(3) ); assert_eq!( frame_system::Pallet::<Runtime>::get(&ferdie).linked_idty, @@ -1250,17 +1268,123 @@ fn test_change_owner_key() { ); // Dave can change his owner key to Ferdie's assert_ok!(Identity::change_owner_key( - frame_system::RawOrigin::Signed(dave.clone()).into(), + frame_system::RawOrigin::Signed(charlie.clone()).into(), ferdie.clone(), signature.into() )); assert_eq!( frame_system::Pallet::<Runtime>::get(&ferdie).linked_idty, - Some(4) + Some(3) + ); + + // Charlie is still an offline smith + assert_eq!( + SmithMembers::smiths(3), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(48), + issued_certs: vec![1, 2], + received_certs: vec![1, 2] + }) + ); + + // Ferdie can set its session_keys and go online + frame_system::Pallet::<Runtime>::inc_providers(&ferdie); + assert_ok!(AuthorityMembers::set_session_keys( + frame_system::RawOrigin::Signed(AccountKeyring::Ferdie.to_account_id()).into(), + create_dummy_session_keys() + )); + assert_ok!(AuthorityMembers::go_online( + frame_system::RawOrigin::Signed(AccountKeyring::Ferdie.to_account_id()).into() + )); + + // Charlie is still an offline smith + assert_eq!( + SmithMembers::smiths(3), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: Some(48), + issued_certs: vec![1, 2], + received_certs: vec![1, 2] + }) + ); + + run_to_block(25); + + System::assert_has_event(RuntimeEvent::AuthorityMembers( + pallet_authority_members::Event::IncomingAuthorities { members: vec![3] }, + )); + System::assert_has_event(RuntimeEvent::AuthorityMembers( + pallet_authority_members::Event::OutgoingAuthorities { members: vec![1] }, + )); + + // "Charlie" (idty 3) is now online because its identity is mapped to Ferdies's key + assert_eq!( + SmithMembers::smiths(3), + Some(SmithMeta { + status: SmithStatus::Smith, + expires_on: None, + issued_certs: vec![1, 2], + received_certs: vec![1, 2] + }) ); }) } +/// members of the smith subwot can revoke their identity +#[test] +fn test_smith_member_can_revoke_its_idty() { + ExtBuilder::new(1, 3, 4).build().execute_with(|| { + run_to_block(2); + + // Charlie goes online + frame_system::Pallet::<Runtime>::inc_providers(&AccountKeyring::Charlie.to_account_id()); + assert_ok!(AuthorityMembers::set_session_keys( + frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into(), + create_dummy_session_keys() + )); + assert_ok!(AuthorityMembers::go_online( + frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into() + )); + + run_to_block(25); + + // Charlie is in the authority members + System::assert_has_event(RuntimeEvent::AuthorityMembers( + pallet_authority_members::Event::IncomingAuthorities { members: vec![3] }, + )); + // Charlie is not going out + assert!(!pallet_authority_members::OutgoingAuthorities::<Runtime>::get().contains(&3)); + + let revocation_payload = RevocationPayload { + idty_index: 3u32, + genesis_hash: System::block_hash(0), + }; + let signature = + AccountKeyring::Charlie.sign(&(REVOCATION_PAYLOAD_PREFIX, revocation_payload).encode()); + + assert_ok!(Identity::revoke_identity( + frame_system::RawOrigin::Signed(AccountKeyring::Charlie.to_account_id()).into(), + 3, + AccountKeyring::Charlie.to_account_id(), + signature.into() + )); + // membership should be removed + System::assert_has_event(RuntimeEvent::Membership( + pallet_membership::Event::MembershipRemoved { + member: 3, + reason: MembershipRemovalReason::Revoked, + }, + )); + // smith membership should be removed as well + System::assert_has_event(RuntimeEvent::SmithMembers( + pallet_smith_members::Event::SmithExcluded { idty_index: 3 }, + )); + // Now Charlie is going out + assert!(pallet_authority_members::OutgoingAuthorities::<Runtime>::get().contains(&3)); + }); +} + /// test genesis account of identity is linked to identity // (and account without identity is not linked) #[test] @@ -1328,11 +1452,10 @@ fn test_new_account_linked() { }) } #[test] +#[ignore = "what was this test supposed to do?"] fn smith_data_problem() { ExtBuilder::new(1, 3, 4) - .change_parameters(|parameters| { - parameters.smith_cert_validity_period = 3; - }) + .change_parameters(|_parameters| {}) .build() .execute_with(|| { run_to_block(4); diff --git a/runtime/gtest/Cargo.toml b/runtime/gtest/Cargo.toml index 8f59a6ad6..8e90489b7 100644 --- a/runtime/gtest/Cargo.toml +++ b/runtime/gtest/Cargo.toml @@ -23,6 +23,7 @@ runtime-benchmarks = [ 'frame-system/runtime-benchmarks', 'hex-literal', 'pallet-authority-members/runtime-benchmarks', + 'pallet-smith-members/runtime-benchmarks', 'pallet-babe/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', 'pallet-certification/runtime-benchmarks', @@ -60,6 +61,7 @@ std = [ 'pallet-atomic-swap/std', 'pallet-authority-discovery/std', 'pallet-authority-members/std', + 'pallet-smith-members/std', 'pallet-babe/std', 'pallet-balances/std', 'pallet-certification/std', @@ -137,6 +139,7 @@ sp-keyring = { git = 'https://github.com/duniter/substrate', branch = 'duniter-s # local common-runtime = { path = "../common", default-features = false } pallet-authority-members = { path = '../../pallets/authority-members', default-features = false } +pallet-smith-members = { path = '../../pallets/smith-members', default-features = false } pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-distance = { path = "../../pallets/distance", default-features = false } pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false } diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs index 88fbd282f..374cc0d79 100644 --- a/runtime/gtest/src/lib.rs +++ b/runtime/gtest/src/lib.rs @@ -66,6 +66,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. +use frame_support::instances::Instance2; pub use frame_support::{ construct_runtime, parameter_types, traits::{EqualPrivilegeOnly, KeyOwnerProofSystem, Randomness}, @@ -140,7 +141,6 @@ pub type TechnicalCommitteeInstance = Instance2; mod benches { define_benchmarks!( [pallet_certification, Cert] - [pallet_certification, SmithCert] [pallet_distance, Distance] [pallet_oneshot_account, OneshotAccount] [pallet_universal_dividend, UniversalDividend] @@ -149,7 +149,7 @@ mod benches { [pallet_duniter_account, Account] [pallet_identity, Identity] [pallet_membership, Membership] - [pallet_membership, SmithMembership] + [pallet_smith_members, SmithMembers] [pallet_authority_members, AuthorityMembers] // Substrate [pallet_balances, Balances] @@ -211,7 +211,9 @@ impl frame_support::traits::InstanceFilter<RuntimeCall> for ProxyType { // Some calls are never authorized from a proxied account !matches!( c, - RuntimeCall::Cert(..) | RuntimeCall::Identity(..) | RuntimeCall::SmithCert(..) + RuntimeCall::Cert(..) + | RuntimeCall::Identity(..) + | RuntimeCall::SmithMembers(..) ) } ProxyType::TransferOnly => { @@ -268,14 +270,15 @@ construct_runtime!( Quota: pallet_quota::{Pallet, Storage, Config<T>, Event<T>} = 66, // Consensus support - AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, - Authorship: pallet_authorship::{Pallet, Storage} = 11, - Offences: pallet_offences::{Pallet, Storage, Event} = 12, - Historical: session_historical::{Pallet} = 13, - Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 14, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 15, - ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 16, - AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 17, + SmithMembers: pallet_smith_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, + AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 11, + Authorship: pallet_authorship::{Pallet, Storage} = 12, + Offences: pallet_offences::{Pallet, Storage, Event} = 13, + Historical: session_historical::{Pallet} = 14, + Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 15, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 16, + ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 17, + AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 18, // Governance stuff Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20, @@ -287,24 +290,19 @@ construct_runtime!( UniversalDividend: pallet_universal_dividend::{Pallet, Call, Config<T>, Storage, Event<T>} = 30, // Web Of Trust - Wot: pallet_duniter_wot::<Instance1>::{Pallet} = 40, + Wot: pallet_duniter_wot::{Pallet} = 40, Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 41, - Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 42, - Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 43, + Membership: pallet_membership::{Pallet, Call, Config<T>, Storage, Event<T>} = 42, + Cert: pallet_certification::{Pallet, Call, Config<T>, Storage, Event<T>} = 43, Distance: pallet_distance::{Pallet, Call, Storage, Inherent, Event<T>} = 44, - // Smith Sub-Wot - SmithSubWot: pallet_duniter_wot::<Instance2>::{Pallet} = 50, - SmithMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52, - SmithCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 53, - // Utilities - AtomicSwap: pallet_atomic_swap::{Pallet, Call, Storage, Event<T>} = 60, - Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 61, - ProvideRandomness: pallet_provide_randomness::{Pallet, Call, Storage, Event} = 62, - Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 63, - Utility: pallet_utility::{Pallet, Call, Event} = 64, - Treasury: pallet_treasury::{Pallet, Call, Config, Storage, Event<T>} = 65, + AtomicSwap: pallet_atomic_swap::{Pallet, Call, Storage, Event<T>} = 50, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 51, + ProvideRandomness: pallet_provide_randomness::{Pallet, Call, Storage, Event} = 52, + Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 53, + Utility: pallet_utility::{Pallet, Call, Event} = 54, + Treasury: pallet_treasury::{Pallet, Call, Config, Storage, Event<T>} = 55, } ); diff --git a/runtime/gtest/src/parameters.rs b/runtime/gtest/src/parameters.rs index 443e8cffa..252ae211a 100644 --- a/runtime/gtest/src/parameters.rs +++ b/runtime/gtest/src/parameters.rs @@ -118,26 +118,13 @@ parameter_types! { } /******************/ -/* SMITHS SUB-WOT */ +/* SMITH-MEMBERS */ /******************/ parameter_types! { - pub const SmithWotFirstCertIssuableOn: BlockNumber = DAYS; pub const SmithWotMinCertForMembership: u32 = 3; -} - -// Membership -parameter_types! { - pub const SmithMembershipPeriod: BlockNumber = 73 * DAYS; - pub const SmithPendingMembershipPeriod: BlockNumber = 12 * DAYS; -} - -// Certification -parameter_types! { - pub const SmithCertPeriod: BlockNumber = DAYS; pub const SmithMaxByIssuer: u32 = 100; - pub const SmithMinReceivedCertToBeAbleToIssueCert: u32 = 5; - pub const SmithValidityPeriod: BlockNumber = 146 * DAYS; + pub const SmithInactivityMaxDuration: u32 = 48; } /*************/ -- GitLab