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

tests(cucumber): add identity creation scenario

parent d5967be0
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !82. Comments created here will be created in the context of that merge request.
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
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
"first_ud": 1000, "first_ud": 1000,
"first_ud_reeval": 100, "first_ud_reeval": 100,
"genesis_parameters": { "genesis_parameters": {
"genesis_certs_expire_on": 1000,
"genesis_certs_min_received": 2, "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_certs_min_received": 2,
"genesis_smith_memberships_expire_on": 100000 "genesis_smith_memberships_expire_on": 100000
}, },
......
// 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 sp_keyring::AccountKeyring;
use subxt::tx::PairSigner;
// 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(())
}
// fetch identity in storage
use crate::DuniterWorld;
// declare IdtyValue types
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>;
// 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)
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
pub mod balances; pub mod balances;
pub mod cert; pub mod cert;
pub mod identity;
pub mod oneshot; pub mod oneshot;
#[subxt::subxt(runtime_metadata_path = "../resources/metadata.scale")] #[subxt::subxt(runtime_metadata_path = "../resources/metadata.scale")]
......
...@@ -297,6 +297,22 @@ async fn certifies(world: &mut DuniterWorld, from: String, to: String) -> Result ...@@ -297,6 +297,22 @@ async fn certifies(world: &mut DuniterWorld, from: String, to: String) -> Result
common::cert::certify(world.client(), from, to).await 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 ====
#[then(regex = r"([a-zA-Z]+) should have (\d+) (ĞD|cĞD)")] #[then(regex = r"([a-zA-Z]+) should have (\d+) (ĞD|cĞD)")]
...@@ -377,6 +393,7 @@ async fn should_be_certified_by( ...@@ -377,6 +393,7 @@ async fn should_be_certified_by(
.expect("unknown to") .expect("unknown to")
.to_account_id(); .to_account_id();
// get corresponding identities index
let issuer_index = world let issuer_index = world
.read( .read(
&gdev::storage() &gdev::storage()
...@@ -398,6 +415,7 @@ async fn should_be_certified_by( ...@@ -398,6 +415,7 @@ async fn should_be_certified_by(
.read_or_default(&gdev::storage().cert().certs_by_receiver(&receiver_index)) .read_or_default(&gdev::storage().cert().certs_by_receiver(&receiver_index))
.await?; .await?;
// look for certification by issuer/receiver pair
match issuers.binary_search_by(|(issuer_, _)| issuer_index.cmp(issuer_)) { match issuers.binary_search_by(|(issuer_, _)| issuer_index.cmp(issuer_)) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(_) => Err(anyhow::anyhow!( Err(_) => Err(anyhow::anyhow!(
...@@ -410,6 +428,32 @@ async fn should_be_certified_by( ...@@ -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)] #[derive(clap::Args)]
......
...@@ -39,7 +39,7 @@ pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Pu ...@@ -39,7 +39,7 @@ pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Pu
.public() .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 pub fn get_account_id_from_pair<TPublic: Public>(pair: TPublic::Pair) -> AccountId
where where
AccountPublic: From<<TPublic::Pair as Pair>::Public>, AccountPublic: From<<TPublic::Pair as Pair>::Public>,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment