From 636c66752e2c6946005c60d5fba1f0a16c401adb Mon Sep 17 00:00:00 2001 From: Vladimir Pesterev Date: Tue, 7 Jun 2022 21:39:38 +0400 Subject: [PATCH] [feature] #2053: Add tests to 'private_blockchain' Signed-off-by: Vladimir Pesterev --- .../src/private_blockchain/mod.rs | 538 ++++++++++++++++++ .../src/private_blockchain/register.rs | 11 +- 2 files changed, 546 insertions(+), 3 deletions(-) diff --git a/permissions_validators/src/private_blockchain/mod.rs b/permissions_validators/src/private_blockchain/mod.rs index 252f67691a5..71fca8169ef 100644 --- a/permissions_validators/src/private_blockchain/mod.rs +++ b/permissions_validators/src/private_blockchain/mod.rs @@ -38,3 +38,541 @@ impl IsGrantAllowed for ProhibitGrant { Err("Granting at runtime is prohibited.".to_owned()) } } + +#[cfg(test)] +mod tests { + #![allow(clippy::restriction)] + + use std::str::FromStr as _; + + use super::*; + + struct TestEnv { + alice_id: AccountId, + bob_id: AccountId, + carol_id: AccountId, + gold_asset_id: AssetId, + gold_asset_definition_id: AssetDefinitionId, + silver_asset_id: AssetId, + silver_asset_definition_id: AssetDefinitionId, + bronze_asset_id: AssetId, + bronze_asset_definition_id: AssetDefinitionId, + first_domain: (DomainId, Domain), + second_domain: (DomainId, Domain), + wsv: WorldStateView, + } + + impl TestEnv { + fn new() -> Self { + // Alice + let alice_id = AccountId::from_str("alice@test0").expect("Valid"); + let mut alice = Account::new(alice_id.clone(), []).build(); + + // Gold asset + let gold_asset_definition_id = + AssetDefinitionId::from_str("gold#test0").expect("Valid"); + let gold_asset_id = AssetId::new(gold_asset_definition_id.clone(), alice_id.clone()); + let gold_asset = Asset::new(gold_asset_id.clone(), AssetValue::Quantity(100)); + + // Alice owns Gold + alice.add_asset(gold_asset); + + // Bob + let bob_id = AccountId::from_str("bob@test0").expect("Valid"); + let mut bob = Account::new(bob_id.clone(), []).build(); + + // Silver asset + let silver_asset_definition_id = + AssetDefinitionId::from_str("silver#test0").expect("Valid"); + let silver_asset_id = AssetId::new(silver_asset_definition_id.clone(), bob_id.clone()); + let silver_asset = Asset::new(silver_asset_id.clone(), AssetValue::Quantity(200)); + + // Bob owns Silver + bob.add_asset(silver_asset); + + // Carol + let carol_id = AccountId::from_str("carol@test1").expect("Valid"); + let mut carol = Account::new(carol_id.clone(), []).build(); + + // Bronze asset + let bronze_asset_definition_id = + AssetDefinitionId::from_str("bronze#test1").expect("Valid"); + let bronze_asset_id = + AssetId::new(bronze_asset_definition_id.clone(), carol_id.clone()); + let bronze_asset = Asset::new(bronze_asset_id.clone(), AssetValue::Quantity(300)); + + // Carol owns Bronze + carol.add_asset(bronze_asset.clone()); + + // Alice also owns Bronze + alice.add_asset(bronze_asset); + + // First domain + let first_domain_id = DomainId::from_str("test0").expect("Valid"); + let mut first_domain = Domain::new(first_domain_id.clone()).build(); + + // First domain includes Alice + first_domain.add_account(alice); + + // First domain includes Bob + first_domain.add_account(bob); + + // Second domain + let second_domain_id = DomainId::from_str("test1").expect("Valid"); + let mut second_domain = Domain::new(second_domain_id.clone()).build(); + + // Second domain includes Carol + second_domain.add_account(carol); + + let wsv = WorldStateView::::new(World::with( + [first_domain.clone(), second_domain.clone()], + vec![], + )); + + Self { + alice_id, + bob_id, + carol_id, + gold_asset_id, + gold_asset_definition_id, + silver_asset_id, + silver_asset_definition_id, + bronze_asset_id, + bronze_asset_definition_id, + first_domain: (first_domain_id, first_domain), + second_domain: (second_domain_id, second_domain), + wsv, + } + } + } + + #[test] + fn find_all_accounts() { + let TestEnv { + alice_id, + bob_id, + carol_id, + wsv, + .. + } = TestEnv::new(); + + let op = QueryBox::FindAllAccounts(FindAllAccounts::new()); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_account_by_id() { + let TestEnv { + alice_id, + bob_id, + carol_id, + wsv, + .. + } = TestEnv::new(); + + let op = QueryBox::FindAccountById(FindAccountById::new(alice_id.clone())); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_ok()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_ok()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_ok()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_account_key_value_by_id_and_key() { + let TestEnv { + alice_id, + bob_id, + carol_id, + wsv, + .. + } = TestEnv::new(); + + let op = QueryBox::FindAccountKeyValueByIdAndKey(FindAccountKeyValueByIdAndKey::new( + alice_id.clone(), + "name".to_owned(), + )); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_ok()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_ok()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_ok()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_account_by_name() { + let TestEnv { + alice_id, + bob_id, + carol_id, + wsv, + .. + } = TestEnv::new(); + + let op = QueryBox::FindAccountsByName(FindAccountsByName::new(alice_id.clone())); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_accounts_by_domain_id() { + let TestEnv { + alice_id, + bob_id, + carol_id, + first_domain: (first_domain_id, _), + second_domain: (second_domain_id, _), + wsv, + .. + } = TestEnv::new(); + + let op = QueryBox::FindAccountsByDomainId(FindAccountsByDomainId::new(first_domain_id)); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_ok()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_ok()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + + let op = QueryBox::FindAccountsByDomainId(FindAccountsByDomainId::new(second_domain_id)); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_ok()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_accounts_with_asset() { + let TestEnv { + alice_id, + bob_id, + carol_id, + wsv, + .. + } = TestEnv::new(); + + let op = QueryBox::FindAccountsWithAsset(FindAccountsWithAsset::new("xor".to_owned())); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_domain.check(&carol_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&bob_id, &op, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_all_assets() { + let TestEnv { alice_id, wsv, .. } = TestEnv::new(); + + let op = QueryBox::FindAllAssets(FindAllAssets::new()); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_all_assets_definitions() { + let TestEnv { alice_id, wsv, .. } = TestEnv::new(); + + let op = QueryBox::FindAllAssetsDefinitions(FindAllAssetsDefinitions::new()); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op, &wsv).is_err()); + } + } + + #[test] + fn find_asset_by_id() { + let TestEnv { + alice_id, + carol_id, + wsv, + gold_asset_id, + silver_asset_id, + bronze_asset_id, + .. + } = TestEnv::new(); + + let op1 = QueryBox::FindAssetById(FindAssetById::new(gold_asset_id)); + let op2 = QueryBox::FindAssetById(FindAssetById::new(silver_asset_id)); + let op3 = QueryBox::FindAssetById(FindAssetById::new(bronze_asset_id)); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op1, &wsv).is_ok()); + assert!(only_accounts_domain.check(&alice_id, &op2, &wsv).is_ok()); + assert!(only_accounts_domain.check(&carol_id, &op3, &wsv).is_ok()); + assert!(only_accounts_domain.check(&alice_id, &op3, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op1, &wsv).is_ok()); + assert!(only_accounts_data.check(&alice_id, &op2, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op3, &wsv).is_ok()); + assert!(only_accounts_data.check(&alice_id, &op3, &wsv).is_err()); + } + } + + #[test] + fn find_asset_definition_by_id() { + let TestEnv { + alice_id, + carol_id, + wsv, + gold_asset_definition_id, + silver_asset_definition_id, + bronze_asset_definition_id, + .. + } = TestEnv::new(); + + let op1 = QueryBox::FindAssetDefinitionById(FindAssetDefinitionById::new( + gold_asset_definition_id, + )); + let op2 = QueryBox::FindAssetDefinitionById(FindAssetDefinitionById::new( + silver_asset_definition_id, + )); + let op3 = QueryBox::FindAssetDefinitionById(FindAssetDefinitionById::new( + bronze_asset_definition_id, + )); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op1, &wsv).is_ok()); + assert!(only_accounts_domain.check(&alice_id, &op2, &wsv).is_ok()); + assert!(only_accounts_domain.check(&carol_id, &op3, &wsv).is_ok()); + assert!(only_accounts_domain.check(&alice_id, &op3, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op1, &wsv).is_err()); + assert!(only_accounts_data.check(&alice_id, &op2, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op3, &wsv).is_err()); + assert!(only_accounts_data.check(&alice_id, &op3, &wsv).is_err()); + } + } + + #[test] + fn find_assets_by_name() { + let TestEnv { + alice_id, + carol_id, + wsv, + .. + } = TestEnv::new(); + + let op1 = QueryBox::FindAssetsByName(FindAssetsByName::new( + Name::from_str("gold").expect("Valid"), + )); + let op2 = QueryBox::FindAssetsByName(FindAssetsByName::new( + Name::from_str("silver").expect("Valid"), + )); + let op3 = QueryBox::FindAssetsByName(FindAssetsByName::new( + Name::from_str("bronze").expect("Valid"), + )); + + { + let only_accounts_domain: IsQueryAllowedBoxed = query::OnlyAccountsDomain.into(); + + assert!(only_accounts_domain.check(&alice_id, &op1, &wsv).is_err()); + assert!(only_accounts_domain.check(&alice_id, &op2, &wsv).is_err()); + assert!(only_accounts_domain.check(&carol_id, &op3, &wsv).is_err()); + assert!(only_accounts_domain.check(&alice_id, &op3, &wsv).is_err()); + } + + { + let only_accounts_data: IsQueryAllowedBoxed = query::OnlyAccountsData.into(); + + assert!(only_accounts_data.check(&alice_id, &op1, &wsv).is_err()); + assert!(only_accounts_data.check(&alice_id, &op2, &wsv).is_err()); + assert!(only_accounts_data.check(&carol_id, &op3, &wsv).is_err()); + assert!(only_accounts_data.check(&alice_id, &op3, &wsv).is_err()); + } + } + + #[test] + fn probihit_register_domains_failed() { + let alice_id = AccountId::from_str("alice@test0").expect("Valid"); + + let instruction = Instruction::Register(RegisterBox::new(Domain::new( + "new_domain".parse().expect("Valid"), + ))); + + let wsv = WorldStateView::::new(World::new()); + + assert!(register::ProhibitRegisterDomains + .check(&alice_id, &instruction, &wsv) + .is_err()); + } + + #[test] + fn prohibit_register_domains_success() { + let alice_id = AccountId::from_str("alice@test0").expect("Valid"); + + let instruction = Instruction::Register(RegisterBox::new(Account::new( + "bob@test".parse().expect("Valid"), + [], + ))); + + let wsv = WorldStateView::::new(World::new()); + + assert!(register::ProhibitRegisterDomains + .check(&alice_id, &instruction, &wsv) + .is_ok()); + } + + #[test] + fn granted_allowed_register_domains_success() { + let alice_id = AccountId::from_str("alice@test0").expect("Valid"); + + let mut alice = Account::new(alice_id.clone(), []).build(); + alice.add_permission(PermissionToken::new( + register::CAN_REGISTER_DOMAINS_TOKEN.clone(), + )); + + let domain_id = DomainId::from_str("test0").expect("Valid"); + let mut domain = Domain::new(domain_id).build(); + domain.add_account(alice.clone()); + + let wsv = WorldStateView::::new(World::with([domain], vec![])); + + let validator: IsInstructionAllowedBoxed = + register::GrantedAllowedRegisterDomains.into(); + + let op = Instruction::Register(RegisterBox::new(Domain::new( + "newdomain".parse().expect("Valid"), + ))); + + assert!(validator.check(&alice_id, &op, &wsv).is_ok()); + } + + #[test] + fn granted_allowed_register_domains_failed() { + let alice_id = AccountId::from_str("alice@test0").expect("Valid"); + + let mut alice = Account::new(alice_id.clone(), []).build(); + alice.add_permission(PermissionToken::new( + Name::from_str("incorrecttoken").expect("Valid"), + )); + + let domain_id = DomainId::from_str("test0").expect("Valid"); + let mut domain = Domain::new(domain_id).build(); + domain.add_account(alice.clone()); + + let wsv = WorldStateView::::new(World::with([domain], vec![])); + + let validator: IsInstructionAllowedBoxed = + register::GrantedAllowedRegisterDomains.into(); + + let op = Instruction::Register(RegisterBox::new(Domain::new( + "newdomain".parse().expect("Valid"), + ))); + + assert!(validator.check(&alice_id, &op, &wsv).is_err()); + } +} diff --git a/permissions_validators/src/private_blockchain/register.rs b/permissions_validators/src/private_blockchain/register.rs index c52118d19b4..005afd1ac98 100644 --- a/permissions_validators/src/private_blockchain/register.rs +++ b/permissions_validators/src/private_blockchain/register.rs @@ -20,14 +20,19 @@ impl IsAllowed for ProhibitRegisterDomains { &self, _authority: &AccountId, instruction: &Instruction, - _wsv: &WorldStateView, + wsv: &WorldStateView, ) -> Result<(), DenialReason> { - let _register_box = if let Instruction::Register(register) = instruction { + let register = if let Instruction::Register(register) = instruction { register } else { return Ok(()); }; - Err("Domain registration is prohibited.".to_owned()) + + if let Ok(RegistrableBox::Domain(_)) = register.object.evaluate(wsv, &Context::new()) { + Err("Domain registration is prohibited.".to_owned()) + } else { + Ok(()) + } } }