From e714b76c30a5bde7a073681cd6fdfdcdcae75807 Mon Sep 17 00:00:00 2001 From: Hugo Trentesaux <hugo.trentesaux@lilo.org> Date: Mon, 12 Sep 2022 19:39:01 +0200 Subject: [PATCH] cucumber test for identity creation (!82) * fix use statement position * fix variable names * Apply 1 suggestion(s) to 1 file(s) * tests(cucumber): add identity creation scenario * fix(wot): typo MinCertForCreateIdtyRigh -> MinCertForCreateIdtyRight --- .../identity_creation.feature | 15 +++ end2end-tests/cucumber-genesis/default.json | 4 +- end2end-tests/tests/common/identity.rs | 98 +++++++++++++++++++ end2end-tests/tests/common/mod.rs | 1 + end2end-tests/tests/cucumber_tests.rs | 44 +++++++++ node/src/chain_spec.rs | 2 +- pallets/duniter-wot/src/mock.rs | 4 +- 7 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 end2end-tests/cucumber-features/identity_creation.feature create mode 100644 end2end-tests/tests/common/identity.rs diff --git a/end2end-tests/cucumber-features/identity_creation.feature b/end2end-tests/cucumber-features/identity_creation.feature new file mode 100644 index 000000000..2cc5bcc99 --- /dev/null +++ b/end2end-tests/cucumber-features/identity_creation.feature @@ -0,0 +1,15 @@ +Feature: Identity creation + + Scenario: alice invites a new member to join the web of trust + # 6 ÄžD covers: + # - account creation fees (3 ÄžD) + # - existential deposit (2 ÄžD) + # - transaction fees (below 1 ÄžD) + When alice sends 6 ÄžD to ferdie + # alice last certification is counted from block zero + # then next cert can be done after cert_period + When 15 block later + When alice creates identity for ferdie + Then ferdie identity should be created + When ferdie confirms his identity with pseudo "Ferdie" + Then ferdie identity should be confirmed diff --git a/end2end-tests/cucumber-genesis/default.json b/end2end-tests/cucumber-genesis/default.json index 2a4229359..ace113862 100644 --- a/end2end-tests/cucumber-genesis/default.json +++ b/end2end-tests/cucumber-genesis/default.json @@ -2,8 +2,10 @@ "first_ud": 1000, "first_ud_reeval": 100, "genesis_parameters": { + "genesis_certs_expire_on": 1000, "genesis_certs_min_received": 2, - "genesis_memberships_expire_on": 100000, + "genesis_memberships_expire_on": 1000, + "genesis_smith_certs_expire_on": 1000, "genesis_smith_certs_min_received": 2, "genesis_smith_memberships_expire_on": 100000 }, diff --git a/end2end-tests/tests/common/identity.rs b/end2end-tests/tests/common/identity.rs new file mode 100644 index 000000000..bbe892d15 --- /dev/null +++ b/end2end-tests/tests/common/identity.rs @@ -0,0 +1,98 @@ +// Copyright 2021 Axiom-Team +// +// This file is part of Substrate-Libre-Currency. +// +// Substrate-Libre-Currency 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. +// +// Substrate-Libre-Currency 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 Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. + +use super::gdev; +use super::gdev::runtime_types::pallet_identity; +use super::*; +use crate::DuniterWorld; +use sp_keyring::AccountKeyring; +use subxt::tx::PairSigner; + +type BlockNumber = u32; +type AccountId = subxt::ext::sp_core::crypto::AccountId32; +type IdtyData = gdev::runtime_types::common_runtime::entities::IdtyData; +type IdtyValue = + gdev::runtime_types::pallet_identity::types::IdtyValue<BlockNumber, AccountId, IdtyData>; + +// submit extrinsics + +pub async fn create_identity( + client: &Client, + from: AccountKeyring, + to: AccountKeyring, +) -> Result<()> { + let from = PairSigner::new(from.pair()); + let to = to.to_account_id(); + + let _events = create_block_with_extrinsic( + client, + client + .tx() + .create_signed( + &gdev::tx().identity().create_identity(to), + &from, + BaseExtrinsicParamsBuilder::new(), + ) + .await?, + ) + .await?; + + Ok(()) +} + +pub async fn confirm_identity(client: &Client, from: AccountKeyring, pseudo: String) -> Result<()> { + let from = PairSigner::new(from.pair()); + + let _events = create_block_with_extrinsic( + client, + client + .tx() + .create_signed( + &gdev::tx().identity().confirm_identity(pseudo), + &from, + BaseExtrinsicParamsBuilder::new(), + ) + .await?, + ) + .await?; + + Ok(()) +} + +// get identity value from account keyring name +pub async fn get_identity_value(world: &mut DuniterWorld, account: String) -> Result<IdtyValue> { + let account = AccountKeyring::from_str(&account) + .expect("unknown account") + .to_account_id(); + + let identity_index = world + .read(&gdev::storage().identity().identity_index_of(&account)) + .await? + .ok_or_else(|| anyhow::anyhow!("identity {} has no associated index", account)) + .unwrap(); + + let identity_value = world + .read(&gdev::storage().identity().identities(&identity_index)) + .await? + .ok_or_else(|| { + anyhow::anyhow!( + "indentity index {} does not have associated value", + identity_index + ) + })?; + + Ok(identity_value) +} diff --git a/end2end-tests/tests/common/mod.rs b/end2end-tests/tests/common/mod.rs index 993e290ed..736c7ad35 100644 --- a/end2end-tests/tests/common/mod.rs +++ b/end2end-tests/tests/common/mod.rs @@ -18,6 +18,7 @@ pub mod balances; pub mod cert; +pub mod identity; pub mod oneshot; #[subxt::subxt(runtime_metadata_path = "../resources/metadata.scale")] diff --git a/end2end-tests/tests/cucumber_tests.rs b/end2end-tests/tests/cucumber_tests.rs index 8f1f7f66d..5bd43d557 100644 --- a/end2end-tests/tests/cucumber_tests.rs +++ b/end2end-tests/tests/cucumber_tests.rs @@ -297,6 +297,22 @@ async fn certifies(world: &mut DuniterWorld, from: String, to: String) -> Result common::cert::certify(world.client(), from, to).await } +#[when(regex = r"([a-zA-Z]+) creates identity for ([a-zA-Z]+)")] +async fn creates_identity(world: &mut DuniterWorld, from: String, to: String) -> Result<()> { + // Parse inputs + let from = AccountKeyring::from_str(&from).expect("unknown from"); + let to = AccountKeyring::from_str(&to).expect("unknown to"); + + common::identity::create_identity(world.client(), from, to).await +} + +#[when(regex = r#"([a-zA-Z]+) confirms (?:his|her) identity with pseudo "([a-zA-Z]+)""#)] +async fn confirm_identity(world: &mut DuniterWorld, from: String, pseudo: String) -> Result<()> { + let from = AccountKeyring::from_str(&from).expect("unknown from"); + + common::identity::confirm_identity(world.client(), from, pseudo).await +} + // ===== then ==== #[then(regex = r"([a-zA-Z]+) should have (\d+) (ÄžD|cÄžD)")] @@ -377,6 +393,7 @@ async fn should_be_certified_by( .expect("unknown to") .to_account_id(); + // get corresponding identities index let issuer_index = world .read( &gdev::storage() @@ -398,6 +415,7 @@ async fn should_be_certified_by( .read_or_default(&gdev::storage().cert().certs_by_receiver(&receiver_index)) .await?; + // look for certification by issuer/receiver pair match issuers.binary_search_by(|(issuer_, _)| issuer_index.cmp(issuer_)) { Ok(_) => Ok(()), Err(_) => Err(anyhow::anyhow!( @@ -410,6 +428,32 @@ async fn should_be_certified_by( } } +use gdev::runtime_types::pallet_identity::types::IdtyStatus; + +#[then(regex = r"([a-zA-Z]+) identity should be created")] +async fn identity_should_be_created(world: &mut DuniterWorld, receiver: String) -> Result<()> { + let identity_value = common::identity::get_identity_value(world, receiver).await?; + + match identity_value.status { + IdtyStatus::Created => Ok(()), + IdtyStatus::ConfirmedByOwner | IdtyStatus::Validated => { + Err(anyhow::anyhow!("status not created").into()) + } + } +} + +#[then(regex = r"([a-zA-Z]+) identity should be confirmed")] +async fn identity_should_be_confirmed(world: &mut DuniterWorld, name: String) -> Result<()> { + let identity_value = common::identity::get_identity_value(world, name).await?; + + match identity_value.status { + IdtyStatus::ConfirmedByOwner => Ok(()), + IdtyStatus::Created | IdtyStatus::Validated => { + Err(anyhow::anyhow!("status not confirmed by owner").into()) + } + } +} + // ============================================================ #[derive(clap::Args)] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 61d6ee4ca..8bdef9198 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -39,7 +39,7 @@ pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Pu .public() } -/*/// Generate an account ID from pain. +/*/// Generate an account ID from pair. pub fn get_account_id_from_pair<TPublic: Public>(pair: TPublic::Pair) -> AccountId where AccountPublic: From<<TPublic::Pair as Pair>::Public>, diff --git a/pallets/duniter-wot/src/mock.rs b/pallets/duniter-wot/src/mock.rs index d155b350d..d6872196f 100644 --- a/pallets/duniter-wot/src/mock.rs +++ b/pallets/duniter-wot/src/mock.rs @@ -92,14 +92,14 @@ impl system::Config for Test { // DuniterWot parameter_types! { pub const MinCertForMembership: u32 = 2; - pub const MinCertForCreateIdtyRigh: u32 = 4; + pub const MinCertForCreateIdtyRight: u32 = 4; pub const FirstIssuableOn: u64 = 2; } impl pallet_duniter_wot::Config<Instance1> for Test { type IsSubWot = frame_support::traits::ConstBool<false>; type MinCertForMembership = MinCertForMembership; - type MinCertForCreateIdtyRight = MinCertForCreateIdtyRigh; + type MinCertForCreateIdtyRight = MinCertForCreateIdtyRight; type FirstIssuableOn = FirstIssuableOn; } -- GitLab