diff --git a/client/tests/integration/queries/mod.rs b/client/tests/integration/queries/mod.rs index 4d85add4e5b..d53bb97853e 100644 --- a/client/tests/integration/queries/mod.rs +++ b/client/tests/integration/queries/mod.rs @@ -1,11 +1,8 @@ -use std::str::FromStr as _; - -use eyre::Result; use iroha_client::{ client::{self, ClientQueryError}, data_model::{ prelude::*, - query::{cursor::ForwardCursor, error::QueryExecutionFail, MAX_FETCH_SIZE}, + query::{error::QueryExecutionFail, MAX_FETCH_SIZE}, }, }; use test_network::*; @@ -14,6 +11,7 @@ mod account; mod asset; mod query_errors; mod role; +mod smart_contract; #[test] fn too_big_fetch_size_is_not_allowed() { @@ -33,43 +31,3 @@ fn too_big_fetch_size_is_not_allowed() { )) )); } - -#[test] -fn live_query_is_dropped_after_smart_contract_end() -> Result<()> { - let (_rt, _peer, client) = ::new().with_port(11_140).start_with_runtime(); - wait_for_genesis_committed(&[client.clone()], 0); - - let wasm = iroha_wasm_builder::Builder::new( - "tests/integration/smartcontracts/query_assets_and_save_cursor", - ) - .show_output() - .build()? - .optimize()? - .into_bytes()?; - - let transaction = client.build_transaction( - WasmSmartContract::from_compiled(wasm), - UnlimitedMetadata::default(), - ); - client.submit_transaction_blocking(&transaction)?; - - let metadata_value = client.request(FindAccountKeyValueByIdAndKey::new( - client.account_id.clone(), - Name::from_str("cursor").unwrap(), - ))?; - let cursor: String = metadata_value.try_into()?; - let asset_cursor = serde_json::from_str::(&cursor)?; - - let err = client - .request_with_cursor::>(asset_cursor) - .expect_err("Request with cursor from smart contract should fail"); - - assert!(matches!( - err, - ClientQueryError::Validation(ValidationFail::QueryFailed( - QueryExecutionFail::UnknownCursor - )) - )); - - Ok(()) -} diff --git a/client/tests/integration/queries/smart_contract.rs b/client/tests/integration/queries/smart_contract.rs new file mode 100644 index 00000000000..1e5cb8a3b56 --- /dev/null +++ b/client/tests/integration/queries/smart_contract.rs @@ -0,0 +1,73 @@ +use std::str::FromStr as _; + +use eyre::Result; +use iroha_client::{ + client::ClientQueryError, + data_model::{ + prelude::*, + query::{cursor::ForwardCursor, error::QueryExecutionFail}, + }, +}; +use test_network::*; + +#[test] +fn live_query_is_dropped_after_smart_contract_end() -> Result<()> { + let (_rt, _peer, client) = ::new().with_port(11_140).start_with_runtime(); + wait_for_genesis_committed(&[client.clone()], 0); + + let wasm = iroha_wasm_builder::Builder::new( + "tests/integration/smartcontracts/query_assets_and_save_cursor", + ) + .show_output() + .build()? + .optimize()? + .into_bytes()?; + + let transaction = client.build_transaction( + WasmSmartContract::from_compiled(wasm), + UnlimitedMetadata::default(), + ); + client.submit_transaction_blocking(&transaction)?; + + let metadata_value = client.request(FindAccountKeyValueByIdAndKey::new( + client.account_id.clone(), + Name::from_str("cursor").unwrap(), + ))?; + let cursor: String = metadata_value.try_into()?; + let asset_cursor = serde_json::from_str::(&cursor)?; + + let err = client + .request_with_cursor::>(asset_cursor) + .expect_err("Request with cursor from smart contract should fail"); + + assert!(matches!( + err, + ClientQueryError::Validation(ValidationFail::QueryFailed( + QueryExecutionFail::UnknownCursor + )) + )); + + Ok(()) +} + +#[test] +fn smart_contract_can_filter_queries() -> Result<()> { + let (_rt, _peer, client) = ::new().with_port(11_260).start_with_runtime(); + wait_for_genesis_committed(&[client.clone()], 0); + + let wasm = iroha_wasm_builder::Builder::new( + "tests/integration/smartcontracts/smart_contract_can_filter_queries", + ) + .show_output() + .build()? + .optimize()? + .into_bytes()?; + + let transaction = client.build_transaction( + WasmSmartContract::from_compiled(wasm), + UnlimitedMetadata::default(), + ); + client.submit_transaction_blocking(&transaction)?; + + Ok(()) +} diff --git a/client/tests/integration/smartcontracts/Cargo.toml b/client/tests/integration/smartcontracts/Cargo.toml index 4739c446174..7ec4b608a57 100644 --- a/client/tests/integration/smartcontracts/Cargo.toml +++ b/client/tests/integration/smartcontracts/Cargo.toml @@ -16,6 +16,7 @@ members = [ "executor_remove_token", "executor_with_migration_fail", "query_assets_and_save_cursor", + "smart_contract_can_filter_queries", ] [profile.dev] @@ -29,8 +30,8 @@ opt-level = "z" # Optimize for size vs speed with "s"/"z"(removes vectorizat codegen-units = 1 # Further reduces binary size but increases compilation time [workspace.dependencies] -iroha_smart_contract = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract", features = ["debug"]} -iroha_trigger = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract/trigger", features = ["debug"]} +iroha_smart_contract = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract", features = ["debug"] } +iroha_trigger = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract/trigger", features = ["debug"] } iroha_executor = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract/executor" } iroha_schema = { version = "=2.0.0-pre-rc.21", path = "../../../../schema" } diff --git a/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/Cargo.toml b/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/Cargo.toml new file mode 100644 index 00000000000..8244730ed6d --- /dev/null +++ b/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "smart_contract_can_filter_queries" + +edition.workspace = true +version.workspace = true +authors.workspace = true + +license.workspace = true + +[lib] +crate-type = ['cdylib'] + +[dependencies] +iroha_smart_contract.workspace = true + +panic-halt.workspace = true +lol_alloc.workspace = true +getrandom.workspace = true +parity-scale-codec.workspace = true +nonzero_ext.workspace = true +serde_json = { workspace = true, default-features = false } diff --git a/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs b/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs new file mode 100644 index 00000000000..420ff477e67 --- /dev/null +++ b/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs @@ -0,0 +1,69 @@ +//! Smart contract which executes [`FindAllAssets`] and saves cursor to the owner's metadata. + +#![no_std] + +#[cfg(not(test))] +extern crate panic_halt; + +extern crate alloc; + +use alloc::{collections::BTreeSet, string::ToString, vec::Vec}; + +use iroha_smart_contract::{ + data_model::query::predicate::{string::StringPredicate, value::QueryOutputPredicate}, + prelude::*, + QueryOutputCursor, +}; +use lol_alloc::{FreeListAllocator, LockedAllocator}; + +#[global_allocator] +static ALLOC: LockedAllocator = LockedAllocator::new(FreeListAllocator::new()); + +getrandom::register_custom_getrandom!(iroha_smart_contract::stub_getrandom); + +/// Create two asset definitions in the looking_glass domain, query all asset definitions, filter them to only be in the looking_glass domain, check that the results are consistent +#[iroha_smart_contract::main] +fn main(_owner: AccountId) { + // create the "looking_glass" domain + Register::domain(Domain::new("looking_glass".parse().unwrap())) + .execute() + .dbg_unwrap(); + + // create two asset definitions inside the `looking_glass` domain + let time_id: AssetDefinitionId = "time#looking_glass".parse().dbg_unwrap(); + let space_id: AssetDefinitionId = "space#looking_glass".parse().dbg_unwrap(); + + Register::asset_definition(AssetDefinition::new( + time_id.clone(), + AssetValueType::Numeric(NumericSpec::default()), + )) + .execute() + .dbg_unwrap(); + + Register::asset_definition(AssetDefinition::new( + space_id.clone(), + AssetValueType::Numeric(NumericSpec::default()), + )) + .execute() + .dbg_unwrap(); + + // genesis registers some more asset definitions, but we apply a filter to find only the ones from the `looking_glass` domain + let cursor: QueryOutputCursor> = FindAllAssetsDefinitions + .filter(QueryOutputPredicate::Identifiable( + StringPredicate::EndsWith("#looking_glass".to_string()), + )) + .execute() + .dbg_unwrap(); + + let mut asset_definition_ids = BTreeSet::new(); + + for asset_definition in cursor { + let asset_definition = asset_definition.dbg_unwrap(); + asset_definition_ids.insert(asset_definition.id().clone()); + } + + assert_eq!( + asset_definition_ids, + [time_id, space_id].into_iter().collect() + ); +}