From a8c1205a9ea08f36589a5e58b29302a4983bd990 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Mon, 29 Jan 2024 10:29:14 +0300 Subject: [PATCH 01/13] [refactor] #1981, #4195: Refactor the event filters - rename the `Filter` trait to `EventFilter` - "manually" implement all the event filters circumventing the macro - as a consequence, move all the filters to a separate module - change the filter types naming scheme to be more logical: - AccountFilter -> AccountEventFilter (filters the event as a whole: by origin id and event type) - AccountEventFilter -> AccountEventMatcher (matches over a type of event) - flattens the event filter hierarchy (account event is a kind of domain event, but account event filter is not) Signed-off-by: Nikita Strygin --- Cargo.lock | 1 + .../integration/triggers/data_trigger.rs | 33 +- .../integration/triggers/event_trigger.rs | 17 +- core/src/smartcontracts/isi/triggers/mod.rs | 2 +- core/src/smartcontracts/isi/triggers/set.rs | 10 +- data_model/Cargo.toml | 2 + data_model/src/events/data/events.rs | 25 +- data_model/src/events/data/filters.rs | 456 +++++++++++---- data_model/src/events/data/mod.rs | 2 +- data_model/src/events/execute_trigger.rs | 2 +- data_model/src/events/mod.rs | 8 +- data_model/src/events/notification.rs | 6 +- data_model/src/events/pipeline.rs | 4 +- data_model/src/events/time.rs | 2 +- docs/source/references/schema.json | 518 +++++------------- schema/gen/src/lib.rs | 42 +- .../parity_scale_decoder/samples/trigger.bin | Bin 77 -> 74 bytes tools/parity_scale_decoder/src/main.rs | 7 +- 18 files changed, 563 insertions(+), 574 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d83e78f461..648312069c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2882,6 +2882,7 @@ name = "iroha_data_model" version = "2.0.0-pre-rc.20" dependencies = [ "base64", + "cfg-if", "criterion", "derive_more", "displaydoc", diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 32f6ae92037..9e813fae800 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -24,15 +24,10 @@ fn must_execute_both_triggers() -> Result<()> { Repeats::Indefinitely, account_id.clone(), // 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), - )))), - ), - )))), + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(AccountEventFilter { + id_matcher: None, + event_matcher: Some(AccountEventMatcher::ByCreated), + }))), ), )); test_client.submit_blocking(register_trigger)?; @@ -43,9 +38,10 @@ fn must_execute_both_triggers() -> Result<()> { [instruction], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByDomain(BySome( - DomainFilter::new(AcceptAll, BySome(DomainEventFilter::ByCreated)), - )))), + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByDomain(DomainEventFilter { + id_matcher: None, + event_matcher: Some(DomainEventMatcher::ByCreated), + }))), ), )); test_client.submit_blocking(register_trigger)?; @@ -96,15 +92,10 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu Repeats::Indefinitely, account_id, // 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), - )))), - ), - )))), + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(AccountEventFilter { + id_matcher: None, + event_matcher: Some(AccountEventMatcher::ByCreated), + }))), ), )); test_client.submit_blocking(register_trigger)?; diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index c6250fdfe3e..d086c90a237 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -25,17 +25,12 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { Repeats::Indefinitely, account_id, // 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::ByAssetDefinition(BySome( - AssetDefinitionFilter::new( - AcceptAll, - BySome(AssetDefinitionEventFilter::ByCreated), - ), - ))), - ), - )))), + TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAssetDefinition( + AssetDefinitionEventFilter { + id_matcher: None, + event_matcher: Some(AssetDefinitionEventMatcher::ByCreated), + }, + ))), ), )); test_client.submit(register_trigger)?; diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index d90b5f65932..6c25c8d2530 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -13,7 +13,7 @@ pub mod set; /// - TODO: authority permissions. pub mod isi { use iroha_data_model::{ - events::Filter, + events::EventFilter, isi::error::{InvalidParameterError, RepetitionError}, trigger::prelude::*, }; diff --git a/core/src/smartcontracts/isi/triggers/set.rs b/core/src/smartcontracts/isi/triggers/set.rs index b8a41ea0b3e..6af4480ca82 100644 --- a/core/src/smartcontracts/isi/triggers/set.rs +++ b/core/src/smartcontracts/isi/triggers/set.rs @@ -14,7 +14,7 @@ use std::{fmt, num::NonZeroU64}; use indexmap::{map::Entry, IndexMap}; use iroha_crypto::HashOf; use iroha_data_model::{ - events::Filter as EventFilter, + events::EventFilter, isi::error::{InstructionExecutionError, MathError}, prelude::*, query::error::FindError, @@ -94,7 +94,7 @@ pub trait LoadedActionTrait { fn clone_and_box(&self) -> LoadedAction; } -impl + Clone> LoadedActionTrait for LoadedAction { +impl + Clone> LoadedActionTrait for LoadedAction { fn executable(&self) -> &LoadedExecutable { &self.executable } @@ -405,7 +405,7 @@ impl Set { /// # Errors /// /// Return [`Err`] if failed to preload wasm trigger - fn add_to( + fn add_to( &mut self, engine: &wasmtime::Engine, trigger: Trigger, @@ -705,7 +705,7 @@ impl Set { /// Note that this function doesn't remove the trigger from [`Set::ids`]. /// /// Returns `true` if trigger was removed and `false` otherwise. - fn remove_from( + fn remove_from( original_contracts: &mut WasmSmartContractMap, triggers: &mut IndexMap>, trigger_id: &TriggerId, @@ -884,7 +884,7 @@ impl Set { } /// Remove actions with zero execution count from `triggers` - fn remove_zeros( + fn remove_zeros( ids: &mut IndexMap, original_contracts: &mut WasmSmartContractMap, triggers: &mut IndexMap>, diff --git a/data_model/Cargo.toml b/data_model/Cargo.toml index db190cb0554..a435b712f3e 100644 --- a/data_model/Cargo.toml +++ b/data_model/Cargo.toml @@ -54,6 +54,8 @@ strum = { workspace = true, features = ["derive"] } base64 = { workspace = true, features = ["alloc"] } once_cell = { workspace = true, optional = true } +cfg-if = "1.0.0" + [dev-dependencies] iroha_crypto = { workspace = true, features = ["rand"] } diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 29472ed2c5d..d72761946f6 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -2,7 +2,7 @@ #![allow(missing_docs)] use getset::Getters; -use iroha_data_model_derive::{model, Filter, HasOrigin}; +use iroha_data_model_derive::{model, HasOrigin}; use iroha_primitives::numeric::Numeric; pub use self::model::*; @@ -18,7 +18,6 @@ macro_rules! data_event { Eq, PartialOrd, Ord, - Filter, HasOrigin, parity_scale_codec::Decode, parity_scale_codec::Encode, @@ -593,7 +592,7 @@ mod executor { } #[cfg(feature = "transparent_api")] - impl super::Filter for ExecutorFilter { + impl super::EventFilter for ExecutorFilter { type Event = ExecutorEvent; fn matches(&self, event: &Self::Event) -> bool { @@ -647,24 +646,18 @@ impl DataEvent { pub mod prelude { pub use super::{ - account::{ - AccountEvent, AccountEventFilter, AccountFilter, AccountPermissionChanged, - AccountRoleChanged, - }, + account::{AccountEvent, AccountPermissionChanged, AccountRoleChanged}, asset::{ - AssetChanged, AssetDefinitionEvent, AssetDefinitionEventFilter, AssetDefinitionFilter, - AssetDefinitionOwnerChanged, AssetDefinitionTotalQuantityChanged, AssetEvent, - AssetEventFilter, AssetFilter, + AssetChanged, AssetDefinitionEvent, AssetDefinitionOwnerChanged, + AssetDefinitionTotalQuantityChanged, AssetEvent, }, config::ConfigurationEvent, - domain::{DomainEvent, DomainEventFilter, DomainFilter, DomainOwnerChanged}, + domain::{DomainEvent, DomainOwnerChanged}, executor::{ExecutorEvent, ExecutorFilter}, - peer::{PeerEvent, PeerEventFilter, PeerFilter}, + peer::PeerEvent, permission::PermissionTokenSchemaUpdateEvent, - role::{RoleEvent, RoleEventFilter, RoleFilter, RolePermissionChanged}, - trigger::{ - TriggerEvent, TriggerEventFilter, TriggerFilter, TriggerNumberOfExecutionsChanged, - }, + role::{RoleEvent, RolePermissionChanged}, + trigger::{TriggerEvent, TriggerNumberOfExecutionsChanged}, DataEvent, HasOrigin, MetadataChanged, }; } diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 2d497cd128c..4f361052ff5 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -1,8 +1,12 @@ //! This module contains `EventFilter` and entities for filter +// TODO write code documentation +// - possible topics to cover: EventFilter vs EventMatcher +// - how this maps to event hierarchy (events are hierarchical, but event filters are flat) +// - how to construct event filters (should be done with builder API when they are implemented) + use core::fmt::Debug; -use derive_more::Constructor; use iroha_data_model_derive::model; pub use self::model::*; @@ -45,42 +49,131 @@ pub mod model { #[derive( Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - #[allow(clippy::enum_variant_names)] - /// Filters event by entity pub enum DataEntityFilter { - /// Filter by Peer entity. `AcceptAll` value will accept all `Peer` events - ByPeer(FilterOpt), - /// Filter by Domain entity. `AcceptAll` value will accept all `Domain` events - ByDomain(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 - ByRole(FilterOpt), + ByPeer(PeerEventFilter), + ByDomain(DomainEventFilter), + ByAccount(AccountEventFilter), + ByAsset(AssetEventFilter), + ByAssetDefinition(AssetDefinitionEventFilter), + ByTrigger(TriggerEventFilter), + ByRole(RoleEventFilter), + // We didn't have filters for these events before the refactor. Should we? + // Configuration(ConfigurationEventFilter), + // Executor(ExecutorEventFilter), } - /// Filter that accepts a data event with the matching origin. - #[derive( - Clone, - PartialOrd, - Ord, - Eq, - Debug, - Constructor, - Decode, - Encode, - Serialize, - Deserialize, - IntoSchema, - )] - #[serde(bound( - deserialize = "<::Origin as Identifiable>::Id: Deserialize<'de>" - ))] - #[serde(transparent)] - #[repr(transparent)] - pub struct OriginFilter(pub(super) ::Id) - where - ::Id: - Debug + Clone + Eq + Ord + Decode + Encode + Serialize + IntoSchema; + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct PeerEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum PeerEventMatcher { + ByAdded, + ByRemoved, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct DomainEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum DomainEventMatcher { + ByCreated, + ByDeleted, + ByMetadataInserted, + ByMetadataRemoved, + ByOwnerChanged, + // we allow filtering for nested events, but if you need to specify an id matcher for, for example, AccountId, you need to use AccountFilter + // nested events + ByAccount, + ByAssetDefinition, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct AccountEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum AccountEventMatcher { + ByCreated, + ByDeleted, + ByAuthenticationAdded, + ByAuthenticationRemoved, + ByPermissionAdded, + ByPermissionRemoved, + ByRoleRevoked, + ByRoleGranted, + ByMetadataInserted, + ByMetadataRemoved, + // nested events + ByAsset, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct AssetEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum AssetEventMatcher { + ByCreated, + ByDeleted, + ByAdded, + ByRemoved, + ByMetadataInserted, + ByMetadataRemoved, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct AssetDefinitionEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum AssetDefinitionEventMatcher { + ByCreated, + ByMintabilityChanged, + ByOwnerChanged, + ByDeleted, + ByMetadataInserted, + ByMetadataRemoved, + ByTotalQuantityChanged, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct TriggerEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum TriggerEventMatcher { + ByCreated, + ByDeleted, + ByExtended, + ByShortened, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub struct RoleEventFilter { + pub id_matcher: Option, + pub event_matcher: Option, + } + + #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + pub enum RoleEventMatcher { + ByCreated, + ByDeleted, + ByPermissionRemoved, + } } mod accept_all_as_string { @@ -120,7 +213,7 @@ mod accept_all_as_string { } #[cfg(feature = "transparent_api")] -impl Filter for FilterOpt { +impl EventFilter for FilterOpt { type Event = F::Event; fn matches(&self, item: &Self::Event) -> bool { @@ -132,61 +225,246 @@ impl Filter for FilterOpt { } #[cfg(feature = "transparent_api")] -impl Filter for DataEntityFilter { - type Event = DataEvent; +impl EventFilter for PeerEventFilter { + type Event = super::PeerEvent; - fn matches(&self, event: &DataEvent) -> bool { - 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::ByTrigger(filter_opt), DataEvent::Trigger(trigger)) => { - filter_opt.matches(trigger) + fn matches(&self, event: &Self::Event) -> bool { + use PeerEventMatcher::*; + + use super::PeerEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; } - (Self::ByRole(filter_opt), DataEvent::Role(role)) => filter_opt.matches(role), - _ => false, + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByAdded, Added(_)) => true, + (ByRemoved, Removed(_)) => true, + _ => false, + } + } else { + true } } } -impl OriginFilter -where - ::Id: - Debug + Clone + Eq + Ord + Decode + Encode + Serialize + IntoSchema, -{ - /// Get the id of the origin of the data event that this filter accepts. - pub fn origin_id(&self) -> &::Id { - &self.0 +#[cfg(feature = "transparent_api")] +impl EventFilter for DomainEventFilter { + type Event = super::DomainEvent; + + fn matches(&self, event: &Self::Event) -> bool { + use DomainEventMatcher::*; + + use super::DomainEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByCreated, Created(_)) => true, + (ByDeleted, Deleted(_)) => true, + (ByMetadataInserted, MetadataInserted(_)) => true, + (ByMetadataRemoved, MetadataRemoved(_)) => true, + (ByOwnerChanged, OwnerChanged(_)) => true, + (ByAccount, Account(_)) => true, + (ByAssetDefinition, AssetDefinition(_)) => true, + _ => false, + } + } else { + true + } } } #[cfg(feature = "transparent_api")] -impl Filter for OriginFilter -where - ::Id: - Debug + Clone + Eq + Ord + Decode + Encode + Serialize + IntoSchema, -{ - type Event = T; - - fn matches(&self, event: &T) -> bool { - event.origin_id() == self.origin_id() +impl super::EventFilter for AccountEventFilter { + type Event = super::AccountEvent; + + fn matches(&self, event: &Self::Event) -> bool { + use AccountEventMatcher::*; + + use super::AccountEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByCreated, Created(_)) => true, + (ByDeleted, Deleted(_)) => true, + (ByAuthenticationAdded, AuthenticationAdded(_)) => true, + (ByAuthenticationRemoved, AuthenticationRemoved(_)) => true, + (ByPermissionAdded, PermissionAdded(_)) => true, + (ByPermissionRemoved, PermissionRemoved(_)) => true, + (ByRoleRevoked, RoleRevoked(_)) => true, + (ByRoleGranted, RoleGranted(_)) => true, + (ByMetadataInserted, MetadataInserted(_)) => true, + (ByMetadataRemoved, MetadataRemoved(_)) => true, + (ByAsset, Asset(_)) => true, + _ => false, + } + } else { + true + } + } +} + +#[cfg(feature = "transparent_api")] +impl super::EventFilter for AssetEventFilter { + type Event = super::AssetEvent; + + fn matches(&self, event: &Self::Event) -> bool { + use AssetEventMatcher::*; + + use super::AssetEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByCreated, Created(_)) => true, + (ByDeleted, Deleted(_)) => true, + (ByAdded, Added(_)) => true, + (ByRemoved, Removed(_)) => true, + (ByMetadataInserted, MetadataInserted(_)) => true, + (ByMetadataRemoved, MetadataRemoved(_)) => true, + _ => false, + } + } else { + true + } + } +} + +#[cfg(feature = "transparent_api")] +impl super::EventFilter for AssetDefinitionEventFilter { + type Event = super::AssetDefinitionEvent; + + fn matches(&self, event: &Self::Event) -> bool { + use AssetDefinitionEventMatcher::*; + + use super::AssetDefinitionEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByCreated, Created(_)) => true, + (ByMintabilityChanged, MintabilityChanged(_)) => true, + (ByOwnerChanged, OwnerChanged(_)) => true, + (ByDeleted, Deleted(_)) => true, + (ByMetadataInserted, MetadataInserted(_)) => true, + (ByMetadataRemoved, MetadataRemoved(_)) => true, + (ByTotalQuantityChanged, TotalQuantityChanged(_)) => true, + _ => false, + } + } else { + true + } + } +} + +#[cfg(feature = "transparent_api")] +impl super::EventFilter for TriggerEventFilter { + type Event = super::TriggerEvent; + + fn matches(&self, event: &Self::Event) -> bool { + use TriggerEventMatcher::*; + + use super::TriggerEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByCreated, Created(_)) => true, + (ByDeleted, Deleted(_)) => true, + (ByExtended, Extended(_)) => true, + (ByShortened, Shortened(_)) => true, + _ => false, + } + } else { + true + } } } -impl PartialEq for OriginFilter -where - ::Id: - Debug + Clone + Eq + Ord + Decode + Encode + Serialize + IntoSchema, -{ - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 +#[cfg(feature = "transparent_api")] +impl super::EventFilter for RoleEventFilter { + type Event = super::RoleEvent; + + fn matches(&self, event: &Self::Event) -> bool { + use RoleEventMatcher::*; + + use super::RoleEvent::*; + + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + if let Some(event_matcher) = &self.event_matcher { + match (event_matcher, event) { + (ByCreated, Created(_)) => true, + (ByDeleted, Deleted(_)) => true, + (ByPermissionRemoved, PermissionRemoved(_)) => true, + _ => false, + } + } else { + true + } + } +} + +#[cfg(feature = "transparent_api")] +impl EventFilter for DataEntityFilter { + type Event = DataEvent; + + fn matches(&self, event: &DataEvent) -> bool { + use DataEntityFilter::*; + use DataEvent::*; + + match (self, event) { + (ByPeer(filter), Peer(event)) => filter.matches(event), + (ByDomain(filter), Domain(event)) => filter.matches(event), + (ByAccount(filter), Domain(DomainEvent::Account(event))) => filter.matches(event), + (ByAsset(filter), Domain(DomainEvent::Account(AccountEvent::Asset(event)))) => { + filter.matches(event) + } + (ByAssetDefinition(filter), Domain(DomainEvent::AssetDefinition(event))) => { + filter.matches(event) + } + (ByTrigger(filter), Trigger(event)) => filter.matches(event), + (ByRole(filter), Role(event)) => filter.matches(event), + _ => false, + } } } pub mod prelude { pub use super::{ - DataEntityFilter, DataEventFilter, + AccountEventFilter, AccountEventMatcher, AssetDefinitionEventFilter, + AssetDefinitionEventMatcher, AssetEventFilter, AssetEventMatcher, DataEntityFilter, + DataEventFilter, DomainEventFilter, DomainEventMatcher, FilterOpt::{self, *}, - OriginFilter, + PeerEventFilter, PeerEventMatcher, RoleEventFilter, RoleEventMatcher, TriggerEventFilter, + TriggerEventMatcher, }; } @@ -240,30 +518,18 @@ mod tests { // 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, - )))), - )))); - 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, - )))), - )))), - )))); + let domain_filter = BySome(DataEntityFilter::ByDomain(DomainEventFilter { + id_matcher: Some(domain_id), + event_matcher: None, + })); + let account_filter = BySome(DataEntityFilter::ByAccount(AccountEventFilter { + id_matcher: Some(account_id), + event_matcher: None, + })); + let asset_filter = BySome(DataEntityFilter::ByAsset(AssetEventFilter { + id_matcher: Some(asset_id), + event_matcher: None, + })); // domain filter matches all of those, because all of those events happened in the same domain assert!(domain_filter.matches(&domain_created)); diff --git a/data_model/src/events/data/mod.rs b/data_model/src/events/data/mod.rs index 70d0cd0d66e..54fe343831d 100644 --- a/data_model/src/events/data/mod.rs +++ b/data_model/src/events/data/mod.rs @@ -11,7 +11,7 @@ use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; #[cfg(feature = "transparent_api")] -use super::Filter; +use super::EventFilter; use crate::prelude::*; pub use crate::Registered; diff --git a/data_model/src/events/execute_trigger.rs b/data_model/src/events/execute_trigger.rs index 9b05dde3163..4825c1141b2 100644 --- a/data_model/src/events/execute_trigger.rs +++ b/data_model/src/events/execute_trigger.rs @@ -60,7 +60,7 @@ pub mod model { } #[cfg(feature = "transparent_api")] -impl Filter for ExecuteTriggerEventFilter { +impl EventFilter for ExecuteTriggerEventFilter { type Event = ExecuteTriggerEvent; /// Check if `event` matches filter diff --git a/data_model/src/events/mod.rs b/data_model/src/events/mod.rs index 37382ddcc8a..21b17ae7652 100644 --- a/data_model/src/events/mod.rs +++ b/data_model/src/events/mod.rs @@ -106,7 +106,7 @@ pub mod model { /// Trait for filters #[cfg(feature = "transparent_api")] -pub trait Filter { +pub trait EventFilter { /// Type of event that can be filtered type Event; @@ -133,7 +133,7 @@ pub trait Filter { } #[cfg(feature = "transparent_api")] -impl Filter for FilterBox { +impl EventFilter for FilterBox { type Event = Event; /// Apply filter to event. @@ -162,7 +162,7 @@ impl Filter for FilterBox { } #[cfg(feature = "transparent_api")] -impl Filter for TriggeringFilterBox { +impl EventFilter for TriggeringFilterBox { type Event = Event; /// Apply filter to event. @@ -225,7 +225,7 @@ pub mod prelude { #[cfg(feature = "http")] pub use super::stream::{EventMessage, EventSubscriptionRequest}; #[cfg(feature = "transparent_api")] - pub use super::Filter; + pub use super::EventFilter; pub use super::{ data::prelude::*, execute_trigger::prelude::*, notification::prelude::*, pipeline::prelude::*, time::prelude::*, Event, FilterBox, TriggeringEventType, diff --git a/data_model/src/events/notification.rs b/data_model/src/events/notification.rs index 8f98f3f0c73..b030edf0962 100644 --- a/data_model/src/events/notification.rs +++ b/data_model/src/events/notification.rs @@ -145,7 +145,7 @@ pub mod model { } #[cfg(feature = "transparent_api")] -impl super::Filter for NotificationEventFilter { +impl super::EventFilter for NotificationEventFilter { type Event = NotificationEvent; /// Check if `self` accepts the `event`. @@ -161,7 +161,7 @@ impl super::Filter for NotificationEventFilter { } #[cfg(feature = "transparent_api")] -impl super::Filter for TriggerCompletedEventFilter { +impl super::EventFilter for TriggerCompletedEventFilter { type Event = TriggerCompletedEvent; /// Check if `self` accepts the `event`. @@ -200,7 +200,7 @@ pub mod prelude { #[cfg(feature = "transparent_api")] mod tests { use super::*; - use crate::events::Filter; + use crate::events::EventFilter; #[test] fn trigger_completed_events_filter() { diff --git a/data_model/src/events/pipeline.rs b/data_model/src/events/pipeline.rs index 62a208fb0d9..49b43d4f0a7 100644 --- a/data_model/src/events/pipeline.rs +++ b/data_model/src/events/pipeline.rs @@ -193,7 +193,7 @@ impl PipelineEventFilter { } #[cfg(feature = "transparent_api")] -impl super::Filter for PipelineEventFilter { +impl super::EventFilter for PipelineEventFilter { type Event = PipelineEvent; /// Check if `self` accepts the `event`. @@ -230,7 +230,7 @@ mod tests { #[cfg(not(feature = "std"))] use alloc::{string::ToString as _, vec, vec::Vec}; - use super::{super::Filter, PipelineRejectionReason::*, *}; + use super::{super::EventFilter, PipelineRejectionReason::*, *}; use crate::{transaction::error::TransactionRejectionReason::*, ValidationFail}; #[test] diff --git a/data_model/src/events/time.rs b/data_model/src/events/time.rs index dc676145f78..65ed91682ad 100644 --- a/data_model/src/events/time.rs +++ b/data_model/src/events/time.rs @@ -132,7 +132,7 @@ pub mod model { } #[cfg(feature = "transparent_api")] -impl Filter for TimeEventFilter { +impl EventFilter for TimeEventFilter { type Event = TimeEvent; /// Isn't useful for time-triggers diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 6e729ccd1d7..92e01b439ba 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -83,6 +83,18 @@ ] }, "AccountEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_matcher", + "type": "Option" + } + ] + }, + "AccountEventMatcher": { "Enum": [ { "tag": "ByCreated", @@ -126,20 +138,7 @@ }, { "tag": "ByAsset", - "discriminant": 10, - "type": "FilterOpt" - } - ] - }, - "AccountFilter": { - "Struct": [ - { - "name": "origin_filter", - "type": "FilterOpt>" - }, - { - "name": "event_filter", - "type": "FilterOpt" + "discriminant": 10 } ] }, @@ -347,6 +346,18 @@ ] }, "AssetDefinitionEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_matcher", + "type": "Option" + } + ] + }, + "AssetDefinitionEventMatcher": { "Enum": [ { "tag": "ByCreated", @@ -378,18 +389,6 @@ } ] }, - "AssetDefinitionFilter": { - "Struct": [ - { - "name": "origin_filter", - "type": "FilterOpt>" - }, - { - "name": "event_filter", - "type": "FilterOpt" - } - ] - }, "AssetDefinitionId": { "Struct": [ { @@ -461,6 +460,18 @@ ] }, "AssetEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_matcher", + "type": "Option" + } + ] + }, + "AssetEventMatcher": { "Enum": [ { "tag": "ByCreated", @@ -488,18 +499,6 @@ } ] }, - "AssetFilter": { - "Struct": [ - { - "name": "origin_filter", - "type": "FilterOpt>" - }, - { - "name": "event_filter", - "type": "FilterOpt" - } - ] - }, "AssetId": { "Struct": [ { @@ -749,22 +748,37 @@ { "tag": "ByPeer", "discriminant": 0, - "type": "FilterOpt" + "type": "PeerEventFilter" }, { "tag": "ByDomain", "discriminant": 1, - "type": "FilterOpt" + "type": "DomainEventFilter" }, { - "tag": "ByTrigger", + "tag": "ByAccount", "discriminant": 2, - "type": "FilterOpt" + "type": "AccountEventFilter" }, { - "tag": "ByRole", + "tag": "ByAsset", "discriminant": 3, - "type": "FilterOpt" + "type": "AssetEventFilter" + }, + { + "tag": "ByAssetDefinition", + "discriminant": 4, + "type": "AssetDefinitionEventFilter" + }, + { + "tag": "ByTrigger", + "discriminant": 5, + "type": "TriggerEventFilter" + }, + { + "tag": "ByRole", + "discriminant": 6, + "type": "RoleEventFilter" } ] }, @@ -879,6 +893,18 @@ ] }, "DomainEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_matcher", + "type": "Option" + } + ] + }, + "DomainEventMatcher": { "Enum": [ { "tag": "ByCreated", @@ -902,25 +928,11 @@ }, { "tag": "ByAccount", - "discriminant": 5, - "type": "FilterOpt" + "discriminant": 5 }, { "tag": "ByAssetDefinition", - "discriminant": 6, - "type": "FilterOpt" - } - ] - }, - "DomainFilter": { - "Struct": [ - { - "name": "origin_filter", - "type": "FilterOpt>" - }, - { - "name": "event_filter", - "type": "FilterOpt" + "discriminant": 6 } ] }, @@ -1107,84 +1119,6 @@ } ] }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "AccountEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "AccountFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "AssetDefinitionEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "AssetDefinitionFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "AssetEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "AssetFilter" - } - ] - }, "FilterOpt": { "Enum": [ { @@ -1198,201 +1132,6 @@ } ] }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "DomainEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "DomainFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt>": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "OriginFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "PeerEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "PeerFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "RoleEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "RoleFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "TriggerEventFilter" - } - ] - }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "TriggerFilter" - } - ] - }, "FindAccountById": { "Struct": [ { @@ -2626,6 +2365,27 @@ } ] }, + "Option": { + "Option": "AccountEventMatcher" + }, + "Option": { + "Option": "AccountId" + }, + "Option": { + "Option": "AssetDefinitionEventMatcher" + }, + "Option": { + "Option": "AssetDefinitionId" + }, + "Option": { + "Option": "AssetEventMatcher" + }, + "Option": { + "Option": "AssetId" + }, + "Option": { + "Option": "DomainEventMatcher" + }, "Option": { "Option": "DomainId" }, @@ -2650,12 +2410,24 @@ "Option>": { "Option": "NonZero" }, + "Option": { + "Option": "PeerEventMatcher" + }, + "Option": { + "Option": "PeerId" + }, "Option": { "Option": "PipelineEntityKind" }, "Option": { "Option": "PipelineStatusKind" }, + "Option": { + "Option": "RoleEventMatcher" + }, + "Option": { + "Option": "RoleId" + }, "Option": { "Option": "String" }, @@ -2668,19 +2440,15 @@ "Option": { "Option": "TriggerCompletedOutcomeType" }, + "Option": { + "Option": "TriggerEventMatcher" + }, "Option": { "Option": "TriggerId" }, "Option": { "Option": "u32" }, - "OriginFilter": "AccountId", - "OriginFilter": "AssetDefinitionId", - "OriginFilter": "AssetId", - "OriginFilter": "DomainId", - "OriginFilter": "PeerId", - "OriginFilter": "RoleId", - "OriginFilter": "TriggerId", "Parameter": { "Struct": [ { @@ -2748,26 +2516,26 @@ ] }, "PeerEventFilter": { - "Enum": [ + "Struct": [ { - "tag": "ByAdded", - "discriminant": 0 + "name": "id_matcher", + "type": "Option" }, { - "tag": "ByRemoved", - "discriminant": 1 + "name": "event_matcher", + "type": "Option" } ] }, - "PeerFilter": { - "Struct": [ + "PeerEventMatcher": { + "Enum": [ { - "name": "origin_filter", - "type": "FilterOpt>" + "tag": "ByAdded", + "discriminant": 0 }, { - "name": "event_filter", - "type": "FilterOpt" + "tag": "ByRemoved", + "discriminant": 1 } ] }, @@ -3552,6 +3320,18 @@ ] }, "RoleEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_matcher", + "type": "Option" + } + ] + }, + "RoleEventMatcher": { "Enum": [ { "tag": "ByCreated", @@ -3571,18 +3351,6 @@ } ] }, - "RoleFilter": { - "Struct": [ - { - "name": "origin_filter", - "type": "FilterOpt>" - }, - { - "name": "event_filter", - "type": "FilterOpt" - } - ] - }, "RoleId": { "Struct": [ { @@ -4289,6 +4057,18 @@ ] }, "TriggerEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_matcher", + "type": "Option" + } + ] + }, + "TriggerEventMatcher": { "Enum": [ { "tag": "ByCreated", @@ -4308,18 +4088,6 @@ } ] }, - "TriggerFilter": { - "Struct": [ - { - "name": "origin_filter", - "type": "FilterOpt>" - }, - { - "name": "event_filter", - "type": "FilterOpt" - } - ] - }, "TriggerId": { "Struct": [ { diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 9107283f683..1ee1a489848 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -65,7 +65,7 @@ types!( Account, AccountEvent, AccountEventFilter, - AccountFilter, + AccountEventMatcher, AccountId, AccountMintBox, AccountPermissionChanged, @@ -77,13 +77,13 @@ types!( AssetDefinition, AssetDefinitionEvent, AssetDefinitionEventFilter, - AssetDefinitionFilter, + AssetDefinitionEventMatcher, AssetDefinitionId, AssetDefinitionOwnerChanged, AssetDefinitionTotalQuantityChanged, AssetEvent, AssetEventFilter, - AssetFilter, + AssetEventMatcher, AssetId, AssetTransferBox, AssetValue, @@ -123,7 +123,7 @@ types!( Domain, DomainEvent, DomainEventFilter, - DomainFilter, + DomainEventMatcher, DomainId, DomainOwnerChanged, Duration, @@ -139,27 +139,6 @@ types!( ExecutorEvent, Fail, FilterBox, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt>, - FilterOpt>, - FilterOpt>, - FilterOpt>, - FilterOpt>, - FilterOpt>, - FilterOpt>, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, - FilterOpt, FindAccountById, FindAccountKeyValueByIdAndKey, FindAccountsByDomainId, @@ -271,20 +250,13 @@ types!( Option, Option, Option, - OriginFilter, - OriginFilter, - OriginFilter, - OriginFilter, - OriginFilter, - OriginFilter, - OriginFilter, Parameter, ParameterId, ParameterValueBox, Peer, PeerEvent, PeerEventFilter, - PeerFilter, + PeerEventMatcher, PeerId, RolePermissionChanged, PermissionToken, @@ -325,7 +297,7 @@ types!( Role, RoleEvent, RoleEventFilter, - RoleFilter, + RoleEventMatcher, RoleId, SemiInterval, SemiInterval, @@ -381,7 +353,7 @@ types!( TriggerCompletedOutcomeType, TriggerEvent, TriggerEventFilter, - TriggerFilter, + TriggerEventMatcher, TriggerId, TriggerNumberOfExecutionsChanged, TriggeringFilterBox, diff --git a/tools/parity_scale_decoder/samples/trigger.bin b/tools/parity_scale_decoder/samples/trigger.bin index f6c3d19d8ce70adcb61d88cfb614c95652ac8d6d..830b2002997b306b4060fab96942de3447a62fba 100644 GIT binary patch delta 8 PcmebEn&8gNz`y_i2}J>N delta 11 ScmebBo#4*K$iT?TzyJUZ#sPc) diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index b84c373dfd6..d872b4d0e41 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -276,9 +276,10 @@ mod tests { Repeats::Indefinitely, account_id, // 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))), - )))), + FilterBox::Data(BySome(DataEntityFilter::ByDomain(DomainEventFilter { + id_matcher: None, + event_matcher: None, + }))), ); let trigger = Trigger::new(trigger_id, action); From 1564e03758bf5a3967bb83369a2b076141dfa293 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Mon, 29 Jan 2024 10:32:10 +0300 Subject: [PATCH 02/13] [refactor] #1981, #4195: Remove the event filter derive macro Signed-off-by: Nikita Strygin --- data_model/derive/src/filter.rs | 265 ---------------------- data_model/derive/src/lib.rs | 176 -------------- data_model/derive/tests/ui_pass/filter.rs | 106 --------- 3 files changed, 547 deletions(-) delete mode 100644 data_model/derive/src/filter.rs delete mode 100644 data_model/derive/tests/ui_pass/filter.rs diff --git a/data_model/derive/src/filter.rs b/data_model/derive/src/filter.rs deleted file mode 100644 index a023f4496cf..00000000000 --- a/data_model/derive/src/filter.rs +++ /dev/null @@ -1,265 +0,0 @@ -use darling::{FromDeriveInput, FromVariant}; -use iroha_macro_utils::Emitter; -use manyhow::emit; -use proc_macro2::TokenStream; -use quote::{format_ident, quote}; -use syn::{Generics, Ident, Variant, Visibility}; - -#[derive(FromDeriveInput)] -#[darling(supports(enum_tuple))] -struct EventEnum { - vis: Visibility, - ident: Ident, - generics: Generics, - data: darling::ast::Data, -} - -enum EventVariant { - /// A variant of event that delegates to some other event. Identified by conventional naming of the event types: ending with `Event`. - /// Delegates all the filterting to the corresponding event's filter. - Delegating { - variant_name: Ident, - /// A name of the event this variant delegates to, without the the `Event` suffix - delegated_event_name_base: String, - }, - /// An actual event. Has either an Id or an identifiable object as a payload - /// The presense of the Id field is not required by this macro per se, but will be enfored by `OriginFilter` requiring a `HasOrigin` impl. - Direct(Ident), -} - -impl FromVariant for EventVariant { - fn from_variant(variant: &Variant) -> darling::Result { - let syn::Fields::Unnamed(fields) = &variant.fields else { - return Err( - darling::Error::custom("Expected an enum with unnamed fields") - .with_span(&variant.fields), - ); - }; - // note: actually, we have only one field in the event variants - // this is not enforced by this macro, but by `IntoSchema` - let Some(first_field_ty) = fields.unnamed.first().map(|v| &v.ty) else { - return Err(darling::Error::custom("Expected at least one field").with_span(&fields)); - }; - let syn::Type::Path(path) = first_field_ty else { - return Err( - darling::Error::custom("Only identifiers supported as event types") - .with_span(first_field_ty), - ); - }; - let Some(first_field_ty_name) = path.path.get_ident() else { - return Err( - darling::Error::custom("Only identifiers supported as event types") - .with_span(first_field_ty), - ); - }; - - // What clippy suggests is much less readable in this case - #[allow(clippy::option_if_let_else)] - if let Some(delegated_event_name_base) = - first_field_ty_name.to_string().strip_suffix("Event") - { - Ok(EventVariant::Delegating { - variant_name: variant.ident.clone(), - delegated_event_name_base: delegated_event_name_base.to_string(), - }) - } else { - Ok(EventVariant::Direct(variant.ident.clone())) - } - } -} - -impl EventEnum { - fn variants(&self) -> &[EventVariant] { - match &self.data { - darling::ast::Data::Enum(variants) => variants, - _ => unreachable!("BUG: only enums should be here"), - } - } - - fn filter_map_variants Option>(&self, fun: F) -> Vec { - self.variants().iter().filter_map(fun).collect() - } - - /// Used to produce fields like `ByAccount(crate::prelude::FilterOpt)` in `DomainEventFilter`. - fn generate_filter_variants_for_delegating_events(&self) -> Vec { - self.filter_map_variants(|variant| { - if let EventVariant::Delegating { - variant_name, - delegated_event_name_base, - } = variant - { - // E.g. `Account` field in the event => `ByAccount` in the event filter - let filter_variant_ident = format_ident!("By{}", variant_name); - // E.g. `AccountEvent` inner field from `Account` variant in event => - // `AccountFilter` inside the event filter - let inner_filter_ident = format_ident!("{}Filter", delegated_event_name_base); - let import_path = quote! {crate::prelude}; - Some(quote! { - #filter_variant_ident(#import_path::FilterOpt<#inner_filter_ident>) - }) - } else { - None - } - }) - } - - /// Used to produce fields like `ByCreated` in `DomainEventFilter`. - fn generate_filter_variants_for_direct_events(&self) -> Vec { - self.filter_map_variants(|variant| { - if let EventVariant::Direct(event_variant_ident) = variant { - // Event fields such as `MetadataRemoved` get mapped to `ByMetadataRemoved` - let filter_variant_ident = format_ident!("By{}", event_variant_ident); - Some(filter_variant_ident) - } else { - None - } - }) - } - - /// Match arms for `Filter` impls of event filters of the form - /// `(Self::ByAccount(filter_opt), crate::prelude::DomainEvent::Account(event)) => {filter_opt.matches(event)}`. - fn generate_filter_arms_for_delegating_events(&self) -> Vec { - self.filter_map_variants(|variant| { - if let EventVariant::Delegating { variant_name, .. } = variant { - let event_ident = &self.ident; - let filter_variant_ident = format_ident!("By{}", variant_name); - let import_path = quote! {crate::prelude}; - Some(quote! { - ( - Self::#filter_variant_ident(filter_opt), - #import_path::#event_ident::#variant_name(event) - ) => { - filter_opt.matches(event) - } - }) - } else { - None - } - }) - } - - /// Match arms for `Filter` impls of event filters of the form - /// `(Self::ByCreated, crate::prelude::DomainEvent::Created(_))`. - fn generate_filter_patterns_for_direct_events(&self) -> Vec { - self.filter_map_variants(|variant| { - if let EventVariant::Direct(event_variant_ident) = variant { - let event_ident = &self.ident; - let filter_variant_ident = format_ident!("By{}", event_variant_ident); - let import_path = quote! {crate::prelude}; - Some(quote! { - ( - Self::#filter_variant_ident, - #import_path::#event_ident::#event_variant_ident(_) - ) - }) - } else { - None - } - }) - } -} - -/// Generates the event filter for the event. E.g. for `AccountEvent`, `AccountEventFilter` -/// and its `impl Filter` are generated. -fn impl_event_filter(event: &EventEnum) -> proc_macro2::TokenStream { - let EventEnum { - vis, - ident: event_ident, - generics, - .. - } = event; - - let id_variants = event.generate_filter_variants_for_direct_events(); - let event_variants = event.generate_filter_variants_for_delegating_events(); - - let id_patterns = event.generate_filter_patterns_for_direct_events(); - let event_arms = event.generate_filter_arms_for_delegating_events(); - - let event_filter_ident = format_ident!("{}Filter", event_ident); - let import_path = quote! { crate::prelude }; - let imp_event = quote! { #import_path::#event_ident }; - - let event_filter_doc = format!(" Event filter for {event_ident} entity"); - - quote! { - iroha_data_model_derive::model_single! { - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] - #[allow(clippy::enum_variant_names, missing_docs)] - #[doc = #event_filter_doc] - #vis enum #event_filter_ident #generics { - #(#id_variants),*, - #(#event_variants),* - } - } - - #[cfg(feature = "transparent_api")] - impl #import_path::Filter for #event_filter_ident { - type Event = #imp_event; - - fn matches(&self, event: &#imp_event) -> bool { - match (self, event) { - #(#id_patterns)|* => true, - #(#event_arms),* - _ => false, - } - } - } - } -} - -/// Generates the filter for the event. E.g. for `AccountEvent`, `AccountFilter` -/// and its `impl Filter` are generated. -pub fn impl_filter(emitter: &mut Emitter, input: &syn::DeriveInput) -> TokenStream { - let Some(event) = emitter.handle(EventEnum::from_derive_input(input)) else { - return quote!(); - }; - - let EventEnum { - vis, - ident: event_ident, - generics, - .. - } = &event; - - let event_filter_and_impl = impl_event_filter(&event); - - let event_base = event_ident.to_string().strip_suffix("Event").map_or_else( - || { - emit!(emitter, event_ident, "Event name should end with `Event`"); - event_ident.to_string() - }, - ToString::to_string, - ); - - let filter_ident = format_ident!("{}Filter", event_base); - let event_filter_ident = format_ident!("{}Filter", event_ident); - - let import_path = quote! { crate::prelude }; - let fil_opt = quote! { #import_path::FilterOpt }; - let orig_fil = quote! { #import_path::OriginFilter }; - let imp_event = quote! { #import_path::#event_ident }; - - let filter_doc = format!(" Filter for {event_ident} entity"); - - quote! { - iroha_data_model_derive::model_single! { - #[derive(Debug, Clone, PartialEq, Eq, derive_more::Constructor, Decode, Encode, Deserialize, Serialize, IntoSchema)] - #[doc = #filter_doc] - #vis struct #filter_ident #generics { - origin_filter: #fil_opt<#orig_fil<#imp_event>>, - event_filter: #fil_opt<#event_filter_ident> - } - } - - #[cfg(feature = "transparent_api")] - impl #import_path::Filter for #filter_ident { - type Event = #imp_event; - - fn matches(&self, event: &Self::Event) -> bool { - self.origin_filter.matches(event) && self.event_filter.matches(event) - } - } - - #event_filter_and_impl - } -} diff --git a/data_model/derive/src/lib.rs b/data_model/derive/src/lib.rs index 36aba376f4f..a51eae6d826 100644 --- a/data_model/derive/src/lib.rs +++ b/data_model/derive/src/lib.rs @@ -1,6 +1,5 @@ //! A crate containing various derive macros for `data_model` mod enum_ref; -mod filter; mod has_origin; mod id; mod model; @@ -285,181 +284,6 @@ pub fn id_eq_ord_hash(input: TokenStream) -> TokenStream { emitter.finish_token_stream_with(result) } -/// [`Filter`] is used for code generation of `...Filter` structs and `...EventFilter` enums, as well as -/// implementing the `Filter` trait for both of them. -/// This macro should only be attributed to `Event` enums. E.g. if the event is called `AccountEvent`, -/// then the macro will produce `AccountEventFilter` and `AccountFilter`. The latter will have `new` and -/// field getters defined, and both will have their respective `Filter` trait impls generated. -/// Due to name scoping, the macro currently properly -/// expands only from within the `iroha_data_model` crate as it relies on a few of `crate::prelude` -/// imports. This macro also depends on the naming conventions adopted so far, such as that -/// `Event` enums always have tuple variants with either some sort of `Id` or another `Event` inside -/// of them, as well as that all `Event` inner fields precede `Id` fields in the enum definition. -/// -/// # Examples -/// -/// ```ignore -/// use iroha_data_model_derive::{Filter, IdEqOrdHash}; -/// use iroha_data_model::prelude::{HasOrigin, Identifiable, IdBox}; -/// use serde::{Deserialize, Serialize}; -/// -/// -/// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Filter, Deserialize, Serialize)] -/// pub enum LayerEvent { -/// SubLayer(SubLayerEvent), -/// Created(LayerId), -/// } -/// -/// pub enum SubLayerEvent { -/// Created(SubLayerId), -/// } -/// -/// pub struct LayerId { -/// name: u32, -/// } -/// -/// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -/// pub struct SubLayerId { -/// name: u32, -/// parent_id: LayerId, -/// } -/// -/// #[derive(Debug, Clone, IdEqOrdHash)] -/// pub struct Layer { -/// id: ::Id, -/// } -/// -/// #[derive(Debug, Clone, IdEqOrdHash)] -/// pub struct SubLayer { -/// id: ::Id, -/// } -/// -/// # impl From for IdBox { -/// # fn from(_source: Layer) -> Self { -/// # unimplemented!("Only present to make the example work") -/// # } -/// # } -/// -/// # impl From for IdBox { -/// # fn from(_source: SubLayer) -> Self { -/// # unimplemented!("Only present to make the example work") -/// # } -/// # } -/// -/// impl HasOrigin for LayerEvent { -/// type Origin = Layer; -/// -/// fn origin_id(&self) -> &::Id { -/// match self { -/// Self::SubLayer(sub_layer) => &sub_layer.origin_id().parent_id, -/// Self::Created(id) => id, -/// } -/// } -/// } -/// -/// impl HasOrigin for SubLayerEvent { -/// type Origin = SubLayer; -/// -/// fn origin_id(&self) -> &::Id { -/// match self { -/// Self::Created(id) => id, -/// } -/// } -/// } -/// ``` -/// -/// Deriving [`Filter`] for `LayerEvent` expands into: -/// -/// ``` -/// /* -/// #[doc = " Filter for LayerEvent entity"] -/// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, derive_more::Constructor, Decode, Encode, Deserialize, Serialize, IntoSchema)] -/// pub struct LayerFilter { -/// origin_filter: -/// crate::prelude::FilterOpt>, -/// event_filter: crate::prelude::FilterOpt, -/// } -/// impl LayerFilter { -/// #[doc = " Construct new LayerFilter"] -/// pub const fn new( -/// origin_filter: crate::prelude::FilterOpt< -/// crate::prelude::OriginFilter, -/// >, -/// event_filter: crate::prelude::FilterOpt, -/// ) -> Self { -/// Self { -/// origin_filter, -/// event_filter, -/// } -/// } -/// #[doc = r" Get `origin_filter`"] -/// #[inline] -/// pub const fn origin_filter( -/// &self, -/// ) -> &crate::prelude::FilterOpt> { -/// &self.origin_filter -/// } -/// #[doc = r" Get `event_filter`"] -/// #[inline] -/// pub const fn event_filter(&self) -> &crate::prelude::FilterOpt { -/// &self.event_filter -/// } -/// } -/// impl crate::prelude::Filter for LayerFilter { -/// type TriggeringEventType = crate::prelude::LayerEvent; -/// fn matches(&self, event: &Self::TriggeringEventType) -> bool { -/// self.origin_filter.matches(event) && self.event_filter.matches(event) -/// } -/// } -/// #[doc = " Event filter for LayerEvent entity"] -/// #[allow(clippy::enum_variant_names, missing_docs)] -/// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Decode, Encode, Deserialize, Serialize, IntoSchema)] -/// pub enum LayerEventFilter { -/// ByCreated, -/// BySubLayer(crate::prelude::FilterOpt), -/// } -/// impl crate::prelude::Filter for LayerEventFilter { -/// type TriggeringEventType = crate::prelude::LayerEvent; -/// fn matches(&self, event: &crate::prelude::LayerEvent) -> bool { -/// match (self, event) { -/// (Self::ByCreated, crate::prelude::LayerEvent::Created(_)) => true, -/// (Self::BySubLayer(filter_opt), crate::prelude::LayerEvent::SubLayer(event)) => { -/// filter_opt.matches(event) -/// } -/// _ => false, -/// } -/// } -/// } */ -/// ``` -/// -/// ## A note on `#[derive(...)]` limitations -/// -/// This proc-macro crate parses the `#[derive(...)]` attributes. -/// Due to technical limitations of proc macros, it does not have access to the resolved path of the macro, only to what is written in the derive. -/// As such, it cannot support derives that are used through aliases, such as -/// -/// ```ignore -/// use getset::Getters as GettersAlias; -/// #[derive(GettersAlias)] -/// pub struct Hello { -/// // ... -/// } -/// ``` -/// -/// It assumes that the derive is imported and referred to by its original name. -#[manyhow] -#[proc_macro_derive(Filter)] -pub fn filter_derive(input: TokenStream) -> TokenStream { - let mut emitter = Emitter::new(); - - let Some(input) = emitter.handle(syn::parse2(input)) else { - return emitter.finish_token_stream(); - }; - - let result = filter::impl_filter(&mut emitter, &input); - emitter.finish_token_stream_with(result) -} - /// Derive `::serde::Serialize` trait for `enum` with possibility to avoid tags for selected variants /// /// ``` diff --git a/data_model/derive/tests/ui_pass/filter.rs b/data_model/derive/tests/ui_pass/filter.rs deleted file mode 100644 index 94dccc72e95..00000000000 --- a/data_model/derive/tests/ui_pass/filter.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! A smoke-test for the `derive(Filter)` - -use iroha_data_model::{ - prelude::{HasOrigin, Identifiable}, - IdBox, -}; -use iroha_data_model_derive::{Filter, IdEqOrdHash}; -use iroha_schema::IntoSchema; -use parity_scale_codec::{Decode, Encode}; -use serde::{Deserialize, Serialize}; - -// These are dummy types for the FilterDerive to work -// They would not work with `feature = transparent_api`, but are enough for the smoke test -mod prelude { - use iroha_schema::IntoSchema; - use parity_scale_codec::{Decode, Encode}; - use serde::{Deserialize, Serialize}; - - #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encode, Decode, IntoSchema)] - pub struct FilterOpt(T); - - #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encode, Decode, IntoSchema)] - pub struct OriginFilter(T); - - pub use super::LayerEvent; -} - -#[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Serialize, - Deserialize, - Encode, - Decode, - IntoSchema, -)] -pub struct SubLayerEvent; - -#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Encode, Decode, IntoSchema)] -pub struct SubLayerFilter; - -#[derive( - Copy, - Clone, - IntoSchema, - Ord, - PartialOrd, - Eq, - PartialEq, - Serialize, - Deserialize, - Decode, - Encode, - Debug, - Hash, -)] -pub struct LayerId { - name: u32, -} - -impl HasOrigin for LayerEvent { - type Origin = Layer; - - fn origin_id(&self) -> &::Id { - todo!() - } -} - -#[derive(Debug, IdEqOrdHash)] -pub struct Layer { - id: LayerId, -} - -impl From for IdBox { - fn from(_: LayerId) -> Self { - unreachable!() - } -} - -/// The tested type -#[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Serialize, - Deserialize, - Encode, - Decode, - IntoSchema, - Filter, -)] -pub enum LayerEvent { - SubLayer(SubLayerEvent), - Created(LayerId), -} - -fn main() {} From 4f6ebe0ab5250e32a6f2017012ed0ce84f6730e4 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Fri, 2 Feb 2024 10:35:09 +0300 Subject: [PATCH 03/13] [refactor] #1981, #4195: Refactor the event filters (even further) - Remove the FilterOpt combinator, fuse it with DataEventFilter - Rename DataEntityFilter to DataEventFilter - Add `Any` suffix to nested events matchers - Add doc-comments to event filters & their variants Signed-off-by: Nikita Strygin --- Cargo.lock | 1 - client/tests/integration/events/data.rs | 4 +- .../tests/integration/events/notification.rs | 4 +- .../integration/triggers/data_trigger.rs | 14 +- .../integration/triggers/event_trigger.rs | 5 +- client_cli/src/main.rs | 4 +- data_model/Cargo.toml | 2 - data_model/src/events/data/events.rs | 2 + data_model/src/events/data/filters.rs | 207 +++++++++--------- data_model/src/events/notification.rs | 8 +- docs/source/references/schema.json | 93 ++++---- schema/gen/src/lib.rs | 1 - .../parity_scale_decoder/samples/trigger.bin | Bin 74 -> 73 bytes .../parity_scale_decoder/samples/trigger.json | 6 +- tools/parity_scale_decoder/src/main.rs | 5 +- 15 files changed, 167 insertions(+), 189 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 648312069c1..0d83e78f461 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2882,7 +2882,6 @@ name = "iroha_data_model" version = "2.0.0-pre-rc.20" dependencies = [ "base64", - "cfg-if", "criterion", "derive_more", "displaydoc", diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 065ac37aa14..0d3c1ee05cd 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -138,7 +138,7 @@ fn transaction_execution_should_produce_events( let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = DataEventFilter::AcceptAll.into(); + let event_filter = FilterBox::Data(DataEventFilter::ByAny); thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; @@ -182,7 +182,7 @@ fn produce_multiple_events() -> Result<()> { let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = DataEventFilter::AcceptAll.into(); + let event_filter = FilterBox::Data(DataEventFilter::ByAny); thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index ae57791710a..e95d41323e5 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -35,7 +35,7 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { let mut event_it = thread_client.listen_for_events( - NotificationEventFilter::TriggerCompleted(TriggerCompletedEventFilter::new( + NotificationEventFilter::ByTriggerCompleted(TriggerCompletedEventFilter::new( Some(trigger_id), Some(TriggerCompletedOutcomeType::Success), )) @@ -84,7 +84,7 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { let mut event_it = thread_client.listen_for_events( - NotificationEventFilter::TriggerCompleted(TriggerCompletedEventFilter::new( + NotificationEventFilter::ByTriggerCompleted(TriggerCompletedEventFilter::new( Some(trigger_id), Some(TriggerCompletedOutcomeType::Failure), )) diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 9e813fae800..0ae18175351 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -23,11 +23,10 @@ fn must_execute_both_triggers() -> Result<()> { [instruction.clone()], Repeats::Indefinitely, account_id.clone(), - // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(AccountEventFilter { + TriggeringFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { id_matcher: None, event_matcher: Some(AccountEventMatcher::ByCreated), - }))), + })), ), )); test_client.submit_blocking(register_trigger)?; @@ -38,10 +37,10 @@ fn must_execute_both_triggers() -> Result<()> { [instruction], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByDomain(DomainEventFilter { + TriggeringFilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { id_matcher: None, event_matcher: Some(DomainEventMatcher::ByCreated), - }))), + })), ), )); test_client.submit_blocking(register_trigger)?; @@ -91,11 +90,10 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu [Mint::asset_numeric(1u32, asset_id.clone())], Repeats::Indefinitely, account_id, - // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAccount(AccountEventFilter { + TriggeringFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { id_matcher: None, event_matcher: Some(AccountEventMatcher::ByCreated), - }))), + })), ), )); test_client.submit_blocking(register_trigger)?; diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index d086c90a237..ae4ca5862f0 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -24,13 +24,12 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { vec![instruction], Repeats::Indefinitely, account_id, - // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 - TriggeringFilterBox::Data(BySome(DataEntityFilter::ByAssetDefinition( + TriggeringFilterBox::Data(DataEventFilter::ByAssetDefinition( AssetDefinitionEventFilter { id_matcher: None, event_matcher: Some(AssetDefinitionEventMatcher::ByCreated), }, - ))), + )), ), )); test_client.submit(register_trigger)?; diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index c38e2e13025..83de90a0d3c 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -266,8 +266,8 @@ mod events { fn run(self, context: &mut dyn RunContext) -> Result<()> { let filter = match self { Args::Pipeline => FilterBox::Pipeline(PipelineEventFilter::new()), - Args::Data => FilterBox::Data(DataEventFilter::AcceptAll), - Args::Notification => FilterBox::Notification(NotificationEventFilter::AcceptAll), + Args::Data => FilterBox::Data(DataEventFilter::ByAny), + Args::Notification => FilterBox::Notification(NotificationEventFilter::ByAny), }; listen(filter, context) } diff --git a/data_model/Cargo.toml b/data_model/Cargo.toml index a435b712f3e..db190cb0554 100644 --- a/data_model/Cargo.toml +++ b/data_model/Cargo.toml @@ -54,8 +54,6 @@ strum = { workspace = true, features = ["derive"] } base64 = { workspace = true, features = ["alloc"] } once_cell = { workspace = true, optional = true } -cfg-if = "1.0.0" - [dev-dependencies] iroha_crypto = { workspace = true, features = ["rand"] } diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index d72761946f6..5be779f4af7 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -32,6 +32,8 @@ macro_rules! data_event { }; } +// NOTE: if adding/editing events here, make sure to update the corresponding event filter in [`super::filter`] + #[model] pub mod model { use super::*; diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 4f361052ff5..90dc956888f 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -1,9 +1,10 @@ -//! This module contains `EventFilter` and entities for filter - -// TODO write code documentation -// - possible topics to cover: EventFilter vs EventMatcher -// - how this maps to event hierarchy (events are hierarchical, but event filters are flat) -// - how to construct event filters (should be done with builder API when they are implemented) +//! This module contains filters for data events. +//! +//! (almost) Each event in [`super::events`], there's two corresponding types in this module: +//! - `*EventMatcher` - matches one event kind (e.g. [`super::events::AccountEvent::Created`] with [`AccountEventMatcher::ByCreated`]) +//! - `*EventFilter` - struct combining an optional id matcher and an optional event matcher +//! +//! The ones not having a filter are [`super::events::ConfigurationEvent`] and [`super::events::ExecutorEvent`] (TODO: why?). use core::fmt::Debug; @@ -12,218 +13,214 @@ use iroha_data_model_derive::model; pub use self::model::*; use super::*; -/// Filter for all events -pub type DataEventFilter = FilterOpt; - #[model] pub mod model { use super::*; - /// Optional filter. May pass all items or may filter them by `F` - /// - /// It's better than `Optional` because `Optional` already has its own `filter` method and it - /// would be ugly to use fully qualified syntax to call `Filter::filter()` method on it. - /// Also `FilterOpt` variant names look better for filter needs - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[serde(untagged)] // Unaffected by #3330 - pub enum FilterOpt { - /// Accept all items that will be passed to `filter()` method - #[serde(with = "accept_all_as_string")] - AcceptAll, - /// Use filter `F` to choose acceptable items passed to `filter()` method - BySome(F), - } - #[derive( Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - pub enum DataEntityFilter { + pub enum DataEventFilter { + /// Matches any data events ([`DataEvent`]) + ByAny, + /// Matches only [`PeerEvent`]s ByPeer(PeerEventFilter), + /// Matches only [`DomainEvent`]s ByDomain(DomainEventFilter), + /// Matches only [`AccountEvent`]s ByAccount(AccountEventFilter), + /// Matches only [`AssetEvent`]s ByAsset(AssetEventFilter), + /// Matches only [`AssetDefinitionEvent`]s ByAssetDefinition(AssetDefinitionEventFilter), + /// Matches only [`TriggerEvent`]s ByTrigger(TriggerEventFilter), + /// Matches only [`RoleEvent`]s ByRole(RoleEventFilter), // We didn't have filters for these events before the refactor. Should we? // Configuration(ConfigurationEventFilter), // Executor(ExecutorEventFilter), } + /// An event filter for [`PeerEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct PeerEventFilter { pub id_matcher: Option, pub event_matcher: Option, } + /// An event matcher for [`PeerEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum PeerEventMatcher { + /// Matches only [`PeerEvent::Added`] ByAdded, + /// Matches only [`PeerEvent::Removed`] ByRemoved, } + /// An event filter for [`DomainEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct DomainEventFilter { + /// If specified matches only events originating from this domain pub id_matcher: Option, + /// If specified matches only events of this type pub event_matcher: Option, } + /// An event matcher for [`DomainEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum DomainEventMatcher { + /// Matches only [`DomainEvent::Created`] ByCreated, + /// Matches only [`DomainEvent::Deleted`] ByDeleted, + /// Matches only [`DomainEvent::MetadataInserted`] ByMetadataInserted, + /// Matches only [`DomainEvent::MetadataRemoved`] ByMetadataRemoved, + /// Matches only [`DomainEvent::OwnerChanged`] ByOwnerChanged, // we allow filtering for nested events, but if you need to specify an id matcher for, for example, AccountId, you need to use AccountFilter - // nested events - ByAccount, - ByAssetDefinition, + /// Matches only [`DomainEvent::Account`] + ByAccountAny, + /// Matches only [`DomainEvent::AssetDefinition`] + ByAssetDefinitionAny, } + /// An event filter for [`AccountEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct AccountEventFilter { + /// If specified matches only events originating from this account pub id_matcher: Option, + /// If specified matches only events of this type pub event_matcher: Option, } + /// An event matcher for [`AccountEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum AccountEventMatcher { + /// Matches only [`AccountEvent::Created`] ByCreated, + /// Matches only [`AccountEvent::Deleted`] ByDeleted, + /// Matches only [`AccountEvent::AuthenticationAdded`] ByAuthenticationAdded, + /// Matches only [`AccountEvent::AuthenticationRemoved`] ByAuthenticationRemoved, + /// Matches only [`AccountEvent::PermissionAdded`] ByPermissionAdded, + /// Matches only [`AccountEvent::PermissionRemoved`] ByPermissionRemoved, + /// Matches only [`AccountEvent::RoleRevoked`] ByRoleRevoked, + /// Matches only [`AccountEvent::RoleGranted`] ByRoleGranted, + /// Matches only [`AccountEvent::MetadataInserted`] ByMetadataInserted, + /// Matches only [`AccountEvent::MetadataRemoved`] ByMetadataRemoved, // nested events - ByAsset, + /// Matches only [`AccountEvent::Asset`] + ByAssetAny, } + /// An event filter for [`AssetEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct AssetEventFilter { + /// If specified matches only events originating from this asset pub id_matcher: Option, + /// If specified matches only events of this type pub event_matcher: Option, } + /// An event matcher for [`AssetEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum AssetEventMatcher { + /// Matches only [`AssetEvent::Created`] ByCreated, + /// Matches only [`AssetEvent::Deleted`] ByDeleted, + /// Matches only [`AssetEvent::Added`] ByAdded, + /// Matches only [`AssetEvent::Removed`] ByRemoved, + /// Matches only [`AssetEvent::MetadataInserted`] ByMetadataInserted, + /// Matches only [`AssetEvent::MetadataRemoved`] ByMetadataRemoved, } + /// An event filter for [`AssetDefinitionEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct AssetDefinitionEventFilter { + /// If specified matches only events originating from this asset definition pub id_matcher: Option, + /// If specified matches only events of this type pub event_matcher: Option, } + /// An event matcher for [`AssetDefinitionEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum AssetDefinitionEventMatcher { + /// Matches only [`AssetDefinitionEvent::Created`] ByCreated, + /// Matches only [`AssetDefinitionEvent::MintabilityChanged`] ByMintabilityChanged, + /// Matches only [`AssetDefinitionEvent::OwnerChanged`] ByOwnerChanged, + /// Matches only [`AssetDefinitionEvent::Deleted`] ByDeleted, + /// Matches only [`AssetDefinitionEvent::MetadataInserted`] ByMetadataInserted, + /// Matches only [`AssetDefinitionEvent::MetadataRemoved`] ByMetadataRemoved, + /// Matches only [`AssetDefinitionEvent::TotalQuantityChanged`] ByTotalQuantityChanged, } + /// An event filter for [`TriggerEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct TriggerEventFilter { + /// If specified matches only events originating from this trigger pub id_matcher: Option, + /// If specified matches only events of this type pub event_matcher: Option, } + /// An event matcher for [`TriggerEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum TriggerEventMatcher { + /// Matches only [`TriggerEvent::Created`] ByCreated, + /// Matches only [`TriggerEvent::Deleted`] ByDeleted, + /// Matches only [`TriggerEvent::Extended`] ByExtended, + /// Matches only [`TriggerEvent::Shortened`] ByShortened, } + /// An event filter for [`RoleEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct RoleEventFilter { + /// If specified matches only events originating from this role pub id_matcher: Option, + /// If specified matches only events of this type pub event_matcher: Option, } + /// An event matcher for [`RoleEvent`]s #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum RoleEventMatcher { + /// Matches only [`RoleEvent::Created`] ByCreated, + /// Matches only [`RoleEvent::Deleted`] ByDeleted, + /// Matches only [`RoleEvent::PermissionRemoved`] ByPermissionRemoved, } } -mod accept_all_as_string { - //! Module to (de-)serialize `FilterOpt::AcceptAll` variant as string - - #[cfg(not(feature = "std"))] - use alloc::format; - - use serde::{Deserializer, Serializer}; - - /// Serialize bytes using `base64` - pub fn serialize(serializer: S) -> Result { - serializer.serialize_str("AcceptAll") - } - - /// Deserialize bytes using `base64` - pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<(), D::Error> { - struct Vis; - - impl serde::de::Visitor<'_> for Vis { - type Value = (); - - fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { - formatter.write_str("an AcceptAll string") - } - - fn visit_str(self, s: &str) -> Result { - if s == "AcceptAll" { - Ok(()) - } else { - Err(E::custom(format!("expected AcceptAll, got {s}"))) - } - } - } - deserializer.deserialize_str(Vis) - } -} - -#[cfg(feature = "transparent_api")] -impl EventFilter for FilterOpt { - type Event = F::Event; - - fn matches(&self, item: &Self::Event) -> bool { - match self { - Self::AcceptAll => true, - Self::BySome(filter) => filter.matches(item), - } - } -} - #[cfg(feature = "transparent_api")] impl EventFilter for PeerEventFilter { type Event = super::PeerEvent; @@ -271,8 +268,8 @@ impl EventFilter for DomainEventFilter { (ByMetadataInserted, MetadataInserted(_)) => true, (ByMetadataRemoved, MetadataRemoved(_)) => true, (ByOwnerChanged, OwnerChanged(_)) => true, - (ByAccount, Account(_)) => true, - (ByAssetDefinition, AssetDefinition(_)) => true, + (ByAccountAny, Account(_)) => true, + (ByAssetDefinitionAny, AssetDefinition(_)) => true, _ => false, } } else { @@ -307,7 +304,7 @@ impl super::EventFilter for AccountEventFilter { (ByRoleGranted, RoleGranted(_)) => true, (ByMetadataInserted, MetadataInserted(_)) => true, (ByMetadataRemoved, MetadataRemoved(_)) => true, - (ByAsset, Asset(_)) => true, + (ByAssetAny, Asset(_)) => true, _ => false, } } else { @@ -433,14 +430,15 @@ impl super::EventFilter for RoleEventFilter { } #[cfg(feature = "transparent_api")] -impl EventFilter for DataEntityFilter { +impl EventFilter for DataEventFilter { type Event = DataEvent; fn matches(&self, event: &DataEvent) -> bool { - use DataEntityFilter::*; use DataEvent::*; + use DataEventFilter::*; match (self, event) { + (ByAny, _) => true, (ByPeer(filter), Peer(event)) => filter.matches(event), (ByDomain(filter), Domain(event)) => filter.matches(event), (ByAccount(filter), Domain(DomainEvent::Account(event))) => filter.matches(event), @@ -460,11 +458,9 @@ impl EventFilter for DataEntityFilter { pub mod prelude { pub use super::{ AccountEventFilter, AccountEventMatcher, AssetDefinitionEventFilter, - AssetDefinitionEventMatcher, AssetEventFilter, AssetEventMatcher, DataEntityFilter, - DataEventFilter, DomainEventFilter, DomainEventMatcher, - FilterOpt::{self, *}, - PeerEventFilter, PeerEventMatcher, RoleEventFilter, RoleEventMatcher, TriggerEventFilter, - TriggerEventMatcher, + AssetDefinitionEventMatcher, AssetEventFilter, AssetEventMatcher, DataEventFilter, + DomainEventFilter, DomainEventMatcher, PeerEventFilter, PeerEventMatcher, RoleEventFilter, + RoleEventMatcher, TriggerEventFilter, TriggerEventMatcher, }; } @@ -517,19 +513,18 @@ mod tests { 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(DomainEventFilter { + let domain_filter = DataEventFilter::ByDomain(DomainEventFilter { id_matcher: Some(domain_id), event_matcher: None, - })); - let account_filter = BySome(DataEntityFilter::ByAccount(AccountEventFilter { + }); + let account_filter = DataEventFilter::ByAccount(AccountEventFilter { id_matcher: Some(account_id), event_matcher: None, - })); - let asset_filter = BySome(DataEntityFilter::ByAsset(AssetEventFilter { + }); + let asset_filter = DataEventFilter::ByAsset(AssetEventFilter { id_matcher: Some(asset_id), event_matcher: None, - })); + }); // domain filter matches all of those, because all of those events happened in the same domain assert!(domain_filter.matches(&domain_created)); diff --git a/data_model/src/events/notification.rs b/data_model/src/events/notification.rs index b030edf0962..3eb484095b9 100644 --- a/data_model/src/events/notification.rs +++ b/data_model/src/events/notification.rs @@ -113,8 +113,8 @@ pub mod model { #[ffi_type] #[non_exhaustive] pub enum NotificationEventFilter { - AcceptAll, - TriggerCompleted(TriggerCompletedEventFilter), + ByAny, + ByTriggerCompleted(TriggerCompletedEventFilter), } /// Filter [`TriggerCompletedEvent`] by @@ -152,8 +152,8 @@ impl super::EventFilter for NotificationEventFilter { #[inline] fn matches(&self, event: &Self::Event) -> bool { match (self, event) { - (Self::AcceptAll, _) => true, - (Self::TriggerCompleted(filter), NotificationEvent::TriggerCompleted(event)) => { + (Self::ByAny, _) => true, + (Self::ByTriggerCompleted(filter), NotificationEvent::TriggerCompleted(event)) => { filter.matches(event) } } diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 92e01b439ba..95ff16deaea 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -137,7 +137,7 @@ "discriminant": 9 }, { - "tag": "ByAsset", + "tag": "ByAssetAny", "discriminant": 10 } ] @@ -743,81 +743,85 @@ } ] }, - "DataEntityFilter": { + "DataEvent": { "Enum": [ { - "tag": "ByPeer", + "tag": "Peer", "discriminant": 0, - "type": "PeerEventFilter" + "type": "PeerEvent" }, { - "tag": "ByDomain", + "tag": "Domain", "discriminant": 1, - "type": "DomainEventFilter" + "type": "DomainEvent" }, { - "tag": "ByAccount", + "tag": "Trigger", "discriminant": 2, - "type": "AccountEventFilter" + "type": "TriggerEvent" }, { - "tag": "ByAsset", + "tag": "Role", "discriminant": 3, - "type": "AssetEventFilter" + "type": "RoleEvent" }, { - "tag": "ByAssetDefinition", + "tag": "PermissionToken", "discriminant": 4, - "type": "AssetDefinitionEventFilter" + "type": "PermissionTokenSchemaUpdateEvent" }, { - "tag": "ByTrigger", + "tag": "Configuration", "discriminant": 5, - "type": "TriggerEventFilter" + "type": "ConfigurationEvent" }, { - "tag": "ByRole", + "tag": "Executor", "discriminant": 6, - "type": "RoleEventFilter" + "type": "ExecutorEvent" } ] }, - "DataEvent": { + "DataEventFilter": { "Enum": [ { - "tag": "Peer", - "discriminant": 0, - "type": "PeerEvent" + "tag": "ByAny", + "discriminant": 0 }, { - "tag": "Domain", + "tag": "ByPeer", "discriminant": 1, - "type": "DomainEvent" + "type": "PeerEventFilter" }, { - "tag": "Trigger", + "tag": "ByDomain", "discriminant": 2, - "type": "TriggerEvent" + "type": "DomainEventFilter" }, { - "tag": "Role", + "tag": "ByAccount", "discriminant": 3, - "type": "RoleEvent" + "type": "AccountEventFilter" }, { - "tag": "PermissionToken", + "tag": "ByAsset", "discriminant": 4, - "type": "PermissionTokenSchemaUpdateEvent" + "type": "AssetEventFilter" }, { - "tag": "Configuration", + "tag": "ByAssetDefinition", "discriminant": 5, - "type": "ConfigurationEvent" + "type": "AssetDefinitionEventFilter" }, { - "tag": "Executor", + "tag": "ByTrigger", "discriminant": 6, - "type": "ExecutorEvent" + "type": "TriggerEventFilter" + }, + { + "tag": "ByRole", + "discriminant": 7, + "type": "RoleEventFilter" } ] }, @@ -927,11 +931,11 @@ "discriminant": 4 }, { - "tag": "ByAccount", + "tag": "ByAccountAny", "discriminant": 5 }, { - "tag": "ByAssetDefinition", + "tag": "ByAssetDefinitionAny", "discriminant": 6 } ] @@ -1100,7 +1104,7 @@ { "tag": "Data", "discriminant": 1, - "type": "FilterOpt" + "type": "DataEventFilter" }, { "tag": "Time", @@ -1119,19 +1123,6 @@ } ] }, - "FilterOpt": { - "Enum": [ - { - "tag": "AcceptAll", - "discriminant": 0 - }, - { - "tag": "BySome", - "discriminant": 1, - "type": "DataEntityFilter" - } - ] - }, "FindAccountById": { "Struct": [ { @@ -2335,11 +2326,11 @@ "NotificationEventFilter": { "Enum": [ { - "tag": "AcceptAll", + "tag": "ByAny", "discriminant": 0 }, { - "tag": "TriggerCompleted", + "tag": "ByTriggerCompleted", "discriminant": 1, "type": "TriggerCompletedEventFilter" } @@ -4122,7 +4113,7 @@ { "tag": "Data", "discriminant": 1, - "type": "FilterOpt" + "type": "DataEventFilter" }, { "tag": "Time", diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 1ee1a489848..3fcc186a964 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -117,7 +117,6 @@ types!( ConstVec, ConstVec, Container, - DataEntityFilter, DataEvent, DataEventFilter, Domain, diff --git a/tools/parity_scale_decoder/samples/trigger.bin b/tools/parity_scale_decoder/samples/trigger.bin index 830b2002997b306b4060fab96942de3447a62fba..98d198162b3bd2b70c5141ace366d87697d814a3 100644 GIT binary patch delta 9 QcmebBoZ!mB#K6D+01A}>ZvX%Q delta 10 RcmebDn&8UH$jHFJ000aK0dN2S diff --git a/tools/parity_scale_decoder/samples/trigger.json b/tools/parity_scale_decoder/samples/trigger.json index f8a8e9e9c2e..a9a7ff5cbab 100644 --- a/tools/parity_scale_decoder/samples/trigger.json +++ b/tools/parity_scale_decoder/samples/trigger.json @@ -18,10 +18,8 @@ "filter": { "Data": { "ByDomain": { - "origin_filter": "AcceptAll", - "event_filter": { - "ByAccount": "AcceptAll" - } + "origin_filter": null, + "event_filter": "ByAccount" } } }, diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index d872b4d0e41..0d3988a2ad8 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -275,11 +275,10 @@ mod tests { vec![Mint::asset_numeric(1u32, rose_id)], Repeats::Indefinitely, account_id, - // FIXME: rewrite the filters using the builder DSL https://github.com/hyperledger/iroha/issues/3068 - FilterBox::Data(BySome(DataEntityFilter::ByDomain(DomainEventFilter { + FilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { id_matcher: None, event_matcher: None, - }))), + })), ); let trigger = Trigger::new(trigger_id, action); From 72279463b9ecff8a2fc40a4c7a30ad0965ac7268 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Tue, 6 Feb 2024 16:58:48 +0300 Subject: [PATCH 04/13] [refactor] #1981, #4195: Rename FilterBox and TriggeringFilterBox to EventFilterBox and TriggeringEventFilterBox To make it consistent with the renamed EventFilter trait Signed-off-by: Nikita Strygin --- client/src/client.rs | 12 +-- .../integration/domain_owner_permissions.rs | 2 +- client/tests/integration/events/data.rs | 4 +- .../tests/integration/events/notification.rs | 4 +- client/tests/integration/events/pipeline.rs | 2 +- .../integration/triggers/by_call_trigger.rs | 26 ++--- .../integration/triggers/data_trigger.rs | 6 +- .../integration/triggers/event_trigger.rs | 2 +- .../integration/triggers/time_trigger.rs | 10 +- .../integration/triggers/trigger_rollback.rs | 2 +- client_cli/src/main.rs | 8 +- core/src/smartcontracts/isi/mod.rs | 2 +- core/src/smartcontracts/isi/query.rs | 2 +- core/src/smartcontracts/isi/triggers/mod.rs | 27 +++--- core/src/smartcontracts/isi/triggers/set.rs | 12 ++- core/test_network/src/lib.rs | 4 +- data_model/src/events/data/events.rs | 2 +- data_model/src/events/mod.rs | 14 +-- data_model/src/isi.rs | 34 +++---- data_model/src/lib.rs | 14 +-- data_model/src/query/mod.rs | 9 +- data_model/src/trigger.rs | 36 +++---- data_model/src/visit.rs | 16 ++-- docs/source/references/schema.json | 94 +++++++++---------- schema/gen/src/lib.rs | 16 ++-- smart_contract/executor/derive/src/default.rs | 8 +- smart_contract/executor/src/default.rs | 8 +- tools/parity_scale_decoder/build.rs | 2 +- tools/parity_scale_decoder/src/main.rs | 6 +- torii/src/event.rs | 6 +- 30 files changed, 198 insertions(+), 192 deletions(-) diff --git a/client/src/client.rs b/client/src/client.rs index 789f6ef7a76..5bf9ce65880 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -323,7 +323,7 @@ impl_query_output! { crate::data_model::metadata::MetadataValueBox, crate::data_model::query::TransactionQueryOutput, crate::data_model::permission::PermissionTokenSchema, - crate::data_model::trigger::Trigger, + crate::data_model::trigger::Trigger, crate::data_model::prelude::Numeric, } @@ -905,7 +905,7 @@ impl Client { /// - Forwards from [`events_api::EventIterator::new`] pub fn listen_for_events( &self, - event_filter: FilterBox, + event_filter: EventFilterBox, ) -> Result>> { iroha_logger::trace!(?event_filter); events_api::EventIterator::new(self.events_handler(event_filter)?) @@ -918,7 +918,7 @@ impl Client { /// - Forwards from [`events_api::AsyncEventStream::new`] pub async fn listen_for_events_async( &self, - event_filter: FilterBox, + event_filter: EventFilterBox, ) -> Result { iroha_logger::trace!(?event_filter, "Async listening with"); events_api::AsyncEventStream::new(self.events_handler(event_filter)?).await @@ -929,7 +929,7 @@ impl Client { /// # Errors /// Fails if handler construction fails #[inline] - pub fn events_handler(&self, event_filter: FilterBox) -> Result { + pub fn events_handler(&self, event_filter: EventFilterBox) -> Result { events_api::flow::Init::new( event_filter, self.headers.clone(), @@ -1235,7 +1235,7 @@ pub mod events_api { /// Initialization struct for Events API flow. pub struct Init { /// Event filter - filter: FilterBox, + filter: EventFilterBox, /// HTTP request headers headers: HashMap, /// TORII URL @@ -1249,7 +1249,7 @@ pub mod events_api { /// Fails if [`transform_ws_url`] fails. #[inline] pub(in super::super) fn new( - filter: FilterBox, + filter: EventFilterBox, headers: HashMap, url: Url, ) -> Result { diff --git a/client/tests/integration/domain_owner_permissions.rs b/client/tests/integration/domain_owner_permissions.rs index 06892c6a3b3..3763b35209d 100644 --- a/client/tests/integration/domain_owner_permissions.rs +++ b/client/tests/integration/domain_owner_permissions.rs @@ -310,7 +310,7 @@ fn domain_owner_trigger_permissions() -> Result<()> { Repeats::from(2_u32), bob_id, // FIXME: due to restriction in `ExecuteTriggerEventFilter` it's impossible to execute trigger on behalf of multiple users - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), alice_id, )), diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 0d3c1ee05cd..e1f41807972 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -138,7 +138,7 @@ fn transaction_execution_should_produce_events( let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = FilterBox::Data(DataEventFilter::ByAny); + let event_filter = EventFilterBox::Data(DataEventFilter::ByAny); thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; @@ -182,7 +182,7 @@ fn produce_multiple_events() -> Result<()> { let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = FilterBox::Data(DataEventFilter::ByAny); + let event_filter = EventFilterBox::Data(DataEventFilter::ByAny); thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index e95d41323e5..5b3f0e9e7bc 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -21,7 +21,7 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { vec![InstructionBox::from(instruction)], Repeats::Indefinitely, asset_id.account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), asset_id.account_id, )), @@ -70,7 +70,7 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { vec![InstructionBox::from(instruction)], Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id, )), diff --git a/client/tests/integration/events/pipeline.rs b/client/tests/integration/events/pipeline.rs index 96f85500fac..292a0f97e95 100644 --- a/client/tests/integration/events/pipeline.rs +++ b/client/tests/integration/events/pipeline.rs @@ -82,7 +82,7 @@ impl Checker { thread::spawn(move || { let mut event_iterator = self .listener - .listen_for_events(FilterBox::Pipeline( + .listen_for_events(EventFilterBox::Pipeline( PipelineEventFilter::new() .entity_kind(PipelineEntityKind::Transaction) .status_kind(status_kind) diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index e00767959a8..7df6f7c1878 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -9,7 +9,7 @@ use iroha_client::{ transaction::Executable, }, }; -use iroha_data_model::{events::TriggeringFilterBox, transaction::WasmSmartContract}; +use iroha_data_model::{events::TriggeringEventFilterBox, transaction::WasmSmartContract}; use iroha_genesis::GenesisNetwork; use iroha_logger::info; use test_network::*; @@ -121,7 +121,7 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { bad_trigger_instructions, Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( bad_trigger_id.clone(), account_id.clone(), )), @@ -139,7 +139,7 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { Repeats::Indefinitely, account_id, // Time-triggers (which are Pre-commit triggers) will be executed last - TriggeringFilterBox::Time(TimeEventFilter::new(ExecutionTime::PreCommit)), + TriggeringEventFilterBox::Time(TimeEventFilter::new(ExecutionTime::PreCommit)), ), )); test_client.submit_blocking(register_trigger)?; @@ -176,7 +176,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { trigger_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id, )), @@ -240,7 +240,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { trigger_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id, )), @@ -283,7 +283,7 @@ fn unregister_trigger() -> Result<()> { Vec::::new(), Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id, )), @@ -360,7 +360,7 @@ fn trigger_in_genesis_using_base64() -> Result<()> { .wrap_err("Can't deserialize wasm using base64")?, Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id.clone(), )), @@ -410,7 +410,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { trigger_unregister_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id_unregister.clone(), account_id.clone(), )), @@ -426,7 +426,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { trigger_should_be_unregistered_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id_to_be_unregistered.clone(), account_id, )), @@ -470,7 +470,7 @@ fn trigger_burn_repetitions() -> Result<()> { trigger_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id, )), @@ -514,7 +514,7 @@ fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_origin wasm.clone(), Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id, account_id.clone(), )), @@ -555,7 +555,7 @@ fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Numeric { fn build_register_trigger_isi( asset_id: AssetId, trigger_instructions: Vec, -) -> Register> { +) -> Register> { let trigger_id: TriggerId = TRIGGER_NAME.parse().expect("Valid"); Register::trigger(Trigger::new( @@ -564,7 +564,7 @@ fn build_register_trigger_isi( trigger_instructions, Repeats::Indefinitely, asset_id.account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id, asset_id.account_id, )), diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 0ae18175351..a6b76dcfd41 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -23,7 +23,7 @@ fn must_execute_both_triggers() -> Result<()> { [instruction.clone()], Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { + TriggeringEventFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { id_matcher: None, event_matcher: Some(AccountEventMatcher::ByCreated), })), @@ -37,7 +37,7 @@ fn must_execute_both_triggers() -> Result<()> { [instruction], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { + TriggeringEventFilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { id_matcher: None, event_matcher: Some(DomainEventMatcher::ByCreated), })), @@ -90,7 +90,7 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu [Mint::asset_numeric(1u32, asset_id.clone())], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { + TriggeringEventFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { id_matcher: None, event_matcher: Some(AccountEventMatcher::ByCreated), })), diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index ae4ca5862f0..f8675fb235d 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -24,7 +24,7 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { vec![instruction], Repeats::Indefinitely, account_id, - TriggeringFilterBox::Data(DataEventFilter::ByAssetDefinition( + TriggeringEventFilterBox::Data(DataEventFilter::ByAssetDefinition( AssetDefinitionEventFilter { id_matcher: None, event_matcher: Some(AssetDefinitionEventMatcher::ByCreated), diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index fcb714bb711..3f05fc05229 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -52,7 +52,7 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result vec![instruction], Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::Time(TimeEventFilter::new(ExecutionTime::Schedule(schedule))), + TriggeringEventFilterBox::Time(TimeEventFilter::new(ExecutionTime::Schedule(schedule))), ), )); test_client.submit(register_trigger)?; @@ -110,7 +110,7 @@ fn change_asset_metadata_after_1_sec() -> Result<()> { vec![instruction], Repeats::from(1_u32), account_id.clone(), - TriggeringFilterBox::Time(TimeEventFilter::new(ExecutionTime::Schedule(schedule))), + TriggeringEventFilterBox::Time(TimeEventFilter::new(ExecutionTime::Schedule(schedule))), ), )); test_client.submit(register_trigger)?; @@ -154,7 +154,7 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> { vec![instruction], Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::Time(TimeEventFilter::new(ExecutionTime::PreCommit)), + TriggeringEventFilterBox::Time(TimeEventFilter::new(ExecutionTime::PreCommit)), ), )); test_client.submit(register_trigger)?; @@ -229,7 +229,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { WasmSmartContract::from_compiled(wasm), Repeats::Indefinitely, alice_id.clone(), - TriggeringFilterBox::Time(TimeEventFilter::new(ExecutionTime::Schedule(schedule))), + TriggeringEventFilterBox::Time(TimeEventFilter::new(ExecutionTime::Schedule(schedule))), ), )); test_client.submit(register_trigger)?; @@ -273,7 +273,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { fn get_block_committed_event_listener( client: &Client, ) -> Result>> { - let block_filter = FilterBox::Pipeline( + let block_filter = EventFilterBox::Pipeline( PipelineEventFilter::new() .entity_kind(PipelineEntityKind::Block) .status_kind(PipelineStatusKind::Committed), diff --git a/client/tests/integration/triggers/trigger_rollback.rs b/client/tests/integration/triggers/trigger_rollback.rs index 82031f7ea42..45396186b12 100644 --- a/client/tests/integration/triggers/trigger_rollback.rs +++ b/client/tests/integration/triggers/trigger_rollback.rs @@ -28,7 +28,7 @@ fn failed_trigger_revert() -> Result<()> { instructions, Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id, )), diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 83de90a0d3c..589b9495c6c 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -265,15 +265,15 @@ mod events { impl RunArgs for Args { fn run(self, context: &mut dyn RunContext) -> Result<()> { let filter = match self { - Args::Pipeline => FilterBox::Pipeline(PipelineEventFilter::new()), - Args::Data => FilterBox::Data(DataEventFilter::ByAny), - Args::Notification => FilterBox::Notification(NotificationEventFilter::ByAny), + Args::Pipeline => EventFilterBox::Pipeline(PipelineEventFilter::new()), + Args::Data => EventFilterBox::Data(DataEventFilter::ByAny), + Args::Notification => EventFilterBox::Notification(NotificationEventFilter::ByAny), }; listen(filter, context) } } - fn listen(filter: FilterBox, context: &mut dyn RunContext) -> Result<()> { + fn listen(filter: EventFilterBox, context: &mut dyn RunContext) -> Result<()> { let iroha_client = context.client_from_config(); eprintln!("Listening to events with filter: {filter:?}"); iroha_client diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index 5f36bb2208c..1a8c9d78aee 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -378,7 +378,7 @@ mod tests { Vec::::new(), Repeats::Indefinitely, account_id.clone(), - TriggeringFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( + TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( trigger_id.clone(), account_id.clone(), )), diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 9560c23c1b5..88db4d6330b 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -50,7 +50,7 @@ impl_lazy! { iroha_data_model::metadata::MetadataValueBox, 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 6c25c8d2530..4205286f724 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -20,7 +20,7 @@ pub mod isi { use super::{super::prelude::*, *}; - impl Execute for Register> { + impl Execute for Register> { #[metrics(+"register_trigger")] fn execute(self, _authority: &AccountId, wsv: &mut WorldStateView) -> Result<(), Error> { let new_trigger = self.object; @@ -38,25 +38,25 @@ pub mod isi { let triggers = wsv.triggers_mut(); let trigger_id = new_trigger.id().clone(); let success = match &new_trigger.action.filter { - TriggeringFilterBox::Data(_) => triggers.add_data_trigger( + TriggeringEventFilterBox::Data(_) => triggers.add_data_trigger( &engine, new_trigger .try_into() .map_err(|e: &str| Error::Conversion(e.to_owned()))?, ), - TriggeringFilterBox::Pipeline(_) => triggers.add_pipeline_trigger( + TriggeringEventFilterBox::Pipeline(_) => triggers.add_pipeline_trigger( &engine, new_trigger .try_into() .map_err(|e: &str| Error::Conversion(e.to_owned()))?, ), - TriggeringFilterBox::Time(_) => triggers.add_time_trigger( + TriggeringEventFilterBox::Time(_) => triggers.add_time_trigger( &engine, new_trigger .try_into() .map_err(|e: &str| Error::Conversion(e.to_owned()))?, ), - TriggeringFilterBox::ExecuteTrigger(_) => triggers.add_by_call_trigger( + TriggeringEventFilterBox::ExecuteTrigger(_) => triggers.add_by_call_trigger( &engine, new_trigger .try_into() @@ -79,7 +79,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(); @@ -98,7 +98,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; @@ -130,7 +130,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; @@ -159,7 +159,7 @@ pub mod isi { wsv.triggers() .inspect_by_id(id, |action| -> Result<(), Error> { - let allow_execute = if let TriggeringFilterBox::ExecuteTrigger(filter) = + let allow_execute = if let TriggeringEventFilterBox::ExecuteTrigger(filter) = action.clone_and_box().filter { let event = ExecuteTriggerEvent { @@ -194,7 +194,7 @@ pub mod isi { pub mod query { //! Queries associated to triggers. use iroha_data_model::{ - events::TriggeringFilterBox, + events::TriggeringEventFilterBox, metadata::MetadataValueBox, query::error::QueryExecutionFail as Error, trigger::{Trigger, TriggerId}, @@ -215,7 +215,10 @@ 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 = &self.id; iroha_logger::trace!(%id); // Can't use just `LoadedActionTrait::clone_and_box` cause this will trigger lifetime mismatch @@ -256,7 +259,7 @@ pub mod query { fn execute<'wsv>( &self, wsv: &'wsv WorldStateView, - ) -> eyre::Result> + 'wsv>, Error> + ) -> eyre::Result> + 'wsv>, Error> { let domain_id = &self.domain_id; diff --git a/core/src/smartcontracts/isi/triggers/set.rs b/core/src/smartcontracts/isi/triggers/set.rs index 6af4480ca82..dc1587848bb 100644 --- a/core/src/smartcontracts/isi/triggers/set.rs +++ b/core/src/smartcontracts/isi/triggers/set.rs @@ -88,13 +88,15 @@ pub trait LoadedActionTrait { fn mintable(&self) -> bool; /// Convert action to a boxed representation - fn into_boxed(self) -> LoadedAction; + fn into_boxed(self) -> LoadedAction; /// Same as [`into_boxed()`](LoadedActionTrait::into_boxed) but clones `self` - fn clone_and_box(&self) -> LoadedAction; + fn clone_and_box(&self) -> LoadedAction; } -impl + Clone> LoadedActionTrait for LoadedAction { +impl + Clone> LoadedActionTrait + for LoadedAction +{ fn executable(&self) -> &LoadedExecutable { &self.executable } @@ -119,7 +121,7 @@ impl + Clone> LoadedActionTrait for L self.filter.mintable() } - fn into_boxed(self) -> LoadedAction { + fn into_boxed(self) -> LoadedAction { let Self { executable, repeats, @@ -137,7 +139,7 @@ impl + Clone> LoadedActionTrait for L } } - fn clone_and_box(&self) -> LoadedAction { + fn clone_and_box(&self) -> LoadedAction { self.clone().into_boxed() } } diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 1d1de7ac494..8b67fe14c53 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -672,7 +672,7 @@ pub trait TestClient: Sized { fn test_with_account(api_url: &SocketAddr, keys: KeyPair, account_id: &AccountId) -> Self; /// Loop for events with filter and handler function - fn for_each_event(self, event_filter: FilterBox, f: impl Fn(Result)); + fn for_each_event(self, event_filter: EventFilterBox, f: impl Fn(Result)); /// Submit instruction with polling /// @@ -811,7 +811,7 @@ impl TestClient for Client { Client::new(config) } - fn for_each_event(self, event_filter: FilterBox, f: impl Fn(Result)) { + fn for_each_event(self, event_filter: EventFilterBox, f: impl Fn(Result)) { for event_result in self .listen_for_events(event_filter) .expect("Failed to create event iterator.") diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 5be779f4af7..8778d95d277 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -486,7 +486,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/events/mod.rs b/data_model/src/events/mod.rs index 21b17ae7652..d6a42cf050d 100644 --- a/data_model/src/events/mod.rs +++ b/data_model/src/events/mod.rs @@ -72,7 +72,7 @@ pub mod model { )] // TODO: Temporarily made opaque #[ffi_type(opaque)] - pub enum FilterBox { + pub enum EventFilterBox { /// Listen to pipeline events with filter. Pipeline(pipeline::PipelineEventFilter), /// Listen to data events with filter. @@ -92,7 +92,7 @@ pub mod model { )] // TODO: Temporarily made opaque #[ffi_type(opaque)] - pub enum TriggeringFilterBox { + pub enum TriggeringEventFilterBox { /// Listen to pipeline events with filter. Pipeline(pipeline::PipelineEventFilter), /// Listen to data events with filter. @@ -133,7 +133,7 @@ pub trait EventFilter { } #[cfg(feature = "transparent_api")] -impl EventFilter for FilterBox { +impl EventFilter for EventFilterBox { type Event = Event; /// Apply filter to event. @@ -162,7 +162,7 @@ impl EventFilter for FilterBox { } #[cfg(feature = "transparent_api")] -impl EventFilter for TriggeringFilterBox { +impl EventFilter for TriggeringEventFilterBox { type Event = Event; /// Apply filter to event. @@ -210,7 +210,7 @@ pub mod stream { /// Request sent by the client to subscribe to events. #[derive(Debug, Clone, Constructor, Decode, Encode, IntoSchema)] #[repr(transparent)] - pub struct EventSubscriptionRequest(pub FilterBox); + pub struct EventSubscriptionRequest(pub EventFilterBox); } impl From for Event { @@ -228,7 +228,7 @@ pub mod prelude { pub use super::EventFilter; pub use super::{ data::prelude::*, execute_trigger::prelude::*, notification::prelude::*, - pipeline::prelude::*, time::prelude::*, Event, FilterBox, TriggeringEventType, - TriggeringFilterBox, + pipeline::prelude::*, time::prelude::*, Event, EventFilterBox, TriggeringEventFilterBox, + TriggeringEventType, }; } diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index ef63f12a28f..2ac25db4fa6 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -147,21 +147,21 @@ impl_instruction! { Register, Register, Register, - Register>, + Register>, Unregister, Unregister, Unregister, Unregister, Unregister, Unregister, - Unregister>, + Unregister>, Mint, Mint, Mint, - Mint>, + Mint>, Burn, Burn, - Burn>, + Burn>, Transfer, Transfer, Transfer, @@ -485,9 +485,9 @@ mod transparent { } } - impl Register> { + impl Register> { /// Constructs a new [`Register`] for a [`Trigger`]. - pub fn trigger(new_trigger: Trigger) -> Self { + pub fn trigger(new_trigger: Trigger) -> Self { Self { object: new_trigger, } @@ -511,7 +511,7 @@ mod transparent { Register | Register | Register | - Register> + Register> => RegisterBox => InstructionBox[Register], => RegisterBoxRef<'a> => InstructionBoxRef<'a>[Register] } @@ -542,7 +542,7 @@ mod transparent { Unregister | Unregister | Unregister | - Unregister> + Unregister> => UnregisterBox => InstructionBox[Unregister], => UnregisterBoxRef<'a> => InstructionBoxRef<'a>[Unregister] } @@ -597,7 +597,7 @@ mod transparent { } } - impl Unregister> { + impl Unregister> { /// Constructs a new [`Unregister`] for a [`Trigger`]. pub fn trigger(trigger_id: TriggerId) -> Self { Self { @@ -650,7 +650,7 @@ mod transparent { } } - impl Mint> { + impl Mint> { /// Constructs a new [`Mint`] for repetition count of [`Trigger`]. pub fn trigger_repetitions(repetitions: u32, trigger_id: TriggerId) -> Self { Self { @@ -683,7 +683,7 @@ mod transparent { Mint | Mint | Mint | - Mint> + Mint> => MintBox => InstructionBox[Mint], => MintBoxRef<'a> => InstructionBoxRef<'a>[Mint] } @@ -719,7 +719,7 @@ mod transparent { } } - impl Burn> { + impl Burn> { /// Constructs a new [`Burn`] for repetition count of [`Trigger`]. pub fn trigger_repetitions(repetitions: u32, trigger_id: TriggerId) -> Self { Self { @@ -744,7 +744,7 @@ mod transparent { impl_into_box! { Burn | Burn | - Burn> + Burn> => BurnBox => InstructionBox[Burn], => BurnBoxRef<'a> => InstructionBoxRef<'a>[Burn] } @@ -1102,7 +1102,7 @@ isi_box! { /// Register [`Role`]. Role(Register), /// Register [`Trigger`]. - Trigger(Register>) + Trigger(Register>) } } @@ -1127,7 +1127,7 @@ isi_box! { /// Unregister [`Role`]. Role(Unregister), /// Unregister [`Trigger`]. - Trigger(Unregister>) + Trigger(Unregister>) } } @@ -1145,7 +1145,7 @@ isi_box! { /// Mint for [`Asset`]. Asset(Mint), /// Mint [`Trigger`] repetitions. - TriggerRepetitions(Mint>), + TriggerRepetitions(Mint>), } } @@ -1177,7 +1177,7 @@ isi_box! { /// Burn [`Asset`]. Asset(Burn), /// Burn [`Trigger`] repetitions. - TriggerRepetitions(Burn>), + TriggerRepetitions(Burn>), } } diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index db04257ad1e..06db2566b03 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -18,7 +18,7 @@ use alloc::{ use core::{fmt, fmt::Debug, ops::RangeInclusive, str::FromStr}; use derive_more::{Constructor, Display, From, FromStr}; -use events::TriggeringFilterBox; +use events::TriggeringEventFilterBox; use getset::Getters; use iroha_crypto::PublicKey; use iroha_data_model_derive::{model, EnumRef, IdEqOrdHash}; @@ -86,7 +86,7 @@ mod seal { Register, Register, Register, - Register >, + Register >, Unregister, Unregister, @@ -94,16 +94,16 @@ mod seal { Unregister, Unregister, Unregister, - Unregister >, + Unregister >, Mint, Mint, Mint, - Mint >, + Mint >, Burn, Burn, - Burn >, + Burn >, Transfer, Transfer, @@ -722,7 +722,7 @@ pub mod model { /// [`Asset`](`asset::Asset`) variant. Asset(asset::Asset), /// [`Trigger`](`trigger::Trigger`) variant. - Trigger(trigger::Trigger), + Trigger(trigger::Trigger), /// [`Role`](`role::Role`) variant. Role(role::Role), /// [`Parameter`](`parameter::Parameter`) variant. @@ -916,7 +916,7 @@ impl_encode_as_identifiable_box! { account::Account, asset::AssetDefinition, asset::Asset, - trigger::Trigger, + trigger::Trigger, role::Role, parameter::Parameter, } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index 9f3e402f8fd..b3d3cc6dded 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -31,7 +31,7 @@ use self::{ use crate::{ account::{Account, AccountId}, block::{BlockHeader, SignedBlock}, - events::TriggeringFilterBox, + events::TriggeringEventFilterBox, metadata::MetadataValueBox, seal, transaction::{SignedTransaction, TransactionPayload, TransactionValue}, @@ -364,9 +364,9 @@ impl_query! { FindAllPeers => Vec, FindAllParameters => Vec, FindAllActiveTriggerIds => Vec, - FindTriggerById => crate::trigger::Trigger, + FindTriggerById => crate::trigger::Trigger, FindTriggerKeyValueByIdAndKey => MetadataValueBox, - FindTriggersByDomainId => Vec>, + FindTriggersByDomainId => Vec>, FindAllTransactions => Vec, FindTransactionsByAccountId => Vec, FindTransactionByHash => TransactionQueryOutput, @@ -477,7 +477,7 @@ from_and_try_from_value_identifiable!( Account(crate::account::Account), AssetDefinition(crate::asset::AssetDefinition), Asset(crate::asset::Asset), - Trigger(crate::trigger::Trigger), + Trigger(crate::trigger::Trigger), Role(crate::role::Role), Parameter(crate::parameter::Parameter), ); @@ -986,6 +986,7 @@ pub mod trigger { use super::{MetadataValueBox, Query, QueryType}; use crate::{ domain::prelude::*, + events::TriggeringEventFilterBox, prelude::InstructionBox, trigger::{Trigger, TriggerId}, Executable, Identifiable, Name, diff --git a/data_model/src/trigger.rs b/data_model/src/trigger.rs index 4270d2d34ac..df53f68707b 100644 --- a/data_model/src/trigger.rs +++ b/data_model/src/trigger.rs @@ -73,30 +73,30 @@ pub mod model { } #[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> { + impl TryFrom> for Trigger<$filter_type> { type Error = &'static str; - fn try_from(boxed: Trigger) -> Result { - if let TriggeringFilterBox::$variant(concrete_filter) = boxed.action.filter { + fn try_from(boxed: Trigger) -> Result { + if let TriggeringEventFilterBox::$variant(concrete_filter) = boxed.action.filter { let action = action::Action::new( boxed.action.executable, boxed.action.repeats, @@ -108,7 +108,7 @@ macro_rules! impl_try_from_box { action, }) } else { - Err(concat!("Expected `TriggeringFilterBox::", stringify!($variant),"`, but another variant found")) + Err(concat!("Expected `TriggeringEventFilterBox::", stringify!($variant),"`, but another variant found")) } } } @@ -222,7 +222,7 @@ pub mod action { } #[ffi_impl_opaque] - impl Action { + impl Action { /// The executable linked to this action pub fn executable(&self) -> &Executable { &self.executable @@ -238,7 +238,7 @@ pub mod action { &self.authority } /// Defines events which trigger the `Action` - pub fn filter(&self) -> &TriggeringFilterBox { + pub fn filter(&self) -> &TriggeringEventFilterBox { &self.filter } } @@ -330,20 +330,22 @@ mod tests { #[test] fn trigger_with_filterbox_can_be_unboxed() { - /// Should fail to compile if a new variant will be added to `TriggeringFilterBox` + /// Should fail to compile if a new variant will be added to `TriggeringEventFilterBox` #[allow(dead_code)] - fn compile_time_check(boxed: Trigger) { + fn compile_time_check(boxed: Trigger) { match &boxed.action.filter { - TriggeringFilterBox::Data(_) => Trigger::::try_from(boxed) + TriggeringEventFilterBox::Data(_) => Trigger::::try_from(boxed) .map(|_| ()) .unwrap(), - TriggeringFilterBox::Pipeline(_) => Trigger::::try_from(boxed) - .map(|_| ()) - .unwrap(), - TriggeringFilterBox::Time(_) => Trigger::::try_from(boxed) + TriggeringEventFilterBox::Pipeline(_) => { + Trigger::::try_from(boxed) + .map(|_| ()) + .unwrap() + } + TriggeringEventFilterBox::Time(_) => Trigger::::try_from(boxed) .map(|_| ()) .unwrap(), - TriggeringFilterBox::ExecuteTrigger(_) => { + TriggeringEventFilterBox::ExecuteTrigger(_) => { Trigger::::try_from(boxed) .map(|_| ()) .unwrap() diff --git a/data_model/src/visit.rs b/data_model/src/visit.rs index e45b1939dc4..56abc38f676 100644 --- a/data_model/src/visit.rs +++ b/data_model/src/visit.rs @@ -94,7 +94,7 @@ pub trait Visit { visit_register_asset_definition(&Register), visit_register_asset(&Register), visit_register_role(&Register), - visit_register_trigger(&Register>), + visit_register_trigger(&Register>), // Visit UnregisterBox visit_unregister_peer(&Unregister), @@ -104,18 +104,18 @@ pub trait Visit { 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 MintBox visit_mint_asset_numeric(&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 BurnBox visit_burn_account_public_key(&Burn), visit_burn_asset_numeric(&Burn), - visit_burn_trigger_repetitions(&Burn>), + visit_burn_trigger_repetitions(&Burn>), // Visit TransferBox visit_transfer_asset_definition(&Transfer), @@ -429,10 +429,10 @@ leaf_visitors! { visit_revoke_account_role(&Revoke), visit_grant_role_permission(&Grant), visit_revoke_role_permission(&Revoke), - visit_register_trigger(&Register>), - visit_unregister_trigger(&Unregister>), - visit_mint_trigger_repetitions(&Mint>), - visit_burn_trigger_repetitions(&Burn>), + visit_register_trigger(&Register>), + visit_unregister_trigger(&Unregister>), + visit_mint_trigger_repetitions(&Mint>), + visit_burn_trigger_repetitions(&Burn>), visit_upgrade(&Upgrade), visit_new_parameter(&NewParameter), visit_set_parameter(&SetParameter), diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 95ff16deaea..4f81e53e4ab 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -192,7 +192,7 @@ } ] }, - "Action": { + "Action": { "Struct": [ { "name": "executable", @@ -208,7 +208,7 @@ }, { "name": "filter", - "type": "TriggeringFilterBox" + "type": "TriggeringEventFilterBox" }, { "name": "metadata", @@ -667,7 +667,7 @@ } ] }, - "Burn>": { + "Burn>": { "Struct": [ { "name": "object", @@ -694,7 +694,7 @@ { "tag": "TriggerRepetitions", "discriminant": 2, - "type": "Burn>" + "type": "Burn>" } ] }, @@ -995,8 +995,37 @@ } ] }, + "EventFilterBox": { + "Enum": [ + { + "tag": "Pipeline", + "discriminant": 0, + "type": "PipelineEventFilter" + }, + { + "tag": "Data", + "discriminant": 1, + "type": "DataEventFilter" + }, + { + "tag": "Time", + "discriminant": 2, + "type": "TimeEventFilter" + }, + { + "tag": "ExecuteTrigger", + "discriminant": 3, + "type": "ExecuteTriggerEventFilter" + }, + { + "tag": "Notification", + "discriminant": 4, + "type": "NotificationEventFilter" + } + ] + }, "EventMessage": "Event", - "EventSubscriptionRequest": "FilterBox", + "EventSubscriptionRequest": "EventFilterBox", "Executable": { "Enum": [ { @@ -1094,35 +1123,6 @@ } ] }, - "FilterBox": { - "Enum": [ - { - "tag": "Pipeline", - "discriminant": 0, - "type": "PipelineEventFilter" - }, - { - "tag": "Data", - "discriminant": 1, - "type": "DataEventFilter" - }, - { - "tag": "Time", - "discriminant": 2, - "type": "TimeEventFilter" - }, - { - "tag": "ExecuteTrigger", - "discriminant": 3, - "type": "ExecuteTriggerEventFilter" - }, - { - "tag": "Notification", - "discriminant": 4, - "type": "NotificationEventFilter" - } - ] - }, "FindAccountById": { "Struct": [ { @@ -1639,7 +1639,7 @@ { "tag": "Trigger", "discriminant": 9, - "type": "Trigger" + "type": "Trigger" }, { "tag": "Role", @@ -2167,7 +2167,7 @@ } ] }, - "Mint>": { + "Mint>": { "Struct": [ { "name": "object", @@ -2194,7 +2194,7 @@ { "tag": "TriggerRepetitions", "discriminant": 2, - "type": "Mint>" + "type": "Mint>" } ] }, @@ -3075,11 +3075,11 @@ } ] }, - "Register>": { + "Register>": { "Struct": [ { "name": "object", - "type": "Trigger" + "type": "Trigger" } ] }, @@ -3118,7 +3118,7 @@ { "tag": "Trigger", "discriminant": 6, - "type": "Register>" + "type": "Register>" } ] }, @@ -3335,10 +3335,6 @@ { "tag": "ByPermissionRemoved", "discriminant": 2 - }, - { - "tag": "ByPermissionAdded", - "discriminant": 3 } ] }, @@ -3962,7 +3958,7 @@ } ] }, - "Trigger": { + "Trigger": { "Struct": [ { "name": "id", @@ -3970,7 +3966,7 @@ }, { "name": "action", - "type": "Action" + "type": "Action" } ] }, @@ -4103,7 +4099,7 @@ } ] }, - "TriggeringFilterBox": { + "TriggeringEventFilterBox": { "Enum": [ { "tag": "Pipeline", @@ -4194,7 +4190,7 @@ } ] }, - "Unregister>": { + "Unregister>": { "Struct": [ { "name": "object_id", @@ -4237,7 +4233,7 @@ { "tag": "Trigger", "discriminant": 6, - "type": "Unregister>" + "type": "Unregister>" } ] }, diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 3fcc186a964..30804bbd706 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -70,7 +70,7 @@ types!( AccountMintBox, AccountPermissionChanged, AccountRoleChanged, - Action, + Action, Algorithm, Asset, AssetChanged, @@ -107,7 +107,7 @@ types!( BlockSubscriptionRequest, Box>, Box, - Burn>, + Burn>, Burn, Burn, BurnBox, @@ -137,7 +137,7 @@ types!( Executor, ExecutorEvent, Fail, - FilterBox, + EventFilterBox, FindAccountById, FindAccountKeyValueByIdAndKey, FindAccountsByDomainId, @@ -212,7 +212,7 @@ types!( MetadataError, MetadataLimits, MetadataValueBox, - Mint>, + Mint>, Mint, Mint, Mint, @@ -280,7 +280,7 @@ types!( Register, Register, Register, - Register>, + Register>, RegisterBox, RemoveKeyValue, RemoveKeyValue, @@ -345,7 +345,7 @@ types!( Transfer, Transfer, TransferBox, - Trigger, + Trigger, TriggerCompletedEvent, TriggerCompletedEventFilter, TriggerCompletedOutcome, @@ -355,7 +355,7 @@ types!( TriggerEventMatcher, TriggerId, TriggerNumberOfExecutionsChanged, - TriggeringFilterBox, + TriggeringEventFilterBox, TypeError, UniqueVec, Unregister, @@ -364,7 +364,7 @@ types!( Unregister, Unregister, Unregister, - Unregister>, + Unregister>, UnregisterBox, Upgrade, ValidationFail, diff --git a/smart_contract/executor/derive/src/default.rs b/smart_contract/executor/derive/src/default.rs index 4e46084bde5..af341e733d3 100644 --- a/smart_contract/executor/derive/src/default.rs +++ b/smart_contract/executor/derive/src/default.rs @@ -151,10 +151,10 @@ pub fn impl_derive_visit(emitter: &mut Emitter, input: &syn::DeriveInput) -> Tok "fn visit_revoke_account_role(operation: &Revoke)", "fn visit_grant_role_permission(operation: &Grant)", "fn visit_revoke_role_permission(operation: &Revoke)", - "fn visit_register_trigger(operation: &Register>)", - "fn visit_unregister_trigger(operation: &Unregister>)", - "fn visit_mint_trigger_repetitions(operation: &Mint>)", - "fn visit_burn_trigger_repetitions(operation: &Burn>)", + "fn visit_register_trigger(operation: &Register>)", + "fn visit_unregister_trigger(operation: &Unregister>)", + "fn visit_mint_trigger_repetitions(operation: &Mint>)", + "fn visit_burn_trigger_repetitions(operation: &Burn>)", "fn visit_execute_trigger(operation: &ExecuteTrigger)", "fn visit_set_parameter(operation: &SetParameter)", "fn visit_new_parameter(operation: &NewParameter)", diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index 41a4ab12b46..e7e9a2645e9 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -1403,7 +1403,7 @@ pub mod trigger { pub fn visit_register_trigger( executor: &mut V, _authority: &AccountId, - isi: &Register>, + isi: &Register>, ) { execute!(executor, isi) } @@ -1411,7 +1411,7 @@ pub mod trigger { pub fn visit_unregister_trigger( executor: &mut V, authority: &AccountId, - isi: &Unregister>, + isi: &Unregister>, ) { let trigger_id = isi.object_id(); @@ -1446,7 +1446,7 @@ pub mod trigger { pub fn visit_mint_trigger_repetitions( executor: &mut V, authority: &AccountId, - isi: &Mint>, + isi: &Mint>, ) { let trigger_id = isi.destination_id(); @@ -1474,7 +1474,7 @@ pub mod trigger { pub fn visit_burn_trigger_repetitions( executor: &mut V, authority: &AccountId, - isi: &Burn>, + isi: &Burn>, ) { let trigger_id = isi.destination_id(); diff --git a/tools/parity_scale_decoder/build.rs b/tools/parity_scale_decoder/build.rs index 00391f5e58e..cab5c555b19 100644 --- a/tools/parity_scale_decoder/build.rs +++ b/tools/parity_scale_decoder/build.rs @@ -12,7 +12,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 0d3988a2ad8..6dfab3905ca 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -271,11 +271,11 @@ 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![Mint::asset_numeric(1u32, rose_id)], Repeats::Indefinitely, account_id, - FilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { + EventFilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { id_matcher: None, event_matcher: None, })), @@ -284,7 +284,7 @@ mod tests { decode_sample( "trigger.bin", - String::from("Trigger"), + String::from("Trigger"), &trigger, ); } diff --git a/torii/src/event.rs b/torii/src/event.rs index 9a9dcc0ff1d..873f81d91ec 100644 --- a/torii/src/event.rs +++ b/torii/src/event.rs @@ -19,7 +19,9 @@ pub enum Error { Stream(Box), /// Error from converting received message to filter #[error("Can't retrieve subscription filter: {0}")] - CantRetrieveSubscriptionFilter(#[from] ErrorTryFromEnum), + CantRetrieveSubscriptionFilter( + #[from] ErrorTryFromEnum, + ), /// Error from provided websocket #[error("WebSocket error: {0}")] WebSocket(#[from] warp::Error), @@ -42,7 +44,7 @@ pub type Result = core::result::Result; #[derive(Debug)] pub struct Consumer { stream: WebSocket, - filter: FilterBox, + filter: EventFilterBox, } impl Consumer { From 20e9c6d714bea9d8fa3d522879b6fa2a30667fca Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Tue, 20 Feb 2024 10:29:52 +0300 Subject: [PATCH 05/13] [refactor] #1981, #4195: make listen_for_events and friends implicitly convert event filter types Signed-off-by: Nikita Strygin --- client/benches/tps/utils.rs | 3 +-- client/src/client.rs | 17 ++++++++++------- client/tests/integration/events/data.rs | 4 ++-- client/tests/integration/events/notification.rs | 6 ++---- client/tests/integration/events/pipeline.rs | 7 +++---- .../integration/triggers/by_call_trigger.rs | 2 +- .../tests/integration/triggers/time_trigger.rs | 8 +++----- 7 files changed, 22 insertions(+), 25 deletions(-) diff --git a/client/benches/tps/utils.rs b/client/benches/tps/utils.rs index c00aed40439..0f791382e5e 100644 --- a/client/benches/tps/utils.rs +++ b/client/benches/tps/utils.rs @@ -173,8 +173,7 @@ impl MeasurerUnit { let (init_sender, init_receiver) = mpsc::channel(); let event_filter = PipelineEventFilter::new() .entity_kind(PipelineEntityKind::Block) - .status_kind(PipelineStatusKind::Committed) - .into(); + .status_kind(PipelineStatusKind::Committed); let blocks_expected = self.config.blocks as usize; let name = self.name; let handle = thread::spawn(move || -> Result<()> { diff --git a/client/src/client.rs b/client/src/client.rs index 5bf9ce65880..0ca27786689 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -605,9 +605,7 @@ impl Client { let mut event_iterator = { let event_iterator_result = tokio::time::timeout_at( deadline, - self.listen_for_events_async( - PipelineEventFilter::new().hash(hash.into()).into(), - ), + self.listen_for_events_async(PipelineEventFilter::new().hash(hash.into())), ) .await .map_err(Into::into) @@ -905,8 +903,9 @@ impl Client { /// - Forwards from [`events_api::EventIterator::new`] pub fn listen_for_events( &self, - event_filter: EventFilterBox, + event_filter: impl Into, ) -> Result>> { + let event_filter = event_filter.into(); iroha_logger::trace!(?event_filter); events_api::EventIterator::new(self.events_handler(event_filter)?) } @@ -918,8 +917,9 @@ impl Client { /// - Forwards from [`events_api::AsyncEventStream::new`] pub async fn listen_for_events_async( &self, - event_filter: EventFilterBox, + event_filter: impl Into, ) -> Result { + let event_filter = event_filter.into(); iroha_logger::trace!(?event_filter, "Async listening with"); events_api::AsyncEventStream::new(self.events_handler(event_filter)?).await } @@ -929,9 +929,12 @@ impl Client { /// # Errors /// Fails if handler construction fails #[inline] - pub fn events_handler(&self, event_filter: EventFilterBox) -> Result { + pub fn events_handler( + &self, + event_filter: impl Into, + ) -> Result { events_api::flow::Init::new( - event_filter, + event_filter.into(), self.headers.clone(), self.torii_url .join(torii_uri::SUBSCRIPTION) diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index e1f41807972..3136f369860 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -138,7 +138,7 @@ fn transaction_execution_should_produce_events( let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = EventFilterBox::Data(DataEventFilter::ByAny); + let event_filter = DataEventFilter::ByAny; thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; @@ -182,7 +182,7 @@ fn produce_multiple_events() -> Result<()> { let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = EventFilterBox::Data(DataEventFilter::ByAny); + let event_filter = DataEventFilter::ByAny; thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index 5b3f0e9e7bc..8ca576a6f33 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -38,8 +38,7 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { NotificationEventFilter::ByTriggerCompleted(TriggerCompletedEventFilter::new( Some(trigger_id), Some(TriggerCompletedOutcomeType::Success), - )) - .into(), + )), )?; if event_it.next().is_some() { sender.send(())?; @@ -87,8 +86,7 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { NotificationEventFilter::ByTriggerCompleted(TriggerCompletedEventFilter::new( Some(trigger_id), Some(TriggerCompletedOutcomeType::Failure), - )) - .into(), + )), )?; if event_it.next().is_some() { sender.send(())?; diff --git a/client/tests/integration/events/pipeline.rs b/client/tests/integration/events/pipeline.rs index 292a0f97e95..fc4bce6f2d9 100644 --- a/client/tests/integration/events/pipeline.rs +++ b/client/tests/integration/events/pipeline.rs @@ -82,12 +82,12 @@ impl Checker { thread::spawn(move || { let mut event_iterator = self .listener - .listen_for_events(EventFilterBox::Pipeline( + .listen_for_events( PipelineEventFilter::new() .entity_kind(PipelineEntityKind::Transaction) .status_kind(status_kind) .hash(*self.hash), - )) + ) .expect("Failed to create event iterator."); let event_result = event_iterator.next().expect("Stream closed"); let _event = event_result.expect("Must be valid"); @@ -102,8 +102,7 @@ fn committed_block_must_be_available_in_kura() { let event_filter = PipelineEventFilter::new() .entity_kind(PipelineEntityKind::Block) - .status_kind(PipelineStatusKind::Committed) - .into(); + .status_kind(PipelineStatusKind::Committed); let mut event_iter = client .listen_for_events(event_filter) .expect("Failed to subscribe for events"); diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index 7df6f7c1878..7d56c0e59ef 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -60,7 +60,7 @@ fn execute_trigger_should_produce_event() -> Result<()> { let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { let mut event_it = thread_client - .listen_for_events(ExecuteTriggerEventFilter::new(trigger_id, account_id).into())?; + .listen_for_events(ExecuteTriggerEventFilter::new(trigger_id, account_id))?; if event_it.next().is_some() { sender.send(())?; return Ok(()); diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index 3f05fc05229..e74679661fc 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -273,11 +273,9 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { fn get_block_committed_event_listener( client: &Client, ) -> Result>> { - let block_filter = EventFilterBox::Pipeline( - PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Block) - .status_kind(PipelineStatusKind::Committed), - ); + let block_filter = PipelineEventFilter::new() + .entity_kind(PipelineEntityKind::Block) + .status_kind(PipelineStatusKind::Committed); client.listen_for_events(block_filter) } From a446c5362d99000e461190cd195897fcf8e48c74 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Tue, 20 Feb 2024 14:12:02 +0300 Subject: [PATCH 06/13] [refactor] #1981, #4195, #3068: Unify various event filter APIs, introduce a fluent builder API - All event filters implement Debug, Clone, Eq, Ord - All event filters (except TimeEventFilter) have a similar fluent builder API Event filter starts by accepting anything, with each method call limiting the accepted events - Structs with hidden fields provide getters & builder APIs to create them - Data event matchers are no longer prefixed with `By` to make them read better inside the `only_events` method call Signed-off-by: Nikita Strygin --- client/benches/tps/utils.rs | 4 +- client/src/client.rs | 6 +- .../integration/domain_owner_permissions.rs | 8 +- client/tests/integration/events/data.rs | 4 +- .../tests/integration/events/notification.rs | 42 +- client/tests/integration/events/pipeline.rs | 10 +- .../integration/triggers/by_call_trigger.rs | 97 ++- .../integration/triggers/data_trigger.rs | 21 +- .../integration/triggers/event_trigger.rs | 7 +- .../integration/triggers/time_trigger.rs | 4 +- .../integration/triggers/trigger_rollback.rs | 9 +- client_cli/src/main.rs | 2 +- core/src/smartcontracts/isi/mod.rs | 9 +- data_model/src/events/data/filters.rs | 736 +++++++++++++----- data_model/src/events/execute_trigger.rs | 49 +- data_model/src/events/mod.rs | 26 +- data_model/src/events/notification.rs | 72 +- data_model/src/events/pipeline.rs | 31 +- docs/source/references/schema.json | 100 +-- .../parity_scale_decoder/samples/trigger.bin | Bin 73 -> 74 bytes .../parity_scale_decoder/samples/trigger.json | 6 +- tools/parity_scale_decoder/src/main.rs | 7 +- 22 files changed, 850 insertions(+), 400 deletions(-) diff --git a/client/benches/tps/utils.rs b/client/benches/tps/utils.rs index 0f791382e5e..2a44abc63a4 100644 --- a/client/benches/tps/utils.rs +++ b/client/benches/tps/utils.rs @@ -172,8 +172,8 @@ impl MeasurerUnit { let listener = self.client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let event_filter = PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Block) - .status_kind(PipelineStatusKind::Committed); + .from_entity_of_kind(PipelineEntityKind::Block) + .with_status(PipelineStatusKind::Committed); let blocks_expected = self.config.blocks as usize; let name = self.name; let handle = thread::spawn(move || -> Result<()> { diff --git a/client/src/client.rs b/client/src/client.rs index 0ca27786689..2212fbf05fa 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -605,7 +605,9 @@ impl Client { let mut event_iterator = { let event_iterator_result = tokio::time::timeout_at( deadline, - self.listen_for_events_async(PipelineEventFilter::new().hash(hash.into())), + self.listen_for_events_async( + PipelineEventFilter::new().from_entity_with_hash(hash.into()), + ), ) .await .map_err(Into::into) @@ -917,7 +919,7 @@ impl Client { /// - Forwards from [`events_api::AsyncEventStream::new`] pub async fn listen_for_events_async( &self, - event_filter: impl Into, + event_filter: impl Into + Send, ) -> Result { let event_filter = event_filter.into(); iroha_logger::trace!(?event_filter, "Async listening with"); diff --git a/client/tests/integration/domain_owner_permissions.rs b/client/tests/integration/domain_owner_permissions.rs index 3763b35209d..188a009883d 100644 --- a/client/tests/integration/domain_owner_permissions.rs +++ b/client/tests/integration/domain_owner_permissions.rs @@ -309,11 +309,9 @@ fn domain_owner_trigger_permissions() -> Result<()> { trigger_instructions, Repeats::from(2_u32), bob_id, - // FIXME: due to restriction in `ExecuteTriggerEventFilter` it's impossible to execute trigger on behalf of multiple users - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - alice_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new().from_trigger(trigger_id.clone()), + ), ), )); test_client.submit_blocking(register_trigger)?; diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 3136f369860..4250ff2b682 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -138,7 +138,7 @@ fn transaction_execution_should_produce_events( let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = DataEventFilter::ByAny; + let event_filter = DataEventFilter::Any; thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; @@ -182,7 +182,7 @@ fn produce_multiple_events() -> Result<()> { let listener = client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel(); - let event_filter = DataEventFilter::ByAny; + let event_filter = DataEventFilter::Any; thread::spawn(move || -> Result<()> { let event_iterator = listener.listen_for_events(event_filter)?; init_sender.send(())?; diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index 8ca576a6f33..1920aeb4420 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -21,10 +21,11 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { vec![InstructionBox::from(instruction)], Repeats::Indefinitely, asset_id.account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - asset_id.account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(asset_id.account_id), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -34,12 +35,12 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { - let mut event_it = thread_client.listen_for_events( - NotificationEventFilter::ByTriggerCompleted(TriggerCompletedEventFilter::new( - Some(trigger_id), - Some(TriggerCompletedOutcomeType::Success), - )), - )?; + let mut event_it = + thread_client.listen_for_events(NotificationEventFilter::ByTriggerCompleted( + TriggerCompletedEventFilter::new() + .from_trigger(trigger_id) + .with_outcome(TriggerCompletedOutcomeType::Success), + ))?; if event_it.next().is_some() { sender.send(())?; return Ok(()); @@ -69,10 +70,11 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { vec![InstructionBox::from(instruction)], Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -82,12 +84,12 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { - let mut event_it = thread_client.listen_for_events( - NotificationEventFilter::ByTriggerCompleted(TriggerCompletedEventFilter::new( - Some(trigger_id), - Some(TriggerCompletedOutcomeType::Failure), - )), - )?; + let mut event_it = + thread_client.listen_for_events(NotificationEventFilter::ByTriggerCompleted( + TriggerCompletedEventFilter::new() + .from_trigger(trigger_id) + .with_outcome(TriggerCompletedOutcomeType::Failure), + ))?; if event_it.next().is_some() { sender.send(())?; return Ok(()); diff --git a/client/tests/integration/events/pipeline.rs b/client/tests/integration/events/pipeline.rs index fc4bce6f2d9..6251e586382 100644 --- a/client/tests/integration/events/pipeline.rs +++ b/client/tests/integration/events/pipeline.rs @@ -84,9 +84,9 @@ impl Checker { .listener .listen_for_events( PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Transaction) - .status_kind(status_kind) - .hash(*self.hash), + .from_entity_of_kind(PipelineEntityKind::Transaction) + .with_status(status_kind) + .from_entity_with_hash(*self.hash), ) .expect("Failed to create event iterator."); let event_result = event_iterator.next().expect("Stream closed"); @@ -101,8 +101,8 @@ fn committed_block_must_be_available_in_kura() { wait_for_genesis_committed(&[client.clone()], 0); let event_filter = PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Block) - .status_kind(PipelineStatusKind::Committed); + .from_entity_of_kind(PipelineEntityKind::Block) + .with_status(PipelineStatusKind::Committed); let mut event_iter = client .listen_for_events(event_filter) .expect("Failed to subscribe for events"); diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index 7d56c0e59ef..b2122ec46a5 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -59,8 +59,11 @@ fn execute_trigger_should_produce_event() -> Result<()> { let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { - let mut event_it = thread_client - .listen_for_events(ExecuteTriggerEventFilter::new(trigger_id, account_id))?; + let mut event_it = thread_client.listen_for_events( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id) + .under_authority(account_id), + )?; if event_it.next().is_some() { sender.send(())?; return Ok(()); @@ -121,10 +124,11 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { bad_trigger_instructions, Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - bad_trigger_id.clone(), - account_id.clone(), - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(bad_trigger_id.clone()) + .under_authority(account_id.clone()), + ), ), )); test_client.submit(register_bad_trigger)?; @@ -176,10 +180,11 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { trigger_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -240,10 +245,11 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { trigger_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -283,10 +289,11 @@ fn unregister_trigger() -> Result<()> { Vec::::new(), Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id), + ), ), ); let register_trigger = Register::trigger(trigger.clone()); @@ -360,10 +367,11 @@ fn trigger_in_genesis_using_base64() -> Result<()> { .wrap_err("Can't deserialize wasm using base64")?, Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id.clone(), - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id.clone()), + ), ), ); @@ -410,10 +418,11 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { trigger_unregister_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id_unregister.clone(), - account_id.clone(), - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id_unregister.clone()) + .under_authority(account_id.clone()), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -426,10 +435,11 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { trigger_should_be_unregistered_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id_to_be_unregistered.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id_to_be_unregistered.clone()) + .under_authority(account_id), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -470,10 +480,11 @@ fn trigger_burn_repetitions() -> Result<()> { trigger_instructions, Repeats::from(1_u32), account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id), + ), ), )); test_client.submit_blocking(register_trigger)?; @@ -514,10 +525,11 @@ fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_origin wasm.clone(), Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id, - account_id.clone(), - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id) + .under_authority(account_id.clone()), + ), ), ) }; @@ -564,10 +576,11 @@ fn build_register_trigger_isi( trigger_instructions, Repeats::Indefinitely, asset_id.account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id, - asset_id.account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id) + .under_authority(asset_id.account_id), + ), ), )) } diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index a6b76dcfd41..02dd12fcd9f 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -23,10 +23,9 @@ fn must_execute_both_triggers() -> Result<()> { [instruction.clone()], Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { - id_matcher: None, - event_matcher: Some(AccountEventMatcher::ByCreated), - })), + TriggeringEventFilterBox::Data(DataEventFilter::Account( + AccountEventFilter::new().only_events(AccountEventMatcher::Created), + )), ), )); test_client.submit_blocking(register_trigger)?; @@ -37,10 +36,9 @@ fn must_execute_both_triggers() -> Result<()> { [instruction], Repeats::Indefinitely, account_id, - TriggeringEventFilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { - id_matcher: None, - event_matcher: Some(DomainEventMatcher::ByCreated), - })), + TriggeringEventFilterBox::Data(DataEventFilter::Domain( + DomainEventFilter::new().only_events(DomainEventMatcher::Created), + )), ), )); test_client.submit_blocking(register_trigger)?; @@ -90,10 +88,9 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu [Mint::asset_numeric(1u32, asset_id.clone())], Repeats::Indefinitely, account_id, - TriggeringEventFilterBox::Data(DataEventFilter::ByAccount(AccountEventFilter { - id_matcher: None, - event_matcher: Some(AccountEventMatcher::ByCreated), - })), + TriggeringEventFilterBox::Data(DataEventFilter::Account( + AccountEventFilter::new().only_events(AccountEventMatcher::Created), + )), ), )); test_client.submit_blocking(register_trigger)?; diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index f8675fb235d..af40ab0aece 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -24,11 +24,8 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { vec![instruction], Repeats::Indefinitely, account_id, - TriggeringEventFilterBox::Data(DataEventFilter::ByAssetDefinition( - AssetDefinitionEventFilter { - id_matcher: None, - event_matcher: Some(AssetDefinitionEventMatcher::ByCreated), - }, + TriggeringEventFilterBox::Data(DataEventFilter::AssetDefinition( + AssetDefinitionEventFilter::new().only_events(AssetDefinitionEventMatcher::Created), )), ), )); diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index e74679661fc..323e0601e34 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -274,8 +274,8 @@ fn get_block_committed_event_listener( client: &Client, ) -> Result>> { let block_filter = PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Block) - .status_kind(PipelineStatusKind::Committed); + .from_entity_of_kind(PipelineEntityKind::Block) + .with_status(PipelineStatusKind::Committed); client.listen_for_events(block_filter) } diff --git a/client/tests/integration/triggers/trigger_rollback.rs b/client/tests/integration/triggers/trigger_rollback.rs index 45396186b12..32abaf249be 100644 --- a/client/tests/integration/triggers/trigger_rollback.rs +++ b/client/tests/integration/triggers/trigger_rollback.rs @@ -28,10 +28,11 @@ fn failed_trigger_revert() -> Result<()> { instructions, Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id, - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id), + ), ), )); let _ = client.submit_blocking(register_trigger); diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 589b9495c6c..f17d374cab8 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -266,7 +266,7 @@ mod events { fn run(self, context: &mut dyn RunContext) -> Result<()> { let filter = match self { Args::Pipeline => EventFilterBox::Pipeline(PipelineEventFilter::new()), - Args::Data => EventFilterBox::Data(DataEventFilter::ByAny), + Args::Data => EventFilterBox::Data(DataEventFilter::Any), Args::Notification => EventFilterBox::Notification(NotificationEventFilter::ByAny), }; listen(filter, context) diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index 1a8c9d78aee..a834e814b46 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -378,10 +378,11 @@ mod tests { Vec::::new(), Repeats::Indefinitely, account_id.clone(), - TriggeringEventFilterBox::ExecuteTrigger(ExecuteTriggerEventFilter::new( - trigger_id.clone(), - account_id.clone(), - )), + TriggeringEventFilterBox::ExecuteTrigger( + ExecuteTriggerEventFilter::new() + .from_trigger(trigger_id.clone()) + .under_authority(account_id.clone()), + ), ), )); diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 90dc956888f..2f11d5322b0 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -1,13 +1,12 @@ //! This module contains filters for data events. //! //! (almost) Each event in [`super::events`], there's two corresponding types in this module: -//! - `*EventMatcher` - matches one event kind (e.g. [`super::events::AccountEvent::Created`] with [`AccountEventMatcher::ByCreated`]) +//! - `*EventMatcher` - matches one event kind (e.g. [`super::events::AccountEvent::Created`] with [`AccountEventMatcher::Created`]) //! - `*EventFilter` - struct combining an optional id matcher and an optional event matcher -//! -//! The ones not having a filter are [`super::events::ConfigurationEvent`] and [`super::events::ExecutorEvent`] (TODO: why?). use core::fmt::Debug; +use getset::Getters; use iroha_data_model_derive::model; pub use self::model::*; @@ -18,206 +17,425 @@ pub mod model { use super::*; #[derive( - Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + FromVariant, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, )] pub enum DataEventFilter { /// Matches any data events ([`DataEvent`]) - ByAny, - /// Matches only [`PeerEvent`]s - ByPeer(PeerEventFilter), - /// Matches only [`DomainEvent`]s - ByDomain(DomainEventFilter), - /// Matches only [`AccountEvent`]s - ByAccount(AccountEventFilter), - /// Matches only [`AssetEvent`]s - ByAsset(AssetEventFilter), - /// Matches only [`AssetDefinitionEvent`]s - ByAssetDefinition(AssetDefinitionEventFilter), - /// Matches only [`TriggerEvent`]s - ByTrigger(TriggerEventFilter), - /// Matches only [`RoleEvent`]s - ByRole(RoleEventFilter), + Any, + /// Matches [`PeerEvent`]s + Peer(PeerEventFilter), + /// Matches [`DomainEvent`]s + Domain(DomainEventFilter), + /// Matches [`AccountEvent`]s + Account(AccountEventFilter), + /// Matches [`AssetEvent`]s + Asset(AssetEventFilter), + /// Matches [`AssetDefinitionEvent`]s + AssetDefinition(AssetDefinitionEventFilter), + /// Matches [`TriggerEvent`]s + Trigger(TriggerEventFilter), + /// Matches [`RoleEvent`]s + Role(RoleEventFilter), // We didn't have filters for these events before the refactor. Should we? // Configuration(ConfigurationEventFilter), // Executor(ExecutorEventFilter), } /// An event filter for [`PeerEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct PeerEventFilter { - pub id_matcher: Option, - pub event_matcher: Option, + /// If specified matches only events originating from this peer + pub(super) id_matcher: Option, + /// If specified matches only events of this type + pub(super) event_matcher: Option, } /// An event matcher for [`PeerEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum PeerEventMatcher { - /// Matches only [`PeerEvent::Added`] - ByAdded, - /// Matches only [`PeerEvent::Removed`] - ByRemoved, + /// Matches [`PeerEvent::Added`] + Added, + /// Matches [`PeerEvent::Removed`] + Removed, } /// An event filter for [`DomainEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct DomainEventFilter { /// If specified matches only events originating from this domain - pub id_matcher: Option, + pub(super) id_matcher: Option, /// If specified matches only events of this type - pub event_matcher: Option, + pub(super) event_matcher: Option, } /// An event matcher for [`DomainEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum DomainEventMatcher { - /// Matches only [`DomainEvent::Created`] - ByCreated, - /// Matches only [`DomainEvent::Deleted`] - ByDeleted, - /// Matches only [`DomainEvent::MetadataInserted`] - ByMetadataInserted, - /// Matches only [`DomainEvent::MetadataRemoved`] - ByMetadataRemoved, - /// Matches only [`DomainEvent::OwnerChanged`] - ByOwnerChanged, + /// Matches [`DomainEvent::Created`] + Created, + /// Matches [`DomainEvent::Deleted`] + Deleted, + /// Matches [`DomainEvent::MetadataInserted`] + MetadataInserted, + /// Matches [`DomainEvent::MetadataRemoved`] + MetadataRemoved, + /// Matches [`DomainEvent::OwnerChanged`] + OwnerChanged, // we allow filtering for nested events, but if you need to specify an id matcher for, for example, AccountId, you need to use AccountFilter - /// Matches only [`DomainEvent::Account`] - ByAccountAny, - /// Matches only [`DomainEvent::AssetDefinition`] - ByAssetDefinitionAny, + /// Matches any [`DomainEvent::Account`]. To further filter by account events, use [`AccountEventFilter`] + AnyAccount, + /// Matches any [`DomainEvent::AssetDefinition`]. To further filter by asset definition events, use [`AssetDefinitionEventFilter`] + AnyAssetDefinition, } /// An event filter for [`AccountEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct AccountEventFilter { /// If specified matches only events originating from this account - pub id_matcher: Option, + pub(super) id_matcher: Option, /// If specified matches only events of this type - pub event_matcher: Option, + pub(super) event_matcher: Option, } /// An event matcher for [`AccountEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum AccountEventMatcher { - /// Matches only [`AccountEvent::Created`] - ByCreated, - /// Matches only [`AccountEvent::Deleted`] - ByDeleted, - /// Matches only [`AccountEvent::AuthenticationAdded`] - ByAuthenticationAdded, - /// Matches only [`AccountEvent::AuthenticationRemoved`] - ByAuthenticationRemoved, - /// Matches only [`AccountEvent::PermissionAdded`] - ByPermissionAdded, - /// Matches only [`AccountEvent::PermissionRemoved`] - ByPermissionRemoved, - /// Matches only [`AccountEvent::RoleRevoked`] - ByRoleRevoked, - /// Matches only [`AccountEvent::RoleGranted`] - ByRoleGranted, - /// Matches only [`AccountEvent::MetadataInserted`] - ByMetadataInserted, - /// Matches only [`AccountEvent::MetadataRemoved`] - ByMetadataRemoved, + /// Matches [`AccountEvent::Created`] + Created, + /// Matches [`AccountEvent::Deleted`] + Deleted, + /// Matches [`AccountEvent::AuthenticationAdded`] + AuthenticationAdded, + /// Matches [`AccountEvent::AuthenticationRemoved`] + AuthenticationRemoved, + /// Matches [`AccountEvent::PermissionAdded`] + PermissionAdded, + /// Matches [`AccountEvent::PermissionRemoved`] + PermissionRemoved, + /// Matches [`AccountEvent::RoleRevoked`] + RoleRevoked, + /// Matches [`AccountEvent::RoleGranted`] + RoleGranted, + /// Matches [`AccountEvent::MetadataInserted`] + MetadataInserted, + /// Matches [`AccountEvent::MetadataRemoved`] + MetadataRemoved, // nested events - /// Matches only [`AccountEvent::Asset`] - ByAssetAny, + /// Matches any [`AccountEvent::Asset`]. To further filter by asset events, use [`AssetEventFilter`] + AnyAsset, } /// An event filter for [`AssetEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct AssetEventFilter { /// If specified matches only events originating from this asset - pub id_matcher: Option, + pub(super) id_matcher: Option, /// If specified matches only events of this type - pub event_matcher: Option, + pub(super) event_matcher: Option, } /// An event matcher for [`AssetEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum AssetEventMatcher { - /// Matches only [`AssetEvent::Created`] - ByCreated, - /// Matches only [`AssetEvent::Deleted`] - ByDeleted, - /// Matches only [`AssetEvent::Added`] - ByAdded, - /// Matches only [`AssetEvent::Removed`] - ByRemoved, - /// Matches only [`AssetEvent::MetadataInserted`] - ByMetadataInserted, - /// Matches only [`AssetEvent::MetadataRemoved`] - ByMetadataRemoved, + /// Matches [`AssetEvent::Created`] + Created, + /// Matches [`AssetEvent::Deleted`] + Deleted, + /// Matches [`AssetEvent::Added`] + Added, + /// Matches [`AssetEvent::Removed`] + Removed, + /// Matches [`AssetEvent::MetadataInserted`] + MetadataInserted, + /// Matches [`AssetEvent::MetadataRemoved`] + MetadataRemoved, } /// An event filter for [`AssetDefinitionEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct AssetDefinitionEventFilter { /// If specified matches only events originating from this asset definition - pub id_matcher: Option, + pub(super) id_matcher: Option, /// If specified matches only events of this type - pub event_matcher: Option, + pub(super) event_matcher: Option, } /// An event matcher for [`AssetDefinitionEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum AssetDefinitionEventMatcher { - /// Matches only [`AssetDefinitionEvent::Created`] - ByCreated, - /// Matches only [`AssetDefinitionEvent::MintabilityChanged`] - ByMintabilityChanged, - /// Matches only [`AssetDefinitionEvent::OwnerChanged`] - ByOwnerChanged, - /// Matches only [`AssetDefinitionEvent::Deleted`] - ByDeleted, - /// Matches only [`AssetDefinitionEvent::MetadataInserted`] - ByMetadataInserted, - /// Matches only [`AssetDefinitionEvent::MetadataRemoved`] - ByMetadataRemoved, - /// Matches only [`AssetDefinitionEvent::TotalQuantityChanged`] - ByTotalQuantityChanged, + /// Matches [`AssetDefinitionEvent::Created`] + Created, + /// Matches [`AssetDefinitionEvent::MintabilityChanged`] + MintabilityChanged, + /// Matches [`AssetDefinitionEvent::OwnerChanged`] + OwnerChanged, + /// Matches [`AssetDefinitionEvent::Deleted`] + Deleted, + /// Matches [`AssetDefinitionEvent::MetadataInserted`] + MetadataInserted, + /// Matches [`AssetDefinitionEvent::MetadataRemoved`] + MetadataRemoved, + /// Matches [`AssetDefinitionEvent::TotalQuantityChanged`] + TotalQuantityChanged, } /// An event filter for [`TriggerEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct TriggerEventFilter { /// If specified matches only events originating from this trigger - pub id_matcher: Option, + pub(super) id_matcher: Option, /// If specified matches only events of this type - pub event_matcher: Option, + pub(super) event_matcher: Option, } /// An event matcher for [`TriggerEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum TriggerEventMatcher { - /// Matches only [`TriggerEvent::Created`] - ByCreated, - /// Matches only [`TriggerEvent::Deleted`] - ByDeleted, - /// Matches only [`TriggerEvent::Extended`] - ByExtended, - /// Matches only [`TriggerEvent::Shortened`] - ByShortened, + /// Matches [`TriggerEvent::Created`] + Created, + /// Matches [`TriggerEvent::Deleted`] + Deleted, + /// Matches [`TriggerEvent::Extended`] + Extended, + /// Matches [`TriggerEvent::Shortened`] + Shortened, } /// An event filter for [`RoleEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Default, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub struct RoleEventFilter { /// If specified matches only events originating from this role - pub id_matcher: Option, + pub(super) id_matcher: Option, /// If specified matches only events of this type - pub event_matcher: Option, + pub(super) event_matcher: Option, } /// An event matcher for [`RoleEvent`]s - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] pub enum RoleEventMatcher { - /// Matches only [`RoleEvent::Created`] - ByCreated, - /// Matches only [`RoleEvent::Deleted`] - ByDeleted, - /// Matches only [`RoleEvent::PermissionRemoved`] - ByPermissionRemoved, + /// Matches [`RoleEvent::Created`] + Created, + /// Matches [`RoleEvent::Deleted`] + Deleted, + /// Matches [`RoleEvent::PermissionRemoved`] + PermissionRemoved, + } +} + +impl PeerEventFilter { + /// Creates a new [`PeerEventFilter`] accepting all [`PeerEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_id(mut self, id_matcher: PeerId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: PeerEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self } } @@ -228,8 +446,6 @@ impl EventFilter for PeerEventFilter { fn matches(&self, event: &Self::Event) -> bool { use PeerEventMatcher::*; - use super::PeerEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -237,8 +453,8 @@ impl EventFilter for PeerEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByAdded, Added(_)) => true, - (ByRemoved, Removed(_)) => true, + (Added, PeerEvent::Added(_)) => true, + (Removed, PeerEvent::Removed(_)) => true, _ => false, } } else { @@ -247,6 +463,30 @@ impl EventFilter for PeerEventFilter { } } +impl DomainEventFilter { + /// Creates a new [`DomainEventFilter`] accepting all [`DomainEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_id(mut self, id_matcher: DomainId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: DomainEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self + } +} + #[cfg(feature = "transparent_api")] impl EventFilter for DomainEventFilter { type Event = super::DomainEvent; @@ -254,8 +494,6 @@ impl EventFilter for DomainEventFilter { fn matches(&self, event: &Self::Event) -> bool { use DomainEventMatcher::*; - use super::DomainEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -263,13 +501,13 @@ impl EventFilter for DomainEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByCreated, Created(_)) => true, - (ByDeleted, Deleted(_)) => true, - (ByMetadataInserted, MetadataInserted(_)) => true, - (ByMetadataRemoved, MetadataRemoved(_)) => true, - (ByOwnerChanged, OwnerChanged(_)) => true, - (ByAccountAny, Account(_)) => true, - (ByAssetDefinitionAny, AssetDefinition(_)) => true, + (Created, DomainEvent::Created(_)) => true, + (Deleted, DomainEvent::Deleted(_)) => true, + (MetadataInserted, DomainEvent::MetadataInserted(_)) => true, + (MetadataRemoved, DomainEvent::MetadataRemoved(_)) => true, + (OwnerChanged, DomainEvent::OwnerChanged(_)) => true, + (AnyAccount, DomainEvent::Account(_)) => true, + (AnyAssetDefinition, DomainEvent::AssetDefinition(_)) => true, _ => false, } } else { @@ -278,6 +516,30 @@ impl EventFilter for DomainEventFilter { } } +impl AccountEventFilter { + /// Creates a new [`AccountEventFilter`] accepting all [`AccountEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_id(mut self, id_matcher: AccountId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: AccountEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for AccountEventFilter { type Event = super::AccountEvent; @@ -285,8 +547,6 @@ impl super::EventFilter for AccountEventFilter { fn matches(&self, event: &Self::Event) -> bool { use AccountEventMatcher::*; - use super::AccountEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -294,17 +554,17 @@ impl super::EventFilter for AccountEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByCreated, Created(_)) => true, - (ByDeleted, Deleted(_)) => true, - (ByAuthenticationAdded, AuthenticationAdded(_)) => true, - (ByAuthenticationRemoved, AuthenticationRemoved(_)) => true, - (ByPermissionAdded, PermissionAdded(_)) => true, - (ByPermissionRemoved, PermissionRemoved(_)) => true, - (ByRoleRevoked, RoleRevoked(_)) => true, - (ByRoleGranted, RoleGranted(_)) => true, - (ByMetadataInserted, MetadataInserted(_)) => true, - (ByMetadataRemoved, MetadataRemoved(_)) => true, - (ByAssetAny, Asset(_)) => true, + (Created, AccountEvent::Created(_)) => true, + (Deleted, AccountEvent::Deleted(_)) => true, + (AuthenticationAdded, AccountEvent::AuthenticationAdded(_)) => true, + (AuthenticationRemoved, AccountEvent::AuthenticationRemoved(_)) => true, + (PermissionAdded, AccountEvent::PermissionAdded(_)) => true, + (PermissionRemoved, AccountEvent::PermissionRemoved(_)) => true, + (RoleRevoked, AccountEvent::RoleRevoked(_)) => true, + (RoleGranted, AccountEvent::RoleGranted(_)) => true, + (MetadataInserted, AccountEvent::MetadataInserted(_)) => true, + (MetadataRemoved, AccountEvent::MetadataRemoved(_)) => true, + (AnyAsset, AccountEvent::Asset(_)) => true, _ => false, } } else { @@ -313,6 +573,30 @@ impl super::EventFilter for AccountEventFilter { } } +impl AssetEventFilter { + /// Creates a new [`AssetEventFilter`] accepting all [`AssetEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`AssetEventFilter`] to accept only [`AssetEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_from(mut self, id_matcher: AssetId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`AssetEventFilter`] to accept only [`AssetEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: AssetEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for AssetEventFilter { type Event = super::AssetEvent; @@ -320,8 +604,6 @@ impl super::EventFilter for AssetEventFilter { fn matches(&self, event: &Self::Event) -> bool { use AssetEventMatcher::*; - use super::AssetEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -329,12 +611,12 @@ impl super::EventFilter for AssetEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByCreated, Created(_)) => true, - (ByDeleted, Deleted(_)) => true, - (ByAdded, Added(_)) => true, - (ByRemoved, Removed(_)) => true, - (ByMetadataInserted, MetadataInserted(_)) => true, - (ByMetadataRemoved, MetadataRemoved(_)) => true, + (Created, AssetEvent::Created(_)) => true, + (Deleted, AssetEvent::Deleted(_)) => true, + (Added, AssetEvent::Added(_)) => true, + (Removed, AssetEvent::Removed(_)) => true, + (MetadataInserted, AssetEvent::MetadataInserted(_)) => true, + (MetadataRemoved, AssetEvent::MetadataRemoved(_)) => true, _ => false, } } else { @@ -343,6 +625,30 @@ impl super::EventFilter for AssetEventFilter { } } +impl AssetDefinitionEventFilter { + /// Creates a new [`AssetDefinitionEventFilter`] accepting all [`AssetDefinitionEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`AssetDefinitionEventFilter`] to accept only [`AssetDefinitionEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_from(mut self, id_matcher: AssetDefinitionId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`AssetDefinitionEventFilter`] to accept only [`AssetDefinitionEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: AssetDefinitionEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for AssetDefinitionEventFilter { type Event = super::AssetDefinitionEvent; @@ -350,8 +656,6 @@ impl super::EventFilter for AssetDefinitionEventFilter { fn matches(&self, event: &Self::Event) -> bool { use AssetDefinitionEventMatcher::*; - use super::AssetDefinitionEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -359,13 +663,13 @@ impl super::EventFilter for AssetDefinitionEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByCreated, Created(_)) => true, - (ByMintabilityChanged, MintabilityChanged(_)) => true, - (ByOwnerChanged, OwnerChanged(_)) => true, - (ByDeleted, Deleted(_)) => true, - (ByMetadataInserted, MetadataInserted(_)) => true, - (ByMetadataRemoved, MetadataRemoved(_)) => true, - (ByTotalQuantityChanged, TotalQuantityChanged(_)) => true, + (Created, AssetDefinitionEvent::Created(_)) => true, + (MintabilityChanged, AssetDefinitionEvent::MintabilityChanged(_)) => true, + (OwnerChanged, AssetDefinitionEvent::OwnerChanged(_)) => true, + (Deleted, AssetDefinitionEvent::Deleted(_)) => true, + (MetadataInserted, AssetDefinitionEvent::MetadataInserted(_)) => true, + (MetadataRemoved, AssetDefinitionEvent::MetadataRemoved(_)) => true, + (TotalQuantityChanged, AssetDefinitionEvent::TotalQuantityChanged(_)) => true, _ => false, } } else { @@ -374,6 +678,30 @@ impl super::EventFilter for AssetDefinitionEventFilter { } } +impl TriggerEventFilter { + /// Creates a new [`TriggerEventFilter`] accepting all [`TriggerEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`TriggerEventFilter`] to accept only [`TriggerEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_from(mut self, id_matcher: TriggerId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`TriggerEventFilter`] to accept only [`TriggerEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: TriggerEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for TriggerEventFilter { type Event = super::TriggerEvent; @@ -381,8 +709,6 @@ impl super::EventFilter for TriggerEventFilter { fn matches(&self, event: &Self::Event) -> bool { use TriggerEventMatcher::*; - use super::TriggerEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -390,10 +716,10 @@ impl super::EventFilter for TriggerEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByCreated, Created(_)) => true, - (ByDeleted, Deleted(_)) => true, - (ByExtended, Extended(_)) => true, - (ByShortened, Shortened(_)) => true, + (Created, TriggerEvent::Created(_)) => true, + (Deleted, TriggerEvent::Deleted(_)) => true, + (Extended, TriggerEvent::Extended(_)) => true, + (Shortened, TriggerEvent::Shortened(_)) => true, _ => false, } } else { @@ -402,6 +728,30 @@ impl super::EventFilter for TriggerEventFilter { } } +impl RoleEventFilter { + /// Creates a new [`RoleEventFilter`] accepting all [`RoleEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_matcher: None, + } + } + + /// Modifies a [`RoleEventFilter`] to accept only [`RoleEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_from(mut self, id_matcher: RoleId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`RoleEventFilter`] to accept only [`RoleEvent`]s of types matching `event_matcher`. + #[must_use] + pub const fn only_events(mut self, event_matcher: RoleEventMatcher) -> Self { + self.event_matcher = Some(event_matcher); + self + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for RoleEventFilter { type Event = super::RoleEvent; @@ -409,8 +759,6 @@ impl super::EventFilter for RoleEventFilter { fn matches(&self, event: &Self::Event) -> bool { use RoleEventMatcher::*; - use super::RoleEvent::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; @@ -418,9 +766,9 @@ impl super::EventFilter for RoleEventFilter { } if let Some(event_matcher) = &self.event_matcher { match (event_matcher, event) { - (ByCreated, Created(_)) => true, - (ByDeleted, Deleted(_)) => true, - (ByPermissionRemoved, PermissionRemoved(_)) => true, + (Created, RoleEvent::Created(_)) => true, + (Deleted, RoleEvent::Deleted(_)) => true, + (PermissionRemoved, RoleEvent::PermissionRemoved(_)) => true, _ => false, } } else { @@ -434,22 +782,24 @@ impl EventFilter for DataEventFilter { type Event = DataEvent; fn matches(&self, event: &DataEvent) -> bool { - use DataEvent::*; use DataEventFilter::*; match (self, event) { - (ByAny, _) => true, - (ByPeer(filter), Peer(event)) => filter.matches(event), - (ByDomain(filter), Domain(event)) => filter.matches(event), - (ByAccount(filter), Domain(DomainEvent::Account(event))) => filter.matches(event), - (ByAsset(filter), Domain(DomainEvent::Account(AccountEvent::Asset(event)))) => { + (Any, _) => true, + (Peer(filter), DataEvent::Peer(event)) => filter.matches(event), + (Domain(filter), DataEvent::Domain(event)) => filter.matches(event), + (Account(filter), DataEvent::Domain(DomainEvent::Account(event))) => { filter.matches(event) } - (ByAssetDefinition(filter), Domain(DomainEvent::AssetDefinition(event))) => { + ( + Asset(filter), + DataEvent::Domain(DomainEvent::Account(AccountEvent::Asset(event))), + ) => filter.matches(event), + (AssetDefinition(filter), DataEvent::Domain(DomainEvent::AssetDefinition(event))) => { filter.matches(event) } - (ByTrigger(filter), Trigger(event)) => filter.matches(event), - (ByRole(filter), Role(event)) => filter.matches(event), + (Trigger(filter), DataEvent::Trigger(event)) => filter.matches(event), + (Role(filter), DataEvent::Role(event)) => filter.matches(event), _ => false, } } @@ -513,15 +863,15 @@ mod tests { DomainEvent::Account(AccountEvent::Asset(AssetEvent::Created(asset))).into(); // test how the differently nested filters with with the events - let domain_filter = DataEventFilter::ByDomain(DomainEventFilter { + let domain_filter = DataEventFilter::Domain(DomainEventFilter { id_matcher: Some(domain_id), event_matcher: None, }); - let account_filter = DataEventFilter::ByAccount(AccountEventFilter { + let account_filter = DataEventFilter::Account(AccountEventFilter { id_matcher: Some(account_id), event_matcher: None, }); - let asset_filter = DataEventFilter::ByAsset(AssetEventFilter { + let asset_filter = DataEventFilter::Asset(AssetEventFilter { id_matcher: Some(asset_id), event_matcher: None, }); diff --git a/data_model/src/events/execute_trigger.rs b/data_model/src/events/execute_trigger.rs index 4825c1141b2..bb085224f9a 100644 --- a/data_model/src/events/execute_trigger.rs +++ b/data_model/src/events/execute_trigger.rs @@ -1,6 +1,5 @@ //! Trigger execution event and filter -use derive_more::Constructor; use getset::Getters; use iroha_data_model_derive::model; @@ -44,7 +43,8 @@ pub mod model { Ord, PartialEq, Eq, - Constructor, + Default, + Getters, Decode, Encode, Deserialize, @@ -53,9 +53,37 @@ pub mod model { )] pub struct ExecuteTriggerEventFilter { /// Id of trigger catch executions of - pub(super) trigger_id: TriggerId, + pub(super) trigger_id: Option, /// Authority of user who owns trigger - pub(super) authority: AccountId, + pub(super) authority: Option, + } +} + +impl ExecuteTriggerEventFilter { + /// Creates a new [`ExecuteTriggerEventFilter`] accepting all [`ExecuteTriggerEvent`]s + #[must_use] + #[inline] + pub const fn new() -> Self { + Self { + trigger_id: None, + authority: None, + } + } + + /// Modifies a [`ExecuteTriggerEventFilter`] to accept only [`ExecuteTriggerEvent`]s originating from a specific trigger + #[must_use] + #[inline] + pub fn from_trigger(mut self, trigger_id: TriggerId) -> Self { + self.trigger_id = Some(trigger_id); + self + } + + /// Modifies a [`ExecuteTriggerEventFilter`] to accept only [`ExecuteTriggerEvent`]s from triggers executed under specific authority + #[must_use] + #[inline] + pub fn under_authority(mut self, authority: AccountId) -> Self { + self.authority = Some(authority); + self } } @@ -67,7 +95,18 @@ impl EventFilter for ExecuteTriggerEventFilter { /// /// Event considered as matched if trigger ids are equal fn matches(&self, event: &ExecuteTriggerEvent) -> bool { - self.trigger_id == event.trigger_id && self.authority == event.authority + if let Some(trigger_id) = &self.trigger_id { + if trigger_id != &event.trigger_id { + return false; + } + } + if let Some(authority) = &self.authority { + if authority != &event.authority { + return false; + } + } + + true } } diff --git a/data_model/src/events/mod.rs b/data_model/src/events/mod.rs index d6a42cf050d..8c3517ecdcc 100644 --- a/data_model/src/events/mod.rs +++ b/data_model/src/events/mod.rs @@ -68,7 +68,18 @@ pub mod model { /// Event filter. #[allow(variant_size_differences)] #[derive( - Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + FromVariant, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, )] // TODO: Temporarily made opaque #[ffi_type(opaque)] @@ -88,7 +99,18 @@ pub mod model { /// Event filter which could be attached to trigger. #[allow(variant_size_differences)] #[derive( - Debug, Clone, PartialEq, Eq, FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + FromVariant, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, )] // TODO: Temporarily made opaque #[ffi_type(opaque)] diff --git a/data_model/src/events/notification.rs b/data_model/src/events/notification.rs index 3eb484095b9..50f9e9c15fc 100644 --- a/data_model/src/events/notification.rs +++ b/data_model/src/events/notification.rs @@ -128,7 +128,7 @@ pub mod model { Eq, PartialOrd, Ord, - Constructor, + Default, Getters, Decode, Encode, @@ -139,8 +139,8 @@ pub mod model { #[ffi_type] #[getset(get = "pub")] pub struct TriggerCompletedEventFilter { - trigger_id: Option, - outcome_type: Option, + pub(super) trigger_id: Option, + pub(super) outcome_type: Option, } } @@ -160,6 +160,34 @@ impl super::EventFilter for NotificationEventFilter { } } +impl TriggerCompletedEventFilter { + /// Creates a new [`TriggerCompletedEventFilter`] accepting all [`TriggerCompletedEvent`]s + #[must_use] + #[inline] + pub const fn new() -> Self { + Self { + trigger_id: None, + outcome_type: None, + } + } + + /// Modifies a [`TriggerCompletedEventFilter`] to accept only [`TriggerCompletedEvent`]s originating from a specific trigger + #[must_use] + #[inline] + pub fn from_trigger(mut self, trigger_id: TriggerId) -> Self { + self.trigger_id = Some(trigger_id); + self + } + + /// Modifies a [`TriggerCompletedEventFilter`] to accept only [`TriggerCompletedEvent`]s with a specific outcome + #[must_use] + #[inline] + pub const fn with_outcome(mut self, outcome_type: TriggerCompletedOutcomeType) -> Self { + self.outcome_type = Some(outcome_type); + self + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for TriggerCompletedEventFilter { type Event = TriggerCompletedEvent; @@ -220,69 +248,65 @@ mod tests { let event_2_success = TriggerCompletedEvent::new(trigger_id_2.clone(), TriggerCompletedOutcome::Success); - let filter_accept_all = TriggerCompletedEventFilter::new(None, None); + let filter_accept_all = TriggerCompletedEventFilter::new(); assert!(filter_accept_all.matches(&event_1_failure)); assert!(filter_accept_all.matches(&event_1_success)); assert!(filter_accept_all.matches(&event_2_failure)); assert!(filter_accept_all.matches(&event_2_success)); let filter_accept_success = - TriggerCompletedEventFilter::new(None, Some(TriggerCompletedOutcomeType::Success)); + TriggerCompletedEventFilter::new().with_outcome(TriggerCompletedOutcomeType::Success); assert!(!filter_accept_success.matches(&event_1_failure)); assert!(filter_accept_success.matches(&event_1_success)); assert!(!filter_accept_success.matches(&event_2_failure)); assert!(filter_accept_success.matches(&event_2_success)); let filter_accept_failure = - TriggerCompletedEventFilter::new(None, Some(TriggerCompletedOutcomeType::Failure)); + TriggerCompletedEventFilter::new().with_outcome(TriggerCompletedOutcomeType::Failure); assert!(filter_accept_failure.matches(&event_1_failure)); assert!(!filter_accept_failure.matches(&event_1_success)); assert!(filter_accept_failure.matches(&event_2_failure)); assert!(!filter_accept_failure.matches(&event_2_success)); - let filter_accept_1 = TriggerCompletedEventFilter::new(Some(trigger_id_1.clone()), None); + let filter_accept_1 = TriggerCompletedEventFilter::new().from_trigger(trigger_id_1.clone()); assert!(filter_accept_1.matches(&event_1_failure)); assert!(filter_accept_1.matches(&event_1_success)); assert!(!filter_accept_1.matches(&event_2_failure)); assert!(!filter_accept_1.matches(&event_2_success)); - let filter_accept_1_failure = TriggerCompletedEventFilter::new( - Some(trigger_id_1.clone()), - Some(TriggerCompletedOutcomeType::Failure), - ); + let filter_accept_1_failure = TriggerCompletedEventFilter::new() + .from_trigger(trigger_id_1.clone()) + .with_outcome(TriggerCompletedOutcomeType::Failure); assert!(filter_accept_1_failure.matches(&event_1_failure)); assert!(!filter_accept_1_failure.matches(&event_1_success)); assert!(!filter_accept_1_failure.matches(&event_2_failure)); assert!(!filter_accept_1_failure.matches(&event_2_success)); - let filter_accept_1_success = TriggerCompletedEventFilter::new( - Some(trigger_id_1), - Some(TriggerCompletedOutcomeType::Success), - ); + let filter_accept_1_success = TriggerCompletedEventFilter::new() + .from_trigger(trigger_id_1) + .with_outcome(TriggerCompletedOutcomeType::Success); assert!(!filter_accept_1_success.matches(&event_1_failure)); assert!(filter_accept_1_success.matches(&event_1_success)); assert!(!filter_accept_1_success.matches(&event_2_failure)); assert!(!filter_accept_1_success.matches(&event_2_success)); - let filter_accept_2 = TriggerCompletedEventFilter::new(Some(trigger_id_2.clone()), None); + let filter_accept_2 = TriggerCompletedEventFilter::new().from_trigger(trigger_id_2.clone()); assert!(!filter_accept_2.matches(&event_1_failure)); assert!(!filter_accept_2.matches(&event_1_success)); assert!(filter_accept_2.matches(&event_2_failure)); assert!(filter_accept_2.matches(&event_2_success)); - let filter_accept_2_failure = TriggerCompletedEventFilter::new( - Some(trigger_id_2.clone()), - Some(TriggerCompletedOutcomeType::Failure), - ); + let filter_accept_2_failure = TriggerCompletedEventFilter::new() + .from_trigger(trigger_id_2.clone()) + .with_outcome(TriggerCompletedOutcomeType::Failure); assert!(!filter_accept_2_failure.matches(&event_1_failure)); assert!(!filter_accept_2_failure.matches(&event_1_success)); assert!(filter_accept_2_failure.matches(&event_2_failure)); assert!(!filter_accept_2_failure.matches(&event_2_success)); - let filter_accept_2_success = TriggerCompletedEventFilter::new( - Some(trigger_id_2), - Some(TriggerCompletedOutcomeType::Success), - ); + let filter_accept_2_success = TriggerCompletedEventFilter::new() + .from_trigger(trigger_id_2) + .with_outcome(TriggerCompletedOutcomeType::Success); assert!(!filter_accept_2_success.matches(&event_1_failure)); assert!(!filter_accept_2_success.matches(&event_1_success)); assert!(!filter_accept_2_success.matches(&event_2_failure)); diff --git a/data_model/src/events/pipeline.rs b/data_model/src/events/pipeline.rs index 49b43d4f0a7..2cd306091e8 100644 --- a/data_model/src/events/pipeline.rs +++ b/data_model/src/events/pipeline.rs @@ -28,6 +28,7 @@ pub mod model { PartialOrd, Ord, Default, + Getters, Decode, Encode, Serialize, @@ -154,33 +155,37 @@ pub mod model { } impl PipelineEventFilter { - /// Construct [`EventFilter`]. + /// Creates a new [`PipelineEventFilter`] accepting all [`PipelineEvent`]s #[must_use] #[inline] - pub fn new() -> Self { - Self::default() + pub const fn new() -> Self { + Self { + status_kind: None, + entity_kind: None, + hash: None, + } } - /// Filter by [`EntityKind`]. + /// Modifies a [`PipelineEventFilter`] to accept only [`PipelineEvent`]s originating from a specific entity kind (block/transaction). #[must_use] #[inline] - pub const fn entity_kind(mut self, entity_kind: PipelineEntityKind) -> Self { + pub const fn from_entity_of_kind(mut self, entity_kind: PipelineEntityKind) -> Self { self.entity_kind = Some(entity_kind); self } - /// Filter by [`StatusKind`]. + /// Modifies a [`PipelineEventFilter`] to accept only [`PipelineEvent`]s with a specific status. #[must_use] #[inline] - pub const fn status_kind(mut self, status_kind: PipelineStatusKind) -> Self { + pub const fn with_status(mut self, status_kind: PipelineStatusKind) -> Self { self.status_kind = Some(status_kind); self } - /// Filter by [`struct@Hash`]. + /// Modifies a [`PipelineEventFilter`] to accept only [`PipelineEvent`]s originating from an entity with specified hash. #[must_use] #[inline] - pub const fn hash(mut self, hash: Hash) -> Self { + pub const fn from_entity_with_hash(mut self, hash: Hash) -> Self { self.hash = Some(hash); self } @@ -277,7 +282,7 @@ mod tests { events .iter() .filter(|&event| PipelineEventFilter::new() - .hash(Hash::prehashed([0_u8; Hash::LENGTH])) + .from_entity_with_hash(Hash::prehashed([0_u8; Hash::LENGTH])) .matches(event)) .cloned() .collect::>() @@ -291,7 +296,7 @@ mod tests { events .iter() .filter(|&event| PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Block) + .from_entity_of_kind(PipelineEntityKind::Block) .matches(event)) .cloned() .collect::>() @@ -305,8 +310,8 @@ mod tests { events .iter() .filter(|&event| PipelineEventFilter::new() - .entity_kind(PipelineEntityKind::Transaction) - .hash(Hash::prehashed([2_u8; Hash::LENGTH])) + .from_entity_of_kind(PipelineEntityKind::Transaction) + .from_entity_with_hash(Hash::prehashed([2_u8; Hash::LENGTH])) .matches(event)) .cloned() .collect::>() diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 4f81e53e4ab..389b71c0bea 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -97,47 +97,47 @@ "AccountEventMatcher": { "Enum": [ { - "tag": "ByCreated", + "tag": "Created", "discriminant": 0 }, { - "tag": "ByDeleted", + "tag": "Deleted", "discriminant": 1 }, { - "tag": "ByAuthenticationAdded", + "tag": "AuthenticationAdded", "discriminant": 2 }, { - "tag": "ByAuthenticationRemoved", + "tag": "AuthenticationRemoved", "discriminant": 3 }, { - "tag": "ByPermissionAdded", + "tag": "PermissionAdded", "discriminant": 4 }, { - "tag": "ByPermissionRemoved", + "tag": "PermissionRemoved", "discriminant": 5 }, { - "tag": "ByRoleRevoked", + "tag": "RoleRevoked", "discriminant": 6 }, { - "tag": "ByRoleGranted", + "tag": "RoleGranted", "discriminant": 7 }, { - "tag": "ByMetadataInserted", + "tag": "MetadataInserted", "discriminant": 8 }, { - "tag": "ByMetadataRemoved", + "tag": "MetadataRemoved", "discriminant": 9 }, { - "tag": "ByAssetAny", + "tag": "AnyAsset", "discriminant": 10 } ] @@ -360,31 +360,31 @@ "AssetDefinitionEventMatcher": { "Enum": [ { - "tag": "ByCreated", + "tag": "Created", "discriminant": 0 }, { - "tag": "ByMintabilityChanged", + "tag": "MintabilityChanged", "discriminant": 1 }, { - "tag": "ByOwnerChanged", + "tag": "OwnerChanged", "discriminant": 2 }, { - "tag": "ByDeleted", + "tag": "Deleted", "discriminant": 3 }, { - "tag": "ByMetadataInserted", + "tag": "MetadataInserted", "discriminant": 4 }, { - "tag": "ByMetadataRemoved", + "tag": "MetadataRemoved", "discriminant": 5 }, { - "tag": "ByTotalQuantityChanged", + "tag": "TotalQuantityChanged", "discriminant": 6 } ] @@ -474,27 +474,27 @@ "AssetEventMatcher": { "Enum": [ { - "tag": "ByCreated", + "tag": "Created", "discriminant": 0 }, { - "tag": "ByDeleted", + "tag": "Deleted", "discriminant": 1 }, { - "tag": "ByAdded", + "tag": "Added", "discriminant": 2 }, { - "tag": "ByRemoved", + "tag": "Removed", "discriminant": 3 }, { - "tag": "ByMetadataInserted", + "tag": "MetadataInserted", "discriminant": 4 }, { - "tag": "ByMetadataRemoved", + "tag": "MetadataRemoved", "discriminant": 5 } ] @@ -785,41 +785,41 @@ "DataEventFilter": { "Enum": [ { - "tag": "ByAny", + "tag": "Any", "discriminant": 0 }, { - "tag": "ByPeer", + "tag": "Peer", "discriminant": 1, "type": "PeerEventFilter" }, { - "tag": "ByDomain", + "tag": "Domain", "discriminant": 2, "type": "DomainEventFilter" }, { - "tag": "ByAccount", + "tag": "Account", "discriminant": 3, "type": "AccountEventFilter" }, { - "tag": "ByAsset", + "tag": "Asset", "discriminant": 4, "type": "AssetEventFilter" }, { - "tag": "ByAssetDefinition", + "tag": "AssetDefinition", "discriminant": 5, "type": "AssetDefinitionEventFilter" }, { - "tag": "ByTrigger", + "tag": "Trigger", "discriminant": 6, "type": "TriggerEventFilter" }, { - "tag": "ByRole", + "tag": "Role", "discriminant": 7, "type": "RoleEventFilter" } @@ -911,31 +911,31 @@ "DomainEventMatcher": { "Enum": [ { - "tag": "ByCreated", + "tag": "Created", "discriminant": 0 }, { - "tag": "ByDeleted", + "tag": "Deleted", "discriminant": 1 }, { - "tag": "ByMetadataInserted", + "tag": "MetadataInserted", "discriminant": 2 }, { - "tag": "ByMetadataRemoved", + "tag": "MetadataRemoved", "discriminant": 3 }, { - "tag": "ByOwnerChanged", + "tag": "OwnerChanged", "discriminant": 4 }, { - "tag": "ByAccountAny", + "tag": "AnyAccount", "discriminant": 5 }, { - "tag": "ByAssetDefinitionAny", + "tag": "AnyAssetDefinition", "discriminant": 6 } ] @@ -1064,11 +1064,11 @@ "Struct": [ { "name": "trigger_id", - "type": "TriggerId" + "type": "Option" }, { "name": "authority", - "type": "AccountId" + "type": "Option" } ] }, @@ -2521,11 +2521,11 @@ "PeerEventMatcher": { "Enum": [ { - "tag": "ByAdded", + "tag": "Added", "discriminant": 0 }, { - "tag": "ByRemoved", + "tag": "Removed", "discriminant": 1 } ] @@ -3325,15 +3325,15 @@ "RoleEventMatcher": { "Enum": [ { - "tag": "ByCreated", + "tag": "Created", "discriminant": 0 }, { - "tag": "ByDeleted", + "tag": "Deleted", "discriminant": 1 }, { - "tag": "ByPermissionRemoved", + "tag": "PermissionRemoved", "discriminant": 2 } ] @@ -4058,19 +4058,19 @@ "TriggerEventMatcher": { "Enum": [ { - "tag": "ByCreated", + "tag": "Created", "discriminant": 0 }, { - "tag": "ByDeleted", + "tag": "Deleted", "discriminant": 1 }, { - "tag": "ByExtended", + "tag": "Extended", "discriminant": 2 }, { - "tag": "ByShortened", + "tag": "Shortened", "discriminant": 3 } ] diff --git a/tools/parity_scale_decoder/samples/trigger.bin b/tools/parity_scale_decoder/samples/trigger.bin index 98d198162b3bd2b70c5141ace366d87697d814a3..606a8247e2f56cf3123a26f440f6743800c0517d 100644 GIT binary patch delta 8 PcmebDn&8gN$jSf!2{Hk6 delta 7 OcmebBoZ!yHzyJUTwE=Aa diff --git a/tools/parity_scale_decoder/samples/trigger.json b/tools/parity_scale_decoder/samples/trigger.json index a9a7ff5cbab..504eb5f125e 100644 --- a/tools/parity_scale_decoder/samples/trigger.json +++ b/tools/parity_scale_decoder/samples/trigger.json @@ -17,9 +17,9 @@ "authority": "alice@wonderland", "filter": { "Data": { - "ByDomain": { - "origin_filter": null, - "event_filter": "ByAccount" + "Domain": { + "id_matcher": null, + "event_matcher": "AnyAccount" } } }, diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index 6dfab3905ca..2bde62a553f 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -275,10 +275,9 @@ mod tests { vec![Mint::asset_numeric(1u32, rose_id)], Repeats::Indefinitely, account_id, - EventFilterBox::Data(DataEventFilter::ByDomain(DomainEventFilter { - id_matcher: None, - event_matcher: None, - })), + EventFilterBox::Data(DataEventFilter::Domain( + DomainEventFilter::new().only_events(DomainEventMatcher::AnyAccount), + )), ); let trigger = Trigger::new(trigger_id, action); From d436e125a6033134cb0e67cc24861f20bf72944b Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Thu, 29 Feb 2024 16:59:20 +0300 Subject: [PATCH 07/13] [refactor] #1981, #4195, #3068: Add an event set proc macro This proc macro generates a wrapper around a bit mask to specifying a set of events to match Signed-off-by: Nikita Strygin --- data_model/derive/src/event_set.rs | 395 ++++++++++++++++++ data_model/derive/src/lib.rs | 81 ++++ data_model/derive/tests/event_set.rs | 166 ++++++++ .../parity_scale_decoder/samples/trigger.bin | Bin 74 -> 76 bytes .../parity_scale_decoder/samples/trigger.json | 2 +- 5 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 data_model/derive/src/event_set.rs create mode 100644 data_model/derive/tests/event_set.rs diff --git a/data_model/derive/src/event_set.rs b/data_model/derive/src/event_set.rs new file mode 100644 index 00000000000..13f39780e18 --- /dev/null +++ b/data_model/derive/src/event_set.rs @@ -0,0 +1,395 @@ +#![allow(unused)] + +use darling::{FromDeriveInput, FromVariant}; +use iroha_macro_utils::Emitter; +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use syn2::{DeriveInput, Variant}; + +enum FieldsStyle { + Unit, + Unnamed, + Named, +} + +/// Converts the `FieldStyle` to an ignoring pattern (to be put after the variant name) +impl ToTokens for FieldsStyle { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + FieldsStyle::Unit => {} + FieldsStyle::Unnamed => tokens.extend(quote!((..))), + FieldsStyle::Named => tokens.extend(quote!({ .. })), + } + } +} + +struct EventSetVariant { + event_ident: syn2::Ident, + flag_ident: syn2::Ident, + fields_style: FieldsStyle, +} + +impl FromVariant for EventSetVariant { + fn from_variant(variant: &Variant) -> darling::Result { + let syn2::Variant { + attrs: _, + ident: event_ident, + fields, + discriminant: _, + } = variant; + + // a nested event is an event within an event (like `AccountEvent::Asset`, which bears an `AssetEvent`) + // we detect those by checking whether the payload type (if any) ends with `Event` + let is_nested = match fields { + syn2::Fields::Unnamed(fields) => { + fields.unnamed.len() == 1 + && matches!(&fields.unnamed[0].ty, syn2::Type::Path(p) if p.path.segments.last().unwrap().ident.to_string().ends_with("Event")) + } + syn2::Fields::Unit | + // just a fail-safe, we don't use named fields in events + syn2::Fields::Named(_) => false, + }; + + // we have a different naming convention for nested events + // to signify that there are actually multiple types of events inside + let flag_ident = if is_nested { + syn2::Ident::new(&format!("Any{event_ident}"), event_ident.span()) + } else { + event_ident.clone() + }; + + let fields_style = match fields { + syn2::Fields::Unnamed(_) => FieldsStyle::Unnamed, + syn2::Fields::Named(_) => FieldsStyle::Named, + syn2::Fields::Unit => FieldsStyle::Unit, + }; + + Ok(Self { + event_ident: event_ident.clone(), + flag_ident, + fields_style, + }) + } +} + +struct EventSetEnum { + vis: syn2::Visibility, + event_enum_ident: syn2::Ident, + set_ident: syn2::Ident, + variants: Vec, +} + +impl FromDeriveInput for EventSetEnum { + fn from_derive_input(input: &DeriveInput) -> darling::Result { + let syn2::DeriveInput { + attrs: _, + vis, + ident: event_ident, + generics, + data, + } = &input; + + let mut accumulator = darling::error::Accumulator::default(); + + if !generics.params.is_empty() { + accumulator.push(darling::Error::custom( + "EventSet cannot be derived on generic enums", + )); + } + + let Some(variants) = darling::ast::Data::::try_from(data)?.take_enum() + else { + accumulator.push(darling::Error::custom( + "EventSet can be derived only on enums", + )); + + return Err(accumulator.finish().unwrap_err()); + }; + + if variants.len() > 32 { + accumulator.push(darling::Error::custom( + "EventSet can be derived only on enums with up to 32 variants", + )); + } + + accumulator.finish_with(Self { + vis: vis.clone(), + event_enum_ident: event_ident.clone(), + set_ident: syn2::Ident::new(&format!("{event_ident}Set"), event_ident.span()), + variants, + }) + } +} + +impl ToTokens for EventSetEnum { + #[allow(clippy::too_many_lines)] // splitting it is not really feasible, it's all tightly coupled =( + fn to_tokens(&self, tokens: &mut TokenStream) { + let Self { + vis, + event_enum_ident, + set_ident, + variants, + } = self; + + // definitions of consts for each event + let flag_defs = variants.iter().zip(0u32..).map( + |( + EventSetVariant { + flag_ident, + event_ident, + .. + }, + i, + )| { + let doc = format!(" Matches [`{event_enum_ident}::{event_ident}`]"); + quote! { + #[doc = #doc] + #vis const #flag_ident: Self = Self(1 << #i); + } + }, + ); + // identifiers of all the flag constants to use in impls + let flag_idents = variants + .iter() + .map(|EventSetVariant { flag_ident, .. }| quote!(#set_ident::#flag_ident)) + .collect::>(); + // names of all the flag (as string literals) to use in debug impl + let flag_names = variants + .iter() + .map(|EventSetVariant { flag_ident, .. }| { + let flag_name = flag_ident.to_string(); + quote! { + #flag_name + } + }) + .collect::>(); + // names of all the flags in `quotes` to use in error message + let flag_names_str = variants + .iter() + .map(|EventSetVariant { flag_ident, .. }| format!("`{flag_ident}`")) + .collect::>() + .join(", "); + // patterns for matching events in the `matches` method + let event_patterns = variants.iter().map( + |EventSetVariant { + event_ident, + fields_style, + .. + }| { + quote! { + #event_enum_ident::#event_ident #fields_style + } + }, + ); + + let doc = format!(" An event set for [`{event_enum_ident}`]s\n\nEvent sets of the same type can be combined with a custom `|` operator"); + + tokens.extend(quote! { + #[derive( + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + // this introduces tight coupling with these crates + // but it's the easiest way to make sure those traits are implemented + parity_scale_codec::Decode, + parity_scale_codec::Encode, + // TODO: we probably want to represent the bit values for each variant in the schema + iroha_schema::IntoSchema, + )] + #[repr(transparent)] + #[doc = #doc] + #vis struct #set_ident(u32); + + // we want to imitate an enum here, so not using the SCREAMING_SNAKE_CASE here + #[allow(non_upper_case_globals)] + impl #set_ident { + #( #flag_defs )* + } + + impl #set_ident { + /// Creates an empty event set + pub const fn empty() -> Self { + Self(0) + } + + /// Creates an event set containing all events + pub const fn all() -> Self { + Self( + #( + #flag_idents.0 + )|* + ) + } + + /// Combines two event sets by computing a union of two sets + /// + /// A const method version of the `|` operator + pub const fn or(self, other: Self) -> Self { + Self(self.0 | other.0) + } + + /// Checks whether an event set is a superset of another event set + /// + /// That is, whether `self` will match all events that `other` contains + const fn contains(&self, other: Self) -> bool { + (self.0 & other.0) == other.0 + } + + /// Decomposes an `EventSet` into a vector of basis `EventSet`s, each containing a single event + /// + /// Each of the event set in the vector will be equal to some of the associated constants for the `EventSet` + fn decompose(&self) -> Vec { + let mut result = Vec::new(); + + #(if self.contains(#flag_idents) { + result.push(#flag_idents); + })* + + result + } + + /// Checks whether an event set contains a specific event + pub const fn matches(&self, event: &#event_enum_ident) -> bool { + match event { + #( + #event_patterns => self.contains(#flag_idents), + )* + } + } + } + + impl core::fmt::Debug for #set_ident { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{}[", stringify!(#set_ident))?; + + let mut need_comma = false; + + #(if self.contains(#flag_idents) { + if need_comma { + write!(f, ", ")?; + } else { + need_comma = true; + } + write!(f, "{}", #flag_names)? + })* + + write!(f, "]") + } + } + + impl core::ops::BitOr for #set_ident { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self { + self.or(rhs) + } + } + + impl core::ops::BitOrAssign for #set_ident { + fn bitor_assign(&mut self, rhs: Self) { + *self = self.or(rhs); + } + } + + impl serde::Serialize for #set_ident { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::*; + + let basis = self.decompose(); + let mut seq = serializer.serialize_seq(Some(basis.len()))?; + for event in basis { + let str = match event { + #(#flag_idents => #flag_names,)* + _ => unreachable!(), + }; + + seq.serialize_element(&str)?; + } + seq.end() + } + } + + impl<'de> serde::Deserialize<'de> for #set_ident { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = #set_ident; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a sequence of strings") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut result = #set_ident::empty(); + + struct SingleEvent(#set_ident); + impl<'de> serde::Deserialize<'de> for SingleEvent { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = SingleEvent; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + let event = match v { + #( + #flag_names => #flag_idents, + )* + _ => return Err(serde::de::Error::custom(format!("unknown event variant `{}`, expected one of {}", v, #flag_names_str))), + }; + + Ok(SingleEvent(event)) + } + } + + deserializer.deserialize_str(Visitor) + } + } + while let Some(SingleEvent(event)) = seq.next_element::()? { + result |= event; + } + + Ok(result) + } + } + + deserializer.deserialize_seq(Visitor) + } + } + }) + } +} + +pub fn impl_event_set_derive(emitter: &mut Emitter, input: &syn2::DeriveInput) -> TokenStream { + let Some(enum_) = emitter.handle(EventSetEnum::from_derive_input(input)) else { + return quote! {}; + }; + + quote! { + #enum_ + } +} diff --git a/data_model/derive/src/lib.rs b/data_model/derive/src/lib.rs index a51eae6d826..b39d5e3704d 100644 --- a/data_model/derive/src/lib.rs +++ b/data_model/derive/src/lib.rs @@ -1,5 +1,6 @@ //! A crate containing various derive macros for `data_model` mod enum_ref; +mod event_set; mod has_origin; mod id; mod model; @@ -477,3 +478,83 @@ pub fn has_origin_derive(input: TokenStream) -> TokenStream { emitter.finish_token_stream_with(result) } + +/// Create an event set structure from an event enum. +/// +/// Event set is a set of multiple event types, allowing to efficiently test whether an event is in a set. +/// +/// For this event enum: +/// +/// ```rust +/// # use iroha_data_model_derive::EventSet; +/// #[derive(EventSet)] +/// pub enum TestEvent { +/// Event1, +/// Event2, +/// NestedEvent(AnotherEvent), +/// } +/// pub struct AnotherEvent; +/// ``` +/// +/// The macro will generate a `TestEventSet` struct. +/// +/// It will have associated constants that correspond to a singleton set for each event that can be accessed like `TestEventSet::Event1`. +/// +/// The sets can be combined either with a `|` operator or with the `or` method to match multiple events at once: `TestEventSet::Event1 | TestEventSet::Event2`. +/// +/// Variants that: +/// 1. have a single unnamed field +/// 2. have the type name end with `Event` +/// +/// are treated as nested events and their set constant has `Any` prepended to the name. For example, `TestEventSet::AnyNestedEvent`. +/// +/// The set has the following methods: +/// ```ignore +/// impl TestEventSet { +/// /// Returns a set that doesn't contain any events +/// const fn empty() -> TestEventSet; +/// /// Returns a set that contains all events +/// const fn all() -> TestEventSet; +/// /// Computes union of two sets, const form of the `|` operator +/// const fn or(self, other: TestEventSet) -> TestEventSet; +/// /// Checks if the set contains a specific event +/// const fn matches(&self, event: &TestEvent) -> bool; +/// } +/// ``` +/// +/// Implemented traits: +/// ```ignore +/// #[derive( +/// Copy, +/// Clone, +/// PartialEq, +/// Eq, +/// PartialOrd, +/// Ord, +/// Hash, +/// parity_scale_codec::Decode, +/// parity_scale_codec::Encode, +/// iroha_schema::IntoSchema, +/// )] +/// +/// /// Prints the list of events in the set +/// /// +/// /// For example: `TestEventSet[Event1, AnyNestedEvent]` +/// impl core::fmt::Debug; +/// +/// /// Union of two sets +/// impl core::ops::BitOr; +/// ``` +#[manyhow] +#[proc_macro_derive(EventSet)] +pub fn event_set_derive(input: TokenStream) -> TokenStream { + let mut emitter = Emitter::new(); + + let Some(input) = emitter.handle(syn2::parse2(input)) else { + return emitter.finish_token_stream(); + }; + + let result = event_set::impl_event_set_derive(&mut emitter, &input); + + emitter.finish_token_stream_with(result) +} diff --git a/data_model/derive/tests/event_set.rs b/data_model/derive/tests/event_set.rs new file mode 100644 index 00000000000..9af5f782506 --- /dev/null +++ b/data_model/derive/tests/event_set.rs @@ -0,0 +1,166 @@ +mod events { + use iroha_data_model_derive::EventSet; + #[derive(EventSet)] + pub enum TestEvent { + Event1, + Event2, + NestedEvent(AnotherEvent), + } + + pub struct AnotherEvent; +} + +use events::{AnotherEvent, TestEvent, TestEventSet}; +use serde_json::json; + +#[test] +fn serialize() { + assert_eq!( + serde_json::to_value(TestEventSet::Event1).unwrap(), + json!(["Event1"]) + ); + assert_eq!( + serde_json::to_value(TestEventSet::Event1 | TestEventSet::Event2).unwrap(), + json!(["Event1", "Event2"]) + ); + assert_eq!( + serde_json::to_value(TestEventSet::Event1 | TestEventSet::AnyNestedEvent).unwrap(), + json!(["Event1", "AnyNestedEvent"]) + ); + assert_eq!( + serde_json::to_value(TestEventSet::all()).unwrap(), + json!(["Event1", "Event2", "AnyNestedEvent"]) + ); +} + +#[test] +fn deserialize() { + assert_eq!( + serde_json::from_value::(json!([])).unwrap(), + TestEventSet::empty() + ); + assert_eq!( + serde_json::from_value::(json!(["Event1"])).unwrap(), + TestEventSet::Event1 + ); + assert_eq!( + serde_json::from_value::(json!(["Event1", "Event2"])).unwrap(), + TestEventSet::Event1 | TestEventSet::Event2 + ); + assert_eq!( + serde_json::from_value::(json!(["Event1", "AnyNestedEvent"])).unwrap(), + TestEventSet::Event1 | TestEventSet::AnyNestedEvent + ); + assert_eq!( + serde_json::from_value::(json!(["Event1", "Event2", "AnyNestedEvent"])) + .unwrap(), + TestEventSet::all(), + ); + + assert_eq!( + serde_json::from_value::(json!(["Event1", "Event1", "AnyNestedEvent"])) + .unwrap(), + TestEventSet::Event1 | TestEventSet::AnyNestedEvent, + ); +} + +#[test] +fn deserialize_invalid() { + assert_eq!( + serde_json::from_value::(json!(32)) + .unwrap_err() + .to_string(), + "invalid type: integer `32`, expected a sequence of strings" + ); + + assert_eq!( + serde_json::from_value::(json!([32])) + .unwrap_err() + .to_string(), + "invalid type: integer `32`, expected a string" + ); + + assert_eq!( + serde_json::from_value::(json!(["InvalidVariant"])) + .unwrap_err() + .to_string(), + "unknown event variant `InvalidVariant`, expected one of `Event1`, `Event2`, `AnyNestedEvent`" + ); + + assert_eq!( + serde_json::from_value::(json!(["Event1", "Event1", "InvalidVariant"])) + .unwrap_err() + .to_string(), + "unknown event variant `InvalidVariant`, expected one of `Event1`, `Event2`, `AnyNestedEvent`" + ); +} + +#[test] +fn full_set() { + let any_matcher = TestEventSet::all(); + assert_eq!( + any_matcher, + TestEventSet::Event1 | TestEventSet::Event2 | TestEventSet::AnyNestedEvent + ); + + assert_eq!( + format!("{any_matcher:?}"), + "TestEventSet[Event1, Event2, AnyNestedEvent]" + ); + + assert!(any_matcher.matches(&TestEvent::Event1)); + assert!(any_matcher.matches(&TestEvent::Event2)); + assert!(any_matcher.matches(&TestEvent::NestedEvent(AnotherEvent))); +} + +#[test] +fn empty_set() { + let none_matcher = TestEventSet::empty(); + + assert_eq!(format!("{none_matcher:?}"), "TestEventSet[]"); + + assert!(!none_matcher.matches(&TestEvent::Event1)); + assert!(!none_matcher.matches(&TestEvent::Event2)); + assert!(!none_matcher.matches(&TestEvent::NestedEvent(AnotherEvent))); +} + +#[test] +fn event1_set() { + let event1_matcher = TestEventSet::Event1; + + assert_eq!(format!("{event1_matcher:?}"), "TestEventSet[Event1]"); + + assert!(event1_matcher.matches(&TestEvent::Event1)); + assert!(!event1_matcher.matches(&TestEvent::Event2)); + assert!(!event1_matcher.matches(&TestEvent::NestedEvent(AnotherEvent))); +} + +#[test] +fn event1_or_2_set() { + let event1_or_2_matcher = TestEventSet::Event1 | TestEventSet::Event2; + + assert_eq!( + format!("{event1_or_2_matcher:?}"), + "TestEventSet[Event1, Event2]" + ); + + assert!(event1_or_2_matcher.matches(&TestEvent::Event1)); + assert!(event1_or_2_matcher.matches(&TestEvent::Event2)); + assert!(!event1_or_2_matcher.matches(&TestEvent::NestedEvent(AnotherEvent))); +} + +#[test] +fn repeated() { + assert_eq!( + TestEventSet::Event1 | TestEventSet::Event1, + TestEventSet::Event1 + ); + assert_eq!( + TestEventSet::Event1 | TestEventSet::Event2 | TestEventSet::Event1, + TestEventSet::Event1 | TestEventSet::Event2 + ); + assert_eq!( + TestEventSet::all() | TestEventSet::AnyNestedEvent, + TestEventSet::all() + ); +} diff --git a/tools/parity_scale_decoder/samples/trigger.bin b/tools/parity_scale_decoder/samples/trigger.bin index 606a8247e2f56cf3123a26f440f6743800c0517d..bf1bf3f4b9e0f3dd4531d14c81a9540770bbaa9e 100644 GIT binary patch delta 9 OcmebBnc%^~00aOEw*hki delta 7 OcmebAn&832$^ZZd*8z3_ diff --git a/tools/parity_scale_decoder/samples/trigger.json b/tools/parity_scale_decoder/samples/trigger.json index 504eb5f125e..bcc84114c88 100644 --- a/tools/parity_scale_decoder/samples/trigger.json +++ b/tools/parity_scale_decoder/samples/trigger.json @@ -19,7 +19,7 @@ "Data": { "Domain": { "id_matcher": null, - "event_matcher": "AnyAccount" + "event_set": ["AnyAccount"] } } }, From 8b2361a1869b2e31bd2e958770d0ef8c80a11237 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Thu, 29 Feb 2024 17:29:52 +0300 Subject: [PATCH 08/13] [refactor] #1981, #4195, #3068: Use the auto-generated event sets instead of handwritten matchers Signed-off-by: Nikita Strygin --- .../integration/triggers/data_trigger.rs | 6 +- .../integration/triggers/event_trigger.rs | 2 +- data_model/derive/src/event_set.rs | 36 +- data_model/derive/src/lib.rs | 2 +- data_model/src/events/data/events.rs | 20 +- data_model/src/events/data/filters.rs | 499 +++++------------- docs/source/references/schema.json | 244 +-------- schema/gen/src/lib.rs | 14 +- tools/parity_scale_decoder/src/main.rs | 2 +- 9 files changed, 194 insertions(+), 631 deletions(-) diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 02dd12fcd9f..e9f2b12bff1 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -24,7 +24,7 @@ fn must_execute_both_triggers() -> Result<()> { Repeats::Indefinitely, account_id.clone(), TriggeringEventFilterBox::Data(DataEventFilter::Account( - AccountEventFilter::new().only_events(AccountEventMatcher::Created), + AccountEventFilter::new().only_events(AccountEventSet::Created), )), ), )); @@ -37,7 +37,7 @@ fn must_execute_both_triggers() -> Result<()> { Repeats::Indefinitely, account_id, TriggeringEventFilterBox::Data(DataEventFilter::Domain( - DomainEventFilter::new().only_events(DomainEventMatcher::Created), + DomainEventFilter::new().only_events(DomainEventSet::Created), )), ), )); @@ -89,7 +89,7 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu Repeats::Indefinitely, account_id, TriggeringEventFilterBox::Data(DataEventFilter::Account( - AccountEventFilter::new().only_events(AccountEventMatcher::Created), + AccountEventFilter::new().only_events(AccountEventSet::Created), )), ), )); diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index af40ab0aece..368da9aa4e8 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -25,7 +25,7 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { Repeats::Indefinitely, account_id, TriggeringEventFilterBox::Data(DataEventFilter::AssetDefinition( - AssetDefinitionEventFilter::new().only_events(AssetDefinitionEventMatcher::Created), + AssetDefinitionEventFilter::new().only_events(AssetDefinitionEventSet::Created), )), ), )); diff --git a/data_model/derive/src/event_set.rs b/data_model/derive/src/event_set.rs index 13f39780e18..e6ed8c573a1 100644 --- a/data_model/derive/src/event_set.rs +++ b/data_model/derive/src/event_set.rs @@ -4,7 +4,7 @@ use darling::{FromDeriveInput, FromVariant}; use iroha_macro_utils::Emitter; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; -use syn2::{DeriveInput, Variant}; +use syn::{DeriveInput, Variant}; enum FieldsStyle { Unit, @@ -24,14 +24,14 @@ impl ToTokens for FieldsStyle { } struct EventSetVariant { - event_ident: syn2::Ident, - flag_ident: syn2::Ident, + event_ident: syn::Ident, + flag_ident: syn::Ident, fields_style: FieldsStyle, } impl FromVariant for EventSetVariant { fn from_variant(variant: &Variant) -> darling::Result { - let syn2::Variant { + let syn::Variant { attrs: _, ident: event_ident, fields, @@ -41,27 +41,27 @@ impl FromVariant for EventSetVariant { // a nested event is an event within an event (like `AccountEvent::Asset`, which bears an `AssetEvent`) // we detect those by checking whether the payload type (if any) ends with `Event` let is_nested = match fields { - syn2::Fields::Unnamed(fields) => { + syn::Fields::Unnamed(fields) => { fields.unnamed.len() == 1 - && matches!(&fields.unnamed[0].ty, syn2::Type::Path(p) if p.path.segments.last().unwrap().ident.to_string().ends_with("Event")) + && matches!(&fields.unnamed[0].ty, syn::Type::Path(p) if p.path.segments.last().unwrap().ident.to_string().ends_with("Event")) } - syn2::Fields::Unit | + syn::Fields::Unit | // just a fail-safe, we don't use named fields in events - syn2::Fields::Named(_) => false, + syn::Fields::Named(_) => false, }; // we have a different naming convention for nested events // to signify that there are actually multiple types of events inside let flag_ident = if is_nested { - syn2::Ident::new(&format!("Any{event_ident}"), event_ident.span()) + syn::Ident::new(&format!("Any{event_ident}"), event_ident.span()) } else { event_ident.clone() }; let fields_style = match fields { - syn2::Fields::Unnamed(_) => FieldsStyle::Unnamed, - syn2::Fields::Named(_) => FieldsStyle::Named, - syn2::Fields::Unit => FieldsStyle::Unit, + syn::Fields::Unnamed(_) => FieldsStyle::Unnamed, + syn::Fields::Named(_) => FieldsStyle::Named, + syn::Fields::Unit => FieldsStyle::Unit, }; Ok(Self { @@ -73,15 +73,15 @@ impl FromVariant for EventSetVariant { } struct EventSetEnum { - vis: syn2::Visibility, - event_enum_ident: syn2::Ident, - set_ident: syn2::Ident, + vis: syn::Visibility, + event_enum_ident: syn::Ident, + set_ident: syn::Ident, variants: Vec, } impl FromDeriveInput for EventSetEnum { fn from_derive_input(input: &DeriveInput) -> darling::Result { - let syn2::DeriveInput { + let syn::DeriveInput { attrs: _, vis, ident: event_ident, @@ -115,7 +115,7 @@ impl FromDeriveInput for EventSetEnum { accumulator.finish_with(Self { vis: vis.clone(), event_enum_ident: event_ident.clone(), - set_ident: syn2::Ident::new(&format!("{event_ident}Set"), event_ident.span()), + set_ident: syn::Ident::new(&format!("{event_ident}Set"), event_ident.span()), variants, }) } @@ -384,7 +384,7 @@ impl ToTokens for EventSetEnum { } } -pub fn impl_event_set_derive(emitter: &mut Emitter, input: &syn2::DeriveInput) -> TokenStream { +pub fn impl_event_set_derive(emitter: &mut Emitter, input: &syn::DeriveInput) -> TokenStream { let Some(enum_) = emitter.handle(EventSetEnum::from_derive_input(input)) else { return quote! {}; }; diff --git a/data_model/derive/src/lib.rs b/data_model/derive/src/lib.rs index b39d5e3704d..384ca813542 100644 --- a/data_model/derive/src/lib.rs +++ b/data_model/derive/src/lib.rs @@ -550,7 +550,7 @@ pub fn has_origin_derive(input: TokenStream) -> TokenStream { pub fn event_set_derive(input: TokenStream) -> TokenStream { let mut emitter = Emitter::new(); - let Some(input) = emitter.handle(syn2::parse2(input)) else { + let Some(input) = emitter.handle(syn::parse2(input)) else { return emitter.finish_token_stream(); }; diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 8778d95d277..3f205445e75 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -2,7 +2,7 @@ #![allow(missing_docs)] use getset::Getters; -use iroha_data_model_derive::{model, HasOrigin}; +use iroha_data_model_derive::{model, EventSet, HasOrigin}; use iroha_primitives::numeric::Numeric; pub use self::model::*; @@ -19,6 +19,7 @@ macro_rules! data_event { PartialOrd, Ord, HasOrigin, + EventSet, parity_scale_codec::Decode, parity_scale_codec::Encode, serde::Deserialize, @@ -648,18 +649,19 @@ impl DataEvent { pub mod prelude { pub use super::{ - account::{AccountEvent, AccountPermissionChanged, AccountRoleChanged}, + account::{AccountEvent, AccountEventSet, AccountPermissionChanged, AccountRoleChanged}, asset::{ - AssetChanged, AssetDefinitionEvent, AssetDefinitionOwnerChanged, - AssetDefinitionTotalQuantityChanged, AssetEvent, + AssetChanged, AssetDefinitionEvent, AssetDefinitionEventSet, + AssetDefinitionOwnerChanged, AssetDefinitionTotalQuantityChanged, AssetEvent, + AssetEventSet, }, - config::ConfigurationEvent, - domain::{DomainEvent, DomainOwnerChanged}, + config::{ConfigurationEvent, ConfigurationEventSet}, + domain::{DomainEvent, DomainEventSet, DomainOwnerChanged}, executor::{ExecutorEvent, ExecutorFilter}, - peer::PeerEvent, + peer::{PeerEvent, PeerEventSet}, permission::PermissionTokenSchemaUpdateEvent, - role::{RoleEvent, RolePermissionChanged}, - trigger::{TriggerEvent, TriggerNumberOfExecutionsChanged}, + role::{RoleEvent, RoleEventSet, RolePermissionChanged}, + trigger::{TriggerEvent, TriggerEventSet, TriggerNumberOfExecutionsChanged}, DataEvent, HasOrigin, MetadataChanged, }; } diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 2f11d5322b0..a9c67c1472f 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -1,8 +1,8 @@ //! This module contains filters for data events. //! -//! (almost) Each event in [`super::events`], there's two corresponding types in this module: -//! - `*EventMatcher` - matches one event kind (e.g. [`super::events::AccountEvent::Created`] with [`AccountEventMatcher::Created`]) -//! - `*EventFilter` - struct combining an optional id matcher and an optional event matcher +//! For each event in [`super::events`], there's a corresponding filter type in this module. It can filter the events by origin id and event type. +//! +//! Event types are filtered with an `EventSet` type, allowing to filter for multiple event types at once. use core::fmt::Debug; @@ -60,7 +60,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -71,29 +70,8 @@ pub mod model { pub struct PeerEventFilter { /// If specified matches only events originating from this peer pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`PeerEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum PeerEventMatcher { - /// Matches [`PeerEvent::Added`] - Added, - /// Matches [`PeerEvent::Removed`] - Removed, + /// Matches only event from this set + pub(super) event_set: PeerEventSet, } /// An event filter for [`DomainEvent`]s @@ -104,7 +82,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -115,40 +92,8 @@ pub mod model { pub struct DomainEventFilter { /// If specified matches only events originating from this domain pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`DomainEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum DomainEventMatcher { - /// Matches [`DomainEvent::Created`] - Created, - /// Matches [`DomainEvent::Deleted`] - Deleted, - /// Matches [`DomainEvent::MetadataInserted`] - MetadataInserted, - /// Matches [`DomainEvent::MetadataRemoved`] - MetadataRemoved, - /// Matches [`DomainEvent::OwnerChanged`] - OwnerChanged, - // we allow filtering for nested events, but if you need to specify an id matcher for, for example, AccountId, you need to use AccountFilter - /// Matches any [`DomainEvent::Account`]. To further filter by account events, use [`AccountEventFilter`] - AnyAccount, - /// Matches any [`DomainEvent::AssetDefinition`]. To further filter by asset definition events, use [`AssetDefinitionEventFilter`] - AnyAssetDefinition, + /// Matches only event from this set + pub(super) event_set: DomainEventSet, } /// An event filter for [`AccountEvent`]s @@ -159,7 +104,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -170,48 +114,8 @@ pub mod model { pub struct AccountEventFilter { /// If specified matches only events originating from this account pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`AccountEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum AccountEventMatcher { - /// Matches [`AccountEvent::Created`] - Created, - /// Matches [`AccountEvent::Deleted`] - Deleted, - /// Matches [`AccountEvent::AuthenticationAdded`] - AuthenticationAdded, - /// Matches [`AccountEvent::AuthenticationRemoved`] - AuthenticationRemoved, - /// Matches [`AccountEvent::PermissionAdded`] - PermissionAdded, - /// Matches [`AccountEvent::PermissionRemoved`] - PermissionRemoved, - /// Matches [`AccountEvent::RoleRevoked`] - RoleRevoked, - /// Matches [`AccountEvent::RoleGranted`] - RoleGranted, - /// Matches [`AccountEvent::MetadataInserted`] - MetadataInserted, - /// Matches [`AccountEvent::MetadataRemoved`] - MetadataRemoved, - // nested events - /// Matches any [`AccountEvent::Asset`]. To further filter by asset events, use [`AssetEventFilter`] - AnyAsset, + /// Matches only event from this set + pub(super) event_set: AccountEventSet, } /// An event filter for [`AssetEvent`]s @@ -222,7 +126,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -233,37 +136,8 @@ pub mod model { pub struct AssetEventFilter { /// If specified matches only events originating from this asset pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`AssetEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum AssetEventMatcher { - /// Matches [`AssetEvent::Created`] - Created, - /// Matches [`AssetEvent::Deleted`] - Deleted, - /// Matches [`AssetEvent::Added`] - Added, - /// Matches [`AssetEvent::Removed`] - Removed, - /// Matches [`AssetEvent::MetadataInserted`] - MetadataInserted, - /// Matches [`AssetEvent::MetadataRemoved`] - MetadataRemoved, + /// Matches only event from this set + pub(super) event_set: AssetEventSet, } /// An event filter for [`AssetDefinitionEvent`]s @@ -274,7 +148,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -285,39 +158,8 @@ pub mod model { pub struct AssetDefinitionEventFilter { /// If specified matches only events originating from this asset definition pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`AssetDefinitionEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum AssetDefinitionEventMatcher { - /// Matches [`AssetDefinitionEvent::Created`] - Created, - /// Matches [`AssetDefinitionEvent::MintabilityChanged`] - MintabilityChanged, - /// Matches [`AssetDefinitionEvent::OwnerChanged`] - OwnerChanged, - /// Matches [`AssetDefinitionEvent::Deleted`] - Deleted, - /// Matches [`AssetDefinitionEvent::MetadataInserted`] - MetadataInserted, - /// Matches [`AssetDefinitionEvent::MetadataRemoved`] - MetadataRemoved, - /// Matches [`AssetDefinitionEvent::TotalQuantityChanged`] - TotalQuantityChanged, + /// Matches only event from this set + pub(super) event_set: AssetDefinitionEventSet, } /// An event filter for [`TriggerEvent`]s @@ -328,7 +170,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -339,33 +180,8 @@ pub mod model { pub struct TriggerEventFilter { /// If specified matches only events originating from this trigger pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`TriggerEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum TriggerEventMatcher { - /// Matches [`TriggerEvent::Created`] - Created, - /// Matches [`TriggerEvent::Deleted`] - Deleted, - /// Matches [`TriggerEvent::Extended`] - Extended, - /// Matches [`TriggerEvent::Shortened`] - Shortened, + /// Matches only event from this set + pub(super) event_set: TriggerEventSet, } /// An event filter for [`RoleEvent`]s @@ -376,7 +192,6 @@ pub mod model { Eq, PartialOrd, Ord, - Default, Getters, Decode, Encode, @@ -387,31 +202,8 @@ pub mod model { pub struct RoleEventFilter { /// If specified matches only events originating from this role pub(super) id_matcher: Option, - /// If specified matches only events of this type - pub(super) event_matcher: Option, - } - - /// An event matcher for [`RoleEvent`]s - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - pub enum RoleEventMatcher { - /// Matches [`RoleEvent::Created`] - Created, - /// Matches [`RoleEvent::Deleted`] - Deleted, - /// Matches [`RoleEvent::PermissionRemoved`] - PermissionRemoved, + /// Matches only event from this set + pub(super) event_set: RoleEventSet, } } @@ -420,46 +212,47 @@ impl PeerEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: PeerEventSet::all(), } } /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_id(mut self, id_matcher: PeerId) -> Self { + pub fn only_from(mut self, id_matcher: PeerId) -> Self { self.id_matcher = Some(id_matcher); self } - /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s of types matching `event_matcher`. + /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: PeerEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: PeerEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for PeerEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl EventFilter for PeerEventFilter { type Event = super::PeerEvent; fn matches(&self, event: &Self::Event) -> bool { - use PeerEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Added, PeerEvent::Added(_)) => true, - (Removed, PeerEvent::Removed(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -468,51 +261,47 @@ impl DomainEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: DomainEventSet::all(), } } /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_id(mut self, id_matcher: DomainId) -> Self { + pub fn only_from(mut self, id_matcher: DomainId) -> Self { self.id_matcher = Some(id_matcher); self } - /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s of types matching `event_matcher`. + /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: DomainEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: DomainEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for DomainEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl EventFilter for DomainEventFilter { type Event = super::DomainEvent; fn matches(&self, event: &Self::Event) -> bool { - use DomainEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Created, DomainEvent::Created(_)) => true, - (Deleted, DomainEvent::Deleted(_)) => true, - (MetadataInserted, DomainEvent::MetadataInserted(_)) => true, - (MetadataRemoved, DomainEvent::MetadataRemoved(_)) => true, - (OwnerChanged, DomainEvent::OwnerChanged(_)) => true, - (AnyAccount, DomainEvent::Account(_)) => true, - (AnyAssetDefinition, DomainEvent::AssetDefinition(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -521,55 +310,47 @@ impl AccountEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: AccountEventSet::all(), } } /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_id(mut self, id_matcher: AccountId) -> Self { + pub fn only_from(mut self, id_matcher: AccountId) -> Self { self.id_matcher = Some(id_matcher); self } - /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s of types matching `event_matcher`. + /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: AccountEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: AccountEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for AccountEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for AccountEventFilter { type Event = super::AccountEvent; fn matches(&self, event: &Self::Event) -> bool { - use AccountEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Created, AccountEvent::Created(_)) => true, - (Deleted, AccountEvent::Deleted(_)) => true, - (AuthenticationAdded, AccountEvent::AuthenticationAdded(_)) => true, - (AuthenticationRemoved, AccountEvent::AuthenticationRemoved(_)) => true, - (PermissionAdded, AccountEvent::PermissionAdded(_)) => true, - (PermissionRemoved, AccountEvent::PermissionRemoved(_)) => true, - (RoleRevoked, AccountEvent::RoleRevoked(_)) => true, - (RoleGranted, AccountEvent::RoleGranted(_)) => true, - (MetadataInserted, AccountEvent::MetadataInserted(_)) => true, - (MetadataRemoved, AccountEvent::MetadataRemoved(_)) => true, - (AnyAsset, AccountEvent::Asset(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -578,7 +359,7 @@ impl AssetEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: AssetEventSet::all(), } } @@ -589,39 +370,36 @@ impl AssetEventFilter { self } - /// Modifies a [`AssetEventFilter`] to accept only [`AssetEvent`]s of types matching `event_matcher`. + /// Modifies a [`AssetEventFilter`] to accept only [`AssetEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: AssetEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: AssetEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for AssetEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for AssetEventFilter { type Event = super::AssetEvent; fn matches(&self, event: &Self::Event) -> bool { - use AssetEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Created, AssetEvent::Created(_)) => true, - (Deleted, AssetEvent::Deleted(_)) => true, - (Added, AssetEvent::Added(_)) => true, - (Removed, AssetEvent::Removed(_)) => true, - (MetadataInserted, AssetEvent::MetadataInserted(_)) => true, - (MetadataRemoved, AssetEvent::MetadataRemoved(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -630,7 +408,7 @@ impl AssetDefinitionEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: AssetDefinitionEventSet::all(), } } @@ -641,40 +419,36 @@ impl AssetDefinitionEventFilter { self } - /// Modifies a [`AssetDefinitionEventFilter`] to accept only [`AssetDefinitionEvent`]s of types matching `event_matcher`. + /// Modifies a [`AssetDefinitionEventFilter`] to accept only [`AssetDefinitionEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: AssetDefinitionEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: AssetDefinitionEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for AssetDefinitionEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for AssetDefinitionEventFilter { type Event = super::AssetDefinitionEvent; fn matches(&self, event: &Self::Event) -> bool { - use AssetDefinitionEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Created, AssetDefinitionEvent::Created(_)) => true, - (MintabilityChanged, AssetDefinitionEvent::MintabilityChanged(_)) => true, - (OwnerChanged, AssetDefinitionEvent::OwnerChanged(_)) => true, - (Deleted, AssetDefinitionEvent::Deleted(_)) => true, - (MetadataInserted, AssetDefinitionEvent::MetadataInserted(_)) => true, - (MetadataRemoved, AssetDefinitionEvent::MetadataRemoved(_)) => true, - (TotalQuantityChanged, AssetDefinitionEvent::TotalQuantityChanged(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -683,7 +457,7 @@ impl TriggerEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: TriggerEventSet::all(), } } @@ -694,37 +468,36 @@ impl TriggerEventFilter { self } - /// Modifies a [`TriggerEventFilter`] to accept only [`TriggerEvent`]s of types matching `event_matcher`. + /// Modifies a [`TriggerEventFilter`] to accept only [`TriggerEvent`]s of types matching `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: TriggerEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: TriggerEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for TriggerEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for TriggerEventFilter { type Event = super::TriggerEvent; fn matches(&self, event: &Self::Event) -> bool { - use TriggerEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Created, TriggerEvent::Created(_)) => true, - (Deleted, TriggerEvent::Deleted(_)) => true, - (Extended, TriggerEvent::Extended(_)) => true, - (Shortened, TriggerEvent::Shortened(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -733,7 +506,7 @@ impl RoleEventFilter { pub const fn new() -> Self { Self { id_matcher: None, - event_matcher: None, + event_set: RoleEventSet::all(), } } @@ -744,36 +517,36 @@ impl RoleEventFilter { self } - /// Modifies a [`RoleEventFilter`] to accept only [`RoleEvent`]s of types matching `event_matcher`. + /// Modifies a [`RoleEventFilter`] to accept only [`RoleEvent`]s of types matching `event_set`. #[must_use] - pub const fn only_events(mut self, event_matcher: RoleEventMatcher) -> Self { - self.event_matcher = Some(event_matcher); + pub const fn only_events(mut self, event_set: RoleEventSet) -> Self { + self.event_set = event_set; self } } +impl Default for RoleEventFilter { + fn default() -> Self { + Self::new() + } +} + #[cfg(feature = "transparent_api")] impl super::EventFilter for RoleEventFilter { type Event = super::RoleEvent; fn matches(&self, event: &Self::Event) -> bool { - use RoleEventMatcher::*; - if let Some(id_matcher) = &self.id_matcher { if id_matcher != event.origin_id() { return false; } } - if let Some(event_matcher) = &self.event_matcher { - match (event_matcher, event) { - (Created, RoleEvent::Created(_)) => true, - (Deleted, RoleEvent::Deleted(_)) => true, - (PermissionRemoved, RoleEvent::PermissionRemoved(_)) => true, - _ => false, - } - } else { - true + + if !self.event_set.matches(event) { + return false; } + + true } } @@ -807,10 +580,8 @@ impl EventFilter for DataEventFilter { pub mod prelude { pub use super::{ - AccountEventFilter, AccountEventMatcher, AssetDefinitionEventFilter, - AssetDefinitionEventMatcher, AssetEventFilter, AssetEventMatcher, DataEventFilter, - DomainEventFilter, DomainEventMatcher, PeerEventFilter, PeerEventMatcher, RoleEventFilter, - RoleEventMatcher, TriggerEventFilter, TriggerEventMatcher, + AccountEventFilter, AssetDefinitionEventFilter, AssetEventFilter, DataEventFilter, + DomainEventFilter, PeerEventFilter, RoleEventFilter, TriggerEventFilter, }; } @@ -863,18 +634,10 @@ mod tests { DomainEvent::Account(AccountEvent::Asset(AssetEvent::Created(asset))).into(); // test how the differently nested filters with with the events - let domain_filter = DataEventFilter::Domain(DomainEventFilter { - id_matcher: Some(domain_id), - event_matcher: None, - }); - let account_filter = DataEventFilter::Account(AccountEventFilter { - id_matcher: Some(account_id), - event_matcher: None, - }); - let asset_filter = DataEventFilter::Asset(AssetEventFilter { - id_matcher: Some(asset_id), - event_matcher: None, - }); + let domain_filter = DataEventFilter::Domain(DomainEventFilter::new().only_from(domain_id)); + let account_filter = + DataEventFilter::Account(AccountEventFilter::new().only_from(account_id)); + let asset_filter = DataEventFilter::Asset(AssetEventFilter::new().only_from(asset_id)); // domain filter matches all of those, because all of those events happened in the same domain assert!(domain_filter.matches(&domain_created)); diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 389b71c0bea..a70f0d7e38b 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -89,59 +89,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "AccountEventMatcher": { - "Enum": [ - { - "tag": "Created", - "discriminant": 0 - }, - { - "tag": "Deleted", - "discriminant": 1 - }, - { - "tag": "AuthenticationAdded", - "discriminant": 2 - }, - { - "tag": "AuthenticationRemoved", - "discriminant": 3 - }, - { - "tag": "PermissionAdded", - "discriminant": 4 - }, - { - "tag": "PermissionRemoved", - "discriminant": 5 - }, - { - "tag": "RoleRevoked", - "discriminant": 6 - }, - { - "tag": "RoleGranted", - "discriminant": 7 - }, - { - "tag": "MetadataInserted", - "discriminant": 8 - }, - { - "tag": "MetadataRemoved", - "discriminant": 9 - }, - { - "tag": "AnyAsset", - "discriminant": 10 + "name": "event_set", + "type": "AccountEventSet" } ] }, + "AccountEventSet": "u32", "AccountId": { "Struct": [ { @@ -352,43 +305,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "AssetDefinitionEventMatcher": { - "Enum": [ - { - "tag": "Created", - "discriminant": 0 - }, - { - "tag": "MintabilityChanged", - "discriminant": 1 - }, - { - "tag": "OwnerChanged", - "discriminant": 2 - }, - { - "tag": "Deleted", - "discriminant": 3 - }, - { - "tag": "MetadataInserted", - "discriminant": 4 - }, - { - "tag": "MetadataRemoved", - "discriminant": 5 - }, - { - "tag": "TotalQuantityChanged", - "discriminant": 6 + "name": "event_set", + "type": "AssetDefinitionEventSet" } ] }, + "AssetDefinitionEventSet": "u32", "AssetDefinitionId": { "Struct": [ { @@ -466,39 +388,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "AssetEventMatcher": { - "Enum": [ - { - "tag": "Created", - "discriminant": 0 - }, - { - "tag": "Deleted", - "discriminant": 1 - }, - { - "tag": "Added", - "discriminant": 2 - }, - { - "tag": "Removed", - "discriminant": 3 - }, - { - "tag": "MetadataInserted", - "discriminant": 4 - }, - { - "tag": "MetadataRemoved", - "discriminant": 5 + "name": "event_set", + "type": "AssetEventSet" } ] }, + "AssetEventSet": "u32", "AssetId": { "Struct": [ { @@ -903,43 +798,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "DomainEventMatcher": { - "Enum": [ - { - "tag": "Created", - "discriminant": 0 - }, - { - "tag": "Deleted", - "discriminant": 1 - }, - { - "tag": "MetadataInserted", - "discriminant": 2 - }, - { - "tag": "MetadataRemoved", - "discriminant": 3 - }, - { - "tag": "OwnerChanged", - "discriminant": 4 - }, - { - "tag": "AnyAccount", - "discriminant": 5 - }, - { - "tag": "AnyAssetDefinition", - "discriminant": 6 + "name": "event_set", + "type": "DomainEventSet" } ] }, + "DomainEventSet": "u32", "DomainId": { "Struct": [ { @@ -2356,27 +2220,15 @@ } ] }, - "Option": { - "Option": "AccountEventMatcher" - }, "Option": { "Option": "AccountId" }, - "Option": { - "Option": "AssetDefinitionEventMatcher" - }, "Option": { "Option": "AssetDefinitionId" }, - "Option": { - "Option": "AssetEventMatcher" - }, "Option": { "Option": "AssetId" }, - "Option": { - "Option": "DomainEventMatcher" - }, "Option": { "Option": "DomainId" }, @@ -2401,9 +2253,6 @@ "Option>": { "Option": "NonZero" }, - "Option": { - "Option": "PeerEventMatcher" - }, "Option": { "Option": "PeerId" }, @@ -2413,9 +2262,6 @@ "Option": { "Option": "PipelineStatusKind" }, - "Option": { - "Option": "RoleEventMatcher" - }, "Option": { "Option": "RoleId" }, @@ -2431,9 +2277,6 @@ "Option": { "Option": "TriggerCompletedOutcomeType" }, - "Option": { - "Option": "TriggerEventMatcher" - }, "Option": { "Option": "TriggerId" }, @@ -2513,23 +2356,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "PeerEventMatcher": { - "Enum": [ - { - "tag": "Added", - "discriminant": 0 - }, - { - "tag": "Removed", - "discriminant": 1 + "name": "event_set", + "type": "PeerEventSet" } ] }, + "PeerEventSet": "u32", "PeerId": { "Struct": [ { @@ -3317,27 +3149,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "RoleEventMatcher": { - "Enum": [ - { - "tag": "Created", - "discriminant": 0 - }, - { - "tag": "Deleted", - "discriminant": 1 - }, - { - "tag": "PermissionRemoved", - "discriminant": 2 + "name": "event_set", + "type": "RoleEventSet" } ] }, + "RoleEventSet": "u32", "RoleId": { "Struct": [ { @@ -4050,31 +3867,12 @@ "type": "Option" }, { - "name": "event_matcher", - "type": "Option" - } - ] - }, - "TriggerEventMatcher": { - "Enum": [ - { - "tag": "Created", - "discriminant": 0 - }, - { - "tag": "Deleted", - "discriminant": 1 - }, - { - "tag": "Extended", - "discriminant": 2 - }, - { - "tag": "Shortened", - "discriminant": 3 + "name": "event_set", + "type": "TriggerEventSet" } ] }, + "TriggerEventSet": "u32", "TriggerId": { "Struct": [ { diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 30804bbd706..49baf0f6a5f 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -65,7 +65,7 @@ types!( Account, AccountEvent, AccountEventFilter, - AccountEventMatcher, + AccountEventSet, AccountId, AccountMintBox, AccountPermissionChanged, @@ -77,13 +77,13 @@ types!( AssetDefinition, AssetDefinitionEvent, AssetDefinitionEventFilter, - AssetDefinitionEventMatcher, + AssetDefinitionEventSet, AssetDefinitionId, AssetDefinitionOwnerChanged, AssetDefinitionTotalQuantityChanged, AssetEvent, AssetEventFilter, - AssetEventMatcher, + AssetEventSet, AssetId, AssetTransferBox, AssetValue, @@ -122,7 +122,7 @@ types!( Domain, DomainEvent, DomainEventFilter, - DomainEventMatcher, + DomainEventSet, DomainId, DomainOwnerChanged, Duration, @@ -255,7 +255,7 @@ types!( Peer, PeerEvent, PeerEventFilter, - PeerEventMatcher, + PeerEventSet, PeerId, RolePermissionChanged, PermissionToken, @@ -296,7 +296,7 @@ types!( Role, RoleEvent, RoleEventFilter, - RoleEventMatcher, + RoleEventSet, RoleId, SemiInterval, SemiInterval, @@ -352,7 +352,7 @@ types!( TriggerCompletedOutcomeType, TriggerEvent, TriggerEventFilter, - TriggerEventMatcher, + TriggerEventSet, TriggerId, TriggerNumberOfExecutionsChanged, TriggeringEventFilterBox, diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index 2bde62a553f..57bb09981b6 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -276,7 +276,7 @@ mod tests { Repeats::Indefinitely, account_id, EventFilterBox::Data(DataEventFilter::Domain( - DomainEventFilter::new().only_events(DomainEventMatcher::AnyAccount), + DomainEventFilter::new().only_events(DomainEventSet::AnyAccount), )), ); let trigger = Trigger::new(trigger_id, action); From fb54f9dffbb8e23a8a934d7f66db540178274811 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Wed, 6 Mar 2024 11:38:53 +0300 Subject: [PATCH 09/13] [refactor] #1981, #4195, #3068: match more exhaustively over events in DataEventFilter This will produce a compile error in case a new top-level data event is introduced. It will not catch new Domain event types (like Account, Asset, AssetDefinition). Achieving that will require listing all (even non-hierarchical) event types, which is probably too much boilerplate Signed-off-by: Nikita Strygin [refactor] #1981, #4195, #3068: match more exhaustively over events in DataEventFilter This will produce a compile error in case a new top-level data event is introduced. It will not catch new Domain event types (like Account, Asset, AssetDefinition). Achieving that will require listing all (even non-hierarchical) event types, which is probably too much boilerplate Signed-off-by: Nikita Strygin --- data_model/src/events/data/filters.rs | 44 +++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index a9c67c1472f..34bf7e5db39 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -557,23 +557,43 @@ impl EventFilter for DataEventFilter { fn matches(&self, event: &DataEvent) -> bool { use DataEventFilter::*; - match (self, event) { - (Any, _) => true, - (Peer(filter), DataEvent::Peer(event)) => filter.matches(event), - (Domain(filter), DataEvent::Domain(event)) => filter.matches(event), - (Account(filter), DataEvent::Domain(DomainEvent::Account(event))) => { - filter.matches(event) - } + match (event, self) { ( - Asset(filter), DataEvent::Domain(DomainEvent::Account(AccountEvent::Asset(event))), + Asset(filter), ) => filter.matches(event), - (AssetDefinition(filter), DataEvent::Domain(DomainEvent::AssetDefinition(event))) => { + (DataEvent::Domain(DomainEvent::Account(event)), Account(filter)) => { + filter.matches(event) + } + (DataEvent::Domain(DomainEvent::AssetDefinition(event)), AssetDefinition(filter)) => { filter.matches(event) } - (Trigger(filter), DataEvent::Trigger(event)) => filter.matches(event), - (Role(filter), DataEvent::Role(event)) => filter.matches(event), - _ => false, + (DataEvent::Domain(event), Domain(filter)) => filter.matches(event), + + (DataEvent::Peer(event), Peer(filter)) => filter.matches(event), + (DataEvent::Trigger(event), Trigger(filter)) => filter.matches(event), + (DataEvent::Role(event), Role(filter)) => filter.matches(event), + + ( + DataEvent::Peer(_) + | DataEvent::Domain(_) + | DataEvent::Trigger(_) + | DataEvent::Role(_) + | DataEvent::PermissionToken(_) + | DataEvent::Configuration(_) + | DataEvent::Executor(_), + Any, + ) => true, + ( + DataEvent::Peer(_) + | DataEvent::Domain(_) + | DataEvent::Trigger(_) + | DataEvent::Role(_) + | DataEvent::PermissionToken(_) + | DataEvent::Configuration(_) + | DataEvent::Executor(_), + _, + ) => false, } } } From a77f305787bc9dbf66f556e6ca745bb05d6dba09 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Wed, 6 Mar 2024 13:31:55 +0300 Subject: [PATCH 10/13] [refactor] #1981, #4195, #3068: Add event filters for PermissionTokenSchemaUpdate, Configuration and Executor events Signed-off-by: Nikita Strygin --- configs/swarm/executor.wasm | Bin 536367 -> 799930 bytes data_model/src/events/data/events.rs | 38 +------ data_model/src/events/data/filters.rs | 145 +++++++++++++++++++++++++- docs/source/references/schema.json | 39 +++++++ schema/gen/src/lib.rs | 10 ++ 5 files changed, 193 insertions(+), 39 deletions(-) mode change 100644 => 100755 configs/swarm/executor.wasm diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm old mode 100644 new mode 100755 index b447246240b4dedfab404603d89baa57f46b58ec..9eabd2f39068c887b6ee4dcf2cd248213c6b655e GIT binary patch literal 799930 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

Gms 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

;{0R#&oh%l3Z%|Di~Z3clh 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­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 J#mfn5{vTbK#IFDV literal 536367 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�jQ9O>bsa{Wp`kC8v6n z+zg!4CC8h+2zq-FhU_J8MD1FNfrk)8m6*`3jRGM_3RRQatjr`LSeMj<>zvwfowIHt zM*XBhnsw4_X^w9ZwvKJA&Q6s=u%^VeQj@_>^(1I*x*fFLt4?G;#XXFdX0oPI*lJEb z|EEmuxTWzDvskm!%^}7p7LU0EV-Cc><3O!Pn8(!($s?!I<**6V%$7+NPlz{CmVL~< z%bG0cMQL(e%xGXEfw!N!?_KK56NTy^5)B5%CX80BM@J((MVbKR>H%Lu;aJyMOMNxL z8Y)<|R5mP)yO~Vv?j=9Q{7839a7ut;3^xHvJ$%p%bi4_8tGU4mdgX;9l+AbTLqDv@ zRDvjw@H^J?sVF!BNm;$47L?b8+F2R)Gmn%0A^Nao5_dbI$n4o~kgxEP?xN#s;ph+= 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

f#j6V|j+pLsU)*bklUM{rizmMT%& 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�{QYn-Xi&Q0jB$xE}id(==aA%)h_+ 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 vup#br;wUu(-TVs!IRTd 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 AxBvhE diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 3f205445e75..618007e6522 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -549,6 +549,8 @@ mod executor { #[cfg(not(feature = "std"))] use alloc::{format, string::String, vec::Vec}; + use iroha_data_model_derive::EventSet; + #[derive( Debug, Copy, @@ -562,6 +564,7 @@ mod executor { serde::Deserialize, serde::Serialize, iroha_schema::IntoSchema, + EventSet, )] #[non_exhaustive] #[ffi_type] @@ -570,39 +573,6 @@ mod executor { pub enum ExecutorEvent { Upgraded, } - - /// Filter for [`ExecutorEvent`]. - #[derive( - Debug, - Copy, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - parity_scale_codec::Decode, - parity_scale_codec::Encode, - serde::Deserialize, - serde::Serialize, - iroha_schema::IntoSchema, - )] - #[non_exhaustive] - #[serde(untagged)] // Unaffected by #3330, as single unit variant - #[repr(transparent)] - pub enum ExecutorFilter { - Upgraded, - } - } - - #[cfg(feature = "transparent_api")] - impl super::EventFilter for ExecutorFilter { - type Event = ExecutorEvent; - - fn matches(&self, event: &Self::Event) -> bool { - match (self, event) { - (Self::Upgraded, Self::Event::Upgraded) => true, - } - } } } @@ -657,7 +627,7 @@ pub mod prelude { }, config::{ConfigurationEvent, ConfigurationEventSet}, domain::{DomainEvent, DomainEventSet, DomainOwnerChanged}, - executor::{ExecutorEvent, ExecutorFilter}, + executor::{ExecutorEvent, ExecutorEventSet}, peer::{PeerEvent, PeerEventSet}, permission::PermissionTokenSchemaUpdateEvent, role::{RoleEvent, RoleEventSet, RolePermissionChanged}, diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 34bf7e5db39..3a53431695e 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -47,9 +47,13 @@ pub mod model { Trigger(TriggerEventFilter), /// Matches [`RoleEvent`]s Role(RoleEventFilter), - // We didn't have filters for these events before the refactor. Should we? - // Configuration(ConfigurationEventFilter), - // Executor(ExecutorEventFilter), + /// Matches [`PermissionTokenSchemaUpdateEvent`]s + // nothing to filter for, really + PermissionTokenSchemaUpdate, + /// Matches [`ConfigurationEvent`]s + Configuration(ConfigurationEventFilter), + /// Matches [`ExecutorEvent`]s + Executor(ExecutorEventFilter), } /// An event filter for [`PeerEvent`]s @@ -205,6 +209,49 @@ pub mod model { /// Matches only event from this set pub(super) event_set: RoleEventSet, } + + /// An event filter for [`ConfigurationEvent`]s + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + pub struct ConfigurationEventFilter { + /// If specified matches only events originating from this configuration + pub(super) id_matcher: Option, + /// Matches only event from this set + pub(super) event_set: ConfigurationEventSet, + } + + /// An event filter for [`ExecutorEvent`]. + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Getters, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + pub struct ExecutorEventFilter { + // executor is a global entity, so no id here + /// Matches only event from this set + pub(super) event_set: ExecutorEventSet, + } } impl PeerEventFilter { @@ -550,6 +597,90 @@ impl super::EventFilter for RoleEventFilter { } } +impl ConfigurationEventFilter { + /// Creates a new [`ConfigurationEventFilter`] accepting all [`ConfigurationEvent`]s. + pub const fn new() -> Self { + Self { + id_matcher: None, + event_set: ConfigurationEventSet::all(), + } + } + + /// Modifies a [`ConfigurationEventFilter`] to accept only [`ConfigurationEvent`]s originating from ids matching `id_matcher`. + #[must_use] + pub fn only_from(mut self, id_matcher: ParameterId) -> Self { + self.id_matcher = Some(id_matcher); + self + } + + /// Modifies a [`ConfigurationEventFilter`] to accept only [`ConfigurationEvent`]s of types matching `event_set`. + #[must_use] + pub const fn only_events(mut self, event_set: ConfigurationEventSet) -> Self { + self.event_set = event_set; + self + } +} + +impl Default for ConfigurationEventFilter { + fn default() -> Self { + Self::new() + } +} + +#[cfg(feature = "transparent_api")] +impl super::EventFilter for ConfigurationEventFilter { + type Event = super::ConfigurationEvent; + + fn matches(&self, event: &Self::Event) -> bool { + if let Some(id_matcher) = &self.id_matcher { + if id_matcher != event.origin_id() { + return false; + } + } + + if !self.event_set.matches(event) { + return false; + } + + true + } +} + +impl ExecutorEventFilter { + /// Creates a new [`ExecutorEventFilter`] accepting all [`ExecutorEvent`]s. + pub const fn new() -> Self { + Self { + event_set: ExecutorEventSet::all(), + } + } + + /// Modifies a [`ExecutorEventFilter`] to accept only [`ExecutorEvent`]s of types matching `event_set`. + #[must_use] + pub const fn only_events(mut self, event_set: ExecutorEventSet) -> Self { + self.event_set = event_set; + self + } +} + +impl Default for ExecutorEventFilter { + fn default() -> Self { + Self::new() + } +} + +#[cfg(feature = "transparent_api")] +impl super::EventFilter for ExecutorEventFilter { + type Event = super::ExecutorEvent; + + fn matches(&self, event: &Self::Event) -> bool { + if !self.event_set.matches(event) { + return false; + } + + true + } +} + #[cfg(feature = "transparent_api")] impl EventFilter for DataEventFilter { type Event = DataEvent; @@ -573,6 +704,9 @@ impl EventFilter for DataEventFilter { (DataEvent::Peer(event), Peer(filter)) => filter.matches(event), (DataEvent::Trigger(event), Trigger(filter)) => filter.matches(event), (DataEvent::Role(event), Role(filter)) => filter.matches(event), + (DataEvent::PermissionToken(_), PermissionTokenSchemaUpdate) => true, + (DataEvent::Configuration(event), Configuration(filter)) => filter.matches(event), + (DataEvent::Executor(event), Executor(filter)) => filter.matches(event), ( DataEvent::Peer(_) @@ -600,8 +734,9 @@ impl EventFilter for DataEventFilter { pub mod prelude { pub use super::{ - AccountEventFilter, AssetDefinitionEventFilter, AssetEventFilter, DataEventFilter, - DomainEventFilter, PeerEventFilter, RoleEventFilter, TriggerEventFilter, + AccountEventFilter, AssetDefinitionEventFilter, AssetEventFilter, ConfigurationEventFilter, + DataEventFilter, DomainEventFilter, ExecutorEventFilter, PeerEventFilter, RoleEventFilter, + TriggerEventFilter, }; } diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index a70f0d7e38b..93c774cd19d 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -619,6 +619,19 @@ } ] }, + "ConfigurationEventFilter": { + "Struct": [ + { + "name": "id_matcher", + "type": "Option" + }, + { + "name": "event_set", + "type": "ConfigurationEventSet" + } + ] + }, + "ConfigurationEventSet": "u32", "Container": { "Enum": [ { @@ -717,6 +730,20 @@ "tag": "Role", "discriminant": 7, "type": "RoleEventFilter" + }, + { + "tag": "PermissionTokenSchemaUpdate", + "discriminant": 8 + }, + { + "tag": "Configuration", + "discriminant": 9, + "type": "ConfigurationEventFilter" + }, + { + "tag": "Executor", + "discriminant": 10, + "type": "ExecutorEventFilter" } ] }, @@ -965,6 +992,15 @@ } ] }, + "ExecutorEventFilter": { + "Struct": [ + { + "name": "event_set", + "type": "ExecutorEventSet" + } + ] + }, + "ExecutorEventSet": "u32", "ExecutorMode": { "Enum": [ { @@ -2253,6 +2289,9 @@ "Option>": { "Option": "NonZero" }, + "Option": { + "Option": "ParameterId" + }, "Option": { "Option": "PeerId" }, diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 49baf0f6a5f..7995f54eaf6 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -113,6 +113,8 @@ types!( BurnBox, ChainId, ConfigurationEvent, + ConfigurationEventFilter, + ConfigurationEventSet, ConstString, ConstVec, ConstVec, @@ -136,6 +138,8 @@ types!( ExecutionTime, Executor, ExecutorEvent, + ExecutorEventFilter, + ExecutorEventSet, Fail, EventFilterBox, FindAccountById, @@ -234,6 +238,9 @@ types!( Numeric, NumericSpec, Option, + Option, + Option, + Option, Option, Option, Option, @@ -242,8 +249,11 @@ types!( Option, Option, Option, + Option, + Option, Option, Option, + Option, Option, Option, Option, From f2c615f3691df990fea0be5b5e928b3ab9959746 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Wed, 13 Mar 2024 11:17:31 +0300 Subject: [PATCH 11/13] [refactor] #1981, #4195, #3068: Remove some more redundancy when constructing event filters Signed-off-by: Nikita Strygin --- client_cli/src/main.rs | 14 +++++++------- core/test_network/src/lib.rs | 4 ++-- tools/parity_scale_decoder/src/main.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index f17d374cab8..1d06e1c8e5b 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -264,16 +264,16 @@ mod events { impl RunArgs for Args { fn run(self, context: &mut dyn RunContext) -> Result<()> { - let filter = match self { - Args::Pipeline => EventFilterBox::Pipeline(PipelineEventFilter::new()), - Args::Data => EventFilterBox::Data(DataEventFilter::Any), - Args::Notification => EventFilterBox::Notification(NotificationEventFilter::ByAny), - }; - listen(filter, context) + match self { + Args::Pipeline => listen(PipelineEventFilter::new(), context), + Args::Data => listen(DataEventFilter::Any, context), + Args::Notification => listen(NotificationEventFilter::ByAny, context), + } } } - fn listen(filter: EventFilterBox, context: &mut dyn RunContext) -> Result<()> { + fn listen(filter: impl Into, context: &mut dyn RunContext) -> Result<()> { + let filter = filter.into(); let iroha_client = context.client_from_config(); eprintln!("Listening to events with filter: {filter:?}"); iroha_client diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 8b67fe14c53..0b036eff0fe 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -672,7 +672,7 @@ pub trait TestClient: Sized { fn test_with_account(api_url: &SocketAddr, keys: KeyPair, account_id: &AccountId) -> Self; /// Loop for events with filter and handler function - fn for_each_event(self, event_filter: EventFilterBox, f: impl Fn(Result)); + fn for_each_event(self, event_filter: impl Into, f: impl Fn(Result)); /// Submit instruction with polling /// @@ -811,7 +811,7 @@ impl TestClient for Client { Client::new(config) } - fn for_each_event(self, event_filter: EventFilterBox, f: impl Fn(Result)) { + fn for_each_event(self, event_filter: impl Into, f: impl Fn(Result)) { for event_result in self .listen_for_events(event_filter) .expect("Failed to create event iterator.") diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index 57bb09981b6..1aa1bb3b0f1 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -271,7 +271,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![Mint::asset_numeric(1u32, rose_id)], Repeats::Indefinitely, account_id, From 491e1d51c3563c820f08af860755eaa679b3e0e0 Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Wed, 13 Mar 2024 11:20:02 +0300 Subject: [PATCH 12/13] [refactor] #1981, #4195, #3068: Update event filter builder methods naming Follow the pattern of [event filter] for_X everywhere Signed-off-by: Nikita Strygin --- client/benches/tps/utils.rs | 4 +- client/src/client.rs | 4 +- .../integration/domain_owner_permissions.rs | 2 +- .../tests/integration/events/notification.rs | 12 +++--- client/tests/integration/events/pipeline.rs | 10 ++--- .../integration/triggers/by_call_trigger.rs | 22 +++++----- .../integration/triggers/data_trigger.rs | 6 +-- .../integration/triggers/event_trigger.rs | 2 +- .../integration/triggers/time_trigger.rs | 4 +- .../integration/triggers/trigger_rollback.rs | 2 +- core/src/smartcontracts/isi/mod.rs | 2 +- data_model/src/events/data/filters.rs | 40 +++++++++---------- data_model/src/events/execute_trigger.rs | 2 +- data_model/src/events/notification.rs | 28 ++++++------- data_model/src/events/pipeline.rs | 14 +++---- tools/parity_scale_decoder/src/main.rs | 2 +- 16 files changed, 77 insertions(+), 79 deletions(-) diff --git a/client/benches/tps/utils.rs b/client/benches/tps/utils.rs index 2a44abc63a4..f9c452980c7 100644 --- a/client/benches/tps/utils.rs +++ b/client/benches/tps/utils.rs @@ -172,8 +172,8 @@ impl MeasurerUnit { let listener = self.client.clone(); let (init_sender, init_receiver) = mpsc::channel(); let event_filter = PipelineEventFilter::new() - .from_entity_of_kind(PipelineEntityKind::Block) - .with_status(PipelineStatusKind::Committed); + .for_entity(PipelineEntityKind::Block) + .for_status(PipelineStatusKind::Committed); let blocks_expected = self.config.blocks as usize; let name = self.name; let handle = thread::spawn(move || -> Result<()> { diff --git a/client/src/client.rs b/client/src/client.rs index 2212fbf05fa..4ec503bf9c2 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -605,9 +605,7 @@ impl Client { let mut event_iterator = { let event_iterator_result = tokio::time::timeout_at( deadline, - self.listen_for_events_async( - PipelineEventFilter::new().from_entity_with_hash(hash.into()), - ), + self.listen_for_events_async(PipelineEventFilter::new().for_hash(hash.into())), ) .await .map_err(Into::into) diff --git a/client/tests/integration/domain_owner_permissions.rs b/client/tests/integration/domain_owner_permissions.rs index 188a009883d..b26eb647728 100644 --- a/client/tests/integration/domain_owner_permissions.rs +++ b/client/tests/integration/domain_owner_permissions.rs @@ -310,7 +310,7 @@ fn domain_owner_trigger_permissions() -> Result<()> { Repeats::from(2_u32), bob_id, TriggeringEventFilterBox::ExecuteTrigger( - ExecuteTriggerEventFilter::new().from_trigger(trigger_id.clone()), + ExecuteTriggerEventFilter::new().for_trigger(trigger_id.clone()), ), ), )); diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index 1920aeb4420..125eec3b8f9 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -23,7 +23,7 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { asset_id.account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(asset_id.account_id), ), ), @@ -38,8 +38,8 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { let mut event_it = thread_client.listen_for_events(NotificationEventFilter::ByTriggerCompleted( TriggerCompletedEventFilter::new() - .from_trigger(trigger_id) - .with_outcome(TriggerCompletedOutcomeType::Success), + .for_trigger(trigger_id) + .for_outcome(TriggerCompletedOutcomeType::Success), ))?; if event_it.next().is_some() { sender.send(())?; @@ -72,7 +72,7 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id), ), ), @@ -87,8 +87,8 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { let mut event_it = thread_client.listen_for_events(NotificationEventFilter::ByTriggerCompleted( TriggerCompletedEventFilter::new() - .from_trigger(trigger_id) - .with_outcome(TriggerCompletedOutcomeType::Failure), + .for_trigger(trigger_id) + .for_outcome(TriggerCompletedOutcomeType::Failure), ))?; if event_it.next().is_some() { sender.send(())?; diff --git a/client/tests/integration/events/pipeline.rs b/client/tests/integration/events/pipeline.rs index 6251e586382..30f17528219 100644 --- a/client/tests/integration/events/pipeline.rs +++ b/client/tests/integration/events/pipeline.rs @@ -84,9 +84,9 @@ impl Checker { .listener .listen_for_events( PipelineEventFilter::new() - .from_entity_of_kind(PipelineEntityKind::Transaction) - .with_status(status_kind) - .from_entity_with_hash(*self.hash), + .for_entity(PipelineEntityKind::Transaction) + .for_status(status_kind) + .for_hash(*self.hash), ) .expect("Failed to create event iterator."); let event_result = event_iterator.next().expect("Stream closed"); @@ -101,8 +101,8 @@ fn committed_block_must_be_available_in_kura() { wait_for_genesis_committed(&[client.clone()], 0); let event_filter = PipelineEventFilter::new() - .from_entity_of_kind(PipelineEntityKind::Block) - .with_status(PipelineStatusKind::Committed); + .for_entity(PipelineEntityKind::Block) + .for_status(PipelineStatusKind::Committed); let mut event_iter = client .listen_for_events(event_filter) .expect("Failed to subscribe for events"); diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index b2122ec46a5..6b4473d8f97 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -61,7 +61,7 @@ fn execute_trigger_should_produce_event() -> Result<()> { let _handle = thread::spawn(move || -> Result<()> { let mut event_it = thread_client.listen_for_events( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id) + .for_trigger(trigger_id) .under_authority(account_id), )?; if event_it.next().is_some() { @@ -126,7 +126,7 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(bad_trigger_id.clone()) + .for_trigger(bad_trigger_id.clone()) .under_authority(account_id.clone()), ), ), @@ -182,7 +182,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id), ), ), @@ -247,7 +247,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id), ), ), @@ -291,7 +291,7 @@ fn unregister_trigger() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id), ), ), @@ -369,7 +369,7 @@ fn trigger_in_genesis_using_base64() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id.clone()), ), ), @@ -420,7 +420,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id_unregister.clone()) + .for_trigger(trigger_id_unregister.clone()) .under_authority(account_id.clone()), ), ), @@ -437,7 +437,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id_to_be_unregistered.clone()) + .for_trigger(trigger_id_to_be_unregistered.clone()) .under_authority(account_id), ), ), @@ -482,7 +482,7 @@ fn trigger_burn_repetitions() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id), ), ), @@ -527,7 +527,7 @@ fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_origin account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id) + .for_trigger(trigger_id) .under_authority(account_id.clone()), ), ), @@ -578,7 +578,7 @@ fn build_register_trigger_isi( asset_id.account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id) + .for_trigger(trigger_id) .under_authority(asset_id.account_id), ), ), diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index e9f2b12bff1..decbb865cd5 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -24,7 +24,7 @@ fn must_execute_both_triggers() -> Result<()> { Repeats::Indefinitely, account_id.clone(), TriggeringEventFilterBox::Data(DataEventFilter::Account( - AccountEventFilter::new().only_events(AccountEventSet::Created), + AccountEventFilter::new().for_events(AccountEventSet::Created), )), ), )); @@ -37,7 +37,7 @@ fn must_execute_both_triggers() -> Result<()> { Repeats::Indefinitely, account_id, TriggeringEventFilterBox::Data(DataEventFilter::Domain( - DomainEventFilter::new().only_events(DomainEventSet::Created), + DomainEventFilter::new().for_events(DomainEventSet::Created), )), ), )); @@ -89,7 +89,7 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu Repeats::Indefinitely, account_id, TriggeringEventFilterBox::Data(DataEventFilter::Account( - AccountEventFilter::new().only_events(AccountEventSet::Created), + AccountEventFilter::new().for_events(AccountEventSet::Created), )), ), )); diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index 368da9aa4e8..a153b262464 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -25,7 +25,7 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { Repeats::Indefinitely, account_id, TriggeringEventFilterBox::Data(DataEventFilter::AssetDefinition( - AssetDefinitionEventFilter::new().only_events(AssetDefinitionEventSet::Created), + AssetDefinitionEventFilter::new().for_events(AssetDefinitionEventSet::Created), )), ), )); diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index 323e0601e34..06042776200 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -274,8 +274,8 @@ fn get_block_committed_event_listener( client: &Client, ) -> Result>> { let block_filter = PipelineEventFilter::new() - .from_entity_of_kind(PipelineEntityKind::Block) - .with_status(PipelineStatusKind::Committed); + .for_entity(PipelineEntityKind::Block) + .for_status(PipelineStatusKind::Committed); client.listen_for_events(block_filter) } diff --git a/client/tests/integration/triggers/trigger_rollback.rs b/client/tests/integration/triggers/trigger_rollback.rs index 32abaf249be..2bbcd387699 100644 --- a/client/tests/integration/triggers/trigger_rollback.rs +++ b/client/tests/integration/triggers/trigger_rollback.rs @@ -30,7 +30,7 @@ fn failed_trigger_revert() -> Result<()> { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id), ), ), diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index a834e814b46..8218f0bb994 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -380,7 +380,7 @@ mod tests { account_id.clone(), TriggeringEventFilterBox::ExecuteTrigger( ExecuteTriggerEventFilter::new() - .from_trigger(trigger_id.clone()) + .for_trigger(trigger_id.clone()) .under_authority(account_id.clone()), ), ), diff --git a/data_model/src/events/data/filters.rs b/data_model/src/events/data/filters.rs index 3a53431695e..77aed5d8558 100644 --- a/data_model/src/events/data/filters.rs +++ b/data_model/src/events/data/filters.rs @@ -265,14 +265,14 @@ impl PeerEventFilter { /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: PeerId) -> Self { + pub fn for_peer(mut self, id_matcher: PeerId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`PeerEventFilter`] to accept only [`PeerEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: PeerEventSet) -> Self { + pub const fn for_events(mut self, event_set: PeerEventSet) -> Self { self.event_set = event_set; self } @@ -314,14 +314,14 @@ impl DomainEventFilter { /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: DomainId) -> Self { + pub fn for_domain(mut self, id_matcher: DomainId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`DomainEventFilter`] to accept only [`DomainEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: DomainEventSet) -> Self { + pub const fn for_events(mut self, event_set: DomainEventSet) -> Self { self.event_set = event_set; self } @@ -363,14 +363,14 @@ impl AccountEventFilter { /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: AccountId) -> Self { + pub fn for_account(mut self, id_matcher: AccountId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`AccountEventFilter`] to accept only [`AccountEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: AccountEventSet) -> Self { + pub const fn for_events(mut self, event_set: AccountEventSet) -> Self { self.event_set = event_set; self } @@ -412,14 +412,14 @@ impl AssetEventFilter { /// Modifies a [`AssetEventFilter`] to accept only [`AssetEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: AssetId) -> Self { + pub fn for_asset(mut self, id_matcher: AssetId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`AssetEventFilter`] to accept only [`AssetEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: AssetEventSet) -> Self { + pub const fn for_events(mut self, event_set: AssetEventSet) -> Self { self.event_set = event_set; self } @@ -461,14 +461,14 @@ impl AssetDefinitionEventFilter { /// Modifies a [`AssetDefinitionEventFilter`] to accept only [`AssetDefinitionEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: AssetDefinitionId) -> Self { + pub fn for_asset_definition(mut self, id_matcher: AssetDefinitionId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`AssetDefinitionEventFilter`] to accept only [`AssetDefinitionEvent`]s of types contained in `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: AssetDefinitionEventSet) -> Self { + pub const fn for_events(mut self, event_set: AssetDefinitionEventSet) -> Self { self.event_set = event_set; self } @@ -510,14 +510,14 @@ impl TriggerEventFilter { /// Modifies a [`TriggerEventFilter`] to accept only [`TriggerEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: TriggerId) -> Self { + pub fn for_trigger(mut self, id_matcher: TriggerId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`TriggerEventFilter`] to accept only [`TriggerEvent`]s of types matching `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: TriggerEventSet) -> Self { + pub const fn for_events(mut self, event_set: TriggerEventSet) -> Self { self.event_set = event_set; self } @@ -559,14 +559,14 @@ impl RoleEventFilter { /// Modifies a [`RoleEventFilter`] to accept only [`RoleEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: RoleId) -> Self { + pub fn for_role(mut self, id_matcher: RoleId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`RoleEventFilter`] to accept only [`RoleEvent`]s of types matching `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: RoleEventSet) -> Self { + pub const fn for_events(mut self, event_set: RoleEventSet) -> Self { self.event_set = event_set; self } @@ -608,14 +608,14 @@ impl ConfigurationEventFilter { /// Modifies a [`ConfigurationEventFilter`] to accept only [`ConfigurationEvent`]s originating from ids matching `id_matcher`. #[must_use] - pub fn only_from(mut self, id_matcher: ParameterId) -> Self { + pub fn for_parameter(mut self, id_matcher: ParameterId) -> Self { self.id_matcher = Some(id_matcher); self } /// Modifies a [`ConfigurationEventFilter`] to accept only [`ConfigurationEvent`]s of types matching `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: ConfigurationEventSet) -> Self { + pub const fn for_events(mut self, event_set: ConfigurationEventSet) -> Self { self.event_set = event_set; self } @@ -656,7 +656,7 @@ impl ExecutorEventFilter { /// Modifies a [`ExecutorEventFilter`] to accept only [`ExecutorEvent`]s of types matching `event_set`. #[must_use] - pub const fn only_events(mut self, event_set: ExecutorEventSet) -> Self { + pub const fn for_events(mut self, event_set: ExecutorEventSet) -> Self { self.event_set = event_set; self } @@ -789,10 +789,10 @@ mod tests { DomainEvent::Account(AccountEvent::Asset(AssetEvent::Created(asset))).into(); // test how the differently nested filters with with the events - let domain_filter = DataEventFilter::Domain(DomainEventFilter::new().only_from(domain_id)); + let domain_filter = DataEventFilter::Domain(DomainEventFilter::new().for_domain(domain_id)); let account_filter = - DataEventFilter::Account(AccountEventFilter::new().only_from(account_id)); - let asset_filter = DataEventFilter::Asset(AssetEventFilter::new().only_from(asset_id)); + DataEventFilter::Account(AccountEventFilter::new().for_account(account_id)); + let asset_filter = DataEventFilter::Asset(AssetEventFilter::new().for_asset(asset_id)); // domain filter matches all of those, because all of those events happened in the same domain assert!(domain_filter.matches(&domain_created)); diff --git a/data_model/src/events/execute_trigger.rs b/data_model/src/events/execute_trigger.rs index bb085224f9a..eb672703b38 100644 --- a/data_model/src/events/execute_trigger.rs +++ b/data_model/src/events/execute_trigger.rs @@ -73,7 +73,7 @@ impl ExecuteTriggerEventFilter { /// Modifies a [`ExecuteTriggerEventFilter`] to accept only [`ExecuteTriggerEvent`]s originating from a specific trigger #[must_use] #[inline] - pub fn from_trigger(mut self, trigger_id: TriggerId) -> Self { + pub fn for_trigger(mut self, trigger_id: TriggerId) -> Self { self.trigger_id = Some(trigger_id); self } diff --git a/data_model/src/events/notification.rs b/data_model/src/events/notification.rs index 50f9e9c15fc..5ee09c449d1 100644 --- a/data_model/src/events/notification.rs +++ b/data_model/src/events/notification.rs @@ -174,7 +174,7 @@ impl TriggerCompletedEventFilter { /// Modifies a [`TriggerCompletedEventFilter`] to accept only [`TriggerCompletedEvent`]s originating from a specific trigger #[must_use] #[inline] - pub fn from_trigger(mut self, trigger_id: TriggerId) -> Self { + pub fn for_trigger(mut self, trigger_id: TriggerId) -> Self { self.trigger_id = Some(trigger_id); self } @@ -182,7 +182,7 @@ impl TriggerCompletedEventFilter { /// Modifies a [`TriggerCompletedEventFilter`] to accept only [`TriggerCompletedEvent`]s with a specific outcome #[must_use] #[inline] - pub const fn with_outcome(mut self, outcome_type: TriggerCompletedOutcomeType) -> Self { + pub const fn for_outcome(mut self, outcome_type: TriggerCompletedOutcomeType) -> Self { self.outcome_type = Some(outcome_type); self } @@ -255,58 +255,58 @@ mod tests { assert!(filter_accept_all.matches(&event_2_success)); let filter_accept_success = - TriggerCompletedEventFilter::new().with_outcome(TriggerCompletedOutcomeType::Success); + TriggerCompletedEventFilter::new().for_outcome(TriggerCompletedOutcomeType::Success); assert!(!filter_accept_success.matches(&event_1_failure)); assert!(filter_accept_success.matches(&event_1_success)); assert!(!filter_accept_success.matches(&event_2_failure)); assert!(filter_accept_success.matches(&event_2_success)); let filter_accept_failure = - TriggerCompletedEventFilter::new().with_outcome(TriggerCompletedOutcomeType::Failure); + TriggerCompletedEventFilter::new().for_outcome(TriggerCompletedOutcomeType::Failure); assert!(filter_accept_failure.matches(&event_1_failure)); assert!(!filter_accept_failure.matches(&event_1_success)); assert!(filter_accept_failure.matches(&event_2_failure)); assert!(!filter_accept_failure.matches(&event_2_success)); - let filter_accept_1 = TriggerCompletedEventFilter::new().from_trigger(trigger_id_1.clone()); + let filter_accept_1 = TriggerCompletedEventFilter::new().for_trigger(trigger_id_1.clone()); assert!(filter_accept_1.matches(&event_1_failure)); assert!(filter_accept_1.matches(&event_1_success)); assert!(!filter_accept_1.matches(&event_2_failure)); assert!(!filter_accept_1.matches(&event_2_success)); let filter_accept_1_failure = TriggerCompletedEventFilter::new() - .from_trigger(trigger_id_1.clone()) - .with_outcome(TriggerCompletedOutcomeType::Failure); + .for_trigger(trigger_id_1.clone()) + .for_outcome(TriggerCompletedOutcomeType::Failure); assert!(filter_accept_1_failure.matches(&event_1_failure)); assert!(!filter_accept_1_failure.matches(&event_1_success)); assert!(!filter_accept_1_failure.matches(&event_2_failure)); assert!(!filter_accept_1_failure.matches(&event_2_success)); let filter_accept_1_success = TriggerCompletedEventFilter::new() - .from_trigger(trigger_id_1) - .with_outcome(TriggerCompletedOutcomeType::Success); + .for_trigger(trigger_id_1) + .for_outcome(TriggerCompletedOutcomeType::Success); assert!(!filter_accept_1_success.matches(&event_1_failure)); assert!(filter_accept_1_success.matches(&event_1_success)); assert!(!filter_accept_1_success.matches(&event_2_failure)); assert!(!filter_accept_1_success.matches(&event_2_success)); - let filter_accept_2 = TriggerCompletedEventFilter::new().from_trigger(trigger_id_2.clone()); + let filter_accept_2 = TriggerCompletedEventFilter::new().for_trigger(trigger_id_2.clone()); assert!(!filter_accept_2.matches(&event_1_failure)); assert!(!filter_accept_2.matches(&event_1_success)); assert!(filter_accept_2.matches(&event_2_failure)); assert!(filter_accept_2.matches(&event_2_success)); let filter_accept_2_failure = TriggerCompletedEventFilter::new() - .from_trigger(trigger_id_2.clone()) - .with_outcome(TriggerCompletedOutcomeType::Failure); + .for_trigger(trigger_id_2.clone()) + .for_outcome(TriggerCompletedOutcomeType::Failure); assert!(!filter_accept_2_failure.matches(&event_1_failure)); assert!(!filter_accept_2_failure.matches(&event_1_success)); assert!(filter_accept_2_failure.matches(&event_2_failure)); assert!(!filter_accept_2_failure.matches(&event_2_success)); let filter_accept_2_success = TriggerCompletedEventFilter::new() - .from_trigger(trigger_id_2) - .with_outcome(TriggerCompletedOutcomeType::Success); + .for_trigger(trigger_id_2) + .for_outcome(TriggerCompletedOutcomeType::Success); assert!(!filter_accept_2_success.matches(&event_1_failure)); assert!(!filter_accept_2_success.matches(&event_1_success)); assert!(!filter_accept_2_success.matches(&event_2_failure)); diff --git a/data_model/src/events/pipeline.rs b/data_model/src/events/pipeline.rs index 2cd306091e8..5d3b962144f 100644 --- a/data_model/src/events/pipeline.rs +++ b/data_model/src/events/pipeline.rs @@ -169,7 +169,7 @@ impl PipelineEventFilter { /// Modifies a [`PipelineEventFilter`] to accept only [`PipelineEvent`]s originating from a specific entity kind (block/transaction). #[must_use] #[inline] - pub const fn from_entity_of_kind(mut self, entity_kind: PipelineEntityKind) -> Self { + pub const fn for_entity(mut self, entity_kind: PipelineEntityKind) -> Self { self.entity_kind = Some(entity_kind); self } @@ -177,7 +177,7 @@ impl PipelineEventFilter { /// Modifies a [`PipelineEventFilter`] to accept only [`PipelineEvent`]s with a specific status. #[must_use] #[inline] - pub const fn with_status(mut self, status_kind: PipelineStatusKind) -> Self { + pub const fn for_status(mut self, status_kind: PipelineStatusKind) -> Self { self.status_kind = Some(status_kind); self } @@ -185,7 +185,7 @@ impl PipelineEventFilter { /// Modifies a [`PipelineEventFilter`] to accept only [`PipelineEvent`]s originating from an entity with specified hash. #[must_use] #[inline] - pub const fn from_entity_with_hash(mut self, hash: Hash) -> Self { + pub const fn for_hash(mut self, hash: Hash) -> Self { self.hash = Some(hash); self } @@ -282,7 +282,7 @@ mod tests { events .iter() .filter(|&event| PipelineEventFilter::new() - .from_entity_with_hash(Hash::prehashed([0_u8; Hash::LENGTH])) + .for_hash(Hash::prehashed([0_u8; Hash::LENGTH])) .matches(event)) .cloned() .collect::>() @@ -296,7 +296,7 @@ mod tests { events .iter() .filter(|&event| PipelineEventFilter::new() - .from_entity_of_kind(PipelineEntityKind::Block) + .for_entity(PipelineEntityKind::Block) .matches(event)) .cloned() .collect::>() @@ -310,8 +310,8 @@ mod tests { events .iter() .filter(|&event| PipelineEventFilter::new() - .from_entity_of_kind(PipelineEntityKind::Transaction) - .from_entity_with_hash(Hash::prehashed([2_u8; Hash::LENGTH])) + .for_entity(PipelineEntityKind::Transaction) + .for_hash(Hash::prehashed([2_u8; Hash::LENGTH])) .matches(event)) .cloned() .collect::>() diff --git a/tools/parity_scale_decoder/src/main.rs b/tools/parity_scale_decoder/src/main.rs index 1aa1bb3b0f1..86f3139d391 100644 --- a/tools/parity_scale_decoder/src/main.rs +++ b/tools/parity_scale_decoder/src/main.rs @@ -276,7 +276,7 @@ mod tests { Repeats::Indefinitely, account_id, EventFilterBox::Data(DataEventFilter::Domain( - DomainEventFilter::new().only_events(DomainEventSet::AnyAccount), + DomainEventFilter::new().for_events(DomainEventSet::AnyAccount), )), ); let trigger = Trigger::new(trigger_id, action); From 60065fed7e249969463e4352232d5d387e44cedb Mon Sep 17 00:00:00 2001 From: Nikita Strygin Date: Wed, 13 Mar 2024 13:11:34 +0300 Subject: [PATCH 13/13] [refactor] #1981, #4195, #3068: Remove NotificationEvent Instead of it, expose TriggerCompletedEvent as a top-level event, same as ExecuteTriggerEvent Signed-off-by: Nikita Strygin --- .../tests/integration/events/notification.rs | 22 +++---- client_cli/src/main.rs | 9 ++- core/src/wsv.rs | 5 +- data_model/src/events/mod.rs | 24 +++---- .../{notification.rs => trigger_completed.rs} | 63 +------------------ docs/source/references/schema.json | 30 ++------- schema/gen/src/lib.rs | 2 - 7 files changed, 37 insertions(+), 118 deletions(-) rename data_model/src/events/{notification.rs => trigger_completed.rs} (85%) diff --git a/client/tests/integration/events/notification.rs b/client/tests/integration/events/notification.rs index 125eec3b8f9..e7738e04aaa 100644 --- a/client/tests/integration/events/notification.rs +++ b/client/tests/integration/events/notification.rs @@ -35,12 +35,11 @@ fn trigger_completion_success_should_produce_event() -> Result<()> { let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { - let mut event_it = - thread_client.listen_for_events(NotificationEventFilter::ByTriggerCompleted( - TriggerCompletedEventFilter::new() - .for_trigger(trigger_id) - .for_outcome(TriggerCompletedOutcomeType::Success), - ))?; + let mut event_it = thread_client.listen_for_events( + TriggerCompletedEventFilter::new() + .for_trigger(trigger_id) + .for_outcome(TriggerCompletedOutcomeType::Success), + )?; if event_it.next().is_some() { sender.send(())?; return Ok(()); @@ -84,12 +83,11 @@ fn trigger_completion_failure_should_produce_event() -> Result<()> { let thread_client = test_client.clone(); let (sender, receiver) = mpsc::channel(); let _handle = thread::spawn(move || -> Result<()> { - let mut event_it = - thread_client.listen_for_events(NotificationEventFilter::ByTriggerCompleted( - TriggerCompletedEventFilter::new() - .for_trigger(trigger_id) - .for_outcome(TriggerCompletedOutcomeType::Failure), - ))?; + let mut event_it = thread_client.listen_for_events( + TriggerCompletedEventFilter::new() + .for_trigger(trigger_id) + .for_outcome(TriggerCompletedOutcomeType::Failure), + )?; if event_it.next().is_some() { sender.send(())?; return Ok(()); diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 1d06e1c8e5b..807d504a280 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -258,8 +258,10 @@ mod events { Pipeline, /// Gets data events Data, - /// Get notification events - Notification, + /// Get execute trigger events + ExecuteTrigger, + /// Get trigger completed events + TriggerCompleted, } impl RunArgs for Args { @@ -267,7 +269,8 @@ mod events { match self { Args::Pipeline => listen(PipelineEventFilter::new(), context), Args::Data => listen(DataEventFilter::Any, context), - Args::Notification => listen(NotificationEventFilter::ByAny, context), + Args::ExecuteTrigger => listen(ExecuteTriggerEventFilter::new(), context), + Args::TriggerCompleted => listen(TriggerCompletedEventFilter::new(), context), } } } diff --git a/core/src/wsv.rs b/core/src/wsv.rs index c736af16b22..fbe6730f77f 100644 --- a/core/src/wsv.rs +++ b/core/src/wsv.rs @@ -12,7 +12,7 @@ use iroha_crypto::HashOf; use iroha_data_model::{ account::AccountId, block::SignedBlock, - events::notification::{TriggerCompletedEvent, TriggerCompletedOutcome}, + events::trigger_completed::{TriggerCompletedEvent, TriggerCompletedOutcome}, isi::error::{InstructionExecutionError as Error, MathError}, parameter::{Parameter, ParameterValueBox}, permission::PermissionTokenSchema, @@ -567,8 +567,7 @@ impl WorldStateView { event } }; - self.events_buffer - .push(NotificationEvent::from(event).into()); + self.events_buffer.push(event.into()); } } diff --git a/data_model/src/events/mod.rs b/data_model/src/events/mod.rs index 8c3517ecdcc..daa9e544e26 100644 --- a/data_model/src/events/mod.rs +++ b/data_model/src/events/mod.rs @@ -13,9 +13,9 @@ pub use self::model::*; pub mod data; pub mod execute_trigger; -pub mod notification; pub mod pipeline; pub mod time; +pub mod trigger_completed; #[model] pub mod model { @@ -46,8 +46,8 @@ pub mod model { Time(time::TimeEvent), /// Trigger execution event. ExecuteTrigger(execute_trigger::ExecuteTriggerEvent), - /// Notification event. - Notification(notification::NotificationEvent), + /// Trigger completion event. + TriggerCompleted(trigger_completed::TriggerCompletedEvent), } /// Event type which could invoke trigger execution. @@ -92,8 +92,8 @@ pub mod model { Time(time::TimeEventFilter), /// Listen to trigger execution event with filter. ExecuteTrigger(execute_trigger::ExecuteTriggerEventFilter), - /// Listen to notifications event with filter. - Notification(notification::NotificationEventFilter), + /// Listen to trigger completion event with filter. + TriggerCompleted(trigger_completed::TriggerCompletedEventFilter), } /// Event filter which could be attached to trigger. @@ -165,19 +165,21 @@ impl EventFilter for EventFilterBox { (Event::Data(event), Self::Data(filter)) => filter.matches(event), (Event::Time(event), Self::Time(filter)) => filter.matches(event), (Event::ExecuteTrigger(event), Self::ExecuteTrigger(filter)) => filter.matches(event), - (Event::Notification(event), Self::Notification(filter)) => filter.matches(event), + (Event::TriggerCompleted(event), Self::TriggerCompleted(filter)) => { + filter.matches(event) + } // Fail to compile in case when new variant to event or filter is added ( Event::Pipeline(_) | Event::Data(_) | Event::Time(_) | Event::ExecuteTrigger(_) - | Event::Notification(_), + | Event::TriggerCompleted(_), Self::Pipeline(_) | Self::Data(_) | Self::Time(_) | Self::ExecuteTrigger(_) - | Self::Notification(_), + | Self::TriggerCompleted(_), ) => false, } } @@ -200,7 +202,7 @@ impl EventFilter for TriggeringEventFilterBox { | Event::Data(_) | Event::Time(_) | Event::ExecuteTrigger(_) - | Event::Notification(_), + | Event::TriggerCompleted(_), Self::Pipeline(_) | Self::Data(_) | Self::Time(_) | Self::ExecuteTrigger(_), ) => false, } @@ -249,8 +251,8 @@ pub mod prelude { #[cfg(feature = "transparent_api")] pub use super::EventFilter; pub use super::{ - data::prelude::*, execute_trigger::prelude::*, notification::prelude::*, - pipeline::prelude::*, time::prelude::*, Event, EventFilterBox, TriggeringEventFilterBox, + data::prelude::*, execute_trigger::prelude::*, pipeline::prelude::*, time::prelude::*, + trigger_completed::prelude::*, Event, EventFilterBox, TriggeringEventFilterBox, TriggeringEventType, }; } diff --git a/data_model/src/events/notification.rs b/data_model/src/events/trigger_completed.rs similarity index 85% rename from data_model/src/events/notification.rs rename to data_model/src/events/trigger_completed.rs index 5ee09c449d1..9d0d43d195c 100644 --- a/data_model/src/events/notification.rs +++ b/data_model/src/events/trigger_completed.rs @@ -19,27 +19,6 @@ use crate::trigger::TriggerId; pub mod model { use super::*; - /// Notification event for events that arise during block application process like trigger execution for example - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - FromVariant, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type] - #[non_exhaustive] - pub enum NotificationEvent { - TriggerCompleted(TriggerCompletedEvent), - } - /// Event that notifies that a trigger was executed #[derive( Debug, @@ -95,28 +74,6 @@ pub mod model { Failure(String), } - /// Filter for [`NotificationEvent`] - #[derive( - Debug, - Clone, - FromVariant, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type] - #[non_exhaustive] - pub enum NotificationEventFilter { - ByAny, - ByTriggerCompleted(TriggerCompletedEventFilter), - } - /// Filter [`TriggerCompletedEvent`] by /// 1. if `triger_id` is some filter based on trigger id /// 2. if `outcome_type` is some filter based on execution outcome (success/failure) @@ -144,22 +101,6 @@ pub mod model { } } -#[cfg(feature = "transparent_api")] -impl super::EventFilter for NotificationEventFilter { - type Event = NotificationEvent; - - /// Check if `self` accepts the `event`. - #[inline] - fn matches(&self, event: &Self::Event) -> bool { - match (self, event) { - (Self::ByAny, _) => true, - (Self::ByTriggerCompleted(filter), NotificationEvent::TriggerCompleted(event)) => { - filter.matches(event) - } - } - } -} - impl TriggerCompletedEventFilter { /// Creates a new [`TriggerCompletedEventFilter`] accepting all [`TriggerCompletedEvent`]s #[must_use] @@ -219,8 +160,8 @@ impl super::EventFilter for TriggerCompletedEventFilter { /// Exports common structs and enums from this module. pub mod prelude { pub use super::{ - NotificationEvent, NotificationEventFilter, TriggerCompletedEvent, - TriggerCompletedEventFilter, TriggerCompletedOutcome, TriggerCompletedOutcomeType, + TriggerCompletedEvent, TriggerCompletedEventFilter, TriggerCompletedOutcome, + TriggerCompletedOutcomeType, }; } diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 93c774cd19d..04e5ed6c954 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -880,9 +880,9 @@ "type": "ExecuteTriggerEvent" }, { - "tag": "Notification", + "tag": "TriggerCompleted", "discriminant": 4, - "type": "NotificationEvent" + "type": "TriggerCompletedEvent" } ] }, @@ -909,9 +909,9 @@ "type": "ExecuteTriggerEventFilter" }, { - "tag": "Notification", + "tag": "TriggerCompleted", "discriminant": 4, - "type": "NotificationEventFilter" + "type": "TriggerCompletedEventFilter" } ] }, @@ -2214,28 +2214,6 @@ "NonTrivial>": "Vec>", "NonZero": "u32", "NonZero": "u64", - "NotificationEvent": { - "Enum": [ - { - "tag": "TriggerCompleted", - "discriminant": 0, - "type": "TriggerCompletedEvent" - } - ] - }, - "NotificationEventFilter": { - "Enum": [ - { - "tag": "ByAny", - "discriminant": 0 - }, - { - "tag": "ByTriggerCompleted", - "discriminant": 1, - "type": "TriggerCompletedEventFilter" - } - ] - }, "Numeric": { "Struct": [ { diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 7995f54eaf6..259120b048d 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -233,8 +233,6 @@ types!( NonTrivial, NonZeroU32, NonZeroU64, - NotificationEvent, - NotificationEventFilter, Numeric, NumericSpec, Option,

H1V0T9ux!FWfcFxj@oTBWH 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%0D;y^74k!pD({+^mog}(Y^XGlv!Ov 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