diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index d3aa2a96834..9f914bb5bb3 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -181,46 +181,46 @@ fn produce_multiple_events() -> Result<()> { } let expected_domain_events: Vec = [ - WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account_id: bob_id.clone(), permission_id: token_1.definition_id.clone(), }, ))), - WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account_id: bob_id.clone(), permission_id: token_2.definition_id.clone(), }, ))), - WorldEvent::Domain(DomainEvent::Account(AccountEvent::RoleGranted( + DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleGranted( AccountRoleChanged { account_id: bob_id.clone(), role_id: role_id.clone(), }, ))), - WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account_id: bob_id.clone(), permission_id: token_1.definition_id, }, ))), - WorldEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( + DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account_id: bob_id.clone(), permission_id: token_2.definition_id, }, ))), - WorldEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoked( + DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoked( AccountRoleChanged { account_id: bob_id, role_id: role_id.clone(), }, ))), - WorldEvent::Role(RoleEvent::Deleted(role_id)), + DataEvent::Role(RoleEvent::Deleted(role_id)), ] .into_iter() - .flat_map(WorldEvent::flatten) + .map(Into::into) .collect(); for expected_event in expected_domain_events { diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index e7096f7b024..2c197c9da18 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -20,8 +20,15 @@ fn must_execute_both_triggers() -> Result<()> { [instruction.clone()], Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(BySome( - AccountFilter::new(AcceptAll, BySome(AccountEventFilter::ByCreated)), + // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByDomain(BySome( + DomainFilter::new( + AcceptAll, + BySome(DomainEventFilter::ByAccount(BySome(AccountFilter::new( + AcceptAll, + BySome(AccountEventFilter::ByCreated), + )))), + ), )))), ), )); @@ -86,8 +93,15 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu [Mint::asset_quantity(1_u32, asset_id.clone())], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(BySome( - AccountFilter::new(AcceptAll, BySome(AccountEventFilter::ByCreated)), + // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByDomain(BySome( + DomainFilter::new( + AcceptAll, + BySome(DomainEventFilter::ByAccount(BySome(AccountFilter::new( + AcceptAll, + BySome(AccountEventFilter::ByCreated), + )))), + ), )))), ), )); diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index 8269a244ad4..bc340775aff 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -24,10 +24,16 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { vec![instruction], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAssetDefinition(BySome( - AssetDefinitionFilter::new( + // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByDomain(BySome( + DomainFilter::new( AcceptAll, - BySome(AssetDefinitionEventFilter::ByCreated), + BySome(DomainEventFilter::ByAssetDefinition(BySome( + AssetDefinitionFilter::new( + AcceptAll, + BySome(AssetDefinitionEventFilter::ByCreated), + ), + ))), ), )))), ), diff --git a/configs/peer/executor.wasm b/configs/peer/executor.wasm index 48c0f25b41c..7af36698d6c 100644 Binary files a/configs/peer/executor.wasm and b/configs/peer/executor.wasm differ diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index 81855321e7c..2912b511b09 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -179,7 +179,7 @@ pub mod isi { domain.remove_asset_total_quantity(&asset_definition_id); - events.push(WorldEvent::from(DomainEvent::AssetDefinition( + events.push(DataEvent::from(DomainEvent::AssetDefinition( AssetDefinitionEvent::Deleted(asset_definition_id), ))); diff --git a/core/src/wsv.rs b/core/src/wsv.rs index 0e653e6c488..2bbf58ff7ca 100644 --- a/core/src/wsv.rs +++ b/core/src/wsv.rs @@ -1252,7 +1252,7 @@ impl WorldStateView { /// The function puts events produced by iterator into `events_buffer`. /// Events should be produced in the order of expanding scope: from specific to general. /// Example: account events before domain events. - pub fn emit_events, T: Into>(&mut self, world_events: I) { + pub fn emit_events, T: Into>(&mut self, world_events: I) { Self::emit_events_impl( &mut self.world.triggers, &mut self.events_buffer, @@ -1263,7 +1263,7 @@ impl WorldStateView { /// Implementation of [`Self::emit_events()`]. /// /// Usable when you can't call [`Self::emit_events()`] due to mutable reference to self. - fn emit_events_impl, T: Into>( + fn emit_events_impl, T: Into>( triggers: &mut TriggerSet, events_buffer: &mut Vec, world_events: I, @@ -1271,7 +1271,7 @@ impl WorldStateView { let data_events: SmallVec<[DataEvent; 3]> = world_events .into_iter() .map(Into::into) - .flat_map(WorldEvent::flatten) + .map(Into::into) .collect(); for event in data_events.iter() { @@ -1285,7 +1285,7 @@ impl WorldStateView { /// Produces [`PermissionTokenSchemaUpdateEvent`]. pub fn set_permission_token_schema(&mut self, schema: PermissionTokenSchema) { let old_schema = std::mem::replace(&mut self.world.permission_token_schema, schema.clone()); - self.emit_events(std::iter::once(WorldEvent::PermissionTokenSchemaUpdate( + self.emit_events(std::iter::once(DataEvent::PermissionToken( PermissionTokenSchemaUpdateEvent { old_schema, new_schema: schema, diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 90f1caf2cf8..c08b9e504c0 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -3,7 +3,6 @@ use getset::Getters; use iroha_data_model_derive::{model, Filter, HasOrigin}; -use iroha_primitives::small::SmallVec; pub use self::model::*; use super::*; @@ -61,22 +60,6 @@ pub mod model { pub value: Box, } - /// World event - /// - /// Does not participate in `Event`, but useful for events warranties when modifying `wsv` - #[derive( - Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, - )] - pub enum WorldEvent { - Peer(peer::PeerEvent), - Domain(domain::DomainEvent), - Role(role::RoleEvent), - Trigger(trigger::TriggerEvent), - PermissionTokenSchemaUpdate(permission::PermissionTokenSchemaUpdateEvent), - Configuration(config::ConfigurationEvent), - Executor(executor::ExecutorEvent), - } - /// Event #[derive( Debug, @@ -98,12 +81,6 @@ pub mod model { Peer(peer::PeerEvent), /// Domain event Domain(domain::DomainEvent), - /// Account event - Account(account::AccountEvent), - /// Asset definition event - AssetDefinition(asset::AssetDefinitionEvent), - /// Asset event - Asset(asset::AssetEvent), /// Trigger event Trigger(trigger::TriggerEvent), /// Role event @@ -629,65 +606,19 @@ pub trait HasOrigin { fn origin_id(&self) -> &::Id; } -impl WorldEvent { - /// Unfold [`Self`] and return vector of [`Event`]s in the expanding scope order: from specific to general. - /// E.g [`AssetEvent`] -> [`AccountEvent`] -> [`DomainEvent`] - pub fn flatten(self) -> SmallVec<[DataEvent; 3]> { - let mut events = SmallVec::new(); - - match self { - WorldEvent::Domain(domain_event) => { - match &domain_event { - DomainEvent::Account(account_event) => { - if let AccountEvent::Asset(asset_event) = account_event { - events.push(DataEvent::Asset(asset_event.clone())); - } - events.push(DataEvent::Account(account_event.clone())); - } - DomainEvent::AssetDefinition(asset_definition_event) => { - events.push(DataEvent::AssetDefinition(asset_definition_event.clone())); - } - _ => (), - } - events.push(DataEvent::Domain(domain_event)); - } - WorldEvent::Peer(peer_event) => { - events.push(DataEvent::Peer(peer_event)); - } - WorldEvent::Role(role_event) => { - events.push(DataEvent::Role(role_event)); - } - WorldEvent::Trigger(trigger_event) => { - events.push(DataEvent::Trigger(trigger_event)); - } - WorldEvent::PermissionTokenSchemaUpdate(token_event) => { - events.push(DataEvent::PermissionToken(token_event)); - } - WorldEvent::Configuration(config_event) => { - events.push(DataEvent::Configuration(config_event)); - } - WorldEvent::Executor(executor_event) => { - events.push(DataEvent::Executor(executor_event)); - } - } - - events - } -} - -impl From for WorldEvent { +impl From for DataEvent { fn from(value: AccountEvent) -> Self { DomainEvent::Account(value).into() } } -impl From for WorldEvent { +impl From for DataEvent { fn from(value: AssetDefinitionEvent) -> Self { DomainEvent::AssetDefinition(value).into() } } -impl From for WorldEvent { +impl From for DataEvent { fn from(value: AssetEvent) -> Self { AccountEvent::Asset(value).into() } @@ -698,9 +629,6 @@ impl DataEvent { pub fn domain_id(&self) -> Option<&DomainId> { match self { Self::Domain(event) => Some(event.origin_id()), - Self::Account(event) => Some(&event.origin_id().domain_id), - Self::AssetDefinition(event) => Some(&event.origin_id().domain_id), - Self::Asset(event) => Some(&event.origin_id().definition_id.domain_id), Self::Trigger(event) => event.origin_id().domain_id.as_ref(), Self::Peer(_) | Self::Configuration(_) @@ -731,6 +659,6 @@ pub mod prelude { trigger::{ TriggerEvent, TriggerEventFilter, TriggerFilter, TriggerNumberOfExecutionsChanged, }, - DataEvent, HasOrigin, MetadataChanged, WorldEvent, + DataEvent, HasOrigin, MetadataChanged, }; } diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 30d4029e018..c03b9b7c6b6 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -52,12 +52,6 @@ pub mod model { ByPeer(FilterOpt), /// Filter by Domain entity. `AcceptAll` value will accept all `Domain` events ByDomain(FilterOpt), - /// Filter by Account entity. `AcceptAll` value will accept all `Account` events - ByAccount(FilterOpt), - /// Filter by AssetDefinition entity. `AcceptAll` value will accept all `AssetDefinition` events - ByAssetDefinition(FilterOpt), - /// Filter by Asset entity. `AcceptAll` value will accept all `Asset` events - ByAsset(FilterOpt), /// Filter by Trigger entity. `AcceptAll` value will accept all `Trigger` events ByTrigger(FilterOpt), /// Filter by Role entity. `AcceptAll` value will accept all `Role` events @@ -145,13 +139,9 @@ impl Filter for DataEntityFilter { match (self, event) { (Self::ByPeer(filter_opt), DataEvent::Peer(peer)) => filter_opt.matches(peer), (Self::ByDomain(filter_opt), DataEvent::Domain(domain)) => filter_opt.matches(domain), - (Self::ByAccount(filter_opt), DataEvent::Account(account)) => { - filter_opt.matches(account) + (Self::ByTrigger(filter_opt), DataEvent::Trigger(trigger)) => { + filter_opt.matches(trigger) } - (Self::ByAssetDefinition(filter_opt), DataEvent::AssetDefinition(asset_definition)) => { - filter_opt.matches(asset_definition) - } - (Self::ByAsset(filter_opt), DataEvent::Asset(asset)) => filter_opt.matches(asset), (Self::ByRole(filter_opt), DataEvent::Role(role)) => filter_opt.matches(role), _ => false, } @@ -241,22 +231,60 @@ mod tests { metadata: Metadata::default(), }; let asset_id = AssetId::new( - AssetDefinitionId::new(asset_name, domain_id), + AssetDefinitionId::new(asset_name, domain_id.clone()), account_id.clone(), ); - let asset = Asset::new(asset_id, 0u32); - - let domain_created = DomainEvent::Created(domain); - let account_created = AccountEvent::Created(account); - let asset_created = AssetEvent::Created(asset); - let account_asset_created = AccountEvent::Asset(asset_created.clone()); - let account_filter = BySome(DataEntityFilter::ByAccount(BySome(AccountFilter::new( - BySome(OriginFilter(account_id)), + let asset = Asset::new(asset_id.clone(), 0u32); + + // Create three events with three levels of nesting + // the first one is just a domain event + // the second one is an account event with a domain event inside + // the third one is an asset event with an account event with a domain event inside + let domain_created = DomainEvent::Created(domain).into(); + let account_created = DomainEvent::Account(AccountEvent::Created(account)).into(); + let asset_created = + DomainEvent::Account(AccountEvent::Asset(AssetEvent::Created(asset))).into(); + + // test how the differently nested filters with with the events + // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 + let domain_filter = BySome(DataEntityFilter::ByDomain(BySome(DomainFilter::new( + BySome(OriginFilter(domain_id)), + AcceptAll, + )))); + let account_filter = BySome(DataEntityFilter::ByDomain(BySome(DomainFilter::new( + // kind of unfortunately, we have to specify the domain id filter, + // even though we will filter it with the account id filter (account id contains domain id with and account name) + // FIXME: maybe make this more orthogonal by introducing a partial id (in account event filter only by account name) AcceptAll, + BySome(DomainEventFilter::ByAccount(BySome(AccountFilter::new( + BySome(OriginFilter(account_id)), + AcceptAll, + )))), )))); - assert!(!account_filter.matches(&domain_created.into())); - assert!(!account_filter.matches(&asset_created.into())); - assert!(account_filter.matches(&account_created.into())); - assert!(account_filter.matches(&account_asset_created.into())); + let asset_filter = BySome(DataEntityFilter::ByDomain(BySome(DomainFilter::new( + AcceptAll, + BySome(DomainEventFilter::ByAccount(BySome(AccountFilter::new( + AcceptAll, + BySome(AccountEventFilter::ByAsset(BySome(AssetFilter::new( + BySome(OriginFilter(asset_id)), + AcceptAll, + )))), + )))), + )))); + + // domain filter matches all of those, because all of those events happened in the same domain + assert!(domain_filter.matches(&domain_created)); + assert!(domain_filter.matches(&account_created)); + assert!(domain_filter.matches(&asset_created)); + + // account event does not match the domain created event, as it is not an account event + assert!(!account_filter.matches(&domain_created)); + assert!(account_filter.matches(&account_created)); + assert!(account_filter.matches(&asset_created)); + + // asset event matches only the domain->account->asset event + assert!(!asset_filter.matches(&domain_created)); + assert!(!asset_filter.matches(&account_created)); + assert!(asset_filter.matches(&asset_created)); } } diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index a4640d1122e..3ac32350d43 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -876,29 +876,14 @@ "discriminant": 1, "type": "FilterOpt" }, - { - "tag": "ByAccount", - "discriminant": 2, - "type": "FilterOpt" - }, - { - "tag": "ByAssetDefinition", - "discriminant": 3, - "type": "FilterOpt" - }, - { - "tag": "ByAsset", - "discriminant": 4, - "type": "FilterOpt" - }, { "tag": "ByTrigger", - "discriminant": 5, + "discriminant": 2, "type": "FilterOpt" }, { "tag": "ByRole", - "discriminant": 6, + "discriminant": 3, "type": "FilterOpt" } ] @@ -915,44 +900,29 @@ "discriminant": 1, "type": "DomainEvent" }, - { - "tag": "Account", - "discriminant": 2, - "type": "AccountEvent" - }, - { - "tag": "AssetDefinition", - "discriminant": 3, - "type": "AssetDefinitionEvent" - }, - { - "tag": "Asset", - "discriminant": 4, - "type": "AssetEvent" - }, { "tag": "Trigger", - "discriminant": 5, + "discriminant": 2, "type": "TriggerEvent" }, { "tag": "Role", - "discriminant": 6, + "discriminant": 3, "type": "RoleEvent" }, { "tag": "PermissionToken", - "discriminant": 7, + "discriminant": 4, "type": "PermissionTokenSchemaUpdateEvent" }, { "tag": "Configuration", - "discriminant": 8, + "discriminant": 5, "type": "ConfigurationEvent" }, { "tag": "Executor", - "discriminant": 9, + "discriminant": 6, "type": "ExecutorEvent" } ] diff --git a/tools/parity_scale_decoder/build.rs b/tools/parity_scale_decoder/build.rs index 58e3db5dbd8..49223203f69 100644 --- a/tools/parity_scale_decoder/build.rs +++ b/tools/parity_scale_decoder/build.rs @@ -23,13 +23,11 @@ where path_to.push("samples/"); path_to.push(filename); - let mut path_to_json_sample = path_to.clone(); - path_to_json_sample.set_extension("json"); + let path_to_json = path_to.with_extension("json"); + let path_to_binary = path_to.with_extension("bin"); - let mut path_to_binary = path_to; - path_to_binary.set_extension("bin"); - - let buf = fs::read_to_string(path_to_json_sample)?; + println!("cargo:rerun-if-changed={}", path_to_json.to_str().unwrap()); + let buf = fs::read_to_string(path_to_json)?; let sample = serde_json::from_str::(buf.as_str())?; diff --git a/tools/parity_scale_decoder/samples/trigger.bin b/tools/parity_scale_decoder/samples/trigger.bin index 9d084408877..4ad7ccdfd9e 100644 Binary files a/tools/parity_scale_decoder/samples/trigger.bin and b/tools/parity_scale_decoder/samples/trigger.bin differ diff --git a/tools/parity_scale_decoder/samples/trigger.json b/tools/parity_scale_decoder/samples/trigger.json index b37816c0352..2cf26cf26f3 100644 --- a/tools/parity_scale_decoder/samples/trigger.json +++ b/tools/parity_scale_decoder/samples/trigger.json @@ -19,7 +19,12 @@ "authority": "alice@wonderland", "filter": { "Data": { - "ByAccount": "AcceptAll" + "ByDomain": { + "origin_filter": "AcceptAll", + "event_filter": { + "ByAccount": "AcceptAll" + } + } } }, "metadata": {} diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index 47dc7801e7a..c57d0d1a7cb 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -264,9 +264,10 @@ mod tests { vec![Mint::asset_quantity(1_u32, rose_id)], Repeats::Indefinitely, account_id, - FilterBox::Data(DataEventFilter::BySome(DataEntityFilter::ByAccount( - AcceptAll, - ))), + // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 + FilterBox::Data(BySome(DataEntityFilter::ByDomain(BySome( + DomainFilter::new(AcceptAll, BySome(DomainEventFilter::ByAccount(AcceptAll))), + )))), ); let trigger = Trigger::new(trigger_id, action);