diff --git a/client/src/client.rs b/client/src/client.rs index f39840c22e4..c5ddff65fef 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -334,7 +334,7 @@ impl_query_result! { iroha_data_model::query::MetadataValue, iroha_data_model::query::TransactionQueryOutput, iroha_data_model::permission::PermissionTokenSchema, - iroha_data_model::trigger::Trigger, + iroha_data_model::trigger::Trigger, } /// Iroha client diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index ba59338c9fa..3baf3732653 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -88,8 +88,7 @@ impl Execute for RegisterExpr { } RegistrableBox::Asset(object) => Register:: { object }.execute(authority, wsv), RegistrableBox::Trigger(object) => { - Register::> { object } - .execute(authority, wsv) + Register::> { object }.execute(authority, wsv) } RegistrableBox::Role(object) => Register:: { object }.execute(authority, wsv), } @@ -115,8 +114,7 @@ impl Execute for UnregisterExpr { IdBox::PeerId(object_id) => Unregister:: { object_id }.execute(authority, wsv), IdBox::RoleId(object_id) => Unregister:: { object_id }.execute(authority, wsv), IdBox::TriggerId(object_id) => { - Unregister::> { object_id } - .execute(authority, wsv) + Unregister::> { object_id }.execute(authority, wsv) } IdBox::PermissionTokenId(_) | IdBox::ParameterId(_) => { Err(Error::Evaluate(InstructionType::Unregister.into())) @@ -169,7 +167,7 @@ impl Execute for MintExpr { .execute(authority, wsv) } (IdBox::TriggerId(destination_id), Value::Numeric(NumericValue::U32(object))) => { - Mint::> { + Mint::> { object, destination_id, } diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 33d2610a39c..3f8eb4e10c0 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -52,7 +52,7 @@ impl_lazy! { iroha_data_model::query::MetadataValue, iroha_data_model::query::TransactionQueryOutput, iroha_data_model::permission::PermissionTokenSchema, - iroha_data_model::trigger::Trigger, + iroha_data_model::trigger::Trigger, } /// Query Request statefully validated on the Iroha node side. diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index 6b6e265f99e..fbe31e230e0 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -22,7 +22,7 @@ pub mod isi { use super::{super::prelude::*, *}; - impl Execute for Register> { + impl Execute for Register> { #[metrics(+"register_trigger")] #[allow(clippy::expect_used)] fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { @@ -82,7 +82,7 @@ pub mod isi { } } - impl Execute for Unregister> { + impl Execute for Unregister> { #[metrics(+"unregister_trigger")] fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { let trigger_id = self.object_id.clone(); @@ -101,7 +101,7 @@ pub mod isi { } } - impl Execute for Mint> { + impl Execute for Mint> { #[metrics(+"mint_trigger_repetitions")] fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { let id = self.destination_id; @@ -133,7 +133,7 @@ pub mod isi { } } - impl Execute for Burn> { + impl Execute for Burn> { #[metrics(+"burn_trigger_repetitions")] fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { let trigger = self.destination_id; @@ -203,7 +203,7 @@ pub mod query { }; use super::*; - use crate::{prelude::*, smartcontracts::triggers::set::LoadedExecutable}; + use crate::prelude::*; impl ValidQuery for FindAllActiveTriggerIds { #[metrics(+"find_all_active_triggers")] @@ -217,41 +217,19 @@ pub mod query { impl ValidQuery for FindTriggerById { #[metrics(+"find_trigger_by_id")] - fn execute( - &self, - wsv: &WorldStateView, - ) -> Result, Error> { + fn execute(&self, wsv: &WorldStateView) -> Result, Error> { let id = wsv .evaluate(&self.id) .map_err(|e| Error::Evaluate(format!("Failed to evaluate trigger id. {e}")))?; iroha_logger::trace!(%id); // Can't use just `ActionTrait::clone_and_box` cause this will trigger lifetime mismatch #[allow(clippy::redundant_closure_for_method_calls)] - let Action { - executable: loaded_executable, - repeats, - authority, - filter, - metadata, - } = wsv + let loaded_action = wsv .triggers() .inspect_by_id(&id, |action| action.clone_and_box()) .ok_or_else(|| Error::Find(FindError::Trigger(id.clone())))?; - let original_executable = match loaded_executable { - LoadedExecutable::Wasm(_) => { - let original_wasm = wsv - .triggers() - .get_original_contract(&id) - .cloned() - .expect("No original smartcontract saved for trigger. This is a bug."); - Executable::Wasm(original_wasm) - } - LoadedExecutable::Instructions(isi) => Executable::Instructions(isi), - }; - - let action = Action::new(original_executable, repeats, authority, filter) - .with_metadata(metadata); + let action = wsv.triggers().get_original_action(loaded_action); // TODO: Should we redact the metadata if the account is not the authority/owner? Ok(Trigger::new(id, action)) @@ -286,44 +264,22 @@ pub mod query { fn execute<'wsv>( &self, wsv: &'wsv WorldStateView, - ) -> eyre::Result< - Box> + 'wsv>, - Error, - > { + ) -> eyre::Result> + 'wsv>, Error> + { let domain_id = wsv .evaluate(&self.domain_id) .map_err(|e| Error::Evaluate(format!("Failed to evaluate domain id. {e}")))?; - Ok(Box::new(wsv.triggers().inspect_by_domain_id( - &domain_id, - |trigger_id, action| { - let Action { - executable: loaded_executable, - repeats, - authority, - filter, - metadata, - } = action.clone_and_box(); - - let original_executable = - match loaded_executable { - LoadedExecutable::Wasm(_) => { - let original_wasm = - wsv.triggers().get_original_contract(&trigger_id).cloned().expect( - "No original smartcontract saved for trigger. This is a bug.", - ); - Executable::Wasm(original_wasm) - } - LoadedExecutable::Instructions(isi) => Executable::Instructions(isi), - }; - - Trigger::new( - trigger_id.clone(), - Action::new(original_executable, repeats, authority, filter) - .with_metadata(metadata), - ) - }, - ))) + Ok(Box::new( + wsv.triggers() + .inspect_by_domain_id(&domain_id, |trigger_id, action| { + (trigger_id.clone(), action.clone_and_box()) + }) + .map(|(trigger_id, action)| { + let action = wsv.triggers().get_original_action(action); + Trigger::new(trigger_id, action) + }), + )) } } } diff --git a/core/src/smartcontracts/isi/triggers/set.rs b/core/src/smartcontracts/isi/triggers/set.rs index a87217bc188..6cfcdb70be0 100644 --- a/core/src/smartcontracts/isi/triggers/set.rs +++ b/core/src/smartcontracts/isi/triggers/set.rs @@ -17,7 +17,8 @@ use iroha_data_model::{ isi::error::{InstructionExecutionError, MathError}, prelude::*, query::error::FindError, - trigger::{action::ActionTrait, OptimizedExecutable, Trigger, WasmInternalRepr}, + transaction::WasmSmartContract, + trigger::Trigger, }; use serde::{ de::{DeserializeSeed, MapAccess, Visitor}, @@ -39,7 +40,88 @@ pub enum Error { pub type Result = core::result::Result; /// Type of action with pre-loaded executable. -pub type LoadedAction = Action; +#[derive(Clone, Debug)] +pub struct LoadedAction { + executable: LoadedExecutable, + pub repeats: Repeats, + pub authority: AccountId, + pub filter: F, + pub metadata: Metadata, +} + +pub trait LoadedActionTrait { + /// Get action executable + fn executable(&self) -> &LoadedExecutable; + + /// Get action repeats enum + fn repeats(&self) -> &Repeats; + + /// Set action repeats + fn set_repeats(&mut self, repeats: Repeats); + + /// Get action technical account + fn authority(&self) -> &AccountId; + + /// Get action metadata + fn metadata(&self) -> &Metadata; + + /// Check if action is mintable. + fn mintable(&self) -> bool; + + /// Convert action to a boxed representation + fn into_boxed(self) -> LoadedAction; + + /// Same as [`into_boxed()`](ActionTrait::into_boxed) but clones `self` + fn clone_and_box(&self) -> LoadedAction; +} + +impl<'a, F: Filter + Into + Clone> LoadedActionTrait for LoadedAction { + fn executable(&self) -> &LoadedExecutable { + &self.executable + } + + fn repeats(&self) -> &iroha_data_model::trigger::action::Repeats { + &self.repeats + } + + fn set_repeats(&mut self, repeats: iroha_data_model::trigger::action::Repeats) { + self.repeats = repeats; + } + + fn authority(&self) -> &AccountId { + &self.authority + } + + fn metadata(&self) -> &Metadata { + &self.metadata + } + + fn mintable(&self) -> bool { + self.filter.mintable() + } + + fn into_boxed(self) -> LoadedAction { + let Self { + executable, + repeats, + authority, + filter, + metadata, + } = self; + + LoadedAction { + executable, + repeats, + authority, + filter: filter.into(), + metadata, + } + } + + fn clone_and_box(&self) -> LoadedAction { + self.clone().into_boxed() + } +} /// Specialized structure that maps event filters to Triggers. // NB: `Set` has custom `Serialize` and `DeserializeSeed` implementations @@ -57,7 +139,7 @@ pub struct Set { /// Trigger ids with type of events they process ids: HashMap, /// Original [`WasmSmartContract`]s by [`TriggerId`] for querying purposes. - original_contracts: HashMap, + original_contracts: HashMap, WasmSmartContract>, /// List of actions that should be triggered by events provided by `handle_*` methods. /// Vector is used to save the exact triggers order. matched_ids: Vec<(Event, TriggerId)>, @@ -85,7 +167,7 @@ impl Serialize for TriggersWithContext<'_, F> { { let mut map = serializer.serialize_map(Some(self.triggers.len()))?; for (id, action) in self.triggers.iter() { - let action = self.set.get_original_action(id, action.clone()); + let action = self.set.get_original_action(action.clone()); map.serialize_entry(&id, &action)?; } map.end() @@ -145,7 +227,7 @@ impl<'de> DeserializeSeed<'de> for WasmSeed<'_, Set> { while let Some(key) = map.next_key::()? { match key.as_str() { "data_triggers" => { - let triggers: HashMap> = + let triggers: HashMap> = map.next_value()?; for (id, action) in triggers { set.add_data_trigger(self.loader.engine, Trigger::new(id, action)) @@ -153,10 +235,8 @@ impl<'de> DeserializeSeed<'de> for WasmSeed<'_, Set> { } } "pipeline_triggers" => { - let triggers: HashMap< - TriggerId, - Action, - > = map.next_value()?; + let triggers: HashMap> = + map.next_value()?; for (id, action) in triggers { set.add_pipeline_trigger( self.loader.engine, @@ -166,7 +246,7 @@ impl<'de> DeserializeSeed<'de> for WasmSeed<'_, Set> { } } "time_triggers" => { - let triggers: HashMap> = + let triggers: HashMap> = map.next_value()?; for (id, action) in triggers { set.add_time_trigger(self.loader.engine, Trigger::new(id, action)) @@ -174,10 +254,8 @@ impl<'de> DeserializeSeed<'de> for WasmSeed<'_, Set> { } } "by_call_triggers" => { - let triggers: HashMap< - TriggerId, - Action, - > = map.next_value()?; + let triggers: HashMap> = + map.next_value()?; for (id, action) in triggers { set.add_by_call_trigger( self.loader.engine, @@ -227,7 +305,7 @@ impl Set { pub fn add_data_trigger( &mut self, engine: &wasmtime::Engine, - trigger: Trigger, + trigger: Trigger, ) -> Result { self.add_to(engine, trigger, TriggeringEventType::Data, |me| { &mut me.data_triggers @@ -245,7 +323,7 @@ impl Set { pub fn add_pipeline_trigger( &mut self, engine: &wasmtime::Engine, - trigger: Trigger, + trigger: Trigger, ) -> Result { self.add_to(engine, trigger, TriggeringEventType::Pipeline, |me| { &mut me.pipeline_triggers @@ -263,7 +341,7 @@ impl Set { pub fn add_time_trigger( &mut self, engine: &wasmtime::Engine, - trigger: Trigger, + trigger: Trigger, ) -> Result { self.add_to(engine, trigger, TriggeringEventType::Time, |me| { &mut me.time_triggers @@ -281,7 +359,7 @@ impl Set { pub fn add_by_call_trigger( &mut self, engine: &wasmtime::Engine, - trigger: Trigger, + trigger: Trigger, ) -> Result { self.add_to(engine, trigger, TriggeringEventType::ExecuteTrigger, |me| { &mut me.by_call_triggers @@ -298,7 +376,7 @@ impl Set { fn add_to( &mut self, engine: &wasmtime::Engine, - trigger: Trigger, + trigger: Trigger, event_type: TriggeringEventType, map: impl FnOnce(&mut Self) -> &mut HashMap>, ) -> Result { @@ -317,12 +395,13 @@ impl Set { let loaded_executable = match executable { Executable::Wasm(bytes) => { + let hash = HashOf::new(&bytes); let loaded = LoadedExecutable::Wasm(LoadedWasm { module: wasm::load_module(engine, &bytes)?, - blob_hash: HashOf::new(&bytes), + blob_hash: hash, }); // Store original executable representation to respond to queries with. - self.original_contracts.insert(trigger_id.clone(), bytes); + self.original_contracts.insert(hash, bytes); loaded } Executable::Instructions(instructions) => LoadedExecutable::Instructions(instructions), @@ -345,16 +424,15 @@ impl Set { /// Returns `None` if there's no [`Trigger`] /// with specified `id` that has WASM executable #[inline] - pub fn get_original_contract(&self, id: &TriggerId) -> Option<&WasmSmartContract> { - self.original_contracts.get(id) + pub fn get_original_contract( + &self, + hash: &HashOf, + ) -> Option<&WasmSmartContract> { + self.original_contracts.get(hash) } - fn get_original_action( - &self, - id: &TriggerId, - action: LoadedAction, - ) -> Action { - let Action { + pub fn get_original_action(&self, action: LoadedAction) -> Action { + let LoadedAction { executable, repeats, authority, @@ -363,9 +441,9 @@ impl Set { } = action; let original_executable = match executable { - LoadedExecutable::Wasm(_) => { + LoadedExecutable::Wasm(LoadedWasm { ref blob_hash, .. }) => { let original_wasm = self - .get_original_contract(id) + .get_original_contract(blob_hash) .cloned() .expect("No original smartcontract saved for trigger. This is a bug."); Executable::Wasm(original_wasm) @@ -388,6 +466,41 @@ impl Set { self.ids.keys() } + pub fn get_executable(&self, id: &TriggerId) -> Option<&LoadedExecutable> { + let event_type = self.ids.get(id)?; + + Some(match event_type { + TriggeringEventType::Data => { + &self + .data_triggers + .get(id) + .expect("`Set::data_triggers` doesn't contain required id. This is a bug") + .executable + } + TriggeringEventType::Pipeline => { + &self + .pipeline_triggers + .get(id) + .expect("`Set::pipeline_triggers` doesn't contain required id. This is a bug") + .executable + } + TriggeringEventType::Time => { + &self + .time_triggers + .get(id) + .expect("`Set::time_triggers` doesn't contain required id. This is a bug") + .executable + } + TriggeringEventType::ExecuteTrigger => { + &self + .by_call_triggers + .get(id) + .expect("`Set::by_call_triggers` doesn't contain required id. This is a bug") + .executable + } + }) + } + /// Apply `f` to triggers that belong to the given [`DomainId`] /// /// Return an empty list if [`Set`] doesn't contain any triggers belonging to [`DomainId`]. @@ -397,7 +510,7 @@ impl Set { f: F, ) -> impl Iterator + '_ where - F: Fn(&TriggerId, &dyn ActionTrait) -> R, + F: Fn(&TriggerId, &dyn LoadedActionTrait) -> R, { let domain_id = domain_id.clone(); @@ -440,7 +553,7 @@ impl Set { /// Return [`None`] if [`Set`] doesn't contain the trigger with the given `id`. pub fn inspect_by_id(&self, id: &TriggerId, f: F) -> Option where - F: Fn(&dyn ActionTrait) -> R, + F: Fn(&dyn LoadedActionTrait) -> R, { let event_type = self.ids.get(id).copied()?; @@ -474,7 +587,7 @@ impl Set { /// Return [`None`] if [`Set`] doesn't contain the trigger with the given `id`. pub fn inspect_by_id_mut(&mut self, id: &TriggerId, f: F) -> Option where - F: Fn(&mut dyn ActionTrait) -> R, + F: Fn(&mut dyn LoadedActionTrait) -> R, { let event_type = self.ids.get(id).copied()?; @@ -507,32 +620,50 @@ impl Set { /// /// Return `false` if [`Set`] doesn't contain the trigger with the given `id`. pub fn remove(&mut self, id: &TriggerId) -> bool { - self.original_contracts.remove(id); - self.ids - .remove(id) - .map(|event_type| match event_type { + if let Some(event_type) = self.ids.remove(id) { + let blob_hash = match event_type { TriggeringEventType::Data => self .data_triggers .remove(id) - .map(|_| ()) + .map(|trigger| match trigger.executable { + LoadedExecutable::Wasm(LoadedWasm { blob_hash, .. }) => Some(blob_hash), + _ => None, + }) .expect("`Set::data_triggers` doesn't contain required id. This is a bug"), - TriggeringEventType::Pipeline => { - self.pipeline_triggers.remove(id).map(|_| ()).expect( - "`Set::pipeline_triggers` doesn't contain required id. This is a bug", - ) - } + TriggeringEventType::Pipeline => self + .pipeline_triggers + .remove(id) + .map(|trigger| match trigger.executable { + LoadedExecutable::Wasm(LoadedWasm { blob_hash, .. }) => Some(blob_hash), + _ => None, + }) + .expect("`Set::pipeline_triggers` doesn't contain required id. This is a bug"), TriggeringEventType::Time => self .time_triggers .remove(id) - .map(|_| ()) + .map(|trigger| match trigger.executable { + LoadedExecutable::Wasm(LoadedWasm { blob_hash, .. }) => Some(blob_hash), + _ => None, + }) .expect("`Set::time_triggers` doesn't contain required id. This is a bug"), - TriggeringEventType::ExecuteTrigger => { - self.by_call_triggers.remove(id).map(|_| ()).expect( - "`Set::by_call_triggers` doesn't contain required id. This is a bug", - ) - } - }) - .is_some() + TriggeringEventType::ExecuteTrigger => self + .by_call_triggers + .remove(id) + .map(|trigger| match trigger.executable { + LoadedExecutable::Wasm(LoadedWasm { blob_hash, .. }) => Some(blob_hash), + _ => None, + }) + .expect("`Set::by_call_triggers` doesn't contain required id. This is a bug"), + }; + + if let Some(blob_hash) = blob_hash { + self.original_contracts.remove(&blob_hash).expect( + "`Set::original_contracts` doesn't contain required hash. This is a bug", + ); + } + } + + false } /// Check if [`Set`] contains `id`. @@ -735,24 +866,6 @@ impl core::fmt::Debug for LoadedExecutable { } } -impl From for OptimizedExecutable { - fn from(executable: LoadedExecutable) -> Self { - match executable { - LoadedExecutable::Wasm(LoadedWasm { module, blob_hash }) => { - OptimizedExecutable::WasmInternalRepr(WasmInternalRepr { - serialized: module - .serialize() - .expect("Serialization of optimized wasm module should always succeed"), - blob_hash, - }) - } - LoadedExecutable::Instructions(instructions) => { - OptimizedExecutable::Instructions(instructions) - } - } - } -} - /// [`Set::mod_repeats()`] error #[derive(Debug, Clone, thiserror::Error, displaydoc::Display)] pub enum ModRepeatsError { diff --git a/core/src/wsv.rs b/core/src/wsv.rs index 7a5c9073de3..ee6010866e8 100644 --- a/core/src/wsv.rs +++ b/core/src/wsv.rs @@ -31,7 +31,6 @@ use iroha_data_model::{ permission::PermissionTokenSchema, prelude::*, query::error::{FindError, QueryExecutionFail}, - trigger::action::ActionTrait, }; use iroha_logger::prelude::*; use iroha_primitives::small::SmallVec; @@ -48,7 +47,7 @@ use crate::{ smartcontracts::{ triggers::{ self, - set::{LoadedExecutable, LoadedWasm, Set as TriggerSet}, + set::{LoadedActionTrait, LoadedWasm, Set as TriggerSet}, }, wasm, Execute, }, @@ -518,7 +517,7 @@ impl WorldStateView { fn process_trigger( &mut self, id: &TriggerId, - action: &dyn ActionTrait, + action: &dyn LoadedActionTrait, event: Event, ) -> Result<()> { use triggers::set::LoadedExecutable::*; diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index c6dfe09c0fe..457e8fd2092 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -472,7 +472,7 @@ mod trigger { use super::*; data_event! { - #[has_origin(origin = Trigger)] + #[has_origin(origin = Trigger)] pub enum TriggerEvent { Created(TriggerId), Deleted(TriggerId), diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index 90bac808f97..ac3fd3acb43 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -639,7 +639,7 @@ pub mod model { Asset(::With), /// [`Trigger`](`trigger::Trigger`) variant. #[display(fmt = "Trigger {_0}")] - Trigger( as Registered>::With), + Trigger( as Registered>::With), /// [`Role`](`role::Role`) variant. #[display(fmt = "Role {_0}")] Role(::With), @@ -681,40 +681,14 @@ pub mod model { AssetDefinition(asset::AssetDefinition), /// [`Asset`](`asset::Asset`) variant. Asset(asset::Asset), - /// [`TriggerBox`] variant. - Trigger(TriggerBox), + /// [`Trigger`](`trigger::Trigger`) variant. + Trigger(trigger::Trigger), /// [`Role`](`role::Role`) variant. Role(role::Role), /// [`Parameter`](`parameter::Parameter`) variant. Parameter(parameter::Parameter), } - /// Sized container for triggers with different executables. - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - FromVariant, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type] - pub enum TriggerBox { - /// Un-optimized [`Trigger`](`trigger::Trigger`) submitted from client to Iroha. - #[display(fmt = "{_0}")] - Raw(trigger::Trigger), - /// Optimized [`Trigger`](`trigger::Trigger`) returned from Iroha to client. - #[display(fmt = "{_0} (optimised)")] - Optimized(trigger::Trigger), - } - /// Sized container for all possible upgradable entities. #[derive( Debug, @@ -993,17 +967,6 @@ pub mod model { } } -impl Identifiable for TriggerBox { - type Id = trigger::TriggerId; - - fn id(&self) -> &Self::Id { - match self { - TriggerBox::Raw(trigger) => trigger.id(), - TriggerBox::Optimized(trigger) => trigger.id(), - } - } -} - // TODO: think of a way to `impl Identifiable for IdentifiableBox`. // The main problem is lifetimes and conversion cost. @@ -1322,7 +1285,7 @@ from_and_try_from_value_identifiable!( Account(account::Account), AssetDefinition(asset::AssetDefinition), Asset(asset::Asset), - Trigger(TriggerBox), + Trigger(trigger::Trigger), Role(role::Role), Parameter(parameter::Parameter), ); @@ -1375,13 +1338,10 @@ impl TryFrom for RegistrableBox { } NewRole(role) => Ok(RegistrableBox::Role(role)), Asset(asset) => Ok(RegistrableBox::Asset(asset)), - Trigger(TriggerBox::Raw(trigger)) => Ok(RegistrableBox::Trigger(trigger)), - Domain(_) - | Account(_) - | AssetDefinition(_) - | Role(_) - | Parameter(_) - | Trigger(TriggerBox::Optimized(_)) => Err(Self::Error::default()), + Trigger(trigger) => Ok(RegistrableBox::Trigger(trigger)), + Domain(_) | Account(_) | AssetDefinition(_) | Role(_) | Parameter(_) => { + Err(Self::Error::default()) + } } } } @@ -1399,7 +1359,7 @@ impl From for IdentifiableBox { } Role(role) => IdentifiableBox::NewRole(role), Asset(asset) => IdentifiableBox::Asset(asset), - Trigger(trigger) => IdentifiableBox::Trigger(TriggerBox::Raw(trigger)), + Trigger(trigger) => IdentifiableBox::Trigger(trigger), } } } @@ -1469,42 +1429,23 @@ impl TryFrom for Value { } } -impl From> for Value { - fn from(trigger: trigger::Trigger) -> Self { - Value::Identifiable(IdentifiableBox::Trigger(TriggerBox::Raw(trigger))) - } -} - -impl From> for Value { - fn from(trigger: trigger::Trigger) -> Self { - Value::Identifiable(IdentifiableBox::Trigger(TriggerBox::Optimized(trigger))) - } -} - -impl TryFrom for trigger::Trigger { - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Identifiable(IdentifiableBox::Trigger(TriggerBox::Raw(trigger))) = value { - return Ok(trigger); - } - - Err(Self::Error::default()) - } -} - -impl TryFrom for trigger::Trigger { - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Identifiable(IdentifiableBox::Trigger(TriggerBox::Optimized(trigger))) = value - { - return Ok(trigger); - } - - Err(Self::Error::default()) - } -} +// impl From> for Value { +// fn from(trigger: trigger::Trigger) -> Self { +// Value::Identifiable(IdentifiableBox::Trigger(trigger)) +// } +// } +// +// impl TryFrom for trigger::Trigger { +// type Error = ErrorTryFromEnum; +// +// fn try_from(value: Value) -> Result { +// if let Value::Identifiable(IdentifiableBox::Trigger(trigger)) = value { +// return Ok(trigger); +// } +// +// Err(Self::Error::default()) +// } +// } impl TryFrom for UpgradableBox { type Error = ErrorTryFromEnum; @@ -1949,7 +1890,7 @@ pub mod prelude { name::prelude::*, parameter::prelude::*, peer::prelude::*, permission::prelude::*, query::prelude::*, role::prelude::*, transaction::prelude::*, trigger::prelude::*, validator::prelude::*, EnumTryAsError, HasMetadata, IdBox, Identifiable, IdentifiableBox, - LengthLimits, NumericValue, PredicateTrait, RegistrableBox, ToValue, TriggerBox, TryAsMut, - TryAsRef, TryToValue, UpgradableBox, ValidationFail, Value, + LengthLimits, NumericValue, PredicateTrait, RegistrableBox, ToValue, TryAsMut, TryAsRef, + TryToValue, UpgradableBox, ValidationFail, Value, }; } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index 622010988bd..44e4025606a 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -1053,7 +1053,7 @@ pub mod trigger { } impl Query for FindTriggerById { - type Output = Trigger; + type Output = Trigger; } impl Query for FindTriggerKeyValueByIdAndKey { @@ -1061,7 +1061,7 @@ pub mod trigger { } impl Query for FindTriggersByDomainId { - type Output = Vec>; + type Output = Vec>; } impl FindTriggerById { diff --git a/data_model/src/trigger.rs b/data_model/src/trigger.rs index 48d6e5a7ed9..93e839e9370 100644 --- a/data_model/src/trigger.rs +++ b/data_model/src/trigger.rs @@ -7,7 +7,7 @@ use core::{cmp, str::FromStr}; use derive_more::{Constructor, Display}; use getset::Getters; use iroha_data_model_derive::{model, IdEqOrdHash}; -use iroha_macro::{ffi_impl_opaque, FromVariant}; +use iroha_macro::ffi_impl_opaque; use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; @@ -15,8 +15,8 @@ use serde_with::{DeserializeFromStr, SerializeDisplay}; pub use self::model::*; use crate::{ - domain::DomainId, events::prelude::*, metadata::Metadata, prelude::InstructionExpr, - transaction::Executable, Identifiable, Name, ParseError, Registered, + domain::DomainId, events::prelude::*, metadata::Metadata, transaction::Executable, + Identifiable, Name, ParseError, Registered, }; #[model] @@ -64,62 +64,38 @@ pub mod model { )] #[display(fmt = "@@{id}")] #[ffi_type] - pub struct Trigger { + pub struct Trigger { /// [`Id`] of the [`Trigger`]. pub id: TriggerId, /// Action to be performed when the trigger matches. - pub action: action::Action, - } - - /// Internal representation of Wasm blob provided by preloading it with `wasmtime` crate. - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] - pub struct WasmInternalRepr { - /// Serialized with `wasmtime::Module::serialize` - pub serialized: Vec, - /// Hash of original WASM blob on blockchain - pub blob_hash: iroha_crypto::HashOf, - } - - /// Same as [`Executable`] but instead of [`Wasm`](Executable::Wasm) contains - /// [`WasmInternalRepr`] with serialized optimized representation - /// from `wasmtime` library. - #[derive( - Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, - )] - // TODO: Made opaque temporarily - #[ffi_type(opaque)] - pub enum OptimizedExecutable { - /// WASM serialized with `wasmtime`. - WasmInternalRepr(WasmInternalRepr), - /// Vector of [`instructions`](InstructionExpr). - Instructions(Vec), + pub action: action::Action, } } #[ffi_impl_opaque] -impl Trigger { +impl Trigger { /// [`Id`] of the [`Trigger`]. pub fn id(&self) -> &TriggerId { &self.id } /// Action to be performed when the trigger matches. - pub fn action(&self) -> &action::Action { + pub fn action(&self) -> &action::Action { &self.action } } -impl Registered for Trigger { +impl Registered for Trigger { type With = Self; } macro_rules! impl_try_from_box { ($($variant:ident => $filter_type:ty),+ $(,)?) => { $( - impl TryFrom> for Trigger<$filter_type, E> { + impl TryFrom> for Trigger<$filter_type> { type Error = &'static str; - fn try_from(boxed: Trigger) -> Result { + fn try_from(boxed: Trigger) -> Result { if let TriggeringFilterBox::$variant(concrete_filter) = boxed.action.filter { let action = action::Action::new( boxed.action.executable, @@ -210,9 +186,9 @@ pub mod action { Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema, )] #[ffi_type] - pub struct Action { + pub struct Action { /// The executable linked to this action - pub executable: E, + pub executable: Executable, /// The repeating scheme of the action. It's kept as part of the /// action and not inside the [`Trigger`] type, so that further /// sanity checking can be done. @@ -239,16 +215,16 @@ pub mod action { } #[cfg(feature = "transparent_api")] - impl crate::HasMetadata for Action { + impl crate::HasMetadata for Action { fn metadata(&self) -> &crate::metadata::Metadata { &self.metadata } } #[ffi_impl_opaque] - impl Action { + impl Action { /// The executable linked to this action - pub fn executable(&self) -> &OptimizedExecutable { + pub fn executable(&self) -> &Executable { &self.executable } /// The repeating scheme of the action. It's kept as part of the @@ -267,10 +243,10 @@ pub mod action { } } - impl Action { + impl Action { /// Construct an action given `executable`, `repeats`, `authority` and `filter`. pub fn new( - executable: impl Into, + executable: impl Into, repeats: impl Into, authority: AccountId, filter: F, @@ -293,7 +269,7 @@ pub mod action { } } - impl PartialOrd for Action { + impl PartialOrd for Action { fn partial_cmp(&self, other: &Self) -> Option { // Exclude the executable. When debugging and replacing // the trigger, its position in Hash and Tree maps should @@ -307,7 +283,7 @@ pub mod action { } #[allow(clippy::expect_used)] - impl Ord for Action { + impl Ord for Action { fn cmp(&self, other: &Self) -> cmp::Ordering { self.partial_cmp(other) .expect("`PartialCmp::partial_cmp()` for `Action` should never return `None`") @@ -317,11 +293,8 @@ pub mod action { /// Trait for common methods for all [`Action`]'s #[cfg(feature = "transparent_api")] pub trait ActionTrait { - /// Type of action executable - type Executable; - /// Get action executable - fn executable(&self) -> &Self::Executable; + fn executable(&self) -> &Executable; /// Get action repeats enum fn repeats(&self) -> &Repeats; @@ -339,17 +312,15 @@ pub mod action { fn mintable(&self) -> bool; /// Convert action to a boxed representation - fn into_boxed(self) -> Action; + fn into_boxed(self) -> Action; /// Same as [`into_boxed()`](ActionTrait::into_boxed) but clones `self` - fn clone_and_box(&self) -> Action; + fn clone_and_box(&self) -> Action; } #[cfg(feature = "transparent_api")] - impl + Clone, E: Clone> ActionTrait for Action { - type Executable = E; - - fn executable(&self) -> &Self::Executable { + impl + Clone> ActionTrait for Action { + fn executable(&self) -> &Executable { &self.executable } @@ -373,8 +344,8 @@ pub mod action { self.filter.mintable() } - fn into_boxed(self) -> Action { - Action:: { + fn into_boxed(self) -> Action { + Action:: { executable: self.executable, repeats: self.repeats, authority: self.authority, @@ -383,8 +354,8 @@ pub mod action { } } - fn clone_and_box(&self) -> Action { - Action:: { + fn clone_and_box(&self) -> Action { + Action:: { executable: self.executable.clone(), repeats: self.repeats.clone(), authority: self.authority.clone(), @@ -439,23 +410,17 @@ mod tests { fn trigger_with_filterbox_can_be_unboxed() { /// Should fail to compile if a new variant will be added to `TriggeringFilterBox` #[allow(dead_code, clippy::unwrap_used)] - fn compile_time_check(boxed: Trigger) { + fn compile_time_check(boxed: Trigger) { match &boxed.action.filter { - TriggeringFilterBox::Data(_) => { - Trigger::::try_from(boxed) - .map(|_| ()) - .unwrap() - } - TriggeringFilterBox::Pipeline(_) => { - Trigger::::try_from(boxed) - .map(|_| ()) - .unwrap() - } - TriggeringFilterBox::Time(_) => { - Trigger::::try_from(boxed) - .map(|_| ()) - .unwrap() - } + TriggeringFilterBox::Data(_) => Trigger::::try_from(boxed) + .map(|_| ()) + .unwrap(), + TriggeringFilterBox::Pipeline(_) => Trigger::::try_from(boxed) + .map(|_| ()) + .unwrap(), + TriggeringFilterBox::Time(_) => Trigger::::try_from(boxed) + .map(|_| ()) + .unwrap(), TriggeringFilterBox::ExecuteTrigger(_) => { Trigger::::try_from(boxed) .map(|_| ()) diff --git a/data_model/src/visit.rs b/data_model/src/visit.rs index 7ef7be8a2b0..174b013c2be 100644 --- a/data_model/src/visit.rs +++ b/data_model/src/visit.rs @@ -115,7 +115,7 @@ pub trait Visit: ExpressionEvaluator { visit_register_asset_definition(Register), visit_register_asset(Register), visit_register_role(Register), - visit_register_trigger(Register>), + visit_register_trigger(Register>), // Visit UnregisterExpr visit_unregister_peer(Unregister), @@ -125,13 +125,13 @@ pub trait Visit: ExpressionEvaluator { visit_unregister_asset(Unregister), // TODO: Need to allow role creator to unregister it somehow visit_unregister_role(Unregister), - visit_unregister_trigger(Unregister>), + visit_unregister_trigger(Unregister>), // Visit MintExpr visit_mint_asset(Mint), visit_mint_account_public_key(Mint), visit_mint_account_signature_check_condition(Mint), - visit_mint_trigger_repetitions(Mint>), + visit_mint_trigger_repetitions(Mint>), // Visit BurnExpr visit_burn_account_public_key(Burn), @@ -698,9 +698,9 @@ leaf_visitors! { visit_unregister_role(Unregister), visit_grant_account_role(Grant), visit_revoke_account_role(Revoke), - visit_register_trigger(Register>), - visit_unregister_trigger(Unregister>), - visit_mint_trigger_repetitions(Mint>), + visit_register_trigger(Register>), + visit_unregister_trigger(Unregister>), + visit_mint_trigger_repetitions(Mint>), visit_upgrade_validator(Upgrade), visit_new_parameter(NewParameter), visit_set_parameter(SetParameter), diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index b149209bcd6..92fe72ebb24 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -179,7 +179,7 @@ } ] }, - "Action": { + "Action": { "Struct": [ { "name": "executable", @@ -203,30 +203,6 @@ } ] }, - "Action": { - "Struct": [ - { - "name": "executable", - "type": "OptimizedExecutable" - }, - { - "name": "repeats", - "type": "Repeats" - }, - { - "name": "authority", - "type": "AccountId" - }, - { - "name": "filter", - "type": "TriggeringFilterBox" - }, - { - "name": "metadata", - "type": "Metadata" - } - ] - }, "Add": { "Struct": [ { @@ -2167,7 +2143,6 @@ "HashOf>": "Hash", "HashOf": "Hash", "HashOf": "Hash", - "HashOf": "Hash", "HashValue": { "Enum": [ { @@ -2281,7 +2256,7 @@ { "tag": "Trigger", "discriminant": 9, - "type": "TriggerBox" + "type": "Trigger" }, { "tag": "Role", @@ -3073,20 +3048,6 @@ } ] }, - "OptimizedExecutable": { - "Enum": [ - { - "tag": "WasmInternalRepr", - "discriminant": 0, - "type": "WasmInternalRepr" - }, - { - "tag": "Instructions", - "discriminant": 1, - "type": "Vec" - } - ] - }, "Option": { "Option": "DomainId" }, @@ -3706,7 +3667,7 @@ { "tag": "Trigger", "discriminant": 5, - "type": "Trigger" + "type": "Trigger" }, { "tag": "Role", @@ -4337,7 +4298,7 @@ } ] }, - "Trigger": { + "Trigger": { "Struct": [ { "name": "id", @@ -4345,33 +4306,7 @@ }, { "name": "action", - "type": "Action" - } - ] - }, - "Trigger": { - "Struct": [ - { - "name": "id", - "type": "TriggerId" - }, - { - "name": "action", - "type": "Action" - } - ] - }, - "TriggerBox": { - "Enum": [ - { - "tag": "Raw", - "discriminant": 0, - "type": "Trigger" - }, - { - "tag": "Optimized", - "discriminant": 1, - "type": "Trigger" + "type": "Action" } ] }, @@ -4845,18 +4780,6 @@ } ] }, - "WasmInternalRepr": { - "Struct": [ - { - "name": "serialized", - "type": "Vec" - }, - { - "name": "blob_hash", - "type": "HashOf" - } - ] - }, "WasmSmartContract": "Vec", "Where": { "Struct": [ diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index c6f384f62a9..31cfece62c6 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -70,7 +70,7 @@ types!( AccountId, AccountPermissionChanged, AccountRoleChanged, - Action, + Action, Add, Algorithm, And, @@ -354,7 +354,7 @@ types!( TransactionRejectionReason, TransactionValue, TransferExpr, - Trigger, + Trigger, TriggerCompletedEventFilter, TriggerCompletedOutcomeType, TriggerEvent, diff --git a/tools/parity_scale_decoder/build.rs b/tools/parity_scale_decoder/build.rs index 5d63316f7a7..cbe491c10df 100644 --- a/tools/parity_scale_decoder/build.rs +++ b/tools/parity_scale_decoder/build.rs @@ -13,7 +13,7 @@ fn main() { sample_into_binary_file::("domain").expect("Failed to encode into domain.bin."); - sample_into_binary_file::>("trigger") + sample_into_binary_file::>("trigger") .expect("Failed to encode into trigger.bin."); } diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index 282634430f8..aa74b4df526 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -269,7 +269,7 @@ mod tests { ); let rose_id = AssetId::new(rose_definition_id, account_id.clone()); let trigger_id = "mint_rose".parse().expect("Valid"); - let action = Action::::new( + let action = Action::::new( vec![MintExpr::new(1_u32, rose_id)], Repeats::Indefinitely, account_id, diff --git a/wasm/validator/src/default.rs b/wasm/validator/src/default.rs index 2ad6a85a32b..9ca88c9b98f 100644 --- a/wasm/validator/src/default.rs +++ b/wasm/validator/src/default.rs @@ -1446,7 +1446,7 @@ pub mod trigger { pub fn visit_unregister_trigger( validator: &mut V, authority: &AccountId, - isi: Unregister>, + isi: Unregister>, ) { let trigger_id = isi.object_id; @@ -1472,7 +1472,7 @@ pub mod trigger { pub fn visit_mint_trigger_repetitions( validator: &mut V, authority: &AccountId, - isi: Mint>, + isi: Mint>, ) { let trigger_id = isi.destination_id;