From 36bbcbd8c329c55619da517b9572869df33e277d Mon Sep 17 00:00:00 2001 From: Dmitry Murzin Date: Tue, 23 Apr 2024 17:43:35 +0300 Subject: [PATCH] [fix] #4331: Revoke removed `PermissionToken`s on `Upgrade` Signed-off-by: Dmitry Murzin --- .../integration/smartcontracts/Cargo.toml | 1 + .../executor_remove_token/Cargo.toml | 24 ++++++ .../executor_remove_token/src/lib.rs | 37 +++++++++ client/tests/integration/upgrade.rs | 70 +++++++++++++++++ configs/swarm/executor.wasm | Bin 526777 -> 526781 bytes core/src/smartcontracts/isi/world.rs | 74 ++++++++++++++++++ data_model/src/isi.rs | 2 +- 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 client/tests/integration/smartcontracts/executor_remove_token/Cargo.toml create mode 100644 client/tests/integration/smartcontracts/executor_remove_token/src/lib.rs diff --git a/client/tests/integration/smartcontracts/Cargo.toml b/client/tests/integration/smartcontracts/Cargo.toml index 663956a73a0..4739c446174 100644 --- a/client/tests/integration/smartcontracts/Cargo.toml +++ b/client/tests/integration/smartcontracts/Cargo.toml @@ -13,6 +13,7 @@ members = [ "mint_rose_trigger", "executor_with_admin", "executor_with_custom_token", + "executor_remove_token", "executor_with_migration_fail", "query_assets_and_save_cursor", ] diff --git a/client/tests/integration/smartcontracts/executor_remove_token/Cargo.toml b/client/tests/integration/smartcontracts/executor_remove_token/Cargo.toml new file mode 100644 index 00000000000..ce62e8c1150 --- /dev/null +++ b/client/tests/integration/smartcontracts/executor_remove_token/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "executor_remove_token" + +edition.workspace = true +version.workspace = true +authors.workspace = true + +license.workspace = true + +[lib] +crate-type = ['cdylib'] + +[dependencies] +iroha_executor.workspace = true +iroha_schema.workspace = true + +parity-scale-codec.workspace = true +anyhow.workspace = true +serde_json.workspace = true +serde.workspace = true + +panic-halt.workspace = true +lol_alloc.workspace = true +getrandom.workspace = true diff --git a/client/tests/integration/smartcontracts/executor_remove_token/src/lib.rs b/client/tests/integration/smartcontracts/executor_remove_token/src/lib.rs new file mode 100644 index 00000000000..4a2c7aa16b3 --- /dev/null +++ b/client/tests/integration/smartcontracts/executor_remove_token/src/lib.rs @@ -0,0 +1,37 @@ +//! Runtime Executor which removes [`token::CanControlDomainLives`] permission token. +//! Needed for tests. + +#![no_std] + +extern crate alloc; +#[cfg(not(test))] +extern crate panic_halt; + +use iroha_executor::{default::default_permission_token_schema, prelude::*}; +use lol_alloc::{FreeListAllocator, LockedAllocator}; + +#[global_allocator] +static ALLOC: LockedAllocator = LockedAllocator::new(FreeListAllocator::new()); + +getrandom::register_custom_getrandom!(iroha_executor::stub_getrandom); + +#[derive(Constructor, ValidateEntrypoints, Validate, Visit)] +struct Executor { + verdict: Result, + block_height: u64, +} + +#[entrypoint] +pub fn migrate(_block_height: u64) -> MigrationResult { + // Note that actually migration will reset token schema to default (minus `CanUnregisterDomain`) + // So any added custom permission tokens will be also removed + let mut schema = default_permission_token_schema(); + schema.remove::(); + + let (token_ids, schema_str) = schema.serialize(); + iroha_executor::set_permission_token_schema( + &iroha_executor::data_model::permission::PermissionTokenSchema::new(token_ids, schema_str), + ); + + Ok(()) +} diff --git a/client/tests/integration/upgrade.rs b/client/tests/integration/upgrade.rs index 32e169b25a4..3d4106c79f5 100644 --- a/client/tests/integration/upgrade.rs +++ b/client/tests/integration/upgrade.rs @@ -113,6 +113,76 @@ fn executor_upgrade_should_run_migration() -> Result<()> { Ok(()) } +#[test] +fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { + let (_rt, _peer, client) = ::new().with_port(11_030).start_with_runtime(); + wait_for_genesis_committed(&vec![client.clone()], 0); + + // Permission which will be removed by executor + let can_unregister_domain_token = PermissionToken::new( + "CanUnregisterDomain".parse()?, + &json!({ "domain_id": DomainId::from_str("wonderland")? }), + ); + + // Register `TEST_ROLE` with permission + let test_role_id: RoleId = "TEST_ROLE".parse()?; + let test_role = + Role::new(test_role_id.clone()).add_permission(can_unregister_domain_token.clone()); + client.submit_blocking(Register::role(test_role))?; + + // Check that permission exists + assert!(client + .request(FindPermissionTokenSchema)? + .token_ids() + .contains(&can_unregister_domain_token.definition_id)); + + // Check that `TEST_ROLE` has permission + assert!(client + .request(FindAllRoles::new())? + .collect::>>()? + .into_iter() + .find(|role| role.id == test_role_id) + .expect("Failed to find Role") + .permissions + .contains(&can_unregister_domain_token)); + + // Check that Alice has permission + let alice_id: AccountId = "alice@wonderland".parse()?; + assert!(client + .request(FindPermissionTokensByAccountId::new(alice_id.clone()))? + .collect::>>()? + .contains(&can_unregister_domain_token)); + + upgrade_executor( + &client, + "tests/integration/smartcontracts/executor_remove_token", + )?; + + // Check that permission doesn't exist + assert!(!client + .request(FindPermissionTokenSchema)? + .token_ids() + .contains(&can_unregister_domain_token.definition_id)); + + // Check that `TEST_ROLE` doesn't have permission + assert!(!client + .request(FindAllRoles::new())? + .collect::>>()? + .into_iter() + .find(|role| role.id == test_role_id) + .expect("Failed to find Role") + .permissions + .contains(&can_unregister_domain_token)); + + // Check that Alice doesn't have permission + assert!(!client + .request(FindPermissionTokensByAccountId::new(alice_id.clone()))? + .collect::>>()? + .contains(&can_unregister_domain_token)); + + Ok(()) +} + #[test] fn migration_fail_should_not_cause_any_effects() { let (_rt, _peer, client) = ::new().with_port(10_995).start_with_runtime(); diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index cc4689ba58f2983a80403e0445e5a10ee1df3901..55348c7b4cb483198f8426b9cce3bddb0050e6f1 100644 GIT binary patch delta 51455 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 JU#S0({a;n`RyhCw diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index d5439ab0716..19b56c01dd4 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -18,6 +18,7 @@ impl Registrable for NewRole { /// Iroha Special Instructions that have `World` as their target. pub mod isi { use eyre::Result; + use indexmap::IndexSet; use iroha_data_model::{ isi::error::{InstructionExecutionError, InvalidParameterError, RepetitionError}, prelude::*, @@ -345,6 +346,12 @@ pub mod isi { ) -> Result<(), Error> { let raw_executor = self.executor; + let permissions_before = state_transaction + .world + .permission_token_schema + .token_ids + .clone(); + // Cloning executor to avoid multiple mutable borrows of `state_transaction`. // Also it's a cheap operation. let mut upgraded_executor = state_transaction.world.executor.clone(); @@ -359,6 +366,8 @@ pub mod isi { *state_transaction.world.executor.get_mut() = upgraded_executor; + revoke_removed_permissions(authority, state_transaction, permissions_before)?; + state_transaction .world .emit_events(std::iter::once(ExecutorEvent::Upgraded)); @@ -367,6 +376,71 @@ pub mod isi { } } + fn revoke_removed_permissions( + authority: &AccountId, + state_transaction: &mut StateTransaction, + permissions_before: Vec, + ) -> Result<(), Error> { + let world = state_transaction.world(); + let permissions_after = world + .permission_token_schema() + .token_ids + .iter() + .collect::>(); + let permissions_removed = permissions_before + .into_iter() + .filter(|permission| !permissions_after.contains(permission)) + .collect::>(); + if permissions_removed.is_empty() { + return Ok(()); + } + + let to_revoke_from_accounts = find_related_accounts(world, &permissions_removed); + let to_revoke_from_roles = find_related_roles(world, &permissions_removed); + + for (account_id, permission) in to_revoke_from_accounts { + let revoke = Revoke::permission(permission, account_id); + revoke.execute(authority, state_transaction)? + } + for (role_id, permission) in to_revoke_from_roles { + let revoke = Revoke::role_permission(permission, role_id); + revoke.execute(authority, state_transaction)? + } + Ok(()) + } + + fn find_related_accounts( + world: &impl WorldReadOnly, + permissions: &IndexSet, + ) -> Vec<(AccountId, PermissionToken)> { + world + .account_permission_tokens() + .iter() + .flat_map(|(account_id, account_permissions)| { + account_permissions + .iter() + .filter(|permission| permissions.contains(&permission.definition_id)) + .map(|permission| (account_id.clone(), permission.clone())) + }) + .collect() + } + + fn find_related_roles( + world: &impl WorldReadOnly, + permissions: &IndexSet, + ) -> Vec<(RoleId, PermissionToken)> { + world + .roles() + .iter() + .flat_map(|(role_id, role)| { + role.permissions + .iter() + .filter(|permission| permissions.contains(&permission.definition_id)) + .map(|permission| (role_id.clone(), permission.clone())) + }) + .collect() + } + impl Execute for Log { fn execute( self, diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index 2e9a73504e3..31aceca6dd6 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -1276,7 +1276,7 @@ isi_box! { PermissionToken(Revoke), /// Revoke [`Role`] from [`Account`]. Role(Revoke), - /// Revoke [`PermissionToken`] from [`Account`]. + /// Revoke [`PermissionToken`] from [`Role`]. RolePermissionToken(Revoke), } }