diff --git a/permission_validators/runtime/Cargo.toml b/permission_validators/runtime/Cargo.toml index 69acef90f56..5a09f5e479a 100644 --- a/permission_validators/runtime/Cargo.toml +++ b/permission_validators/runtime/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "asset/burn", "asset/mint", + "asset/set_key_value", "asset/transfer", "asset/unregister", ] diff --git a/permission_validators/runtime/asset/set_key_value/Cargo.toml b/permission_validators/runtime/asset/set_key_value/Cargo.toml new file mode 100644 index 00000000000..47296750c65 --- /dev/null +++ b/permission_validators/runtime/asset/set_key_value/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "iroha_asset_set_key_value_validator" +version.workspace = true +authors.workspace = true +edition.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ['rlib'] + +[dependencies] +iroha_wasm.workspace = true diff --git a/permission_validators/runtime/asset/set_key_value/src/lib.rs b/permission_validators/runtime/asset/set_key_value/src/lib.rs new file mode 100644 index 00000000000..2f18a335d0b --- /dev/null +++ b/permission_validators/runtime/asset/set_key_value/src/lib.rs @@ -0,0 +1,56 @@ +//! Validator that checks [`SetKeyValue`] instruction +//! related to assets and respective [`Grant`] and [`Revoke`] instructions. + +#![no_std] +#![no_main] + +extern crate alloc; + +use iroha_wasm::validator::{pass_conditions, prelude::*}; + +/// Strongly-typed representation of `can_set_key_value_in_user_asset` permission token. +#[derive(Token, Validate, pass_conditions::derive_conversions::asset::Owner)] +#[validate(pass_conditions::asset::Owner)] +pub struct CanSetKeyValueInUserAsset { + asset_id: ::Id, +} + +/// Validate [`SetKeyValue`] instruction as well as [`Grant`] and [`Revoke`] instructions for +/// [`can_set_key_value_in_user_asset`] permission tokens. +/// +/// # [`SetKeyValue`] +/// +/// ## Pass +/// +/// - [`SetKeyValue`] `object_id` is not an [`AssetId`]; +/// - `authority` is an asset owner; +/// - `authority` has a corresponding [`can_set_key_value_in_user_asset`] permission token. +/// +/// ## Deny +/// +/// If none of the `Pass` conditions are met. +/// +/// # [`Grant`] and [`Revoke`] +/// +/// For more details about [`Grant`] and [`Revoke`] instructions validation, +/// see [`can_set_key_value_in_user_asset`]. +/// +/// [`can_set_key_value_in_user_asset`]: CanSetKeyValueInUserAsset +pub fn validate(authority: ::Id, instruction: Instruction) -> Verdict { + validate_grant_revoke!(, (authority, instruction)); + + let Instruction::SetKeyValue(set_key_value) = instruction else { + pass!(); + }; + + let IdBox::AssetId(asset_id) = set_key_value.object_id + .evaluate_on_host() + .dbg_expect("Failed to evaluate `SetKeyValue` object id") else { + pass!(); + }; + + pass_if!(asset_id.account_id == authority); + pass_if!(CanSetKeyValueInUserAsset { asset_id }.is_owned_by(&authority)); + + deny!("Can't set value to the asset metadata of another account") +}