From 7248a40b26a904904191ee4f34590b993196c5f6 Mon Sep 17 00:00:00 2001
From: librelois <c@elo.tf>
Date: Sat, 18 Jun 2022 00:32:39 +0200
Subject: [PATCH] tests(live): improve sanity-gdev: verify idty_index_of

---
 .cargo/config                   |  2 +-
 live-tests/tests/sanity_gdev.rs | 86 ++++++++++++++++++++++++++-------
 2 files changed, 69 insertions(+), 19 deletions(-)

diff --git a/.cargo/config b/.cargo/config
index 42f6b4bfc..e07889471 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -1,6 +1,6 @@
 [alias]
 cucumber = "test -p duniter-end2end-tests --test cucumber_tests --"
-sanity-gdev = "test -p duniter-live-tests --test sanity_gdev --"
+sanity-gdev = "test -p duniter-live-tests --test sanity_gdev -- --nocapture"
 tu = "test --workspace --exclude duniter-end2end-tests"
 xtask = "run --package xtask --"
 
diff --git a/live-tests/tests/sanity_gdev.rs b/live-tests/tests/sanity_gdev.rs
index 978da9d6a..4e6e14938 100644
--- a/live-tests/tests/sanity_gdev.rs
+++ b/live-tests/tests/sanity_gdev.rs
@@ -19,7 +19,7 @@ pub mod gdev_runtime {}
 
 use hex_literal::hex;
 use sp_core::crypto::AccountId32;
-use sp_core::{ByteArray, H256};
+use sp_core::{blake2_128, ByteArray, H256};
 use std::collections::HashMap;
 use subxt::{ClientBuilder, DefaultConfig, DefaultExtra};
 
@@ -49,6 +49,7 @@ use gdev_runtime::runtime_types::pallet_identity::types::IdtyStatus;
 struct Storage {
     accounts: HashMap<AccountId32, AccountInfo>,
     identities: HashMap<IdtyIndex, IdtyValue>,
+    identity_index_of: HashMap<[u8; 16], IdtyIndex>,
 }
 
 #[tokio::test(flavor = "current_thread")]
@@ -64,7 +65,7 @@ async fn main() -> anyhow::Result<()> {
 
     let maybe_block_hash = if let Ok(block_number) = std::env::var("AT_BLOCK_NUMBER") {
         let block_number: BlockNumber = block_number.parse()?;
-        println!("Run sanity tests against ÄžDev at block #{}", block_number);
+        println!("Run sanity tests against ÄžDev at block #{}.", block_number);
         client.rpc().block_hash(Some(block_number.into())).await?
     } else {
         println!("Run sanity tests against ÄžDev at last best block");
@@ -92,7 +93,7 @@ async fn sanity_tests_at(client: Client, maybe_block_hash: Option<H256>) -> anyh
         account_id_bytes.copy_from_slice(&key.0[48..]);
         accounts.insert(AccountId32::new(account_id_bytes), account_info);
     }
-    println!("{} accounts.", accounts.len());
+    println!("accounts: {}.", accounts.len());
 
     // Collect identities
     let mut identities = HashMap::new();
@@ -106,11 +107,26 @@ async fn sanity_tests_at(client: Client, maybe_block_hash: Option<H256>) -> anyh
         idty_index_bytes.copy_from_slice(&key.0[40..]);
         identities.insert(IdtyIndex::from_le_bytes(idty_index_bytes), idty_value);
     }
-    println!("{} identities.", identities.len());
+    println!("identities: {}.", identities.len());
+
+    // Collect identity_index_of
+    let mut identity_index_of = HashMap::new();
+    let mut idty_index_of_iter = api
+        .storage()
+        .identity()
+        .identity_index_of_iter(maybe_block_hash)
+        .await?;
+    while let Some((key, idty_index)) = idty_index_of_iter.next().await? {
+        let mut blake2_128_bytes = [0u8; 16];
+        blake2_128_bytes.copy_from_slice(&key.0[32..]);
+        identity_index_of.insert(blake2_128_bytes, idty_index);
+    }
+    println!("identity_index_of: {}.", identities.len());
 
     let storage = Storage {
         accounts,
         identities,
+        identity_index_of,
     };
 
     // ===== Verify storage ===== //
@@ -131,9 +147,11 @@ mod verifier {
         }
 
         pub(super) async fn verify_storage(&mut self, storage: &Storage) -> anyhow::Result<()> {
-            self.verify_accounts(&storage.accounts).await?;
+            self.verify_accounts(&storage.accounts).await;
             self.verify_identities(&storage.accounts, &storage.identities)
-                .await?;
+                .await;
+            self.verify_identity_index_of(&storage.identities, &storage.identity_index_of)
+                .await;
 
             if self.errors.is_empty() {
                 Ok(())
@@ -154,22 +172,19 @@ mod verifier {
             }
         }
 
-        async fn verify_accounts(
-            &mut self,
-            accounts: &HashMap<AccountId32, AccountInfo>,
-        ) -> anyhow::Result<()> {
+        async fn verify_accounts(&mut self, accounts: &HashMap<AccountId32, AccountInfo>) {
             for (account_id, account_info) in accounts {
                 if account_info.sufficients == 0 {
                     // Rule 1: If the account is not sufficient, it should have at least one provider
                     self.assert(
                         account_info.providers > 0,
-                        format!("Account {} has no providers nor sufficients", account_id),
+                        format!("Account {} has no providers nor sufficients.", account_id),
                     );
                     // Rule 2: If the account is not sufficient, it should comply to the existential deposit
                     self.assert(
                         (account_info.data.free + account_info.data.reserved) >= 200,
                         format!(
-                            "Account {} not respect existential deposit rule",
+                            "Account {} not respect existential deposit rule.",
                             account_id
                         ),
                     );
@@ -180,7 +195,7 @@ mod verifier {
                     // Rule 1: If the account is not s
                     self.assert(
                         account_info.providers > 0,
-                        format!("Account {} has no providers nor sufficients", account_id),
+                        format!("Account {} has no providers nor sufficients.", account_id),
                     );
                 }
 
@@ -189,24 +204,23 @@ mod verifier {
                     // it should have a random id or a consumer
                     self.assert(
                         account_info.data.random_id.is_some() || account_info.consumers > 0,
-                        format!("Account {} has no random_id nor consumer", account_id),
+                        format!("Account {} has no random_id nor consumer.", account_id),
                     );
                 }
             }
-            Ok(())
         }
 
         async fn verify_identities(
             &mut self,
             accounts: &HashMap<AccountId32, AccountInfo>,
             identities: &HashMap<IdtyIndex, IdtyValue>,
-        ) -> anyhow::Result<()> {
+        ) {
             for (idty_index, idty_value) in identities {
                 // Rule 1: each identity should have an account
                 let maybe_account = accounts.get(&idty_value.owner_key);
                 self.assert(
                     maybe_account.is_some(),
-                    format!("Identity {} has no account", idty_index),
+                    format!("Identity {} has no account.", idty_index),
                 );
 
                 if let Some(account) = maybe_account {
@@ -241,7 +255,43 @@ mod verifier {
                     }
                 }
             }
-            Ok(())
+        }
+
+        async fn verify_identity_index_of(
+            &mut self,
+            identities: &HashMap<IdtyIndex, IdtyValue>,
+            identity_index_of: &HashMap<[u8; 16], IdtyIndex>,
+        ) {
+            // Rule1: identity_index_of should have the same lenght as identities
+            self.assert(
+                identities.len() == identity_index_of.len(),
+                "identities.len() != identity_index_of.len().".to_owned(),
+            );
+
+            for (blake2_128_owner_key, idty_index) in identity_index_of {
+                let maybe_idty_value = identities.get(idty_index);
+
+                // Rule2: Each identity_index_of should point to an existing identity
+                self.assert(
+                    maybe_idty_value.is_some(),
+                    format!(
+                        "Identity {} not exist, but still referenced in IdentityIndexOf.",
+                        idty_index
+                    ),
+                );
+
+                if let Some(idty_value) = maybe_idty_value {
+                    // Rule3: identity_index_of key should correspond to the blake2_12- hash of
+                    // identity owner key
+                    self.assert(
+                        blake2_128_owner_key == &blake2_128(idty_value.owner_key.as_slice()),
+                        format!(
+                            "Identity {} is referenced in IdentityIndexOf with an invalid key hash.",
+                            idty_index
+                        ),
+                    );
+                }
+            }
         }
     }
 }
-- 
GitLab