diff --git a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs index 2a725479740..89f1e48aba9 100644 --- a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs +++ b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs @@ -16,7 +16,7 @@ static ALLOC: LockedAllocator = LockedAllocator::new(FreeList getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); #[iroha_trigger::main] -fn main(_owner: AccountId, _event: Event) { +fn main(_id: TriggerId, _owner: AccountId, _event: Event) { iroha_trigger::log::info!("Executing trigger"); let accounts_cursor = FindAllAccounts.execute().dbg_unwrap(); diff --git a/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs b/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs index e3558de7c61..396efd60dc6 100644 --- a/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs +++ b/client/tests/integration/smartcontracts/mint_rose_trigger/src/lib.rs @@ -17,12 +17,14 @@ getrandom::register_custom_getrandom!(iroha_trigger::stub_getrandom); /// Mint 1 rose for owner #[iroha_trigger::main] -fn main(owner: AccountId, _event: Event) { +fn main(id: TriggerId, owner: AccountId, _event: Event) { let rose_definition_id = AssetDefinitionId::from_str("rose#wonderland") .dbg_expect("Failed to parse `rose#wonderland` asset definition id"); let rose_id = AssetId::new(rose_definition_id, owner); - Mint::asset_numeric(1u32, rose_id) + let val = FindTriggerKeyValueByIdAndKey::new(id, "VAL".parse().unwrap()).dbg_unwrap(); + + Mint::asset_numeric(val, rose_id) .execute() .dbg_expect("Failed to mint rose"); } diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index a2c2ac2b41d..0a77a8bf086 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -378,8 +378,12 @@ fn trigger_in_genesis_using_base64() -> Result<()> { let prev_value = get_asset_value(&mut test_client, asset_id.clone()); // Executing trigger - let call_trigger = ExecuteTrigger::new(trigger_id); - test_client.submit_blocking(call_trigger)?; + let call_trigger = ExecuteTrigger::new(trigger_id.clone()); + let set_trigger_metadata = SetKeyValue::trigger(trigger_id, "VAL".parse()?, numeric!(1)); + test_client.submit_all_blocking(vec![ + InstructionBox::from(set_trigger_metadata), + call_trigger.into(), + ])?; // Checking result let new_value = get_asset_value(&mut test_client, asset_id); diff --git a/config/src/parameters/actual.rs b/config/src/parameters/actual.rs index df23be982f7..6b10b3d870b 100644 --- a/config/src/parameters/actual.rs +++ b/config/src/parameters/actual.rs @@ -177,10 +177,11 @@ pub struct ChainWide { pub block_time: Duration, pub commit_time: Duration, pub transaction_limits: TransactionLimits, - pub asset_metadata_limits: MetadataLimits, + pub domain_metadata_limits: MetadataLimits, pub asset_definition_metadata_limits: MetadataLimits, pub account_metadata_limits: MetadataLimits, - pub domain_metadata_limits: MetadataLimits, + pub asset_metadata_limits: MetadataLimits, + pub trigger_metadata_limits: MetadataLimits, pub ident_length_limits: LengthLimits, pub executor_runtime: WasmRuntime, pub wasm_runtime: WasmRuntime, @@ -204,6 +205,7 @@ impl Default for ChainWide { account_metadata_limits: defaults::chain_wide::DEFAULT_METADATA_LIMITS, asset_definition_metadata_limits: defaults::chain_wide::DEFAULT_METADATA_LIMITS, asset_metadata_limits: defaults::chain_wide::DEFAULT_METADATA_LIMITS, + trigger_metadata_limits: defaults::chain_wide::DEFAULT_METADATA_LIMITS, ident_length_limits: defaults::chain_wide::DEFAULT_IDENT_LENGTH_LIMITS, executor_runtime: WasmRuntime::default(), wasm_runtime: WasmRuntime::default(), diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index 1a0d7a5ced1..5afae534472 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -566,10 +566,11 @@ pub struct ChainWide { pub block_time: Duration, pub commit_time: Duration, pub transaction_limits: TransactionLimits, - pub asset_metadata_limits: MetadataLimits, + pub domain_metadata_limits: MetadataLimits, pub asset_definition_metadata_limits: MetadataLimits, pub account_metadata_limits: MetadataLimits, - pub domain_metadata_limits: MetadataLimits, + pub asset_metadata_limits: MetadataLimits, + pub trigger_metadata_limits: MetadataLimits, pub ident_length_limits: LengthLimits, pub executor_fuel_limit: u64, pub executor_max_memory: HumanBytes, @@ -585,6 +586,7 @@ impl ChainWide { commit_time, transaction_limits, asset_metadata_limits, + trigger_metadata_limits, asset_definition_metadata_limits, account_metadata_limits, domain_metadata_limits, @@ -601,6 +603,7 @@ impl ChainWide { commit_time, transaction_limits, asset_metadata_limits, + trigger_metadata_limits, asset_definition_metadata_limits, account_metadata_limits, domain_metadata_limits, diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 2e9b8695474..b2863772d71 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -656,10 +656,11 @@ pub struct ChainWidePartial { pub block_time: UserField, pub commit_time: UserField, pub transaction_limits: UserField, - pub asset_metadata_limits: UserField, + pub domain_metadata_limits: UserField, pub asset_definition_metadata_limits: UserField, pub account_metadata_limits: UserField, - pub domain_metadata_limits: UserField, + pub asset_metadata_limits: UserField, + pub trigger_metadata_limits: UserField, pub ident_length_limits: UserField, pub executor_fuel_limit: UserField, pub executor_max_memory: UserField>, @@ -682,8 +683,8 @@ impl UnwrapPartial for ChainWidePartial { transaction_limits: self .transaction_limits .unwrap_or(DEFAULT_TRANSACTION_LIMITS), - asset_metadata_limits: self - .asset_metadata_limits + domain_metadata_limits: self + .domain_metadata_limits .unwrap_or(DEFAULT_METADATA_LIMITS), asset_definition_metadata_limits: self .asset_definition_metadata_limits @@ -691,8 +692,11 @@ impl UnwrapPartial for ChainWidePartial { account_metadata_limits: self .account_metadata_limits .unwrap_or(DEFAULT_METADATA_LIMITS), - domain_metadata_limits: self - .domain_metadata_limits + asset_metadata_limits: self + .asset_metadata_limits + .unwrap_or(DEFAULT_METADATA_LIMITS), + trigger_metadata_limits: self + .trigger_metadata_limits .unwrap_or(DEFAULT_METADATA_LIMITS), ident_length_limits: self .ident_length_limits diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index fb05db1652e..b327627fea7 100644 Binary files a/configs/swarm/executor.wasm and b/configs/swarm/executor.wasm differ diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index aa814e37f7a..fd238417169 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -285,8 +285,8 @@ pub mod isi { state_transaction .world .emit_events(Some(AccountEvent::MetadataInserted(MetadataChanged { - target_id: account_id.clone(), - key: self.key.clone(), + target_id: account_id, + key: self.key, value: self.value, }))); @@ -316,7 +316,7 @@ pub mod isi { state_transaction .world .emit_events(Some(AccountEvent::MetadataRemoved(MetadataChanged { - target_id: account_id.clone(), + target_id: account_id, key: self.key, value, }))); diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index 7d04c07c6ba..2c8dde57a15 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -181,6 +181,7 @@ impl Execute for SetKeyValueBox { Self::Account(isi) => isi.execute(authority, state_transaction), Self::AssetDefinition(isi) => isi.execute(authority, state_transaction), Self::Asset(isi) => isi.execute(authority, state_transaction), + Self::Trigger(isi) => isi.execute(authority, state_transaction), } } } @@ -196,6 +197,7 @@ impl Execute for RemoveKeyValueBox { Self::Account(isi) => isi.execute(authority, state_transaction), Self::AssetDefinition(isi) => isi.execute(authority, state_transaction), Self::Asset(isi) => isi.execute(authority, state_transaction), + Self::Trigger(isi) => isi.execute(authority, state_transaction), } } } diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index 611f87e01db..00ea4338215 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -177,6 +177,72 @@ pub mod isi { } } + impl Execute for SetKeyValue { + #[metrics(+"set_trigger_key_value")] + fn execute( + self, + _authority: &AccountId, + state_transaction: &mut StateTransaction<'_, '_>, + ) -> Result<(), Error> { + let trigger_id = self.object_id; + + let trigger_metadata_limits = state_transaction.config.account_metadata_limits; + state_transaction + .world + .triggers + .inspect_by_id_mut(&trigger_id, |action| { + action.metadata_mut().insert_with_limits( + self.key.clone(), + self.value.clone(), + trigger_metadata_limits, + ) + }) + .ok_or(FindError::Trigger(trigger_id.clone()))??; + + state_transaction + .world + .emit_events(Some(TriggerEvent::MetadataInserted(MetadataChanged { + target_id: trigger_id, + key: self.key, + value: self.value, + }))); + + Ok(()) + } + } + + impl Execute for RemoveKeyValue { + #[metrics(+"remove_trigger_key_value")] + fn execute( + self, + _authority: &AccountId, + state_transaction: &mut StateTransaction<'_, '_>, + ) -> Result<(), Error> { + let trigger_id = self.object_id; + + let value = state_transaction + .world + .triggers + .inspect_by_id_mut(&trigger_id, |action| { + action + .metadata_mut() + .remove(&self.key) + .ok_or_else(|| FindError::MetadataKey(self.key.clone())) + }) + .ok_or(FindError::Trigger(trigger_id.clone()))??; + + state_transaction + .world + .emit_events(Some(TriggerEvent::MetadataRemoved(MetadataChanged { + target_id: trigger_id, + key: self.key, + value, + }))); + + Ok(()) + } + } + impl Execute for ExecuteTrigger { #[metrics(+"execute_trigger")] fn execute( diff --git a/core/src/smartcontracts/isi/triggers/specialized.rs b/core/src/smartcontracts/isi/triggers/specialized.rs index 09e898b126d..cb0957f114c 100644 --- a/core/src/smartcontracts/isi/triggers/specialized.rs +++ b/core/src/smartcontracts/isi/triggers/specialized.rs @@ -152,6 +152,9 @@ pub trait LoadedActionTrait { /// Get action metadata fn metadata(&self) -> &Metadata; + /// Get action metadata + fn metadata_mut(&mut self) -> &mut Metadata; + /// Check if action is mintable. fn mintable(&self) -> bool; @@ -181,10 +184,15 @@ impl + Clone> LoadedActionTrait &self.authority } + /// Get action metadata fn metadata(&self) -> &Metadata { &self.metadata } + fn metadata_mut(&mut self) -> &mut Metadata { + &mut self.metadata + } + fn mintable(&self) -> bool { self.filter.mintable() } diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index dd8df4bd163..034ea428db6 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -464,6 +464,8 @@ pub mod state { /// Trigger execution state #[derive(Constructor)] pub struct Trigger { + pub(in super::super) id: TriggerId, + /// Event which activated this trigger pub(in super::super) triggering_event: Event, } @@ -985,7 +987,7 @@ impl<'wrld, 'block: 'wrld, 'state: 'block> Runtime Runtime payloads::Trigger { payloads::Trigger { + id: state.specific_state.id.clone(), owner: state.authority.clone(), event: state.specific_state.triggering_event.clone(), } diff --git a/core/src/state.rs b/core/src/state.rs index b9291530cbf..9b85eb84fa2 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -285,7 +285,7 @@ impl World { } } - /// Create struct to apply block's changes while reverting changes made in the latest block + /// Create struct to apply block's changes while reverting changes made in the latest block pub fn block_and_revert(&self) -> WorldBlock { WorldBlock { parameters: self.parameters.block_and_revert(), @@ -1333,10 +1333,11 @@ impl<'state> StateBlock<'state> { } update_params! { - WSV_ASSET_METADATA_LIMITS => self.config.asset_metadata_limits, + WSV_DOMAIN_METADATA_LIMITS => self.config.domain_metadata_limits, WSV_ASSET_DEFINITION_METADATA_LIMITS => self.config.asset_definition_metadata_limits, WSV_ACCOUNT_METADATA_LIMITS => self.config.account_metadata_limits, - WSV_DOMAIN_METADATA_LIMITS => self.config.domain_metadata_limits, + WSV_ASSET_METADATA_LIMITS => self.config.asset_metadata_limits, + WSV_TRIGGER_METADATA_LIMITS => self.config.trigger_metadata_limits, WSV_IDENT_LENGTH_LIMITS => self.config.ident_length_limits, EXECUTOR_FUEL_LIMIT => self.config.executor_runtime.fuel_limit, EXECUTOR_MAX_MEMORY => self.config.executor_runtime.max_memory_bytes, diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 156be776be1..3c6fc21b909 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -486,6 +486,9 @@ mod trigger { pub use self::model::*; use super::*; + // type alias required by `Filter` macro + type TriggerMetadataChanged = MetadataChanged; + data_event! { #[has_origin(origin = Trigger)] pub enum TriggerEvent { @@ -495,6 +498,10 @@ mod trigger { Extended(TriggerNumberOfExecutionsChanged), #[has_origin(number_of_executions_changed => &number_of_executions_changed.trigger_id)] Shortened(TriggerNumberOfExecutionsChanged), + #[has_origin(metadata_changed => &metadata_changed.target_id)] + MetadataInserted(TriggerMetadataChanged), + #[has_origin(metadata_changed => &metadata_changed.target_id)] + MetadataRemoved(TriggerMetadataChanged), } } diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index 1ecd901aba7..40cdcc316d3 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -134,13 +134,15 @@ macro_rules! impl_instruction { impl_instruction! { SetKeyValue, - SetKeyValue, SetKeyValue, + SetKeyValue, SetKeyValue, + SetKeyValue, RemoveKeyValue, - RemoveKeyValue, RemoveKeyValue, + RemoveKeyValue, RemoveKeyValue, + RemoveKeyValue, Register, Register, Register, @@ -339,6 +341,21 @@ mod transparent { } } + impl SetKeyValue { + /// Constructs a new [`SetKeyValue`] for a [`Trigger`] with the given `key` and `value`. + pub fn trigger( + trigger_id: TriggerId, + key: Name, + value: impl Into, + ) -> Self { + Self { + object_id: trigger_id, + key, + value: value.into(), + } + } + } + impl_display! { SetKeyValue where @@ -353,7 +370,8 @@ mod transparent { SetKeyValue | SetKeyValue | SetKeyValue | - SetKeyValue + SetKeyValue | + SetKeyValue => SetKeyValueBox => InstructionBox[SetKeyValue], => SetKeyValueBoxRef<'a> => InstructionBoxRef<'a>[SetKeyValue] } @@ -410,6 +428,16 @@ mod transparent { } } + impl RemoveKeyValue { + /// Constructs a new [`RemoveKeyValue`] for an [`Asset`] with the given `key`. + pub fn trigger(trigger_id: TriggerId, key: Name) -> Self { + Self { + object_id: trigger_id, + key, + } + } + } + impl_display! { RemoveKeyValue where @@ -424,7 +452,8 @@ mod transparent { RemoveKeyValue | RemoveKeyValue | RemoveKeyValue | - RemoveKeyValue + RemoveKeyValue | + RemoveKeyValue => RemoveKeyValueBox => InstructionBox[RemoveKeyValue], => RemoveKeyValueBoxRef<'a> => InstructionBoxRef<'a>[RemoveKeyValue] } @@ -1059,6 +1088,8 @@ isi_box! { AssetDefinition(SetKeyValue), /// Set key value for [`Asset`]. Asset(SetKeyValue), + /// Set key value for [`Trigger`]. + Trigger(SetKeyValue), } } @@ -1078,6 +1109,8 @@ isi_box! { AssetDefinition(RemoveKeyValue), /// Remove key value from [`Asset`]. Asset(RemoveKeyValue), + /// Remove key value for [`Trigger`]. + Trigger(RemoveKeyValue), } } diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index 87352bead15..ab1fadfa65b 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -70,14 +70,16 @@ mod seal { InstructionBox, SetKeyValue, - SetKeyValue, SetKeyValue, + SetKeyValue, SetKeyValue, + SetKeyValue, RemoveKeyValue, - RemoveKeyValue, RemoveKeyValue, + RemoveKeyValue, RemoveKeyValue, + RemoveKeyValue, Register, Register, @@ -231,10 +233,11 @@ pub mod parameter { pub const BLOCK_TIME: &str = "BlockTime"; pub const COMMIT_TIME_LIMIT: &str = "CommitTimeLimit"; pub const TRANSACTION_LIMITS: &str = "TransactionLimits"; - pub const WSV_ASSET_METADATA_LIMITS: &str = "WSVAssetMetadataLimits"; + pub const WSV_DOMAIN_METADATA_LIMITS: &str = "WSVDomainMetadataLimits"; pub const WSV_ASSET_DEFINITION_METADATA_LIMITS: &str = "WSVAssetDefinitionMetadataLimits"; pub const WSV_ACCOUNT_METADATA_LIMITS: &str = "WSVAccountMetadataLimits"; - pub const WSV_DOMAIN_METADATA_LIMITS: &str = "WSVDomainMetadataLimits"; + pub const WSV_ASSET_METADATA_LIMITS: &str = "WSVAssetMetadataLimits"; + pub const WSV_TRIGGER_METADATA_LIMITS: &str = "WSVTriggerMetadataLimits"; pub const WSV_IDENT_LENGTH_LIMITS: &str = "WSVIdentLengthLimits"; pub const EXECUTOR_FUEL_LIMIT: &str = "ExecutorFuelLimit"; pub const EXECUTOR_MAX_MEMORY: &str = "ExecutorMaxMemory"; diff --git a/data_model/src/smart_contract.rs b/data_model/src/smart_contract.rs index 379da0585d9..928eee6f827 100644 --- a/data_model/src/smart_contract.rs +++ b/data_model/src/smart_contract.rs @@ -17,6 +17,8 @@ pub mod payloads { /// Payload for trigger entrypoint #[derive(Debug, Clone, Encode, Decode)] pub struct Trigger { + /// Id of this trigger + pub id: TriggerId, /// Trigger owner who registered the trigger pub owner: AccountId, /// Event which triggered the execution diff --git a/data_model/src/visit.rs b/data_model/src/visit.rs index b626e8bcde7..f25fc3dc9e0 100644 --- a/data_model/src/visit.rs +++ b/data_model/src/visit.rs @@ -128,12 +128,14 @@ pub trait Visit { visit_set_account_key_value(&SetKeyValue), visit_set_asset_definition_key_value(&SetKeyValue), visit_set_asset_key_value(&SetKeyValue), + visit_set_trigger_key_value(&SetKeyValue), // Visit RemoveKeyValueBox visit_remove_domain_key_value(&RemoveKeyValue), visit_remove_account_key_value(&RemoveKeyValue), visit_remove_asset_definition_key_value(&RemoveKeyValue), visit_remove_asset_key_value(&RemoveKeyValue), + visit_remove_trigger_key_value(&RemoveKeyValue), // Visit GrantBox visit_grant_account_permission(&Grant), @@ -350,6 +352,7 @@ pub fn visit_set_key_value( visitor.visit_set_asset_definition_key_value(authority, obj) } SetKeyValueBox::Asset(obj) => visitor.visit_set_asset_key_value(authority, obj), + SetKeyValueBox::Trigger(obj) => visitor.visit_set_trigger_key_value(authority, obj), } } @@ -365,6 +368,7 @@ pub fn visit_remove_key_value( visitor.visit_remove_asset_definition_key_value(authority, obj) } RemoveKeyValueBox::Asset(obj) => visitor.visit_remove_asset_key_value(authority, obj), + RemoveKeyValueBox::Trigger(obj) => visitor.visit_remove_trigger_key_value(authority, obj), } } @@ -409,6 +413,8 @@ leaf_visitors! { visit_transfer_asset_store(&Transfer), visit_set_asset_key_value(&SetKeyValue), visit_remove_asset_key_value(&RemoveKeyValue), + visit_set_trigger_key_value(&SetKeyValue), + visit_remove_trigger_key_value(&RemoveKeyValue), visit_register_asset_definition(&Register), visit_unregister_asset_definition(&Unregister), visit_transfer_asset_definition(&Transfer), diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index c409a082878..f37af837c27 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -376,10 +376,10 @@ pub mod domain { AnyPermissionToken::CanMintUserSignatureCheckConditions(permission) => { permission.account_id.domain_id() == domain_id } - AnyPermissionToken::CanSetKeyValueInUserAccount(permission) => { + AnyPermissionToken::CanSetKeyValueInAccount(permission) => { permission.account_id.domain_id() == domain_id } - AnyPermissionToken::CanRemoveKeyValueInUserAccount(permission) => { + AnyPermissionToken::CanRemoveKeyValueInAccount(permission) => { permission.account_id.domain_id() == domain_id } AnyPermissionToken::CanUnregisterUserTrigger(permission) => { @@ -566,10 +566,9 @@ pub mod account { Ok(true) => execute!(executor, isi), Ok(false) => {} } - let can_set_key_value_in_user_account_token = - tokens::account::CanSetKeyValueInUserAccount { - account_id: account_id.clone(), - }; + let can_set_key_value_in_user_account_token = tokens::account::CanSetKeyValueInAccount { + account_id: account_id.clone(), + }; if can_set_key_value_in_user_account_token.is_owned_by(authority) { execute!(executor, isi); } @@ -596,7 +595,7 @@ pub mod account { Ok(false) => {} } let can_remove_key_value_in_user_account_token = - tokens::account::CanRemoveKeyValueInUserAccount { + tokens::account::CanRemoveKeyValueInAccount { account_id: account_id.clone(), }; if can_remove_key_value_in_user_account_token.is_owned_by(authority) { @@ -626,10 +625,10 @@ pub mod account { AnyPermissionToken::CanMintUserSignatureCheckConditions(permission) => { &permission.account_id == account_id } - AnyPermissionToken::CanSetKeyValueInUserAccount(permission) => { + AnyPermissionToken::CanSetKeyValueInAccount(permission) => { &permission.account_id == account_id } - AnyPermissionToken::CanRemoveKeyValueInUserAccount(permission) => { + AnyPermissionToken::CanRemoveKeyValueInAccount(permission) => { &permission.account_id == account_id } AnyPermissionToken::CanBurnUserAsset(permission) => { @@ -893,8 +892,8 @@ pub mod asset_definition { | AnyPermissionToken::CanMintUserPublicKeys(_) | AnyPermissionToken::CanBurnUserPublicKeys(_) | AnyPermissionToken::CanMintUserSignatureCheckConditions(_) - | AnyPermissionToken::CanSetKeyValueInUserAccount(_) - | AnyPermissionToken::CanRemoveKeyValueInUserAccount(_) + | AnyPermissionToken::CanSetKeyValueInAccount(_) + | AnyPermissionToken::CanRemoveKeyValueInAccount(_) | AnyPermissionToken::CanUnregisterUserTrigger(_) | AnyPermissionToken::CanExecuteUserTrigger(_) | AnyPermissionToken::CanBurnUserTrigger(_) @@ -1394,7 +1393,7 @@ pub mod role { } pub mod trigger { - use iroha_smart_contract::data_model::{permission::PermissionToken, trigger::TriggerId}; + use iroha_smart_contract::data_model::{permission::PermissionToken, trigger::Trigger}; use permission::{accounts_permission_tokens, trigger::is_trigger_owner}; use tokens::AnyPermissionToken; @@ -1524,6 +1523,62 @@ pub mod trigger { deny!(executor, "Can't execute trigger owned by another account"); } + pub fn visit_set_trigger_key_value( + executor: &mut V, + authority: &AccountId, + isi: &SetKeyValue, + ) { + let trigger_id = isi.object_id(); + + if is_genesis(executor) { + execute!(executor, isi); + } + match is_trigger_owner(trigger_id, authority) { + Err(err) => deny!(executor, err), + Ok(true) => execute!(executor, isi), + Ok(false) => {} + } + let can_set_key_value_in_user_trigger_token = tokens::trigger::CanSetKeyValueInTrigger { + trigger_id: trigger_id.clone(), + }; + if can_set_key_value_in_user_trigger_token.is_owned_by(authority) { + execute!(executor, isi); + } + + deny!( + executor, + "Can't set value to the metadata of another trigger" + ); + } + + pub fn visit_remove_trigger_key_value( + executor: &mut V, + authority: &AccountId, + isi: &RemoveKeyValue, + ) { + let trigger_id = isi.object_id(); + + if is_genesis(executor) { + execute!(executor, isi); + } + match is_trigger_owner(trigger_id, authority) { + Err(err) => deny!(executor, err), + Ok(true) => execute!(executor, isi), + Ok(false) => {} + } + let can_remove_key_value_in_trigger_token = tokens::trigger::CanRemoveKeyValueInTrigger { + trigger_id: trigger_id.clone(), + }; + if can_remove_key_value_in_trigger_token.is_owned_by(authority) { + execute!(executor, isi); + } + + deny!( + executor, + "Can't remove value from the metadata of another trigger" + ); + } + fn is_token_trigger_associated(permission: &PermissionToken, trigger_id: &TriggerId) -> bool { let Ok(permission) = AnyPermissionToken::try_from(permission) else { return false; @@ -1551,8 +1606,8 @@ pub mod trigger { | AnyPermissionToken::CanMintUserPublicKeys(_) | AnyPermissionToken::CanBurnUserPublicKeys(_) | AnyPermissionToken::CanMintUserSignatureCheckConditions(_) - | AnyPermissionToken::CanSetKeyValueInUserAccount(_) - | AnyPermissionToken::CanRemoveKeyValueInUserAccount(_) + | AnyPermissionToken::CanSetKeyValueInAccount(_) + | AnyPermissionToken::CanRemoveKeyValueInAccount(_) | AnyPermissionToken::CanUnregisterAssetDefinition(_) | AnyPermissionToken::CanSetKeyValueInAssetDefinition(_) | AnyPermissionToken::CanRemoveKeyValueInAssetDefinition(_) diff --git a/smart_contract/executor/src/default/tokens.rs b/smart_contract/executor/src/default/tokens.rs index 92289ffa755..3aaa5baf65f 100644 --- a/smart_contract/executor/src/default/tokens.rs +++ b/smart_contract/executor/src/default/tokens.rs @@ -105,8 +105,8 @@ declare_tokens! { crate::default::tokens::account::{CanMintUserPublicKeys}, crate::default::tokens::account::{CanBurnUserPublicKeys}, crate::default::tokens::account::{CanMintUserSignatureCheckConditions}, - crate::default::tokens::account::{CanSetKeyValueInUserAccount}, - crate::default::tokens::account::{CanRemoveKeyValueInUserAccount}, + crate::default::tokens::account::{CanSetKeyValueInAccount}, + crate::default::tokens::account::{CanRemoveKeyValueInAccount}, crate::default::tokens::asset_definition::{CanUnregisterAssetDefinition}, crate::default::tokens::asset_definition::{CanSetKeyValueInAssetDefinition}, @@ -229,14 +229,14 @@ pub mod account { token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] - pub struct CanSetKeyValueInUserAccount { + pub struct CanSetKeyValueInAccount { pub account_id: AccountId, } } token! { #[derive(ValidateGrantRevoke, permission::derive_conversions::account::Owner)] #[validate(permission::account::Owner)] - pub struct CanRemoveKeyValueInUserAccount { + pub struct CanRemoveKeyValueInAccount { pub account_id: AccountId, } } @@ -507,11 +507,29 @@ pub mod trigger { } } + token! { + #[derive(ValidateGrantRevoke)] + #[validate(permission::trigger::Owner)] + pub struct CanSetKeyValueInTrigger { + pub trigger_id: TriggerId, + } + } + + token! { + #[derive(ValidateGrantRevoke)] + #[validate(permission::trigger::Owner)] + pub struct CanRemoveKeyValueInTrigger { + pub trigger_id: TriggerId, + } + } + impl_froms!( - CanExecuteUserTrigger, CanUnregisterUserTrigger, CanMintUserTrigger, CanBurnUserTrigger, + CanExecuteUserTrigger, + CanSetKeyValueInTrigger, + CanRemoveKeyValueInTrigger, ); } diff --git a/smart_contract/trigger/derive/src/entrypoint.rs b/smart_contract/trigger/derive/src/entrypoint.rs index a054363cdfe..fba9a75df6b 100644 --- a/smart_contract/trigger/derive/src/entrypoint.rs +++ b/smart_contract/trigger/derive/src/entrypoint.rs @@ -47,7 +47,7 @@ pub fn impl_entrypoint(emitter: &mut Emitter, item: syn::ItemFn) -> TokenStream #[doc(hidden)] unsafe extern "C" fn #main_fn_name() { let payload = ::iroha_trigger::get_trigger_payload(); - #fn_name(payload.owner, payload.event) + #fn_name(payload.trigger_id, payload.owner, payload.event) } // NOTE: Host objects are always passed by value to wasm diff --git a/tools/kagami/src/genesis.rs b/tools/kagami/src/genesis.rs index 94c851f0e91..73a1367e998 100644 --- a/tools/kagami/src/genesis.rs +++ b/tools/kagami/src/genesis.rs @@ -143,13 +143,14 @@ pub fn generate_default( Numeric::new(DEFAULT_COMMIT_TIME.as_millis(), 0), )? .add_parameter(TRANSACTION_LIMITS, DEFAULT_TRANSACTION_LIMITS)? - .add_parameter(WSV_ASSET_METADATA_LIMITS, DEFAULT_METADATA_LIMITS)? + .add_parameter(WSV_DOMAIN_METADATA_LIMITS, DEFAULT_METADATA_LIMITS)? .add_parameter( WSV_ASSET_DEFINITION_METADATA_LIMITS, DEFAULT_METADATA_LIMITS, )? .add_parameter(WSV_ACCOUNT_METADATA_LIMITS, DEFAULT_METADATA_LIMITS)? - .add_parameter(WSV_DOMAIN_METADATA_LIMITS, DEFAULT_METADATA_LIMITS)? + .add_parameter(WSV_ASSET_METADATA_LIMITS, DEFAULT_METADATA_LIMITS)? + .add_parameter(WSV_TRIGGER_METADATA_LIMITS, DEFAULT_METADATA_LIMITS)? .add_parameter(WSV_IDENT_LENGTH_LIMITS, DEFAULT_IDENT_LENGTH_LIMITS)? .add_parameter( EXECUTOR_FUEL_LIMIT,