Skip to content
Snippets Groups Projects
Commit eec7100c authored by Éloïs's avatar Éloïs
Browse files

collect and print all errors

parent 9c0dce2e
No related branches found
No related tags found
1 merge request!76tests(live): add sanity tests against gdev live chain
This commit is part of merge request !76. Comments created here will be created in the context of that merge request.
...@@ -46,6 +46,11 @@ type IdtyValue = ...@@ -46,6 +46,11 @@ type IdtyValue =
gdev_runtime::runtime_types::pallet_identity::types::IdtyValue<BlockNumber, AccountId32>; gdev_runtime::runtime_types::pallet_identity::types::IdtyValue<BlockNumber, AccountId32>;
use gdev_runtime::runtime_types::pallet_identity::types::IdtyStatus; use gdev_runtime::runtime_types::pallet_identity::types::IdtyStatus;
struct Storage {
accounts: HashMap<AccountId32, AccountInfo>,
identities: HashMap<IdtyIndex, IdtyValue>,
}
#[tokio::test(flavor = "current_thread")] #[tokio::test(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let ws_rpc_endpoint = let ws_rpc_endpoint =
...@@ -87,6 +92,7 @@ async fn sanity_tests_at(client: Client, maybe_block_hash: Option<H256>) -> anyh ...@@ -87,6 +92,7 @@ async fn sanity_tests_at(client: Client, maybe_block_hash: Option<H256>) -> anyh
account_id_bytes.copy_from_slice(&key.0[48..]); account_id_bytes.copy_from_slice(&key.0[48..]);
accounts.insert(AccountId32::new(account_id_bytes), account_info); accounts.insert(AccountId32::new(account_id_bytes), account_info);
} }
println!("{} accounts.", accounts.len());
// Collect identities // Collect identities
let mut identities = HashMap::new(); let mut identities = HashMap::new();
...@@ -100,90 +106,138 @@ async fn sanity_tests_at(client: Client, maybe_block_hash: Option<H256>) -> anyh ...@@ -100,90 +106,138 @@ async fn sanity_tests_at(client: Client, maybe_block_hash: Option<H256>) -> anyh
idty_index_bytes.copy_from_slice(&key.0[40..]); idty_index_bytes.copy_from_slice(&key.0[40..]);
identities.insert(IdtyIndex::from_le_bytes(idty_index_bytes), idty_value); identities.insert(IdtyIndex::from_le_bytes(idty_index_bytes), idty_value);
} }
println!("{} identities.", identities.len());
// ===== Verify storage ===== // let storage = Storage {
accounts,
identities,
};
verify_accounts(&accounts).await?; // ===== Verify storage ===== //
verify_identities(&accounts, &identities).await?;
Ok(()) verifier::Verifier::new().verify_storage(&storage).await
} }
async fn verify_accounts(accounts: &HashMap<AccountId32, AccountInfo>) -> anyhow::Result<()> { mod verifier {
for (account_id, account_info) in accounts { use super::*;
if account_info.sufficients == 0 {
// Rule 1: If the account is not sufficient, it should have at least one provider pub(super) struct Verifier {
assert!( errors: Vec<String>,
account_info.providers > 0, }
"Account {} has no providers nor sufficients",
account_id impl Verifier {
); pub(super) fn new() -> Self {
// Rule 2: If the account is not sufficient, it should comply to the existential deposit Self { errors: Vec::new() }
assert!(
(account_info.data.free + account_info.data.reserved) >= 200,
"Account {} not respect existential deposit rule",
account_id
);
} }
// Rule 3: If the account have consumers, it shoul have at least one provider pub(super) async fn verify_storage(&mut self, storage: &Storage) -> anyhow::Result<()> {
if account_info.consumers > 0 { self.verify_accounts(&storage.accounts).await?;
// Rule 1: If the account is not s self.verify_identities(&storage.accounts, &storage.identities)
assert!( .await?;
account_info.providers > 0,
"Account {} has no providers nor sufficients", if self.errors.is_empty() {
account_id Ok(())
); } else {
for error in &self.errors {
println!("{}", error);
}
Err(anyhow::anyhow!(
"Storage corrupted: {} errors.",
self.errors.len()
))
}
} }
if account_id.as_slice() != TREASURY_ACCOUNT_ID { fn assert(&mut self, assertion: bool, error: String) {
// Rule 4: If the account is not a "special account", if !assertion {
// it should have a random id or a consumer self.errors.push(error);
assert!( }
account_info.data.random_id.is_some() || account_info.consumers > 0,
"Account {} has no random_id nor consumer",
account_id
);
} }
}
Ok(())
}
async fn verify_identities( async fn verify_accounts(
accounts: &HashMap<AccountId32, AccountInfo>, &mut self,
identities: &HashMap<IdtyIndex, IdtyValue>, accounts: &HashMap<AccountId32, AccountInfo>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
for (idty_index, idty_value) in identities { for (account_id, account_info) in accounts {
// Rule 1: each identity should have an account if account_info.sufficients == 0 {
let idty_account = accounts // Rule 1: If the account is not sufficient, it should have at least one provider
.get(&idty_value.owner_key) self.assert(
.unwrap_or_else(|| panic!("Identity {} has no account", idty_index)); account_info.providers > 0,
format!("Account {} has no providers nor sufficients", account_id),
// Rule 2: each identity account should be sufficient );
assert!( // Rule 2: If the account is not sufficient, it should comply to the existential deposit
idty_account.sufficients > 0, self.assert(
"Identity {} is corrupted: idty_account.sufficients == 0", (account_info.data.free + account_info.data.reserved) >= 200,
idty_index format!(
); "Account {} not respect existential deposit rule",
account_id
match idty_value.status { ),
IdtyStatus::Validated => { );
// Rule 3: If the identity is validated, removable_on shoud be zero }
assert!(
idty_value.removable_on == 0, // Rule 3: If the account have consumers, it shoul have at least one provider
"Identity {} is corrupted: removable_on > 0 on validated idty", if account_info.consumers > 0 {
idty_index // Rule 1: If the account is not s
); self.assert(
account_info.providers > 0,
format!("Account {} has no providers nor sufficients", account_id),
);
}
if account_id.as_slice() != TREASURY_ACCOUNT_ID {
// Rule 4: If the account is not a "special account",
// 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),
);
}
} }
_ => { Ok(())
// Rule 4: If the identity is not validated, next_creatable_identity_on shoud be zero }
assert!(
idty_value.next_creatable_identity_on == 0, async fn verify_identities(
"Identity {} is corrupted: next_creatable_identity_on > 0 on non-validated idty", &mut self,
idty_index 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 idty_account = accounts
.get(&idty_value.owner_key)
.unwrap_or_else(|| panic!("Identity {} has no account", idty_index));
// Rule 2: each identity account should be sufficient
self.assert(
idty_account.sufficients > 0,
format!(
"Identity {} is corrupted: idty_account.sufficients == 0",
idty_index
),
); );
match idty_value.status {
IdtyStatus::Validated => {
// Rule 3: If the identity is validated, removable_on shoud be zero
self.assert(
idty_value.removable_on == 0,
format!(
"Identity {} is corrupted: removable_on > 0 on validated idty",
idty_index
),
);
}
_ => {
// Rule 4: If the identity is not validated, next_creatable_identity_on shoud be zero
self.assert(
idty_value.next_creatable_identity_on == 0,
format!("Identity {} is corrupted: next_creatable_identity_on > 0 on non-validated idty",
idty_index)
);
}
}
} }
Ok(())
} }
} }
Ok(())
} }
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