diff --git a/live-tests/tests/sanity_gdev.rs b/live-tests/tests/sanity_gdev.rs index eb4c296f1f93dc41f4c5997ed98a636ecd4e3b4e..d94cc95be9855efa918e3e75b5949fd249794e25 100644 --- a/live-tests/tests/sanity_gdev.rs +++ b/live-tests/tests/sanity_gdev.rs @@ -22,7 +22,7 @@ pub mod gdev {} use countmap::CountMap; -use hex_literal::hex; +//use hex_literal::hex; use sp_core::crypto::AccountId32; use sp_core::{blake2_128, ByteArray, H256}; use std::collections::{HashMap, HashSet}; @@ -37,8 +37,8 @@ use subxt::ext::sp_core; const DEFAULT_ENDPOINT: &str = "ws://localhost:9944"; const EXISTENTIAL_DEPOSIT: u64 = 100; -const TREASURY_ACCOUNT_ID: [u8; 32] = - hex!("6d6f646c70792f74727372790000000000000000000000000000000000000000"); +//const TREASURY_ACCOUNT_ID: [u8; 32] = +// hex!("6d6f646c70792f74727372790000000000000000000000000000000000000000"); type Client = subxt::OnlineClient<GdevConfig>; @@ -57,12 +57,15 @@ type IdtyIndex = u32; type IdtyValue = gdev::runtime_types::pallet_identity::types::IdtyValue<BlockNumber, AccountId32, IdtyData>; type MembershipData = gdev::runtime_types::sp_membership::MembershipData<BlockNumber>; -// use gdev::runtime_types::pallet_identity::types::IdtyStatus; +use gdev::runtime_types::pallet_identity::types::IdtyName; +use gdev::runtime_types::pallet_identity::types::IdtyStatus; struct Storage { accounts: HashMap<AccountId32, AccountInfo>, identities: HashMap<IdtyIndex, IdtyValue>, identity_index_of: HashMap<[u8; 16], IdtyIndex>, + memberships: HashMap<IdtyIndex, MembershipData>, + identities_names: HashMap<IdtyIndex, IdtyName>, } #[tokio::test(flavor = "current_thread")] @@ -147,6 +150,21 @@ async fn sanity_tests_at(client: Client, _maybe_block_hash: Option<H256>) -> any } println!("identity_index_of.len(): {}.", identity_index_of.len()); + // Collect identity_names + let mut identities_names: HashMap<IdtyIndex, IdtyName> = HashMap::new(); + let mut idty_name_iter = client + .storage() + .at_latest() + .await + .unwrap() + .iter(gdev::storage().identity().identities_names_iter()) + .await?; + while let Some(Ok((key, idty_index))) = idty_name_iter.next().await { + let name = IdtyName(key); + identities_names.insert(idty_index, name); + } + println!("identities_names.len(): {}.", identities_names.len()); + // Collect memberships let mut memberships: HashMap<IdtyIndex, MembershipData> = HashMap::new(); let mut membership_iter = client @@ -170,6 +188,8 @@ async fn sanity_tests_at(client: Client, _maybe_block_hash: Option<H256>) -> any accounts, identities, identity_index_of, + memberships, + identities_names, }; // ===== Verify storage ===== // @@ -198,6 +218,12 @@ mod verifier { .await; self.verify_identity_coherence(&storage.identities, &storage.identity_index_of) .await; + self.verify_status_coherence( + &storage.identities, + &storage.memberships, + &storage.identities_names, + ) + .await; if self.errors.is_empty() { Ok(()) @@ -253,14 +279,14 @@ mod verifier { ); } - if account_id.as_slice() != TREASURY_ACCOUNT_ID { + /*if account_id.as_slice() != TREASURY_ACCOUNT_ID { // Rule 4: If the account is not a "special account", // it should have a consumer self.assert( account_info.consumers > 0, format!("Account {} has no consumer.", account_id), ); - } + }*/ //TODO check that is not true anymore } } @@ -360,6 +386,76 @@ mod verifier { } } + /// check identities status and membership coherence + async fn verify_status_coherence( + &mut self, + identities: &HashMap<IdtyIndex, IdtyValue>, + memberships: &HashMap<IdtyIndex, MembershipData>, + names: &HashMap<IdtyIndex, IdtyName>, + ) { + for (idty_index, idty_value) in identities { + // Rule 1: each Status::Member should have a membership and a name. + if let IdtyStatus::Member = idty_value.status { + self.assert( + memberships.get(idty_index).is_some(), + format!("identity number {idty_index} should have a valid membership"), + ); + self.assert( + names.get(idty_index).is_some(), + format!("identity number {idty_index} should have a name"), + ); + } + + // Rule 2: each Status::NotMember should have a name but no membership. + if let IdtyStatus::NotMember = idty_value.status { + self.assert( + memberships.get(idty_index).is_none(), + format!("identity number {idty_index} should not have a valid membership"), + ); + self.assert( + names.get(idty_index).is_some(), + format!("identity number {idty_index} should have a name"), + ); + } + + // Rule 3: each Status::Revoke should should have a name but no membership. + if let IdtyStatus::Revoked = idty_value.status { + self.assert( + memberships.get(idty_index).is_none(), + format!("identity number {idty_index} should not have a valid membership"), + ); + self.assert( + names.get(idty_index).is_some(), + format!("identity number {idty_index} should have a name"), + ); + } + + // Rule 4: each Status::Unvalidaded should have a name but no membership. + if let IdtyStatus::Unvalidated = idty_value.status { + self.assert( + memberships.get(idty_index).is_none(), + format!("identity number {idty_index} should not have a valid membership"), + ); + self.assert( + names.get(idty_index).is_some(), + format!("identity number {idty_index} should have a name"), + ); + } + + // Rule 5: each Status::Unconfirmed should not have a name neither a membership. + if let IdtyStatus::Unconfirmed = idty_value.status { + self.assert( + memberships.get(idty_index).is_none(), + format!("identity number {idty_index} should not have a valid membership"), + ); + self.assert( + names.get(idty_index).is_none(), + format!("identity number {idty_index} should not have a name"), + ); + } + } + } + /// check coherence between identity list and identity index hashmap async fn verify_identity_coherence( &mut self,