From f984cee9789daffe72e23fc0d4507455e6d4af89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Ver=C5=A1i=C4=87?= Date: Tue, 20 Feb 2024 14:11:16 +0300 Subject: [PATCH] [refactor]: remove `Value` enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marin Veršić --- client/src/client.rs | 54 +- client/src/query_builder.rs | 10 +- client/tests/integration/burn_public_keys.rs | 12 +- client/tests/integration/queries/asset.rs | 1 - client/tests/integration/queries/mod.rs | 6 +- client/tests/integration/roles.rs | 2 +- .../query_assets_and_save_cursor/src/lib.rs | 4 +- client/tests/integration/sorting.rs | 62 +- client/tests/integration/transfer_asset.rs | 1 - .../integration/triggers/by_call_trigger.rs | 39 +- .../integration/triggers/data_trigger.rs | 20 +- .../integration/triggers/event_trigger.rs | 15 +- .../integration/triggers/time_trigger.rs | 33 +- client/tests/integration/tx_history.rs | 16 +- client_cli/src/main.rs | 81 +- configs/swarm/executor.wasm | Bin 586428 -> 536367 bytes core/src/query/store.rs | 65 +- core/src/queue.rs | 21 +- core/src/smartcontracts/isi/account.rs | 11 +- core/src/smartcontracts/isi/asset.rs | 65 +- core/src/smartcontracts/isi/domain.rs | 15 +- core/src/smartcontracts/isi/mod.rs | 41 +- core/src/smartcontracts/isi/query.rs | 71 +- core/src/smartcontracts/isi/triggers/mod.rs | 5 +- core/src/smartcontracts/isi/tx.rs | 5 +- core/src/smartcontracts/wasm.rs | 14 +- core/src/wsv.rs | 6 +- core/test_network/src/lib.rs | 18 +- data_model/Cargo.toml | 2 + data_model/src/account.rs | 10 - data_model/src/asset.rs | 93 +- data_model/src/domain.rs | 9 - data_model/src/events/data/events.rs | 3 +- data_model/src/events/data/mod.rs | 2 +- data_model/src/integer.rs | 268 ---- data_model/src/isi.rs | 37 +- data_model/src/lib.rs | 1116 ++--------------- data_model/src/metadata.rs | 350 ++++-- data_model/src/peer.rs | 11 +- data_model/src/permission.rs | 28 +- data_model/src/query/mod.rs | 284 ++++- data_model/src/{ => query}/predicate.rs | 721 ++++++----- docs/source/references/schema.json | 592 +++------ genesis/src/lib.rs | 1 + primitives/numeric/src/lib.rs | 36 +- primitives/src/unique_vec.rs | 3 + schema/gen/src/lib.rs | 194 ++- smart_contract/executor/src/default.rs | 10 +- smart_contract/src/lib.rs | 59 +- tools/kagami/src/genesis.rs | 40 +- tools/parity_scale_decoder/src/main.rs | 44 +- torii/src/routing.rs | 4 +- 52 files changed, 1801 insertions(+), 2809 deletions(-) delete mode 100644 data_model/src/integer.rs rename data_model/src/{ => query}/predicate.rs (65%) diff --git a/client/src/client.rs b/client/src/client.rs index c57fa73a3d9..bfee9800b76 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -14,6 +14,7 @@ use eyre::{eyre, Result, WrapErr}; use futures_util::StreamExt; use http_default::{AsyncWebSocketStream, WebSocketStream}; pub use iroha_config::client_api::ConfigDTO; +use iroha_data_model::query::QueryOutputBox; use iroha_logger::prelude::*; use iroha_telemetry::metrics::Status; use iroha_torii_const::uri as torii_uri; @@ -29,9 +30,8 @@ use crate::{ data_model::{ block::SignedBlock, isi::Instruction, - predicate::PredicateBox, prelude::*, - query::{Pagination, Query, Sorting}, + query::{predicate::PredicateBox, Pagination, Query, Sorting}, BatchedResponse, ChainId, ValidationFail, }, http::{Method as HttpMethod, RequestBuilder, Response, StatusCode}, @@ -81,13 +81,13 @@ impl Sign for SignedTransaction { impl QueryResponseHandler where - >::Error: Into, + >::Error: Into, { fn handle(&mut self, resp: &Response>) -> QueryResult { // Separate-compilation friendly response handling fn _handle_query_response_base( resp: &Response>, - ) -> QueryResult> { + ) -> QueryResult> { match resp.status() { StatusCode::OK => { let res = BatchedResponse::decode_all_versioned(resp.body()); @@ -127,12 +127,12 @@ where let (batch, cursor) = _handle_query_response_base(resp)?.into(); - let value = R::try_from(batch) + let output = R::try_from(batch) .map_err(Into::into) .wrap_err("Unexpected type")?; self.query_request.request = crate::data_model::query::QueryRequest::Cursor(cursor); - Ok(value) + Ok(output) } } @@ -215,12 +215,12 @@ impl From for eyre::Report { } /// Output of a query -pub trait QueryOutput: Into + TryFrom { +pub trait QueryOutput: Into + TryFrom { /// Type of the query output type Target: Clone; /// Construct query output from query response - fn new(value: Self, query_request: QueryResponseHandler) -> Self::Target; + fn new(output: Self, query_request: QueryResponseHandler) -> Self::Target; } /// Iterable query output @@ -244,7 +244,7 @@ impl ResultSet { impl Iterator for ResultSet where Vec: QueryOutput, - as TryFrom>::Error: Into, + as TryFrom>::Error: Into, { type Item = QueryResult; @@ -268,11 +268,11 @@ where Err(err) => return Some(Err(ClientQueryError::Other(err))), Ok(ok) => ok, }; - let value = match self.query_handler.handle(&response) { + let output = match self.query_handler.handle(&response) { Err(err) => return Some(Err(err)), Ok(ok) => ok, }; - self.iter = value; + self.iter = output; self.client_cursor = 0; } @@ -284,14 +284,14 @@ where impl QueryOutput for Vec where - Self: Into + TryFrom, + Self: Into + TryFrom, { type Target = ResultSet; - fn new(value: Self, query_handler: QueryResponseHandler) -> Self::Target { + fn new(output: Self, query_handler: QueryResponseHandler) -> Self::Target { ResultSet { query_handler, - iter: value, + iter: output, client_cursor: 0, } } @@ -302,22 +302,20 @@ macro_rules! impl_query_output { impl QueryOutput for $ident { type Target = Self; - fn new(value: Self, _query_handler: QueryResponseHandler) -> Self::Target { - value + fn new(output: Self, _query_handler: QueryResponseHandler) -> Self::Target { + output } } )+ }; } impl_query_output! { - bool, - crate::data_model::Value, crate::data_model::role::Role, crate::data_model::asset::Asset, crate::data_model::asset::AssetDefinition, crate::data_model::account::Account, crate::data_model::domain::Domain, crate::data_model::block::BlockHeader, - crate::data_model::query::MetadataValue, + crate::data_model::metadata::MetadataValueBox, crate::data_model::query::TransactionQueryOutput, crate::data_model::permission::PermissionTokenSchema, crate::data_model::trigger::Trigger, @@ -791,7 +789,7 @@ impl Client { fetch_size: FetchSize, ) -> (DefaultRequestBuilder, QueryResponseHandler) where - >::Error: Into, + >::Error: Into, { let query_builder = QueryBuilder::new(request, self.account_id.clone()).with_filter(filter); let request = self.sign_query(query_builder).encode_versioned(); @@ -826,15 +824,15 @@ impl Client { ) -> QueryResult<::Target> where R::Output: QueryOutput, - >::Error: Into, + >::Error: Into, { iroha_logger::trace!(?request, %pagination, ?sorting, ?filter); let (req, mut resp_handler) = self.prepare_query_request::(request, filter, pagination, sorting, fetch_size); let response = req.build()?.send()?; - let value = resp_handler.handle(&response)?; - let output = QueryOutput::new(value, resp_handler); + let output = resp_handler.handle(&response)?; + let output = QueryOutput::new(output, resp_handler); Ok(output) } @@ -847,7 +845,7 @@ impl Client { where R: Query + Debug, R::Output: QueryOutput, - >::Error: Into, + >::Error: Into, { self.build_query(request).execute() } @@ -865,7 +863,7 @@ impl Client { ) -> QueryResult where O: QueryOutput, - >::Error: Into, + >::Error: Into, { let request = QueryRequest { torii_url: self.torii_url.clone(), @@ -875,8 +873,8 @@ impl Client { let response = request.clone().assemble().build()?.send()?; let mut resp_handler = QueryResponseHandler::::new(request); - let value = resp_handler.handle(&response)?; - let output = O::new(value, resp_handler); + let output = resp_handler.handle(&response)?; + let output = O::new(output, resp_handler); Ok(output) } @@ -890,7 +888,7 @@ impl Client { where R: Query + Debug, R::Output: QueryOutput, - >::Error: Into, + >::Error: Into, { QueryRequestBuilder::new(self, request) } diff --git a/client/src/query_builder.rs b/client/src/query_builder.rs index e12b09f6769..4ccfe7c99db 100644 --- a/client/src/query_builder.rs +++ b/client/src/query_builder.rs @@ -1,12 +1,10 @@ use std::fmt::Debug; +use iroha_data_model::query::QueryOutputBox; + use crate::{ client::{Client, QueryOutput, QueryResult}, - data_model::{ - predicate::PredicateBox, - query::{sorting::Sorting, FetchSize, Pagination, Query}, - Value, - }, + data_model::query::{predicate::PredicateBox, sorting::Sorting, FetchSize, Pagination, Query}, }; pub struct QueryRequestBuilder<'a, R> { @@ -22,7 +20,7 @@ impl<'a, R> QueryRequestBuilder<'a, R> where R: Query + Debug, R::Output: QueryOutput, - >::Error: Into, + >::Error: Into, { pub(crate) fn new(client: &'a Client, request: R) -> Self { Self { diff --git a/client/tests/integration/burn_public_keys.rs b/client/tests/integration/burn_public_keys.rs index d86348da2d2..f99cb7bb933 100644 --- a/client/tests/integration/burn_public_keys.rs +++ b/client/tests/integration/burn_public_keys.rs @@ -3,6 +3,7 @@ use iroha_client::{ crypto::{HashOf, KeyPair, PublicKey}, data_model::{isi::Instruction, prelude::*}, }; +use iroha_data_model::query::TransactionQueryOutput; use test_network::*; fn submit( @@ -27,11 +28,8 @@ fn submit( (tx.hash(), client.submit_transaction_blocking(&tx)) } -fn get(client: &Client, hash: HashOf) -> TransactionValue { - *client - .request(transaction::by_hash(hash)) - .unwrap() - .transaction +fn get(client: &Client, hash: HashOf) -> TransactionQueryOutput { + client.request(transaction::by_hash(hash)).unwrap() } fn account_keys_count(client: &Client, account_id: AccountId) -> usize { @@ -95,7 +93,7 @@ fn public_keys_cannot_be_burned_to_nothing() { let committed_txn = get(&client, tx_hash); keys_count = charlie_keys_count(&client); assert_eq!(keys_count, 1); - assert!(committed_txn.error.is_none()); + assert!(committed_txn.as_ref().error.is_none()); let burn_the_last_key = burn(charlie_initial_keypair.public_key().clone()); @@ -108,5 +106,5 @@ fn public_keys_cannot_be_burned_to_nothing() { let committed_txn = get(&client, tx_hash); keys_count = charlie_keys_count(&client); assert_eq!(keys_count, 1); - assert!(committed_txn.error.is_some()); + assert!(committed_txn.as_ref().error.is_some()); } diff --git a/client/tests/integration/queries/asset.rs b/client/tests/integration/queries/asset.rs index c13c4b7b356..4a8c565fda6 100644 --- a/client/tests/integration/queries/asset.rs +++ b/client/tests/integration/queries/asset.rs @@ -146,7 +146,6 @@ fn test_total_quantity( ) -> Result<()> where T: Copy + Into, - Value: From, Mint: Instruction, Burn: Instruction, { diff --git a/client/tests/integration/queries/mod.rs b/client/tests/integration/queries/mod.rs index d4ed9a45cd6..4d85add4e5b 100644 --- a/client/tests/integration/queries/mod.rs +++ b/client/tests/integration/queries/mod.rs @@ -1,6 +1,6 @@ use std::str::FromStr as _; -use eyre::{bail, Result}; +use eyre::Result; use iroha_client::{ client::{self, ClientQueryError}, data_model::{ @@ -57,9 +57,7 @@ fn live_query_is_dropped_after_smart_contract_end() -> Result<()> { client.account_id.clone(), Name::from_str("cursor").unwrap(), ))?; - let Value::String(cursor) = metadata_value.0 else { - bail!("Expected `Value::String`, got {:?}", metadata_value.0); - }; + let cursor: String = metadata_value.try_into()?; let asset_cursor = serde_json::from_str::(&cursor)?; let err = client diff --git a/client/tests/integration/roles.rs b/client/tests/integration/roles.rs index 94feb92a082..f28328ffa41 100644 --- a/client/tests/integration/roles.rs +++ b/client/tests/integration/roles.rs @@ -89,7 +89,7 @@ fn register_and_grant_role_for_metadata_access() -> Result<()> { let set_key_value = SetKeyValue::account( mouse_id, Name::from_str("key").expect("Valid"), - Value::String("value".to_owned()), + "value".to_owned(), ); test_client.submit_blocking(set_key_value)?; diff --git a/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs b/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs index 2ec5094f4d1..4b009d7f592 100644 --- a/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs +++ b/client/tests/integration/smartcontracts/query_assets_and_save_cursor/src/lib.rs @@ -10,7 +10,7 @@ extern crate alloc; use alloc::string::ToString as _; use core::num::NonZeroU32; -use iroha_smart_contract::{parse, prelude::*}; +use iroha_smart_contract::{data_model::metadata::MetadataValue, parse, prelude::*}; use lol_alloc::{FreeListAllocator, LockedAllocator}; #[global_allocator] @@ -31,7 +31,7 @@ fn main(owner: AccountId) { SetKeyValue::account( owner, parse!("cursor" as Name), - Value::String( + MetadataValue::String( serde_json::to_value(cursor) .dbg_expect("Failed to convert cursor to JSON") .to_string(), diff --git a/client/tests/integration/sorting.rs b/client/tests/integration/sorting.rs index 5483fcfbdca..f444db9146c 100644 --- a/client/tests/integration/sorting.rs +++ b/client/tests/integration/sorting.rs @@ -9,9 +9,11 @@ use iroha_client::{ client::{self, QueryResult}, data_model::{ account::Account, - predicate::{string, value, PredicateBox}, prelude::*, - query::{Pagination, Sorting}, + query::{ + predicate::{string, value, PredicateBox}, + Pagination, Sorting, + }, }, }; use iroha_data_model::isi::InstructionBox; @@ -30,17 +32,13 @@ fn correct_pagination_assets_after_creating_new_one() { let mut assets = vec![]; let mut instructions = vec![]; - for i in 0..20_u128 { + for i in 0..20_u32 { let asset_definition_id = AssetDefinitionId::from_str(&format!("xor{i}#wonderland")).expect("Valid"); let asset_definition = AssetDefinition::store(asset_definition_id.clone()); let mut asset_metadata = Metadata::new(); asset_metadata - .insert_with_limits( - sort_by_metadata_key.clone(), - i.to_value(), - MetadataLimits::new(10, 23), - ) + .insert_with_limits(sort_by_metadata_key.clone(), i, MetadataLimits::new(10, 23)) .expect("Valid"); let asset = Asset::new( AssetId::new(asset_definition_id, account_id.clone()), @@ -89,7 +87,7 @@ fn correct_pagination_assets_after_creating_new_one() { new_asset_metadata .insert_with_limits( sort_by_metadata_key, - 20_u128.to_value(), + numeric!(20), MetadataLimits::new(10, 23), ) .expect("Valid"); @@ -140,7 +138,7 @@ fn correct_sorting_of_entities() { let mut asset_definitions = vec![]; let mut metadata_of_assets = vec![]; let mut instructions = vec![]; - let n = 10u128; + let n = 10_u32; for i in 0..n { let asset_definition_id = AssetDefinitionId::from_str(&format!("xor_{i}#wonderland")).expect("Valid"); @@ -148,7 +146,7 @@ fn correct_sorting_of_entities() { asset_metadata .insert_with_limits( sort_by_metadata_key.clone(), - (n - i - 1).to_value(), + n - i - 1, MetadataLimits::new(10, 28), ) .expect("Valid"); @@ -169,9 +167,9 @@ fn correct_sorting_of_entities() { let res = test_client .build_query(client::asset::all_definitions()) .with_sorting(Sorting::by_metadata_key(sort_by_metadata_key.clone())) - .with_filter(PredicateBox::new(value::ValuePredicate::Identifiable( - string::StringPredicate::starts_with("xor_"), - ))) + .with_filter(PredicateBox::new( + value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with("xor_")), + )) .execute() .expect("Valid") .collect::>>() @@ -199,7 +197,7 @@ fn correct_sorting_of_entities() { account_metadata .insert_with_limits( sort_by_metadata_key.clone(), - (n - i - 1).to_value(), + n - i - 1, MetadataLimits::new(10, 28), ) .expect("Valid"); @@ -220,9 +218,11 @@ fn correct_sorting_of_entities() { let res = test_client .build_query(client::account::all()) .with_sorting(Sorting::by_metadata_key(sort_by_metadata_key.clone())) - .with_filter(PredicateBox::new(value::ValuePredicate::Identifiable( - string::StringPredicate::starts_with("charlie"), - ))) + .with_filter(PredicateBox::new( + value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with( + "charlie", + )), + )) .execute() .expect("Valid") .collect::>>() @@ -246,7 +246,7 @@ fn correct_sorting_of_entities() { domain_metadata .insert_with_limits( sort_by_metadata_key.clone(), - (n - i - 1).to_value(), + n - i - 1, MetadataLimits::new(10, 28), ) .expect("Valid"); @@ -266,9 +266,11 @@ fn correct_sorting_of_entities() { let res = test_client .build_query(client::domain::all()) .with_sorting(Sorting::by_metadata_key(sort_by_metadata_key.clone())) - .with_filter(PredicateBox::new(value::ValuePredicate::Identifiable( - string::StringPredicate::starts_with("neverland"), - ))) + .with_filter(PredicateBox::new( + value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with( + "neverland", + )), + )) .execute() .expect("Valid") .collect::>>() @@ -281,7 +283,7 @@ fn correct_sorting_of_entities() { .eq(metadata_of_domains.iter().rev())); // Naive test sorting of domains - let input = [(0i32, 1u128), (2, 0), (1, 2)]; + let input = [(0_i32, 1_u32), (2, 0), (1, 2)]; let mut domains = vec![]; let mut metadata_of_domains = vec![]; let mut instructions = vec![]; @@ -291,7 +293,7 @@ fn correct_sorting_of_entities() { domain_metadata .insert_with_limits( sort_by_metadata_key.clone(), - val.to_value(), + val, MetadataLimits::new(10, 28), ) .expect("Valid"); @@ -307,7 +309,7 @@ fn correct_sorting_of_entities() { .submit_all_blocking(instructions) .expect("Valid"); - let filter = PredicateBox::new(value::ValuePredicate::Identifiable( + let filter = PredicateBox::new(value::QueryOutputPredicate::Identifiable( string::StringPredicate::starts_with("neverland_"), )); let res = test_client @@ -353,7 +355,7 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { account_metadata .insert_with_limits( sort_by_metadata_key.clone(), - (n - i - 1).to_value(), + n - i - 1, MetadataLimits::new(10, 28), ) .expect("Valid"); @@ -374,9 +376,11 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> { let res = test_client .build_query(client::account::all()) .with_sorting(Sorting::by_metadata_key(sort_by_metadata_key)) - .with_filter(PredicateBox::new(value::ValuePredicate::Identifiable( - string::StringPredicate::starts_with("charlie"), - ))) + .with_filter(PredicateBox::new( + value::QueryOutputPredicate::Identifiable(string::StringPredicate::starts_with( + "charlie", + )), + )) .execute() .wrap_err("Failed to submit request")? .collect::>>()?; diff --git a/client/tests/integration/transfer_asset.rs b/client/tests/integration/transfer_asset.rs index f277d6731a7..d13445c9ea3 100644 --- a/client/tests/integration/transfer_asset.rs +++ b/client/tests/integration/transfer_asset.rs @@ -83,7 +83,6 @@ fn simulate_transfer( port_number: u16, ) where T: std::fmt::Debug + Clone + Into, - Value: From, Mint: Instruction, Transfer: Instruction, { diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index f32b9a43af5..e00767959a8 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -24,7 +24,7 @@ fn call_execute_trigger() -> Result<()> { let asset_definition_id = "rose#wonderland".parse()?; let account_id = "alice@wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, account_id); - let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_value = get_asset_value(&mut test_client, asset_id.clone()); let instruction = Mint::asset_numeric(1u32, asset_id.clone()); let register_trigger = build_register_trigger_isi(asset_id.clone(), vec![instruction.into()]); @@ -34,7 +34,7 @@ fn call_execute_trigger() -> Result<()> { let call_trigger = ExecuteTrigger::new(trigger_id); test_client.submit_blocking(call_trigger)?; - let new_value = get_asset_value(&mut test_client, asset_id)?; + let new_value = get_asset_value(&mut test_client, asset_id); assert_eq!(new_value, prev_value.checked_add(Numeric::ONE).unwrap()); Ok(()) @@ -85,7 +85,7 @@ fn infinite_recursion_should_produce_one_call_per_block() -> Result<()> { let asset_id = AssetId::new(asset_definition_id, account_id); let trigger_id = TriggerId::from_str(TRIGGER_NAME)?; let call_trigger = ExecuteTrigger::new(trigger_id); - let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_value = get_asset_value(&mut test_client, asset_id.clone()); let instructions = vec![ Mint::asset_numeric(1u32, asset_id.clone()).into(), @@ -96,7 +96,7 @@ fn infinite_recursion_should_produce_one_call_per_block() -> Result<()> { test_client.submit_blocking(call_trigger)?; - let new_value = get_asset_value(&mut test_client, asset_id)?; + let new_value = get_asset_value(&mut test_client, asset_id); assert_eq!(new_value, prev_value.checked_add(Numeric::ONE).unwrap()); Ok(()) @@ -145,13 +145,13 @@ fn trigger_failure_should_not_cancel_other_triggers_execution() -> Result<()> { test_client.submit_blocking(register_trigger)?; // Saving current asset value - let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone()); // Executing bad trigger test_client.submit_blocking(ExecuteTrigger::new(bad_trigger_id))?; // Checking results - let new_asset_value = get_asset_value(&mut test_client, asset_id)?; + let new_asset_value = get_asset_value(&mut test_client, asset_id); assert_eq!( new_asset_value, prev_asset_value.checked_add(Numeric::ONE).unwrap() @@ -185,7 +185,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { test_client.submit_blocking(register_trigger)?; // Saving current asset value - let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone()); // Executing trigger first time let execute_trigger = ExecuteTrigger::new(trigger_id.clone()); @@ -211,7 +211,7 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { )); // Checking results - let new_asset_value = get_asset_value(&mut test_client, asset_id)?; + let new_asset_value = get_asset_value(&mut test_client, asset_id); assert_eq!( new_asset_value, prev_asset_value.checked_add(Numeric::ONE).unwrap() @@ -249,7 +249,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { test_client.submit_blocking(register_trigger)?; // Saving current asset value - let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone()); // Executing trigger first time let execute_trigger = ExecuteTrigger::new(trigger_id); @@ -259,7 +259,7 @@ fn trigger_should_be_able_to_modify_its_own_repeats_count() -> Result<()> { test_client.submit_blocking(execute_trigger)?; // Checking results - let new_asset_value = get_asset_value(&mut test_client, asset_id)?; + let new_asset_value = get_asset_value(&mut test_client, asset_id); assert_eq!( new_asset_value, prev_asset_value.checked_add(numeric!(2)).unwrap() @@ -378,14 +378,14 @@ fn trigger_in_genesis_using_base64() -> Result<()> { let asset_definition_id = "rose#wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, account_id); - let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_value = get_asset_value(&mut test_client, asset_id.clone()); // Executing trigger let call_trigger = ExecuteTrigger::new(trigger_id); test_client.submit_blocking(call_trigger)?; // Checking result - let new_value = get_asset_value(&mut test_client, asset_id)?; + let new_value = get_asset_value(&mut test_client, asset_id); assert_eq!(new_value, prev_value.checked_add(Numeric::ONE).unwrap()); Ok(()) @@ -435,7 +435,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { test_client.submit_blocking(register_trigger)?; // Saving current asset value - let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone()); // Executing triggers let execute_trigger_unregister = ExecuteTrigger::new(trigger_id_unregister); @@ -447,7 +447,7 @@ fn trigger_should_be_able_to_modify_other_trigger() -> Result<()> { // Checking results // First trigger should cancel second one, so value should stay the same - let new_asset_value = get_asset_value(&mut test_client, asset_id)?; + let new_asset_value = get_asset_value(&mut test_client, asset_id); assert_eq!(new_asset_value, prev_asset_value); Ok(()) @@ -542,9 +542,14 @@ fn unregistering_one_of_two_triggers_with_identical_wasm_should_not_cause_origin Ok(()) } -fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Result { - let asset = client.request(client::asset::by_id(asset_id))?; - Ok(*TryAsRef::::try_as_ref(asset.value())?) +fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Numeric { + let asset = client.request(client::asset::by_id(asset_id)).unwrap(); + + let AssetValue::Numeric(val) = *asset.value() else { + panic!("Unexpected asset value"); + }; + + val } fn build_register_trigger_isi( diff --git a/client/tests/integration/triggers/data_trigger.rs b/client/tests/integration/triggers/data_trigger.rs index 26f0e325e8a..32f6ae92037 100644 --- a/client/tests/integration/triggers/data_trigger.rs +++ b/client/tests/integration/triggers/data_trigger.rs @@ -1,5 +1,6 @@ use eyre::Result; use iroha_client::{client, data_model::prelude::*}; +use iroha_data_model::asset::AssetValue; use test_network::*; use crate::integration::new_account_with_random_public_key; @@ -13,7 +14,7 @@ fn must_execute_both_triggers() -> Result<()> { let asset_definition_id = "rose#wonderland".parse()?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - let prev_value = get_asset_value(&test_client, asset_id.clone())?; + let prev_value = get_asset_value(&test_client, asset_id.clone()); let instruction = Mint::asset_numeric(1u32, asset_id.clone()); let register_trigger = Register::trigger(Trigger::new( @@ -54,7 +55,7 @@ fn must_execute_both_triggers() -> Result<()> { )))?; test_client.submit_blocking(Register::domain(Domain::new("neverland".parse()?)))?; - let new_value = get_asset_value(&test_client, asset_id)?; + let new_value = get_asset_value(&test_client, asset_id); assert_eq!(new_value, prev_value.checked_add(numeric!(2)).unwrap()); Ok(()) @@ -86,7 +87,7 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu create_sakura_asset, ])?; - let prev_value = get_asset_value(&test_client, asset_id.clone())?; + let prev_value = get_asset_value(&test_client, asset_id.clone()); let register_trigger = Register::trigger(Trigger::new( "mint_sakura$neverland".parse()?, @@ -116,13 +117,18 @@ fn domain_scoped_trigger_must_be_executed_only_on_events_in_its_domain() -> Resu "asahi@neverland".parse()?, )))?; - let new_value = get_asset_value(&test_client, asset_id)?; + let new_value = get_asset_value(&test_client, asset_id); assert_eq!(new_value, prev_value.checked_add(Numeric::ONE).unwrap()); Ok(()) } -fn get_asset_value(client: &client::Client, asset_id: AssetId) -> Result { - let asset = client.request(client::asset::by_id(asset_id))?; - Ok(*TryAsRef::::try_as_ref(asset.value())?) +fn get_asset_value(client: &client::Client, asset_id: AssetId) -> Numeric { + let asset = client.request(client::asset::by_id(asset_id)).unwrap(); + + let AssetValue::Numeric(val) = *asset.value() else { + panic!("Expected u32 asset value") + }; + + val } diff --git a/client/tests/integration/triggers/event_trigger.rs b/client/tests/integration/triggers/event_trigger.rs index 89ed6b48ca5..c6250fdfe3e 100644 --- a/client/tests/integration/triggers/event_trigger.rs +++ b/client/tests/integration/triggers/event_trigger.rs @@ -15,7 +15,7 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { let asset_definition_id = "rose#wonderland".parse()?; let account_id = AccountId::from_str("alice@wonderland")?; let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_value = get_asset_value(&mut test_client, asset_id.clone()); let instruction = Mint::asset_numeric(1u32, asset_id.clone()); let register_trigger = Register::trigger(Trigger::new( @@ -45,13 +45,18 @@ fn test_mint_asset_when_new_asset_definition_created() -> Result<()> { Register::asset_definition(AssetDefinition::numeric(tea_definition_id)); test_client.submit_blocking(register_tea_definition)?; - let new_value = get_asset_value(&mut test_client, asset_id)?; + let new_value = get_asset_value(&mut test_client, asset_id); assert_eq!(new_value, prev_value.checked_add(Numeric::ONE).unwrap()); Ok(()) } -fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Result { - let asset = client.request(client::asset::by_id(asset_id))?; - Ok(*TryAsRef::::try_as_ref(asset.value())?) +fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Numeric { + let asset = client.request(client::asset::by_id(asset_id)).unwrap(); + + let AssetValue::Numeric(val) = *asset.value() else { + panic!("Unexpected asset value"); + }; + + val } diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index d6ec578e73b..fcb714bb711 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -42,7 +42,7 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result let asset_definition_id = "rose#wonderland".parse().expect("Valid"); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - let prev_value = get_asset_value(&mut test_client, asset_id.clone())?; + let prev_value = get_asset_value(&mut test_client, asset_id.clone()); let schedule = TimeSchedule::starting_at(start_time).with_period(PERIOD); let instruction = Mint::asset_numeric(1u32, asset_id.clone()); @@ -69,7 +69,7 @@ fn time_trigger_execution_count_error_should_be_less_than_15_percent() -> Result let finish_time = current_time(); let average_count = finish_time.saturating_sub(start_time).as_millis() / PERIOD.as_millis(); - let actual_value = get_asset_value(&mut test_client, asset_id)?; + let actual_value = get_asset_value(&mut test_client, asset_id); let expected_value = prev_value .checked_add(Numeric::new(average_count, 0)) .unwrap(); @@ -103,7 +103,7 @@ fn change_asset_metadata_after_1_sec() -> Result<()> { let schedule = TimeSchedule::starting_at(start_time + PERIOD); let instruction = - SetKeyValue::asset_definition(asset_definition_id.clone(), key.clone(), 3_u32.to_value()); + SetKeyValue::asset_definition(asset_definition_id.clone(), key.clone(), 3_u32); let register_trigger = Register::trigger(Trigger::new( "change_rose_metadata".parse().expect("Valid"), Action::new( @@ -122,13 +122,11 @@ fn change_asset_metadata_after_1_sec() -> Result<()> { usize::try_from(PERIOD.as_millis() / DEFAULT_CONSENSUS_ESTIMATION.as_millis() + 1)?, )?; - let value: Value = test_client - .request(FindAssetDefinitionKeyValueByIdAndKey { - id: asset_definition_id, - key, - })? - .into(); - assert_eq!(value, 3u32.to_value()); + let value = test_client.request(FindAssetDefinitionKeyValueByIdAndKey { + id: asset_definition_id, + key, + })?; + assert_eq!(value, numeric!(3).into()); Ok(()) } @@ -144,7 +142,7 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> { let account_id: AccountId = "alice@wonderland".parse().expect("Valid"); let asset_id = AssetId::new(asset_definition_id, account_id.clone()); - let mut prev_value = get_asset_value(&mut test_client, asset_id.clone())?; + let mut prev_value = get_asset_value(&mut test_client, asset_id.clone()); // Start listening BEFORE submitting any transaction not to miss any block committed event let event_listener = get_block_committed_event_listener(&test_client)?; @@ -162,7 +160,7 @@ fn pre_commit_trigger_should_be_executed() -> Result<()> { test_client.submit(register_trigger)?; for _ in event_listener.take(CHECKS_COUNT) { - let new_value = get_asset_value(&mut test_client, asset_id.clone())?; + let new_value = get_asset_value(&mut test_client, asset_id.clone()); assert_eq!(new_value, prev_value.checked_add(Numeric::ONE).unwrap()); prev_value = new_value; @@ -284,9 +282,14 @@ fn get_block_committed_event_listener( } /// Get asset numeric value -fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Result { - let asset = client.request(client::asset::by_id(asset_id))?; - Ok(*TryAsRef::::try_as_ref(asset.value())?) +fn get_asset_value(client: &mut Client, asset_id: AssetId) -> Numeric { + let asset = client.request(client::asset::by_id(asset_id)).unwrap(); + + let AssetValue::Numeric(val) = *asset.value() else { + panic!("Unexpected asset value"); + }; + + val } /// Submit some sample ISIs to create new blocks diff --git a/client/tests/integration/tx_history.rs b/client/tests/integration/tx_history.rs index 3ace4e8806d..bfddd8270c4 100644 --- a/client/tests/integration/tx_history.rs +++ b/client/tests/integration/tx_history.rs @@ -64,11 +64,15 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()> assert_eq!(transactions.len(), 50); let mut prev_creation_time = core::time::Duration::from_millis(0); - for tx in &transactions { - assert_eq!(tx.as_ref().authority(), &account_id); - //check sorted - assert!(tx.as_ref().creation_time() >= prev_creation_time); - prev_creation_time = tx.as_ref().creation_time(); - } + transactions + .iter() + .map(AsRef::as_ref) + .map(AsRef::as_ref) + .for_each(|tx| { + assert_eq!(tx.authority(), &account_id); + //check sorted + assert!(tx.creation_time() >= prev_creation_time); + prev_creation_time = tx.creation_time(); + }); Ok(()) } diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 94250a822dd..c38e2e13025 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -15,9 +15,9 @@ use erased_serde::Serialize; use iroha_client::{ client::{Client, QueryResult}, config::Config, - data_model::prelude::*, + data_model::{metadata::MetadataValueBox, prelude::*}, }; -use iroha_primitives::addr::{Ipv4Addr, Ipv6Addr, SocketAddr}; +use iroha_primitives::addr::SocketAddr; /// Re-usable clap `--metadata ` (`-m`) argument. /// Should be combined with `#[command(flatten)]` attr. @@ -53,33 +53,29 @@ impl MetadataArgs { } } -/// Re-usable clap `--value ` (`-v`) argument. +/// Re-usable clap `--value ` (`-v`) argument. /// Should be combined with `#[command(flatten)]` attr. #[derive(clap::Args, Debug, Clone, PartialEq, Eq)] -pub struct ValueArg { - /// Wrapper around Value to accept possible values and fallback to json. +pub struct MetadataValueArg { + /// Wrapper around MetadataValue to accept possible values and fallback to json. + /// /// The following types are supported: /// Numbers: decimal with optional point /// Booleans: false/true - /// IPv4/IPv6: e.g. 127.0.0.1, ::1 - /// Iroha Public Key Multihash: e.g. ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0 /// JSON: e.g. {"Vec":[{"String":"a"},{"String":"b"}]} #[arg(short, long)] - value: Value, + value: MetadataValueBox, } -impl FromStr for ValueArg { +impl FromStr for MetadataValueArg { type Err = Error; fn from_str(s: &str) -> Result { s.parse::() - .map(Value::Bool) - .or_else(|_| s.parse::().map(Value::Ipv4Addr)) - .or_else(|_| s.parse::().map(Value::Ipv6Addr)) - .or_else(|_| s.parse::().map(Value::Numeric)) - .or_else(|_| s.parse::().map(Value::PublicKey)) - .or_else(|_| serde_json::from_str::(s).map_err(Into::into)) - .map(|value| ValueArg { value }) + .map(MetadataValueBox::Bool) + .or_else(|_| s.parse::().map(MetadataValueBox::Numeric)) + .or_else(|_| serde_json::from_str::(s).map_err(Into::into)) + .map(|value| MetadataValueArg { value }) } } @@ -234,7 +230,7 @@ fn submit( } mod filter { - use iroha_client::data_model::predicate::PredicateBox; + use iroha_client::data_model::query::predicate::PredicateBox; use super::*; @@ -450,7 +446,7 @@ mod domain { #[arg(short, long)] key: Name, #[command(flatten)] - value: ValueArg, + value: MetadataValueArg, } impl RunArgs for Set { @@ -458,7 +454,7 @@ mod domain { let Self { id, key, - value: ValueArg { value }, + value: MetadataValueArg { value }, } = self; let set_key_value = SetKeyValue::domain(id, key, value); submit([set_key_value], UnlimitedMetadata::new(), context) @@ -788,7 +784,7 @@ mod asset { } = self; let mint_asset = iroha_client::data_model::isi::Mint::asset_numeric(quantity, asset_id); submit([mint_asset], metadata.load()?, context) - .wrap_err("Failed to mint asset of type `NumericValue::U32`") + .wrap_err("Failed to mint asset of type `Numeric`") } } @@ -814,7 +810,7 @@ mod asset { } = self; let burn_asset = iroha_client::data_model::isi::Burn::asset_numeric(quantity, asset_id); submit([burn_asset], metadata.load()?, context) - .wrap_err("Failed to burn asset of type `NumericValue::U32`") + .wrap_err("Failed to burn asset of type `Numeric`") } } @@ -905,7 +901,7 @@ mod asset { #[clap(long)] pub key: Name, #[command(flatten)] - pub value: ValueArg, + pub value: MetadataValueArg, } impl RunArgs for SetKeyValue { @@ -913,7 +909,7 @@ mod asset { let Self { asset_id, key, - value: ValueArg { value }, + value: MetadataValueArg { value }, } = self; let set = iroha_client::data_model::isi::SetKeyValue::asset(asset_id, key, value); @@ -1100,58 +1096,35 @@ mod json { mod tests { use std::str::FromStr; - use iroha_client::data_model::Value; - use super::*; #[test] fn parse_value_arg_cases() { macro_rules! case { ($input:expr, $expected:expr) => { - let ValueArg { value } = - ValueArg::from_str($input).expect("should not fail with valid input"); + let MetadataValueArg { value } = + MetadataValueArg::from_str($input).expect("should not fail with valid input"); assert_eq!(value, $expected); }; } - // IPv4 address - case!( - "192.168.0.1", - Value::Ipv4Addr(Ipv4Addr::new([192, 168, 0, 1])) - ); - - // IPv6 address - case!( - "::1", - Value::Ipv6Addr(Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 1])) - ); - // Boolean values - case!("true", Value::Bool(true)); - case!("false", Value::Bool(false)); + case!("true", true.into()); + case!("false", false.into()); // Numeric values - case!("123", Value::Numeric(numeric!(123))); - case!("123.0", Value::Numeric(numeric!(123.0))); - - // Public Key - let public_key_str = - "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0"; - case!( - public_key_str, - Value::PublicKey(PublicKey::from_str(public_key_str).unwrap()) - ); + case!("123", numeric!(123).into()); + case!("123.0", numeric!(123.0).into()); // JSON Value let json_str = r#"{"Vec":[{"String":"a"},{"String":"b"}]}"#; - let expected_json: Value = serde_json::from_str(json_str).unwrap(); - case!(json_str, expected_json); + case!(json_str, serde_json::from_str(json_str).unwrap()); } #[test] fn error_parse_invalid_value() { let invalid_str = "not_a_valid_value"; - let _invalid_value = ValueArg::from_str(invalid_str) + let _invalid_value = MetadataValueArg::from_str(invalid_str) .expect_err("Should fail invalid type from string but passed"); } } diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index cb37d9b18403817a0f3d3617fe8b6ba4cf53898b..b447246240b4dedfab404603d89baa57f46b58ec 100644 GIT binary patch delta 201133 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 uAzF|LCEVhDg}APIO1m&-uV{?gTG1u literal 586428 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 A`v3p{ diff --git a/core/src/query/store.rs b/core/src/query/store.rs index 6691ee24a48..d9df7ba4a7b 100644 --- a/core/src/query/store.rs +++ b/core/src/query/store.rs @@ -12,9 +12,9 @@ use iroha_data_model::{ asset::AssetValue, query::{ cursor::ForwardCursor, error::QueryExecutionFail, pagination::Pagination, sorting::Sorting, - FetchSize, QueryId, DEFAULT_FETCH_SIZE, MAX_FETCH_SIZE, + FetchSize, QueryId, QueryOutputBox, DEFAULT_FETCH_SIZE, MAX_FETCH_SIZE, }, - BatchedResponse, BatchedResponseV1, HasMetadata, IdentifiableBox, ValidationFail, Value, + BatchedResponse, BatchedResponseV1, HasMetadata, IdentifiableBox, ValidationFail, }; use iroha_logger::trace; use parity_scale_codec::{Decode, Encode}; @@ -25,7 +25,7 @@ use super::{ cursor::{Batch as _, Batched, UnknownCursor}, pagination::Paginate as _, }; -use crate::smartcontracts::query::LazyValue; +use crate::smartcontracts::query::LazyQueryOutput; /// Query service error. #[derive(Debug, thiserror::Error, Copy, Clone, Serialize, Deserialize, Encode, Decode)] @@ -61,7 +61,7 @@ impl From for ValidationFail { /// Result type for [`LiveQueryStore`] methods. pub type Result = std::result::Result; -type LiveQuery = Batched>; +type LiveQuery = Batched>; /// Service which stores queries which might be non fully consumed by a client. /// @@ -143,8 +143,11 @@ impl LiveQueryStore { } enum Message { - Insert(QueryId, Batched>), - Remove(QueryId, oneshot::Sender>>>), + Insert(QueryId, Batched>), + Remove( + QueryId, + oneshot::Sender>>>, + ), } /// Handle to interact with [`LiveQueryStore`]. @@ -162,18 +165,18 @@ impl LiveQueryStoreHandle { /// - Otherwise throws up query output handling errors. pub fn handle_query_output( &self, - query_output: LazyValue<'_>, + query_output: LazyQueryOutput<'_>, sorting: &Sorting, pagination: Pagination, fetch_size: FetchSize, - ) -> Result> { + ) -> Result> { match query_output { - LazyValue::Value(batch) => { + LazyQueryOutput::QueryOutput(batch) => { let cursor = ForwardCursor::default(); let result = BatchedResponseV1 { batch, cursor }; Ok(result.into()) } - LazyValue::Iter(iter) => { + LazyQueryOutput::Iter(iter) => { let fetch_size = fetch_size.fetch_size.unwrap_or(DEFAULT_FETCH_SIZE); if fetch_size > MAX_FETCH_SIZE { return Err(Error::FetchSizeTooBig); @@ -195,7 +198,10 @@ impl LiveQueryStoreHandle { /// /// - Returns [`Error::ConnectionClosed`] if [`LiveQueryStore`] is dropped, /// - Otherwise throws up query output handling errors. - pub fn handle_query_cursor(&self, cursor: ForwardCursor) -> Result> { + pub fn handle_query_cursor( + &self, + cursor: ForwardCursor, + ) -> Result> { let query_id = cursor.query_id.ok_or(UnknownCursor)?; let live_query = self.remove(query_id.clone())?.ok_or(UnknownCursor)?; @@ -236,8 +242,8 @@ impl LiveQueryStoreHandle { &self, query_id: QueryId, curr_cursor: Option, - mut live_query: Batched>, - ) -> Result> { + mut live_query: Batched>, + ) -> Result> { let (batch, next_cursor) = live_query.next_batch(curr_cursor)?; if !live_query.is_depleted() { @@ -245,7 +251,7 @@ impl LiveQueryStoreHandle { } let query_response = BatchedResponseV1 { - batch: Value::Vec(batch), + batch: QueryOutputBox::Vec(batch), cursor: ForwardCursor { query_id: Some(query_id), cursor: next_cursor, @@ -256,22 +262,25 @@ impl LiveQueryStoreHandle { } fn apply_sorting_and_pagination( - iter: impl Iterator, + iter: impl Iterator, sorting: &Sorting, pagination: Pagination, - ) -> Vec { + ) -> Vec { if let Some(key) = &sorting.sort_by_metadata_key { - let mut pairs: Vec<(Option, Value)> = iter + let mut pairs: Vec<(Option, QueryOutputBox)> = iter .map(|value| { let key = match &value { - Value::Identifiable(IdentifiableBox::Asset(asset)) => match asset.value() { - AssetValue::Store(store) => store.get(key).cloned(), - _ => None, - }, - Value::Identifiable(v) => TryInto::<&dyn HasMetadata>::try_into(v) + QueryOutputBox::Identifiable(IdentifiableBox::Asset(asset)) => { + match asset.value() { + AssetValue::Store(store) => store.get(key).cloned().map(Into::into), + _ => None, + } + } + QueryOutputBox::Identifiable(v) => TryInto::<&dyn HasMetadata>::try_into(v) .ok() .and_then(|has_metadata| has_metadata.metadata().get(key)) - .cloned(), + .cloned() + .map(Into::into), _ => None, }; (key, value) @@ -300,6 +309,8 @@ impl LiveQueryStoreHandle { mod tests { use std::num::NonZeroU32; + use iroha_data_model::metadata::MetadataValueBox; + use super::*; #[test] @@ -315,7 +326,9 @@ mod tests { }; let sorting = Sorting::default(); - let query_output = LazyValue::Iter(Box::new((0..100).map(|_| Value::Bool(false)))); + let query_output = LazyQueryOutput::Iter(Box::new( + (0..100).map(|_| MetadataValueBox::from(false).into()), + )); let mut counter = 0; @@ -323,7 +336,7 @@ mod tests { .handle_query_output(query_output, &sorting, pagination, fetch_size) .unwrap() .into(); - let Value::Vec(v) = batch else { + let QueryOutputBox::Vec(v) = batch else { panic!("not expected result") }; counter += v.len(); @@ -333,7 +346,7 @@ mod tests { break; }; let (batch, new_cursor) = batched.into(); - let Value::Vec(v) = batch else { + let QueryOutputBox::Vec(v) = batch else { panic!("not expected result") }; counter += v.len(); diff --git a/core/src/queue.rs b/core/src/queue.rs index 1d3245aa665..e6740741c46 100644 --- a/core/src/queue.rs +++ b/core/src/queue.rs @@ -246,20 +246,17 @@ impl Queue { }; let tx = entry.get(); - match self.check_tx(tx, wsv) { - Err(e) => { - let (_, tx) = entry.remove_entry(); - self.decrease_per_user_tx_count(tx.as_ref().authority()); - if let Error::Expired = e { - expired_transactions.push(tx); - } - continue; - } - Ok(()) => { - seen.push(hash); - return Some(tx.clone()); + if let Err(e) = self.check_tx(tx, wsv) { + let (_, tx) = entry.remove_entry(); + self.decrease_per_user_tx_count(tx.as_ref().authority()); + if let Error::Expired = e { + expired_transactions.push(tx); } + continue; } + + seen.push(hash); + return Some(tx.clone()); } } diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index 69d266f5f5d..5060488a4d1 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -228,7 +228,7 @@ pub mod isi { wsv.emit_events(Some(AccountEvent::MetadataInserted(MetadataChanged { target_id: account_id.clone(), key: self.key.clone(), - value: Box::new(self.value), + value: self.value, }))); Ok(()) @@ -250,7 +250,7 @@ pub mod isi { wsv.emit_events(Some(AccountEvent::MetadataRemoved(MetadataChanged { target_id: account_id.clone(), key: self.key, - value: Box::new(value), + value, }))); Ok(()) @@ -483,9 +483,8 @@ pub mod query { use eyre::Result; use iroha_data_model::{ - account::Account, - permission::PermissionToken, - query::{error::QueryExecutionFail as Error, MetadataValue}, + account::Account, metadata::MetadataValueBox, permission::PermissionToken, + query::error::QueryExecutionFail as Error, }; use super::*; @@ -580,7 +579,7 @@ pub mod query { impl ValidQuery for FindAccountKeyValueByIdAndKey { #[metrics(+"find_account_key_value_by_id_and_key")] - fn execute(&self, wsv: &WorldStateView) -> Result { + fn execute(&self, wsv: &WorldStateView) -> Result { let id = &self.id; let key = &self.key; iroha_logger::trace!(%id, %key); diff --git a/core/src/smartcontracts/isi/asset.rs b/core/src/smartcontracts/isi/asset.rs index c4d6dc912b3..b1a8764ab3b 100644 --- a/core/src/smartcontracts/isi/asset.rs +++ b/core/src/smartcontracts/isi/asset.rs @@ -57,10 +57,10 @@ pub mod isi { let asset = wsv.asset_or_insert(asset_id.clone(), Metadata::new())?; { - let store: &mut Metadata = asset - .try_as_mut() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + let AssetValue::Store(store) = &mut asset.value else { + return Err(Error::Conversion("Expected store asset type".to_owned())); + }; + store.insert_with_limits( self.key.clone(), self.value.clone(), @@ -71,7 +71,7 @@ pub mod isi { wsv.emit_events(Some(AssetEvent::MetadataInserted(MetadataChanged { target_id: asset_id, key: self.key, - value: Box::new(self.value), + value: self.value, }))); Ok(()) @@ -91,10 +91,11 @@ pub mod isi { let value = { let asset = wsv.asset_mut(&asset_id)?; - let store: &mut Metadata = asset - .try_as_mut() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + + let AssetValue::Store(store) = &mut asset.value else { + return Err(Error::Conversion("Expected store asset type".to_owned())); + }; + store .remove(&self.key) .ok_or_else(|| FindError::MetadataKey(self.key.clone()))? @@ -103,7 +104,7 @@ pub mod isi { wsv.emit_events(Some(AssetEvent::MetadataRemoved(MetadataChanged { target_id: asset_id, key: self.key, - value: Box::new(value), + value, }))); Ok(()) @@ -158,10 +159,9 @@ pub mod isi { assert_can_mint(&asset_definition, wsv)?; let asset = wsv.asset_or_insert(asset_id.clone(), Numeric::ZERO)?; - let quantity: &mut Numeric = asset - .try_as_mut() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + let AssetValue::Numeric(quantity) = &mut asset.value else { + return Err(Error::Conversion("Expected numeric asset type".to_owned())); + }; *quantity = quantity .checked_add(self.object) .ok_or(MathError::Overflow)?; @@ -197,10 +197,9 @@ pub mod isi { .assets .get_mut(&asset_id) .ok_or_else(|| FindError::Asset(asset_id.clone()))?; - let quantity: &mut Numeric = asset - .try_as_mut() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + let AssetValue::Numeric(quantity) = &mut asset.value else { + return Err(Error::Conversion("Expected numeric asset type".to_owned())); + }; *quantity = quantity .checked_sub(self.object) .ok_or(MathError::NotEnoughQuantity)?; @@ -243,10 +242,9 @@ pub mod isi { .assets .get_mut(&source_id) .ok_or_else(|| FindError::Asset(source_id.clone()))?; - let quantity: &mut Numeric = asset - .try_as_mut() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + let AssetValue::Numeric(quantity) = &mut asset.value else { + return Err(Error::Conversion("Expected numeric asset type".to_owned())); + }; *quantity = quantity .checked_sub(self.object) .ok_or(MathError::NotEnoughQuantity)?; @@ -257,10 +255,9 @@ pub mod isi { let destination_asset = wsv.asset_or_insert(destination_id.clone(), Numeric::ZERO)?; { - let quantity: &mut Numeric = destination_asset - .try_as_mut() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + let AssetValue::Numeric(quantity) = &mut destination_asset.value else { + return Err(Error::Conversion("Expected numeric asset type".to_owned())); + }; *quantity = quantity .checked_add(self.object) .ok_or(MathError::Overflow)?; @@ -368,9 +365,8 @@ pub mod query { use eyre::Result; use iroha_data_model::{ asset::{Asset, AssetDefinition, AssetValue}, - query::{ - asset::FindAssetDefinitionById, error::QueryExecutionFail as Error, MetadataValue, - }, + metadata::MetadataValueBox, + query::{asset::FindAssetDefinitionById, error::QueryExecutionFail as Error}, }; use super::*; @@ -591,7 +587,7 @@ pub mod query { impl ValidQuery for FindAssetKeyValueByIdAndKey { #[metrics(+"find_asset_key_value_by_id_and_key")] - fn execute(&self, wsv: &WorldStateView) -> Result { + fn execute(&self, wsv: &WorldStateView) -> Result { let id = &self.id; let key = &self.key; let asset = wsv.asset(id).map_err(|asset_err| { @@ -602,11 +598,10 @@ pub mod query { } })?; iroha_logger::trace!(%id, %key); - let store: &Metadata = asset - .value - .try_as_ref() - .map_err(eyre::Error::from) - .map_err(|e| Error::Conversion(e.to_string()))?; + let AssetValue::Store(store) = &asset.value else { + return Err(Error::Conversion("expected store, found other".to_owned())); + }; + store .get(key) .ok_or_else(|| Error::Find(FindError::MetadataKey(key.clone()))) diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index 19528612664..7917bb07066 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -194,7 +194,7 @@ pub mod isi { MetadataChanged { target_id: asset_definition_id, key: self.key, - value: Box::new(self.value), + value: self.value, }, ))); @@ -220,7 +220,7 @@ pub mod isi { MetadataChanged { target_id: asset_definition_id, key: self.key, - value: Box::new(value), + value, }, ))); @@ -243,7 +243,7 @@ pub mod isi { wsv.emit_events(Some(DomainEvent::MetadataInserted(MetadataChanged { target_id: domain_id, key: self.key, - value: Box::new(self.value), + value: self.value, }))); Ok(()) @@ -264,7 +264,7 @@ pub mod isi { wsv.emit_events(Some(DomainEvent::MetadataRemoved(MetadataChanged { target_id: domain_id, key: self.key, - value: Box::new(value), + value, }))); Ok(()) @@ -303,8 +303,7 @@ pub mod isi { pub mod query { use eyre::Result; use iroha_data_model::{ - domain::Domain, - query::{error::QueryExecutionFail as Error, MetadataValue}, + domain::Domain, metadata::MetadataValueBox, query::error::QueryExecutionFail as Error, }; use super::*; @@ -330,7 +329,7 @@ pub mod query { impl ValidQuery for FindDomainKeyValueByIdAndKey { #[metrics(+"find_domain_key_value_by_id_and_key")] - fn execute(&self, wsv: &WorldStateView) -> Result { + fn execute(&self, wsv: &WorldStateView) -> Result { let id = &self.id; let key = &self.key; iroha_logger::trace!(%id, %key); @@ -342,7 +341,7 @@ pub mod query { impl ValidQuery for FindAssetDefinitionKeyValueByIdAndKey { #[metrics(+"find_asset_definition_key_value_by_id_and_key")] - fn execute(&self, wsv: &WorldStateView) -> Result { + fn execute(&self, wsv: &WorldStateView) -> Result { let id = &self.id; let key = &self.key; iroha_logger::trace!(%id, %key); diff --git a/core/src/smartcontracts/isi/mod.rs b/core/src/smartcontracts/isi/mod.rs index d188729cef6..41b6d702c1f 100644 --- a/core/src/smartcontracts/isi/mod.rs +++ b/core/src/smartcontracts/isi/mod.rs @@ -205,6 +205,7 @@ mod tests { use std::sync::Arc; use iroha_crypto::KeyPair; + use iroha_data_model::metadata::MetadataValueBox; use tokio::test; use super::*; @@ -241,16 +242,16 @@ mod tests { ) .execute(&account_id, &mut wsv)?; let asset = wsv.asset(&asset_id)?; - let metadata: &Metadata = asset.try_as_ref()?; - let bytes = metadata - .get(&Name::from_str("Bytes").expect("Valid")) - .cloned(); + let AssetValue::Store(store) = &asset.value else { + panic!("expected store asset"); + }; + let bytes = store.get(&"Bytes".parse::().expect("Valid")).cloned(); assert_eq!( bytes, - Some(Value::Vec(vec![ - 1_u32.to_value(), - 2_u32.to_value(), - 3_u32.to_value(), + Some(MetadataValueBox::Vec(vec![ + 1_u32.into(), + 2_u32.into(), + 3_u32.into(), ])) ); Ok(()) @@ -275,10 +276,10 @@ mod tests { })?; assert_eq!( bytes, - Some(Value::Vec(vec![ - 1_u32.to_value(), - 2_u32.to_value(), - 3_u32.to_value(), + Some(MetadataValueBox::Vec(vec![ + 1_u32.into(), + 2_u32.into(), + 3_u32.into(), ])) ); Ok(()) @@ -303,10 +304,10 @@ mod tests { .cloned(); assert_eq!( bytes, - Some(Value::Vec(vec![ - 1_u32.to_value(), - 2_u32.to_value(), - 3_u32.to_value(), + Some(MetadataValueBox::Vec(vec![ + 1_u32.into(), + 2_u32.into(), + 3_u32.into(), ])) ); Ok(()) @@ -331,10 +332,10 @@ mod tests { .cloned(); assert_eq!( bytes, - Some(Value::Vec(vec![ - 1_u32.to_value(), - 2_u32.to_value(), - 3_u32.to_value(), + Some(MetadataValueBox::Vec(vec![ + 1_u32.into(), + 2_u32.into(), + 3_u32.into(), ])) ); Ok(()) diff --git a/core/src/smartcontracts/isi/query.rs b/core/src/smartcontracts/isi/query.rs index 0f8f8ab8a31..11414202d9d 100644 --- a/core/src/smartcontracts/isi/query.rs +++ b/core/src/smartcontracts/isi/query.rs @@ -1,7 +1,10 @@ //! Query functionality. The common error type is also defined here, //! alongside functions for converting them into HTTP responses. use eyre::Result; -use iroha_data_model::{prelude::*, query::error::QueryExecutionFail as Error}; +use iroha_data_model::{ + prelude::*, + query::{error::QueryExecutionFail as Error, QueryOutputBox}, +}; use parity_scale_codec::{Decode, Encode}; use crate::{prelude::ValidQuery, WorldStateView}; @@ -12,16 +15,16 @@ pub trait Lazy { type Lazy<'a>; } -/// Lazily evaluated equivalent of [`Value`] -pub enum LazyValue<'a> { - /// Concrete computed [`Value`] - Value(Value), - /// Iterator over a set of [`Value`]s - Iter(Box + 'a>), +/// Lazily evaluated equivalent of [`Query::Output`] +pub enum LazyQueryOutput<'a> { + /// Concrete computed [`Query::Output`] + QueryOutput(QueryOutputBox), + /// Iterator over a set of [`Query::Output`]s + Iter(Box + 'a>), } -impl Lazy for Value { - type Lazy<'a> = LazyValue<'a>; +impl Lazy for QueryOutputBox { + type Lazy<'a> = LazyQueryOutput<'a>; } impl Lazy for Vec { @@ -44,7 +47,7 @@ impl_lazy! { iroha_data_model::account::Account, iroha_data_model::domain::Domain, iroha_data_model::block::BlockHeader, - iroha_data_model::query::MetadataValue, + iroha_data_model::metadata::MetadataValueBox, iroha_data_model::query::TransactionQueryOutput, iroha_data_model::permission::PermissionTokenSchema, iroha_data_model::trigger::Trigger, @@ -83,13 +86,16 @@ impl ValidQueryRequest { /// /// # Errors /// Forwards `self.query.execute` error. - pub fn execute<'wsv>(&'wsv self, wsv: &'wsv WorldStateView) -> Result, Error> { - let value = self.0.query().execute(wsv)?; - - Ok(if let LazyValue::Iter(iter) = value { - LazyValue::Iter(Box::new(iter.filter(|val| self.0.filter().applies(val)))) + pub fn execute<'wsv>( + &'wsv self, + wsv: &'wsv WorldStateView, + ) -> Result, Error> { + let output = self.0.query().execute(wsv)?; + + Ok(if let LazyQueryOutput::Iter(iter) = output { + LazyQueryOutput::Iter(Box::new(iter.filter(|val| self.0.filter().applies(val)))) } else { - value + output }) // We're not handling the LimitedMetadata case, because @@ -103,14 +109,14 @@ impl ValidQueryRequest { } impl ValidQuery for QueryBox { - fn execute<'wsv>(&self, wsv: &'wsv WorldStateView) -> Result, Error> { + fn execute<'wsv>(&self, wsv: &'wsv WorldStateView) -> Result, Error> { iroha_logger::debug!(query=%self, "Executing"); macro_rules! match_all { ( non_iter: {$( $non_iter_query:ident ),+ $(,)?} $( $query:ident, )+ ) => { match self { $( - QueryBox::$non_iter_query(query) => query.execute(wsv).map(Value::from).map(LazyValue::Value), )+ $( - QueryBox::$query(query) => query.execute(wsv).map(|i| i.map(Value::from)).map(|iter| LazyValue::Iter(Box::new(iter))), )+ + QueryBox::$non_iter_query(query) => query.execute(wsv).map(QueryOutputBox::from).map(LazyQueryOutput::QueryOutput), )+ $( + QueryBox::$query(query) => query.execute(wsv).map(|i| i.map(QueryOutputBox::from)).map(|iter| LazyQueryOutput::Iter(Box::new(iter))), )+ } }; } @@ -168,7 +174,9 @@ mod tests { use std::str::FromStr as _; use iroha_crypto::{Hash, HashOf, KeyPair}; - use iroha_data_model::{query::error::FindError, transaction::TransactionLimits}; + use iroha_data_model::{ + metadata::MetadataValueBox, query::error::FindError, transaction::TransactionLimits, + }; use iroha_primitives::unique_vec::UniqueVec; use once_cell::sync::Lazy; use tokio::test; @@ -212,7 +220,7 @@ mod tests { store .insert_with_limits( Name::from_str("Bytes").expect("Valid"), - Value::Vec(vec![1_u32.to_value(), 2_u32.to_value(), 3_u32.to_value()]), + MetadataValueBox::Vec(vec![1_u32.into(), 2_u32.into(), 3_u32.into()]), MetadataLimits::new(10, 100), ) .unwrap(); @@ -228,7 +236,7 @@ mod tests { let mut metadata = Metadata::new(); metadata.insert_with_limits( Name::from_str("Bytes")?, - Value::Vec(vec![1_u32.to_value(), 2_u32.to_value(), 3_u32.to_value()]), + MetadataValueBox::Vec(vec![1_u32.into(), 2_u32.into(), 3_u32.into()]), MetadataLimits::new(10, 100), )?; @@ -319,8 +327,8 @@ mod tests { let bytes = FindAssetKeyValueByIdAndKey::new(asset_id, Name::from_str("Bytes")?).execute(&wsv)?; assert_eq!( - Value::Vec(vec![1_u32.to_value(), 2_u32.to_value(), 3_u32.to_value()]), - bytes.into(), + MetadataValueBox::Vec(vec![1_u32.into(), 2_u32.into(), 3_u32.into()]), + bytes, ); Ok(()) } @@ -334,8 +342,8 @@ mod tests { let bytes = FindAccountKeyValueByIdAndKey::new(ALICE_ID.clone(), Name::from_str("Bytes")?) .execute(&wsv)?; assert_eq!( - Value::Vec(vec![1_u32.to_value(), 2_u32.to_value(), 3_u32.to_value()]), - bytes.into(), + MetadataValueBox::Vec(vec![1_u32.into(), 2_u32.into(), 3_u32.into()]), + bytes, ); Ok(()) } @@ -447,7 +455,10 @@ mod tests { let found_accepted = FindTransactionByHash::new(va_tx.as_ref().hash()).execute(&wsv)?; if found_accepted.transaction.error.is_none() { - assert_eq!(va_tx.as_ref().hash(), found_accepted.as_ref().hash()) + assert_eq!( + va_tx.as_ref().hash(), + found_accepted.as_ref().as_ref().hash() + ) } Ok(()) } @@ -459,7 +470,7 @@ mod tests { let mut metadata = Metadata::new(); metadata.insert_with_limits( Name::from_str("Bytes")?, - Value::Vec(vec![1_u32.to_value(), 2_u32.to_value(), 3_u32.to_value()]), + MetadataValueBox::Vec(vec![1_u32.into(), 2_u32.into(), 3_u32.into()]), MetadataLimits::new(10, 100), )?; let mut domain = Domain::new(DomainId::from_str("wonderland")?) @@ -482,8 +493,8 @@ mod tests { let key = Name::from_str("Bytes")?; let bytes = FindDomainKeyValueByIdAndKey::new(domain_id, key).execute(&wsv)?; assert_eq!( - Value::Vec(vec![1_u32.to_value(), 2_u32.to_value(), 3_u32.to_value()]), - bytes.into(), + MetadataValueBox::Vec(vec![1_u32.into(), 2_u32.into(), 3_u32.into()]), + bytes, ); Ok(()) } diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index fd5459cacad..d90b5f65932 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -195,7 +195,8 @@ pub mod query { //! Queries associated to triggers. use iroha_data_model::{ events::TriggeringFilterBox, - query::{error::QueryExecutionFail as Error, MetadataValue}, + metadata::MetadataValueBox, + query::error::QueryExecutionFail as Error, trigger::{Trigger, TriggerId}, }; @@ -233,7 +234,7 @@ pub mod query { impl ValidQuery for FindTriggerKeyValueByIdAndKey { #[metrics(+"find_trigger_key_value_by_id_and_key")] - fn execute(&self, wsv: &WorldStateView) -> Result { + fn execute(&self, wsv: &WorldStateView) -> Result { let id = &self.id; let key = &self.key; iroha_logger::trace!(%id, %key); diff --git a/core/src/smartcontracts/isi/tx.rs b/core/src/smartcontracts/isi/tx.rs index 009b61484be..ac282bd37b3 100644 --- a/core/src/smartcontracts/isi/tx.rs +++ b/core/src/smartcontracts/isi/tx.rs @@ -74,7 +74,7 @@ impl ValidQuery for FindAllTransactions { .flat_map(BlockTransactionIter::new) .map(|tx| TransactionQueryOutput { block_hash: tx.block_hash(), - transaction: Box::new(tx.value()), + transaction: tx.value(), }), )) } @@ -94,7 +94,7 @@ impl ValidQuery for FindTransactionsByAccountId { .filter(move |tx| *tx.authority() == account_id) .map(|tx| TransactionQueryOutput { block_hash: tx.block_hash(), - transaction: Box::new(tx.value()), + transaction: tx.value(), }), )) } @@ -118,7 +118,6 @@ impl ValidQuery for FindTransactionByHash { transactions .find(|transaction| transaction.value.hash() == tx_hash) .cloned() - .map(Box::new) .map(|transaction| TransactionQueryOutput { block_hash, transaction, diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index c78bb327168..d3a1c0b374f 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -13,7 +13,7 @@ use iroha_data_model::{ isi::InstructionBox, permission::PermissionTokenSchema, prelude::*, - query::{QueryBox, QueryRequest, QueryWithParameters}, + query::{QueryBox, QueryId, QueryOutputBox, QueryRequest, QueryWithParameters}, smart_contract::payloads::{self, Validate}, BatchedResponse, Level as LogLevel, ValidationFail, }; @@ -78,7 +78,7 @@ mod import { fn execute_query( query_request: SmartContractQueryRequest, state: &mut S, - ) -> Result, ValidationFail>; + ) -> Result, ValidationFail>; /// Execute `instruction` on host #[codec::wrap_trait_fn] @@ -761,7 +761,7 @@ where fn default_execute_query( query_request: SmartContractQueryRequest, state: &mut state::CommonState, - ) -> Result, ValidationFail> { + ) -> Result, ValidationFail> { iroha_logger::debug!(%query_request, "Executing"); match query_request.0 { @@ -907,7 +907,7 @@ impl<'wrld> import::traits::ExecuteOperations> fn execute_query( query_request: SmartContractQueryRequest, state: &mut state::SmartContract<'wrld>, - ) -> Result, ValidationFail> { + ) -> Result, ValidationFail> { Self::default_execute_query(query_request, state) } @@ -979,7 +979,7 @@ impl<'wrld> import::traits::ExecuteOperations> fn execute_query( query_request: SmartContractQueryRequest, state: &mut state::Trigger<'wrld>, - ) -> Result, ValidationFail> { + ) -> Result, ValidationFail> { Self::default_execute_query(query_request, state) } @@ -1008,7 +1008,7 @@ where fn execute_query( query_request: SmartContractQueryRequest, state: &mut state::CommonState, S>, - ) -> Result, ValidationFail> { + ) -> Result, ValidationFail> { debug!(%query_request, "Executing as executor"); Runtime::default_execute_query(query_request, state) @@ -1246,7 +1246,7 @@ impl<'wrld> import::traits::ExecuteOperations, - ) -> Result, ValidationFail> { + ) -> Result, ValidationFail> { debug!(%query_request, "Executing as executor"); Runtime::default_execute_query(query_request, state) diff --git a/core/src/wsv.rs b/core/src/wsv.rs index 0d4c2b7248d..c736af16b22 100644 --- a/core/src/wsv.rs +++ b/core/src/wsv.rs @@ -14,7 +14,7 @@ use iroha_data_model::{ block::SignedBlock, events::notification::{TriggerCompletedEvent, TriggerCompletedOutcome}, isi::error::{InstructionExecutionError as Error, MathError}, - parameter::Parameter, + parameter::{Parameter, ParameterValueBox}, permission::PermissionTokenSchema, prelude::*, query::error::{FindError, QueryExecutionFail}, @@ -1067,7 +1067,7 @@ impl WorldStateView { } /// Query parameter and convert it to a proper type - pub fn query_param, P: core::hash::Hash + Eq + ?Sized>( + pub fn query_param, P: core::hash::Hash + Eq + ?Sized>( &self, param: &P, ) -> Option @@ -1078,7 +1078,7 @@ impl WorldStateView { .parameters .get(param) .as_ref() - .map(|param| &*param.val) + .map(|param| ¶m.val) .cloned() .and_then(|param_val| param_val.try_into().ok()) } diff --git a/core/test_network/src/lib.rs b/core/test_network/src/lib.rs index 1c187480a74..128df3827b2 100644 --- a/core/test_network/src/lib.rs +++ b/core/test_network/src/lib.rs @@ -14,7 +14,7 @@ use iroha_client::{ }; use iroha_config::parameters::actual::Root as Config; use iroha_crypto::prelude::*; -use iroha_data_model::ChainId; +use iroha_data_model::{query::QueryOutputBox, ChainId}; use iroha_genesis::{GenesisNetwork, RawGenesisBlock}; use iroha_logger::InstrumentFutures; use iroha_primitives::{ @@ -687,7 +687,7 @@ pub trait TestClient: Sized { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into; + >::Error: Into; /// Submits instructions with polling /// @@ -702,7 +702,7 @@ pub trait TestClient: Sized { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into; + >::Error: Into; /// Polls request till predicate `f` is satisfied, with default period and max attempts. /// @@ -716,7 +716,7 @@ pub trait TestClient: Sized { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into; + >::Error: Into; /// Polls request till predicate `f` is satisfied with `period` and `max_attempts` supplied. /// @@ -732,7 +732,7 @@ pub trait TestClient: Sized { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into; + >::Error: Into; } impl TestRuntime for Runtime { @@ -829,7 +829,7 @@ impl TestClient for Client { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into, + >::Error: Into, { self.submit(instruction) .expect("Failed to submit instruction."); @@ -845,7 +845,7 @@ impl TestClient for Client { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into, + >::Error: Into, { self.submit_all(instructions) .expect("Failed to submit instruction."); @@ -862,7 +862,7 @@ impl TestClient for Client { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into, + >::Error: Into, { let mut query_result = None; for _ in 0..max_attempts { @@ -883,7 +883,7 @@ impl TestClient for Client { where R::Output: QueryOutput, ::Target: core::fmt::Debug, - >::Error: Into, + >::Error: Into, { self.poll_request_with_period(request, Config::pipeline_time() / 2, 10, f) } diff --git a/data_model/Cargo.toml b/data_model/Cargo.toml index 9b80ee2b6fc..db190cb0554 100644 --- a/data_model/Cargo.toml +++ b/data_model/Cargo.toml @@ -55,6 +55,8 @@ base64 = { workspace = true, features = ["alloc"] } once_cell = { workspace = true, optional = true } [dev-dependencies] +iroha_crypto = { workspace = true, features = ["rand"] } + trybuild = { workspace = true } criterion = { workspace = true } diff --git a/data_model/src/account.rs b/data_model/src/account.rs index 9226d54952e..0ac65442415 100644 --- a/data_model/src/account.rs +++ b/data_model/src/account.rs @@ -359,16 +359,6 @@ impl Registered for Account { type With = NewAccount; } -#[cfg(feature = "transparent_api")] -impl FromIterator for crate::Value { - fn from_iter>(iter: T) -> Self { - iter.into_iter() - .map(Into::into) - .collect::>() - .into() - } -} - /// Account Identification is represented by `name@domain_name` string. impl FromStr for AccountId { type Err = ParseError; diff --git a/data_model/src/asset.rs b/data_model/src/asset.rs index 1b3be4bd075..6bf4cf6447d 100644 --- a/data_model/src/asset.rs +++ b/data_model/src/asset.rs @@ -18,7 +18,7 @@ use serde_with::{DeserializeFromStr, SerializeDisplay}; pub use self::model::*; use crate::{ account::prelude::*, domain::prelude::*, ipfs::IpfsPath, metadata::Metadata, HasMetadata, - Identifiable, Name, ParseError, Registered, TryAsMut, TryAsRef, Value, + Identifiable, Name, ParseError, Registered, }; /// API to work with collections of [`Id`] : [`Asset`] mappings. @@ -34,6 +34,7 @@ pub type AssetTotalQuantityMap = btree_map::BTreeMap #[model] pub mod model { + use iroha_macro::FromVariant; use super::*; @@ -212,6 +213,7 @@ pub mod model { Eq, PartialOrd, Ord, + FromVariant, Decode, Encode, Deserialize, @@ -222,7 +224,11 @@ pub mod model { pub enum AssetValue { /// Asset's qualitative value. #[display(fmt = "{_0}")] - Numeric(Numeric), + Numeric( + #[skip_from] + #[skip_try_from] + Numeric, + ), /// Asset's key-value structured data. Store(Metadata), } @@ -366,51 +372,12 @@ impl AssetValue { } } -impl From for AssetValue { - fn from(value: Metadata) -> Self { - AssetValue::Store(value) - } -} - impl> From for AssetValue { fn from(value: T) -> Self { - AssetValue::Numeric(value.into()) + Self::Numeric(value.into()) } } -macro_rules! impl_try_as_for_asset_value { - ( $($variant:ident( $ty:ty ),)* ) => {$( - impl TryAsMut<$ty> for AssetValue { - type Error = crate::EnumTryAsError<$ty, AssetValueType>; - - fn try_as_mut(&mut self) -> Result<&mut $ty, Self::Error> { - if let AssetValue:: $variant (value) = self { - Ok(value) - } else { - Err(crate::EnumTryAsError::got(self.value_type())) - } - } - } - - impl TryAsRef<$ty> for AssetValue { - type Error = crate::EnumTryAsError<$ty, AssetValueType>; - - fn try_as_ref(&self) -> Result<& $ty, Self::Error> { - if let AssetValue:: $variant (value) = self { - Ok(value) - } else { - Err(crate::EnumTryAsError::got(self.value_type())) - } - } - } - )*} -} - -impl_try_as_for_asset_value! { - Numeric(Numeric), - Store(Metadata), -} - /// Asset Definition Identification is represented by `name#domain_name` string. impl FromStr for AssetDefinitionId { type Err = ParseError; @@ -508,30 +475,6 @@ impl HasMetadata for NewAssetDefinition { } } -impl TryAsMut for Asset -where - AssetValue: TryAsMut, -{ - type Error = >::Error; - - #[inline] - fn try_as_mut(&mut self) -> Result<&mut T, Self::Error> { - self.value.try_as_mut() - } -} - -impl TryAsRef for Asset -where - AssetValue: TryAsRef, -{ - type Error = >::Error; - - #[inline] - fn try_as_ref(&self) -> Result<&T, Self::Error> { - self.value.try_as_ref() - } -} - impl Registered for Asset { type With = Self; } @@ -540,24 +483,6 @@ impl Registered for AssetDefinition { type With = NewAssetDefinition; } -impl FromIterator for Value { - fn from_iter>(iter: T) -> Self { - iter.into_iter() - .map(Into::into) - .collect::>() - .into() - } -} - -impl FromIterator for Value { - fn from_iter>(iter: T) -> Self { - iter.into_iter() - .map(Into::into) - .collect::>() - .into() - } -} - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{ diff --git a/data_model/src/domain.rs b/data_model/src/domain.rs index 6eeff49dedb..c631996224d 100644 --- a/data_model/src/domain.rs +++ b/data_model/src/domain.rs @@ -257,15 +257,6 @@ impl Domain { } } -impl FromIterator for crate::Value { - fn from_iter>(iter: T) -> Self { - iter.into_iter() - .map(Into::into) - .collect::>() - .into() - } -} - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{Domain, DomainId}; diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 550815f6021..29472ed2c5d 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -36,6 +36,7 @@ macro_rules! data_event { #[model] pub mod model { use super::*; + use crate::metadata::MetadataValueBox; /// Generic [`MetadataChanged`] struct. /// Contains the changed metadata (`(key, value)` pair), either inserted or removed, which is determined by the wrapping event. @@ -58,7 +59,7 @@ pub mod model { pub struct MetadataChanged { pub target_id: ID, pub key: Name, - pub value: Box, + pub value: MetadataValueBox, } /// Event diff --git a/data_model/src/events/data/mod.rs b/data_model/src/events/data/mod.rs index 1c1ab8494f8..70d0cd0d66e 100644 --- a/data_model/src/events/data/mod.rs +++ b/data_model/src/events/data/mod.rs @@ -1,7 +1,7 @@ //! Data events. #[cfg(not(feature = "std"))] -use alloc::{boxed::Box, format, string::String, vec::Vec}; +use alloc::{format, string::String, vec::Vec}; pub use events::DataEvent; pub use filters::DataEventFilter; diff --git a/data_model/src/integer.rs b/data_model/src/integer.rs deleted file mode 100644 index 465e7b0c174..00000000000 --- a/data_model/src/integer.rs +++ /dev/null @@ -1,268 +0,0 @@ -//! Tagged polymorphic numerical type. -//! -//! Special care is taken to work around limitations for wide-integer -//! types commonly used in Rust and in the code-base, -#[cfg(not(feature = "std"))] -use alloc::{ - format, - string::{String, ToString}, - vec::Vec, -}; -use core::{num::ParseIntError, str::FromStr}; - -use derive_more::From; -use serde::{de::Error, Deserializer, Serializer}; - -pub use self::model::*; -use super::{DebugCustom, Decode, Deserialize, Display, Encode, FromVariant, IntoSchema}; - -#[iroha_data_model_derive::model] -pub mod model { - use super::*; - - /// Enum for all supported numeric values - #[derive( - DebugCustom, - Display, - Copy, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - FromVariant, - Decode, - Encode, - IntoSchema, - )] - #[ffi_type] - pub enum Integer { - /// `u32` value - #[debug(fmt = "{_0}_u32")] - U32(u32), - /// `u64` value - #[debug(fmt = "{_0}_u64")] - U64(u64), - /// `u128` value - #[debug(fmt = "{_0}_u128")] - U128(u128), - } -} - -impl Integer { - /// Return `true` if value is zero - pub const fn is_zero_value(self) -> bool { - use Integer::*; - match self { - U32(value) => value == 0_u32, - U64(value) => value == 0_u64, - U128(value) => value == 0_u128, - } - } -} - -struct IntegerVisitor; - -#[derive(Deserialize)] -#[serde(field_identifier)] -enum Discriminants { - U32, - U64, - U128, -} - -impl FromStr for Integer { - type Err = ParseNumericError; - - fn from_str(s: &str) -> Result { - if s.contains('_') { - if s.ends_with("_u32") { - Ok(Integer::U32( - s.rsplit_once("_u32") - .ok_or(ParseNumericError::Format)? - .0 - .parse()?, - )) - } else if s.ends_with("_u64") { - Ok(Integer::U64( - s.rsplit_once("_u64") - .ok_or(ParseNumericError::Format)? - .0 - .parse()?, - )) - } else if s.ends_with("_u128") { - Ok(Integer::U128( - s.rsplit_once("_u128") - .ok_or(ParseNumericError::Format)? - .0 - .parse()?, - )) - } else { - Err(ParseNumericError::Format) - } - } else { - Err(ParseNumericError::Format) - } - } -} - -// serialize and deserialize numbers as string literals with tagged numbers inside -// U32(42) <-> "42_u32" -// U64(42) <-> "42_u64" -// U128(42) <-> "42_u128" - -impl serde::Serialize for Integer { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&format!("{self:?}")) - } -} - -impl serde::de::Visitor<'_> for IntegerVisitor { - type Value = Integer; - - #[inline] - fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { - formatter.write_str("A quoted string containing a tagged number") - } - - fn visit_str(self, v: &str) -> Result - where - E: Error, - { - let parsed = v.parse::().map_err(|e| E::custom(e.to_string()))?; - - Ok(parsed) - } -} - -impl<'de> Deserialize<'de> for Integer { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(IntegerVisitor) - } -} - -/// Error emitted when a integer value failed to be parsed from a -/// string or a JSON literal. -#[derive(Clone, Debug, Display, From)] -#[allow(missing_docs)] -pub enum ParseNumericError { - #[display( - fmt = "A correctly formatted value was not found. Correct values are integer followed by an underscore and a type identifier, which is one of [`u32`, `u64`, `u128`]. Example:\"12_u32\"." - )] - Format, - #[from] - #[display(fmt = "Failed to parse value as an integer. {_0}")] - ParseInt(ParseIntError), -} - -#[cfg(feature = "std")] -impl std::error::Error for ParseNumericError {} - -// TODO: impl source correctly for conversions. - -#[cfg(test)] -mod tests { - #![allow(clippy::pedantic)] - use super::*; - - #[test] - fn tagged_quoted_inclusion_u128() { - let values = [ - 0_u128, - 1_u128, - (u32::MAX - 1_u32) as u128, - u32::MAX as u128, - (u64::MAX - 1_u64) as u128, - u64::MAX as u128, - u128::MAX - 1_u128, - u128::MAX, - ]; - for value in values { - let json = format!("\"{value}_u128\"",); - let val: Integer = serde_json::from_str(&json).expect("Invalid JSON"); - assert_eq!(val, Integer::U128(value)); - } - } - - #[test] - fn tagged_quoted_inclusion_u64() { - let values = [ - 0_u64, - 1_u64, - (u32::MAX - 1_u32) as u64, - u32::MAX as u64, - u64::MAX - 1_u64, - u64::MAX, - ]; - for value in values { - let json = format!("\"{value}_u64\"",); - let val: Integer = serde_json::from_str(&json).expect("Invalid JSON"); - assert_eq!(Integer::U64(value), val) - } - } - - #[test] - fn tagged_quoted_inclusion_u32() { - let values = [0_u32, 1_u32, (u32::MAX - 1_u32), u32::MAX]; - for value in values { - let json = format!("\"{value}_u32\"",); - let val: Integer = serde_json::from_str(&json).expect("Invalid JSON"); - assert_eq!(val, Integer::U32(value)); - } - } - - #[test] - fn serialize_is_quoted_u128() { - let value = Integer::U128(u128::MAX); - let string = serde_json::to_string(&value).unwrap(); - let expectation = format!("\"{}_u128\"", u128::MAX); - assert_eq!(string, expectation); - } - - #[test] - fn debug_and_from_str_invert_each_other() { - let values = [ - Integer::U32(0_u32), - Integer::U128(0_u128), - Integer::U128(u128::MAX), - Integer::U128((u64::MAX - 1) as u128), - ]; - for val in values { - let new_value: Integer = format!("{val:?}").parse().expect("Failed to parse"); - assert_eq!(new_value, val); - } - } - - fn as_u32(v: impl Into) -> String { - Integer::U32(v.into()).to_string() - } - - #[test] - #[should_panic] - /// We deny ambiguous deserialisation from strings. - fn display_from_str_integer_unsupported() { - assert_eq!( - Integer::from_str(&as_u32(0_u32)).unwrap(), - Integer::U128(0_u128) - ); - } - - #[test] - #[should_panic] - /// We deny ambiguous deserialisation from int literals - fn deserialize_int_literal_unsupported() { - serde_json::from_str::("0").unwrap(); - } - - #[test] - fn deserialize_without_prefix_fails() { - assert!(serde_json::from_str::("\"100\"").is_err()); - assert!(serde_json::from_str::("\"100.0\"").is_err()); - } -} diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index 0dc5af335b9..ef63f12a28f 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use strum::EnumDiscriminants; pub use self::{model::*, transparent::*}; -use super::{prelude::*, Value}; +use super::{metadata::MetadataValueBox, prelude::*}; use crate::{seal, Level, Registered}; /// Marker trait designating instruction. @@ -283,13 +283,13 @@ mod transparent { /// Key. pub key: Name, /// Value. - pub value: Value, + pub value: MetadataValueBox, } } impl SetKeyValue { /// Constructs a new [`SetKeyValue`] for a [`Domain`] with the given `key` and `value`. - pub fn domain(domain_id: DomainId, key: Name, value: impl Into) -> Self { + pub fn domain(domain_id: DomainId, key: Name, value: impl Into) -> Self { Self { object_id: domain_id, key, @@ -300,7 +300,11 @@ mod transparent { impl SetKeyValue { /// Constructs a new [`SetKeyValue`] for an [`Account`] with the given `key` and `value`. - pub fn account(account_id: AccountId, key: Name, value: impl Into) -> Self { + pub fn account( + account_id: AccountId, + key: Name, + value: impl Into, + ) -> Self { Self { object_id: account_id, key, @@ -314,7 +318,7 @@ mod transparent { pub fn asset_definition( asset_definition_id: AssetDefinitionId, key: Name, - value: impl Into, + value: impl Into, ) -> Self { Self { object_id: asset_definition_id, @@ -326,7 +330,7 @@ mod transparent { impl SetKeyValue { /// Constructs a new [`SetKeyValue`] for an [`Asset`] with the given `key` and `value`. - pub fn asset(asset_id: AssetId, key: Name, value: impl Into) -> Self { + pub fn asset(asset_id: AssetId, key: Name, value: impl Into) -> Self { Self { object_id: asset_id, key, @@ -855,8 +859,8 @@ mod transparent { isi! { /// Generic instruction for granting permission to an entity. - #[schema(bounds = "O: Into + IntoSchema, D: Identifiable, D::Id: IntoSchema")] - pub struct Grant, D: Identifiable> { + #[schema(bounds = "O: IntoSchema, D: Identifiable, D::Id: IntoSchema")] + pub struct Grant { /// Object to grant. pub object: O, /// Entity to which to grant this token. @@ -897,7 +901,7 @@ mod transparent { impl_display! { Grant where - O: Into + Display, + O: Display, D: Identifiable, D::Id: Display, => @@ -916,8 +920,8 @@ mod transparent { isi! { /// Generic instruction for revoking permission from an entity. - #[schema(bounds = "O: Into + IntoSchema, D: Identifiable, D::Id: IntoSchema")] - pub struct Revoke, D: Identifiable> { + #[schema(bounds = "O: IntoSchema, D: Identifiable, D::Id: IntoSchema")] + pub struct Revoke { /// Object to revoke. pub object: O, /// Entity which is being revoked this token from. @@ -958,7 +962,7 @@ mod transparent { impl_display! { Revoke where - O: Into + Display, + O: Display, D: Identifiable, D::Id: Display, => @@ -1248,7 +1252,7 @@ pub mod error { //! Module containing errors that can occur during instruction evaluation #[cfg(not(feature = "std"))] - use alloc::{boxed::Box, format, string::String, vec::Vec}; + use alloc::{format, string::String, vec::Vec}; use core::fmt::Debug; use derive_more::Display; @@ -1271,7 +1275,6 @@ pub mod error { use serde::{Deserialize, Serialize}; use super::*; - use crate::{asset::AssetDefinitionId, Value}; /// Instruction execution error type #[derive( @@ -1406,12 +1409,6 @@ pub mod error { pub enum TypeError { /// Asset Ids correspond to assets with different underlying types, {0} AssetValueType(#[cfg_attr(feature = "std", source)] Mismatch), - /// Value passed to the parameter doesn't have the right type, {0} - ParameterValueType(#[cfg_attr(feature = "std", source)] Box>), - /// AssetDefinition Ids don't match, {0} - AssetDefinitionId( - #[cfg_attr(feature = "std", source)] Box>, - ), /// Numeric asset value type was expected, received: {0} NumericAssetValueTypeExpected( #[skip_from] diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index b99870744b2..db04257ad1e 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -15,40 +15,24 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::{ - convert::AsRef, - fmt, - fmt::Debug, - ops::{ControlFlow, RangeInclusive}, - str::FromStr, -}; +use core::{fmt, fmt::Debug, ops::RangeInclusive, str::FromStr}; -use block::SignedBlock; -#[cfg(not(target_arch = "aarch64"))] -use derive_more::Into; -use derive_more::{AsRef, Constructor, DebugCustom, Deref, Display, From, FromStr}; +use derive_more::{Constructor, Display, From, FromStr}; use events::TriggeringFilterBox; use getset::Getters; -pub use integer::model::Integer; -use iroha_crypto::{HashOf, PublicKey}; -use iroha_data_model_derive::{ - model, EnumRef, IdEqOrdHash, PartiallyTaggedDeserialize, PartiallyTaggedSerialize, -}; -use iroha_macro::{error::ErrorTryFromEnum, FromVariant}; -use iroha_primitives::{ - numeric::Numeric, - small::{Array as SmallArray, SmallVec}, -}; +use iroha_crypto::PublicKey; +use iroha_data_model_derive::{model, EnumRef, IdEqOrdHash}; +use iroha_macro::FromVariant; use iroha_schema::IntoSchema; use iroha_version::{declare_versioned_with_scale, version_with_scale}; use parity_scale_codec::{Decode, Encode}; -use prelude::{Executable, SignedTransaction, TransactionQueryOutput}; +use prelude::Executable; use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use strum::FromRepr; pub use self::model::*; -use crate::{account::SignatureCheckCondition, name::Name}; +use crate::name::Name; pub mod account; pub mod asset; @@ -56,15 +40,12 @@ pub mod block; pub mod domain; pub mod events; pub mod executor; -pub mod integer; pub mod ipfs; pub mod isi; pub mod metadata; pub mod name; pub mod peer; pub mod permission; -#[cfg(feature = "http")] -pub mod predicate; pub mod query; pub mod role; pub mod smart_contract; @@ -199,26 +180,6 @@ pub struct ParseError { #[cfg(feature = "std")] impl std::error::Error for ParseError {} -#[allow(clippy::missing_errors_doc)] -/// [`AsMut`] but reference conversion can fail. -pub trait TryAsMut { - /// The type returned in the event of a conversion error. - type Error; - - /// Perform the conversion. - fn try_as_mut(&mut self) -> Result<&mut T, Self::Error>; -} - -#[allow(clippy::missing_errors_doc)] -/// Similar to [`AsRef`] but indicating that this reference conversion can fail. -pub trait TryAsRef { - /// The type returned in the event of a conversion error. - type Error; - - /// Perform the conversion. - fn try_as_ref(&self) -> Result<&T, Self::Error>; -} - /// Error which occurs when converting an enum reference to a variant reference #[derive(Debug, Clone, Copy)] #[repr(transparent)] @@ -241,7 +202,8 @@ impl fmt::Display for EnumTryAsError { } impl EnumTryAsError { - const fn got(got: GOT) -> Self { + #[allow(missing_docs)] + pub const fn got(got: GOT) -> Self { Self { expected: core::marker::PhantomData, got, @@ -257,6 +219,8 @@ pub mod parameter { use core::borrow::Borrow; + use iroha_primitives::numeric::Numeric; + pub use self::model::*; use super::*; use crate::isi::InstructionBox; @@ -283,6 +247,32 @@ pub mod parameter { pub mod model { use super::*; + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + FromVariant, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + #[ffi_type(local)] + pub enum ParameterValueBox { + TransactionLimits(transaction::TransactionLimits), + MetadataLimits(metadata::Limits), + LengthLimits(LengthLimits), + Numeric( + #[skip_from] + #[skip_try_from] + Numeric, + ), + } + /// Identification of a [`Parameter`]. #[derive( Debug, @@ -315,8 +305,8 @@ pub mod parameter { Debug, Display, Clone, + Constructor, IdEqOrdHash, - Getters, Decode, Encode, DeserializeFromStr, @@ -330,20 +320,63 @@ pub mod parameter { /// Unique [`Id`] of the [`Parameter`]. pub id: ParameterId, /// Current value of the [`Parameter`]. - #[getset(get = "pub")] - pub val: Box, + pub val: ParameterValueBox, } } - impl Parameter { - fn new(id: ParameterId, val: Value) -> Self { - Self { - id, - val: Box::new(val), + // TODO: Maybe derive + impl core::fmt::Display for ParameterValueBox { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::MetadataLimits(v) => core::fmt::Display::fmt(&v, f), + Self::TransactionLimits(v) => core::fmt::Display::fmt(&v, f), + Self::LengthLimits(v) => core::fmt::Display::fmt(&v, f), + Self::Numeric(v) => core::fmt::Display::fmt(&v, f), } } } + impl> From for ParameterValueBox { + fn from(value: T) -> Self { + Self::Numeric(value.into()) + } + } + + impl TryFrom for u32 { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: ParameterValueBox) -> Result { + use iroha_macro::error::ErrorTryFromEnum; + + let ParameterValueBox::Numeric(numeric) = value else { + return Err(ErrorTryFromEnum::default()); + }; + + numeric.try_into().map_err(|_| ErrorTryFromEnum::default()) + } + } + + impl TryFrom for u64 { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: ParameterValueBox) -> Result { + use iroha_macro::error::ErrorTryFromEnum; + + let ParameterValueBox::Numeric(numeric) = value else { + return Err(ErrorTryFromEnum::default()); + }; + + numeric.try_into().map_err(|_| ErrorTryFromEnum::default()) + } + } + + impl Parameter { + /// Current value of the [`Parameter`]. + pub fn val(&self) -> &ParameterValueBox { + &self.val + } + } + impl Borrow for ParameterId { fn borrow(&self) -> &str { self.name.borrow() @@ -382,7 +415,7 @@ pub mod parameter { reason: "Failed to parse the `val` part of the `Parameter` as `LengthLimits`. Invalid upper `u32` bound.", })?; - Value::LengthLimits(LengthLimits::new(lower, upper)) + LengthLimits::new(lower, upper).into() } // Shorthand for `TransactionLimits` "TL" => { @@ -398,10 +431,10 @@ pub mod parameter { reason: "Failed to parse the `val` part of the `Parameter` as `TransactionLimits`. `max_wasm_size_bytes` field should be a valid `u64`.", })?; - Value::TransactionLimits(transaction::TransactionLimits::new( + transaction::TransactionLimits::new( max_instr, max_wasm_size, - )) + ).into() } // Shorthand for `MetadataLimits` "ML" => { @@ -417,7 +450,7 @@ pub mod parameter { reason: "Failed to parse the `val` part of the `Parameter` as `MetadataLimits`. Invalid `u32` in `max_entry_len` field.", })?; - Value::MetadataLimits(metadata::Limits::new(lower, upper)) + metadata::Limits::new(lower, upper).into() } _ => return Err(ParseError { reason: @@ -426,10 +459,12 @@ pub mod parameter { }; Ok(Self::new(param_id, val)) } else { - let val = val_candidate.parse::().map_err(|_| ParseError { - reason: "Failed to parse the `val` part of the `Parameter` as `u64`.", + let val = val_candidate.parse::().map_err(|_| ParseError { + reason: + "Failed to parse the `val` part of the `Parameter` as `Numeric`.", })?; - Ok(Self::new(param_id, Value::Integer(Integer::U64(val)))) + + Ok(Self::new(param_id, val.into())) } } else { Err(ParseError { @@ -474,11 +509,11 @@ pub mod parameter { pub fn add_parameter( mut self, parameter_id: &str, - val: impl Into, + val: impl Into, ) -> Result { let parameter = Parameter { id: parameter_id.parse()?, - val: Box::new(val.into()), + val: val.into(), }; self.parameters.push(parameter); Ok(self) @@ -550,19 +585,19 @@ pub mod parameter { Parameter::new( ParameterId::from_str("TransactionLimits") .expect("Failed to parse `ParameterId`"), - Value::TransactionLimits(TransactionLimits::new(42, 24)), + TransactionLimits::new(42, 24).into(), ), Parameter::new( ParameterId::from_str("MetadataLimits").expect("Failed to parse `ParameterId`"), - Value::MetadataLimits(MetadataLimits::new(42, 24)), + MetadataLimits::new(42, 24).into(), ), Parameter::new( ParameterId::from_str("LengthLimits").expect("Failed to parse `ParameterId`"), - Value::LengthLimits(LengthLimits::new(24, 42)), + LengthLimits::new(24, 42).into(), ), Parameter::new( ParameterId::from_str("Int").expect("Failed to parse `ParameterId`"), - Value::Numeric(numeric!(42)), + numeric!(42).into(), ), ]; @@ -648,49 +683,6 @@ pub mod model { ParameterId(parameter::ParameterId), } - /// Sized container for constructors of all [`Identifiable`]s that can be registered via transaction - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - EnumRef, - FromVariant, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[enum_ref(derive(Encode, FromVariant))] - #[ffi_type] - pub enum RegistrableBox { - /// [`Peer`](`peer::Peer`) variant. - #[display(fmt = "Peer {_0}")] - Peer(::With), - /// [`Domain`](`domain::Domain`) variant. - #[display(fmt = "Domain {_0}")] - Domain(::With), - /// [`Account`](`account::Account`) variant. - #[display(fmt = "Account {_0}")] - Account(::With), - /// [`AssetDefinition`](`asset::AssetDefinition`) variant. - #[display(fmt = "AssetDefinition {_0}")] - AssetDefinition(::With), - /// [`Asset`](`asset::Asset`) variant. - #[display(fmt = "Asset {_0}")] - Asset(::With), - /// [`Trigger`](`trigger::Trigger`) variant. - #[display(fmt = "Trigger {_0}")] - Trigger( as Registered>::With), - /// [`Role`](`role::Role`) variant. - #[display(fmt = "Role {_0}")] - Role(::With), - } - /// Sized container for all possible entities. #[derive( Debug, @@ -737,167 +729,6 @@ pub mod model { Parameter(parameter::Parameter), } - /// Sized container for all possible upgradable entities. - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - EnumRef, - FromVariant, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[enum_ref(derive(Encode, FromVariant))] - // SAFETY: `UpgradableBox` has no trap representations in `executor::Executor` - #[ffi_type(unsafe {robust})] - #[serde(untagged)] // Unaffected by #3330, because stores binary data with no `u128` - #[repr(transparent)] - pub enum UpgradableBox { - /// [`Executor`](`executor::Executor`) variant. - #[display(fmt = "Executor")] - Executor(executor::Executor), - } - - /// Sized container for all possible values. - #[derive( - DebugCustom, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - FromVariant, - Decode, - Encode, - PartiallyTaggedDeserialize, - PartiallyTaggedSerialize, - IntoSchema, - )] - #[allow(clippy::enum_variant_names, missing_docs)] - #[ffi_type(opaque)] - pub enum Value { - Bool(bool), - String(String), - Name(Name), - Vec( - #[skip_from] - #[skip_try_from] - Vec, - ), - LimitedMetadata(metadata::Metadata), - MetadataLimits(metadata::Limits), - TransactionLimits(transaction::TransactionLimits), - LengthLimits(LengthLimits), - #[serde_partially_tagged(untagged)] - Id(IdBox), - #[serde_partially_tagged(untagged)] - Identifiable(IdentifiableBox), - PublicKey(PublicKey), - SignatureCheckCondition(SignatureCheckCondition), - TransactionQueryOutput(TransactionQueryOutput), - PermissionToken(permission::PermissionToken), - PermissionTokenSchema(permission::PermissionTokenSchema), - Hash(HashValue), - Block(SignedBlockWrapper), - BlockHeader(block::BlockHeader), - Ipv4Addr(iroha_primitives::addr::Ipv4Addr), - Ipv6Addr(iroha_primitives::addr::Ipv6Addr), - #[serde_partially_tagged(untagged)] - #[debug(fmt = "{_0:?}")] - Numeric(Numeric), - // Workaround to allow integer values in parameter - #[serde_partially_tagged(untagged)] - #[debug(fmt = "{_0:?}")] - Integer(Integer), - Executor(executor::Executor), - LogLevel(Level), - } - - /// Enum for all supported hash types - #[derive( - Debug, - Display, - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[ffi_type] - pub enum HashValue { - /// Transaction hash - Transaction(HashOf), - /// Block hash - Block(HashOf), - } - - /// Cross-platform wrapper for [`SignedBlock`]. - #[cfg(not(target_arch = "aarch64"))] - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - AsRef, - Deref, - From, - Into, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - // SAFETY: SignedBlockWrapper has no trap representations in SignedBlock - #[schema(transparent)] - #[ffi_type(unsafe {robust})] - #[serde(transparent)] - #[repr(transparent)] - pub struct SignedBlockWrapper(SignedBlock); - - /// Cross-platform wrapper for `BlockValue`. - #[cfg(target_arch = "aarch64")] - #[derive( - Debug, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - AsRef, - Deref, - From, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[schema(transparent)] - #[as_ref(forward)] - #[deref(forward)] - #[from(forward)] - // SAFETY: SignedBlockWrapper has no trap representations in Box - #[ffi_type(unsafe {robust})] - #[serde(transparent)] - #[repr(transparent)] - pub struct SignedBlockWrapper(pub(super) Box); - /// Limits of length of the identifiers (e.g. in [`domain::Domain`], [`account::Account`], [`asset::AssetDefinition`]) in number of chars #[derive( Debug, @@ -1063,32 +894,6 @@ macro_rules! impl_encode_as_identifiable_box { } } -macro_rules! impl_encode_as_registrable_box { - ($($ty:ty),+ $(,)?) => { $( - impl $ty { - /// [`Encode`] [`Self`] as [`RegistrableBox`]. - /// - /// Used to avoid an unnecessary clone - pub fn encode_as_registrable_box(&self) -> Vec { - RegistrableBoxRef::from(self).encode() - } - } )+ - } -} - -macro_rules! impl_encode_as_upgradable_box { - ($($ty:ty),+ $(,)?) => { $( - impl $ty { - /// [`Encode`] [`Self`] as [`UpgradableBox`]. - /// - /// Used to avoid an unnecessary clone - pub fn encode_as_upgradable_box(&self) -> Vec { - UpgradableBoxRef::from(self).encode() - } - } )+ - } -} - impl_encode_as_id_box! { peer::PeerId, domain::DomainId, @@ -1116,20 +921,6 @@ impl_encode_as_identifiable_box! { parameter::Parameter, } -impl_encode_as_registrable_box! { - peer::Peer, - domain::NewDomain, - account::NewAccount, - asset::NewAssetDefinition, - asset::Asset, - trigger::Trigger, - role::NewRole, -} - -impl_encode_as_upgradable_box! { - executor::Executor, -} - impl Decode for ChainId { fn decode( input: &mut I, @@ -1190,463 +981,6 @@ impl<'idbox> TryFrom<&'idbox IdentifiableBox> for &'idbox dyn HasMetadata { } } -/// Create a [`Vec`] containing the arguments, which should satisfy `Into` bound. -/// -/// Syntax is the same as in [`vec`](macro@vec) -#[macro_export] -macro_rules! val_vec { - () => { Vec::new() }; - ($elem:expr; $n:expr) => { vec![$crate::Value::from($elem); $n] }; - ($($x:expr),+ $(,)?) => { vec![$($crate::Value::from($x),)+] }; -} - -#[cfg(target_arch = "aarch64")] -impl From for SignedBlock { - fn from(block_value: SignedBlockWrapper) -> Self { - *block_value.0 - } -} - -impl fmt::Display for Value { - // TODO: Maybe derive - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Value::Bool(v) => fmt::Display::fmt(&v, f), - Value::String(v) => fmt::Display::fmt(&v, f), - Value::Name(v) => fmt::Display::fmt(&v, f), - Value::Vec(v) => { - // TODO: Remove so we can derive. - let list_of_display: Vec<_> = v.iter().map(ToString::to_string).collect(); - // this prints with quotation marks, which is fine 90% - // of the time, and helps delineate where a display of - // one value stops and another one begins. - write!(f, "{list_of_display:?}") - } - Value::LimitedMetadata(v) => fmt::Display::fmt(&v, f), - Value::Id(v) => fmt::Display::fmt(&v, f), - Value::Identifiable(v) => fmt::Display::fmt(&v, f), - Value::PublicKey(v) => fmt::Display::fmt(&v, f), - Value::SignatureCheckCondition(v) => fmt::Display::fmt(&v, f), - Value::TransactionQueryOutput(_) => write!(f, "TransactionQueryOutput"), - Value::PermissionToken(v) => fmt::Display::fmt(&v, f), - Value::PermissionTokenSchema(v) => fmt::Display::fmt(&v, f), - Value::Hash(v) => fmt::Display::fmt(&v, f), - Value::Block(v) => fmt::Display::fmt(&**v, f), - Value::BlockHeader(v) => fmt::Display::fmt(&v, f), - Value::Ipv4Addr(v) => fmt::Display::fmt(&v, f), - Value::Ipv6Addr(v) => fmt::Display::fmt(&v, f), - Value::Numeric(v) => fmt::Display::fmt(&v, f), - Value::Integer(v) => fmt::Display::fmt(&v, f), - Value::MetadataLimits(v) => fmt::Display::fmt(&v, f), - Value::TransactionLimits(v) => fmt::Display::fmt(&v, f), - Value::LengthLimits(v) => fmt::Display::fmt(&v, f), - Value::Executor(v) => write!(f, "Executor({} bytes)", v.wasm.as_ref().len()), - Value::LogLevel(v) => fmt::Display::fmt(&v, f), - } - } -} - -#[allow(clippy::len_without_is_empty)] -impl Value { - /// Number of underneath expressions. - pub fn len(&self) -> usize { - use Value::*; - - match self { - Id(_) - | PublicKey(_) - | Bool(_) - | Identifiable(_) - | String(_) - | Name(_) - | TransactionQueryOutput(_) - | PermissionToken(_) - | PermissionTokenSchema(_) - | Hash(_) - | Block(_) - | Ipv4Addr(_) - | Ipv6Addr(_) - | BlockHeader(_) - | MetadataLimits(_) - | TransactionLimits(_) - | LengthLimits(_) - | Numeric(_) - | Integer(_) - | Executor(_) - | LogLevel(_) - | SignatureCheckCondition(_) => 1_usize, - Vec(v) => v.iter().map(Self::len).sum::() + 1_usize, - LimitedMetadata(data) => data.nested_len() + 1_usize, - } - } -} - -impl From for Value { - fn from(block_value: SignedBlock) -> Self { - Value::Block(block_value.into()) - } -} - -impl From> for Value -where - A::Item: Into, -{ - fn from(sv: SmallVec) -> Self { - // This looks inefficient, but `Value` can only hold a - // heap-allocated `Vec` (it's recursive) and the vector - // conversions only do a heap allocation (if that). - let vec: Vec<_> = sv.into_vec(); - vec.into() - } -} - -// TODO: The following macros looks very similar. Try to generalize them under one macro -macro_rules! from_and_try_from_value_idbox { - ( $($variant:ident( $ty:ty ),)+ $(,)? ) => { $( - impl TryFrom for $ty { - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Id(IdBox::$variant(id)) = value { - Ok(id) - } else { - Err(Self::Error::default()) - } - } - } - - impl From<$ty> for Value { - fn from(id: $ty) -> Self { - Value::Id(IdBox::$variant(id)) - } - })+ - }; -} - -macro_rules! from_and_try_from_value_identifiable { - ( $( $variant:ident( $ty:ty ), )+ $(,)? ) => { $( - impl TryFrom for $ty { - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Identifiable(IdentifiableBox::$variant(id)) = value { - Ok(id) - } else { - Err(Self::Error::default()) - } - } - } - - impl From<$ty> for Value { - fn from(id: $ty) -> Self { - Value::Identifiable(IdentifiableBox::$variant(id)) - } - } )+ - }; -} - -macro_rules! from_and_try_from_and_try_as_value_hash { - ( $( $variant:ident($ty:ty)),+ $(,)? ) => { $( - impl TryFrom for $ty { - type Error = ErrorTryFromEnum; - - #[inline] - fn try_from(value: Value) -> Result { - if let Value::Hash(HashValue::$variant(value)) = value { - Ok(value) - } else { - Err(Self::Error::default()) - } - } - } - - impl From<$ty> for Value { - #[inline] - fn from(value: $ty) -> Self { - Value::Hash(HashValue::$variant(value)) - } - } - - impl TryAsMut<$ty> for HashValue { - type Error = crate::EnumTryAsError<$ty, HashValue>; - - #[inline] - fn try_as_mut(&mut self) -> Result<&mut $ty, Self::Error> { - if let HashValue::$variant (value) = self { - Ok(value) - } else { - Err(crate::EnumTryAsError::got(*self)) - } - } - } - - impl TryAsRef<$ty> for HashValue { - type Error = crate::EnumTryAsError<$ty, HashValue>; - - #[inline] - fn try_as_ref(&self) -> Result<& $ty, Self::Error> { - if let HashValue::$variant (value) = self { - Ok(value) - } else { - Err(crate::EnumTryAsError::got(*self)) - } - } - })+ - }; -} - -macro_rules! from_and_try_from_and_try_as_value_integer { - ( $( $variant:ident($ty:ty),)+ $(,)? ) => { $( - impl TryFrom for $ty { - type Error = ErrorTryFromEnum; - - #[inline] - fn try_from(value: Value) -> Result { - if let Value::Integer(Integer::$variant(value)) = value { - Ok(value) - } else { - Err(Self::Error::default()) - } - } - } - - impl From<$ty> for Value { - #[inline] - fn from(value: $ty) -> Self { - Value::Integer(Integer::$variant(value)) - } - } - - impl TryAsMut<$ty> for Integer { - type Error = crate::EnumTryAsError<$ty, Integer>; - - #[inline] - fn try_as_mut(&mut self) -> Result<&mut $ty, Self::Error> { - if let Integer:: $variant (value) = self { - Ok(value) - } else { - Err(crate::EnumTryAsError::got(*self)) - } - } - } - - impl TryAsRef<$ty> for Integer { - type Error = crate::EnumTryAsError<$ty, Integer>; - - #[inline] - fn try_as_ref(&self) -> Result<& $ty, Self::Error> { - if let Integer:: $variant (value) = self { - Ok(value) - } else { - Err(crate::EnumTryAsError::got(*self)) - } - } - })+ - }; -} - -from_and_try_from_value_idbox!( - PeerId(peer::PeerId), - DomainId(domain::DomainId), - AccountId(account::AccountId), - AssetId(asset::AssetId), - AssetDefinitionId(asset::AssetDefinitionId), - TriggerId(trigger::TriggerId), - RoleId(role::RoleId), - ParameterId(parameter::ParameterId), - // TODO: Should we wrap String with new type in order to convert like here? - //from_and_try_from_value_idbox!((DomainName(Name), ErrorValueTryFromDomainName),); -); - -from_and_try_from_value_identifiable!( - NewDomain(domain::NewDomain), - NewAccount(account::NewAccount), - NewAssetDefinition(asset::NewAssetDefinition), - NewRole(role::NewRole), - Peer(peer::Peer), - Domain(domain::Domain), - Account(account::Account), - AssetDefinition(asset::AssetDefinition), - Asset(asset::Asset), - Trigger(trigger::Trigger), - Role(role::Role), - Parameter(parameter::Parameter), -); - -from_and_try_from_and_try_as_value_hash! { - Transaction(HashOf), - Block(HashOf), -} - -from_and_try_from_and_try_as_value_integer! { - U32(u32), - U64(u64), - U128(u128), -} - -impl TryFrom for RegistrableBox { - type Error = ErrorTryFromEnum; - - fn try_from(source: Value) -> Result { - if let Value::Identifiable(identifiable) = source { - identifiable - .try_into() - .map_err(|_err| Self::Error::default()) - } else { - Err(Self::Error::default()) - } - } -} - -impl From for Value { - fn from(source: RegistrableBox) -> Self { - let identifiable = source.into(); - Value::Identifiable(identifiable) - } -} - -impl TryFrom for RegistrableBox { - type Error = ErrorTryFromEnum; - - fn try_from(source: IdentifiableBox) -> Result { - use IdentifiableBox::*; - - match source { - Peer(peer) => Ok(RegistrableBox::Peer(peer)), - NewDomain(domain) => Ok(RegistrableBox::Domain(domain)), - NewAccount(account) => Ok(RegistrableBox::Account(account)), - NewAssetDefinition(asset_definition) => { - Ok(RegistrableBox::AssetDefinition(asset_definition)) - } - NewRole(role) => Ok(RegistrableBox::Role(role)), - Asset(asset) => Ok(RegistrableBox::Asset(asset)), - Trigger(trigger) => Ok(RegistrableBox::Trigger(trigger)), - Domain(_) | Account(_) | AssetDefinition(_) | Role(_) | Parameter(_) => { - Err(Self::Error::default()) - } - } - } -} - -impl From for IdentifiableBox { - fn from(registrable: RegistrableBox) -> Self { - use RegistrableBox::*; - - match registrable { - Peer(peer) => IdentifiableBox::Peer(peer), - Domain(domain) => IdentifiableBox::NewDomain(domain), - Account(account) => IdentifiableBox::NewAccount(account), - AssetDefinition(asset_definition) => { - IdentifiableBox::NewAssetDefinition(asset_definition) - } - Role(role) => IdentifiableBox::NewRole(role), - Asset(asset) => IdentifiableBox::Asset(asset), - Trigger(trigger) => IdentifiableBox::Trigger(trigger), - } - } -} - -impl> From> for Value { - fn from(values: Vec) -> Value { - Value::Vec(values.into_iter().map(Into::into).collect()) - } -} - -impl TryFrom for Vec -where - Value: TryInto, -{ - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Vec(vec) = value { - return vec - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .map_err(|_e| Self::Error::default()); - } - - Err(Self::Error::default()) - } -} - -impl TryFrom for SignedBlock { - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Block(block_value) = value { - return Ok(block_value.into()); - } - - Err(Self::Error::default()) - } -} - -impl TryFrom for SmallVec -where - Value: TryInto, -{ - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - if let Value::Vec(vec) = value { - return vec - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .map_err(|_e| Self::Error::default()); - } - Err(Self::Error::default()) - } -} - -impl TryFrom for UpgradableBox { - type Error = ErrorTryFromEnum; - - fn try_from(value: Value) -> Result { - match value { - Value::Executor(executor) => Ok(Self::Executor(executor)), - _ => Err(Self::Error::default()), - } - } -} - -/// Represent type which can be converted into [`Value`] infallibly. -/// This trait can be used when type inference can't properly inference desired type. -pub trait ToValue { - /// Convert [`Self`] into [`Value`]. - fn to_value(self) -> Value; -} - -/// Represent type which can be converted into `Value` with possibility of failure. -/// This trait can be used when type inference can't properly inference desired type. -pub trait TryToValue { - /// Type which represents conversation error. - type Error; - /// Try convert [`Self`] into [`Value`]. - /// - /// # Errors - /// Fail when it is not possible to convert [`Self`] into `Value` - fn try_to_value(self) -> Result; -} - -impl> ToValue for T { - #[inline] - fn to_value(self) -> Value { - self.into() - } -} - -impl> TryToValue for T { - type Error = T::Error; - - #[inline] - fn try_to_value(self) -> Result { - self.try_into() - } -} - /// Uniquely identifiable entity ([`Domain`], [`Account`], etc.). /// This trait should always be derived with [`IdEqOrdHash`] pub trait Identifiable: Ord + Eq { @@ -1672,7 +1006,7 @@ pub trait Registered: Identifiable { /// `Self`, but if you have a complex structure where most fields /// would be empty, to save space you create a builder for it, and /// set `With` to the builder's type. - type With: Into; + type With; } impl LengthLimits { @@ -1689,244 +1023,6 @@ impl From for RangeInclusive { } } -/// Trait for boolean-like values -/// -/// [`or`](`Self::or`) and [`and`](`Self::and`) must satisfy De Morgan's laws, commutativity and associativity -/// [`Not`](`core::ops::Not`) implementation should satisfy double negation elimintation. -/// -/// Short-circuiting behaviour for `and` and `or` can be controlled by returning -/// `ControlFlow::Break` when subsequent application of the same operation -/// won't change the end result, no matter what operands. -/// -/// When implementing, it's recommended to generate exhaustive tests with -/// [`test_conformity`](`Self::test_conformity`). -pub trait PredicateSymbol -where - Self: Sized + core::ops::Not, -{ - /// Conjunction (e.g. boolean and) - #[must_use] - fn and(self, other: Self) -> ControlFlow; - /// Disjunction (e.g. boolean or) - #[must_use] - fn or(self, other: Self) -> ControlFlow; - - #[doc(hidden)] - #[must_use] - fn unwrapped_and(self, other: Self) -> Self { - match self.and(other) { - ControlFlow::Continue(val) | ControlFlow::Break(val) => val, - } - } - - #[doc(hidden)] - #[must_use] - fn unwrapped_or(self, other: Self) -> Self { - match self.or(other) { - ControlFlow::Continue(val) | ControlFlow::Break(val) => val, - } - } - - /// Given a list of all possible values of a type implementing [`PredicateSymbol`] - /// which are different in predicate context, exhaustively tests for: - /// - commutativity of `and` and `or` - /// - associativity of `and` and `or` - /// - De Mornan duality of `and` and `or` - /// - double negation elimination - /// - /// # Examples - /// - /// ```rust - /// use iroha_data_model::PredicateSymbol; - /// - /// fn test() { - /// PredicateSymbol::test_conformity(vec![true, false]); - /// } - /// ``` - /// - fn test_conformity(values: Vec) - where - Self: PartialEq + Clone, - { - Self::test_conformity_with_eq(values, ::eq); - } - - /// Same as [`test_conformity`](`PredicateSymbol::test_conformity`), but - /// if type implementing [`PredicateSymbol`] carries some internal state - /// that isn't associative, one can provide custom `shallow_eq` function - /// that will be called instead of [`PartialEq::eq`] - /// - /// # Examples - /// - /// - /// ``` - /// use std::ops::ControlFlow; - /// use iroha_data_model::PredicateSymbol; - /// - /// #[derive(Clone, PartialEq)] - /// enum Check { - /// Good, - /// // Encapsulates reason for badness which - /// // doesn't behave associatively - /// // (but if we ignore it, Check as a whole does) - /// Bad(String), - /// } - /// - /// impl core::ops::Not for Check { - /// type Output = Self; - /// fn not(self) -> Self { - /// // ... - /// todo!() - /// } - /// } - /// - /// impl PredicateSymbol for Check { - /// fn and(self, other: Self) -> ControlFlow { - /// // ... - /// todo!() - /// } - /// - /// fn or(self, other: Self) -> ControlFlow { - /// // ... - /// todo!() - /// } - /// } - /// - /// fn shallow_eq(left: &Check, right: &Check) -> bool { - /// match (left, right) { - /// (Check::Good, Check::Good) | (Check::Bad(_), Check::Bad(_)) => true, - /// _ => false - /// } - /// } - /// - /// fn test() { - /// let good = Check::Good; - /// let bad = Check::Bad("example".to_owned()); - /// // Would fail some assertions, since derived PartialEq is "deep" - /// // PredicateSymbol::test_conformity(vec![good, bad]); - /// - /// // Works as expected - /// PredicateSymbol::test_conformity_with_eq(vec![good, bad], shallow_eq); - /// } - /// ``` - fn test_conformity_with_eq(values: Vec, shallow_eq: impl FnMut(&Self, &Self) -> bool) - where - Self: Clone, - { - let mut eq = shallow_eq; - let values = values - .into_iter() - .map(|val| move || val.clone()) - .collect::>(); - - let typ = core::any::type_name::(); - - for a in &values { - assert!( - eq(&a().not().not(), &a()), - "Double negation elimination doesn't hold for {typ}", - ); - } - - for a in &values { - for b in &values { - assert!( - eq( - &PredicateSymbol::unwrapped_and(a(), b()), - &PredicateSymbol::unwrapped_and(b(), a()) - ), - "Commutativity doesn't hold for `PredicateSymbol::and` implementation for {typ}" - ); - - assert!( - eq( - &PredicateSymbol::unwrapped_or(a(), b()), - &PredicateSymbol::unwrapped_or(b(), a()) - ), - "Commutativity doesn't hold for `PredicateSymbol::or` implementation for {typ}" - ); - - assert!( - eq( - &PredicateSymbol::unwrapped_or(!a(), !b()), - &!PredicateSymbol::unwrapped_and(a(), b()) - ), - "De Morgan's law doesn't hold for {typ}", - ); - - assert!( - eq( - &PredicateSymbol::unwrapped_and(!a(), !b()), - &!PredicateSymbol::unwrapped_or(a(), b()) - ), - "De Morgan's law doesn't hold for {typ}", - ); - } - } - - for a in &values { - for b in &values { - for c in &values { - assert!( - eq( - &PredicateSymbol::unwrapped_and( - PredicateSymbol::unwrapped_and(a(), b()), - c() - ), - &PredicateSymbol::unwrapped_and( - a(), - PredicateSymbol::unwrapped_and(b(), c()), - ), - ), - "Associativity doesn't hold for `PredicateSymbol::or` implementation for {typ}", - ); - - assert!( - eq( - &PredicateSymbol::unwrapped_or( - PredicateSymbol::unwrapped_or(a(), b()), - c() - ), - &PredicateSymbol::unwrapped_or( - a(), - PredicateSymbol::unwrapped_or(b(), c()), - ), - ), - "Associativity doesn't hold for `PredicateSymbol::and` implementation for {typ}", - ); - } - } - } - } -} - -impl PredicateSymbol for bool { - fn and(self, other: Self) -> ControlFlow { - if self && other { - ControlFlow::Continue(true) - } else { - ControlFlow::Break(false) - } - } - - fn or(self, other: Self) -> ControlFlow { - if self || other { - ControlFlow::Break(true) - } else { - ControlFlow::Continue(false) - } - } -} - -/// Trait for generic predicates. -pub trait PredicateTrait { - /// Type the predicate evaluates to. - type EvaluatesTo: PredicateSymbol; - - /// The result of applying the predicate to a value. - fn applies(&self, input: T) -> Self::EvaluatesTo; -} - /// Get the current system time as `Duration` since the unix epoch. #[cfg(feature = "std")] pub fn current_time() -> core::time::Duration { @@ -1998,8 +1094,6 @@ pub mod prelude { executor::prelude::*, isi::prelude::*, metadata::prelude::*, name::prelude::*, parameter::prelude::*, peer::prelude::*, permission::prelude::*, query::prelude::*, role::prelude::*, transaction::prelude::*, trigger::prelude::*, ChainId, EnumTryAsError, - HasMetadata, IdBox, Identifiable, IdentifiableBox, Integer, LengthLimits, PredicateTrait, - RegistrableBox, ToValue, TryAsMut, TryAsRef, TryToValue, UpgradableBox, ValidationFail, - Value, + HasMetadata, IdBox, Identifiable, IdentifiableBox, LengthLimits, ValidationFail, }; } diff --git a/data_model/src/metadata.rs b/data_model/src/metadata.rs index 5ddc6c595cd..871f14d9c51 100644 --- a/data_model/src/metadata.rs +++ b/data_model/src/metadata.rs @@ -1,27 +1,92 @@ //! Metadata: key-value pairs that can be attached to accounts, transactions and assets. #[cfg(not(feature = "std"))] -use alloc::{collections::btree_map, format, string::String, vec::Vec}; +use alloc::{ + collections::btree_map, + format, + string::{String, ToString}, + vec::Vec, +}; use core::borrow::Borrow; #[cfg(feature = "std")] use std::collections::btree_map; use derive_more::Display; use iroha_data_model_derive::model; +use iroha_macro::FromVariant; +use iroha_primitives::numeric::Numeric; use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::{Name, Value}; +use crate::Name; + +/// A path slice, composed of [`Name`]s. +pub type Path = [Name]; /// Collection of parameters by their names. -pub type UnlimitedMetadata = btree_map::BTreeMap; +pub type UnlimitedMetadata = btree_map::BTreeMap; #[model] pub mod model { use super::*; + /// Collection of parameters by their names with checked insertion. + #[derive( + Debug, + Display, + Clone, + Default, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + Decode, + Encode, + IntoSchema, + )] + #[ffi_type(opaque)] + #[repr(transparent)] + #[serde(transparent)] + #[display(fmt = "Metadata")] + #[allow(clippy::multiple_inherent_impl)] + pub struct Metadata(pub(super) btree_map::BTreeMap); + + /// Metadata value + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + FromVariant, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + )] + #[ffi_type(opaque)] + #[allow(missing_docs)] + pub enum MetadataValueBox { + Bool(bool), + String(String), + Name(Name), + Bytes(Vec), + Numeric(Numeric), + LimitedMetadata(Metadata), + + Vec( + #[skip_from] + #[skip_try_from] + Vec, + ), + } + /// Limits for [`Metadata`]. #[derive( Debug, @@ -38,8 +103,8 @@ pub mod model { Serialize, IntoSchema, )] - #[display(fmt = "{capacity},{max_entry_len}_ML")] #[ffi_type] + #[display(fmt = "{capacity},{max_entry_len}_ML")] pub struct Limits { /// Maximum number of entries pub capacity: u32, @@ -47,82 +112,61 @@ pub mod model { pub max_entry_len: u32, } - /// Collection of parameters by their names with checked insertion. + /// Metadata related errors. #[derive( Debug, - Display, + displaydoc::Display, Clone, - Default, PartialEq, Eq, PartialOrd, Ord, + Decode, + Encode, Deserialize, Serialize, + IntoSchema, + )] + #[ffi_type(local)] + #[cfg_attr(feature = "std", derive(thiserror::Error))] + pub enum MetadataError { + /// Path specification empty + EmptyPath, + /// Metadata entry is too big + EntryTooBig(#[cfg_attr(feature = "std", source)] SizeError), + /// Metadata exceeds overall length limit + MaxCapacity(#[cfg_attr(feature = "std", source)] SizeError), + /// `{0}`: path segment not found, i.e. nothing was found at that key + MissingSegment(Name), + /// `{0}`: path segment not an instance of metadata + InvalidSegment(Name), + } + + /// Size limits exhaustion error + #[derive( + Debug, + Display, + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, Decode, Encode, + Deserialize, + Serialize, IntoSchema, )] - #[allow(clippy::multiple_inherent_impl)] - #[display(fmt = "Metadata")] - #[ffi_type(opaque)] - #[serde(transparent)] - #[repr(transparent)] - pub struct Metadata(pub(super) btree_map::BTreeMap); -} - -/// Metadata related errors. -#[derive( - Debug, - displaydoc::Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, -)] -#[cfg_attr(feature = "std", derive(thiserror::Error))] -pub enum MetadataError { - /// Path specification empty - EmptyPath, - /// Metadata entry is too big - EntryTooBig(#[cfg_attr(feature = "std", source)] SizeError), - /// Metadata exceeds overall length limit - MaxCapacity(#[cfg_attr(feature = "std", source)] SizeError), - /// `{0}`: path segment not found, i.e. nothing was found at that key - MissingSegment(Name), - /// `{0}`: path segment not an instance of metadata - InvalidSegment(Name), -} - -/// Size limits exhaustion error -#[derive( - Debug, - Display, - Copy, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, -)] -#[display(fmt = "Limits are {limits}, while the actual value is {actual}")] -#[cfg_attr(feature = "std", derive(thiserror::Error))] -pub struct SizeError { - /// The limits that were set for this entry - limits: Limits, - /// The actual *entry* size in bytes - actual: u64, + #[ffi_type] + #[cfg_attr(feature = "std", derive(thiserror::Error))] + #[display(fmt = "Limits are {limits}, while the actual value is {actual}")] + pub struct SizeError { + /// The limits that were set for this entry + pub limits: Limits, + /// The actual *entry* size in bytes + pub actual: u64, + } } impl Limits { @@ -135,8 +179,106 @@ impl Limits { } } -/// A path slice, composed of [`Name`]s. -pub type Path = [Name]; +impl From for MetadataValueBox { + fn from(value: u32) -> Self { + Self::Numeric(value.into()) + } +} + +impl From for MetadataValueBox { + fn from(value: u64) -> Self { + Self::Numeric(value.into()) + } +} + +impl TryFrom for u32 { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: MetadataValueBox) -> Result { + use iroha_macro::error::ErrorTryFromEnum; + + let MetadataValueBox::Numeric(numeric) = value else { + return Err(ErrorTryFromEnum::default()); + }; + + numeric.try_into().map_err(|_| ErrorTryFromEnum::default()) + } +} + +impl TryFrom for u64 { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: MetadataValueBox) -> Result { + use iroha_macro::error::ErrorTryFromEnum; + + let MetadataValueBox::Numeric(numeric) = value else { + return Err(ErrorTryFromEnum::default()); + }; + + numeric.try_into().map_err(|_| ErrorTryFromEnum::default()) + } +} + +impl> From> for MetadataValueBox { + fn from(values: Vec) -> MetadataValueBox { + MetadataValueBox::Vec(values.into_iter().map(Into::into).collect()) + } +} + +impl TryFrom for Vec +where + MetadataValueBox: TryInto, +{ + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: MetadataValueBox) -> Result { + if let MetadataValueBox::Vec(vec) = value { + return vec + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .map_err(|_e| Self::Error::default()); + } + + Err(Self::Error::default()) + } +} + +impl core::fmt::Display for MetadataValueBox { + // TODO: Maybe derive + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + MetadataValueBox::Bool(v) => core::fmt::Display::fmt(&v, f), + MetadataValueBox::String(v) => core::fmt::Display::fmt(&v, f), + MetadataValueBox::Name(v) => core::fmt::Display::fmt(&v, f), + MetadataValueBox::Numeric(v) => core::fmt::Display::fmt(&v, f), + MetadataValueBox::Bytes(v) => write!(f, "{v:?}"), + MetadataValueBox::Vec(v) => { + // TODO: Remove so we can derive. + let list_of_display: Vec<_> = v.iter().map(ToString::to_string).collect(); + // this prints with quotation marks, which is fine 90% + // of the time, and helps delineate where a display of + // one value stops and another one begins. + write!(f, "{list_of_display:?}") + } + MetadataValueBox::LimitedMetadata(v) => core::fmt::Display::fmt(&v, f), + } + } +} + +#[allow(clippy::len_without_is_empty)] +impl MetadataValueBox { + /// Number of underneath expressions. + fn len(&self) -> usize { + use MetadataValueBox::*; + + match self { + Bool(_) | String(_) | Name(_) | Bytes(_) | Numeric(_) => 1, + Vec(v) => v.iter().map(Self::len).sum::() + 1, + LimitedMetadata(data) => data.nested_len() + 1, + } + } +} impl Metadata { /// Constructor. @@ -155,12 +297,12 @@ impl Metadata { /// incorrect (if e.g. any of interior path segments are not /// [`Metadata`] instances return `None`. Else borrow the value /// corresponding to that path. - pub fn nested_get(&self, path: &Path) -> Option<&Value> { + pub fn nested_get(&self, path: &Path) -> Option<&MetadataValueBox> { let key = path.last()?; let mut map = &self.0; for k in path.iter().take(path.len() - 1) { map = match map.get(k)? { - Value::LimitedMetadata(data) => &data.0, + MetadataValueBox::LimitedMetadata(data) => &data.0, _ => return None, }; } @@ -173,13 +315,13 @@ impl Metadata { } /// Iterate over key/value pairs stored in the internal map. - pub fn iter(&self) -> impl ExactSizeIterator { + pub fn iter(&self) -> impl ExactSizeIterator { self.0.iter() } /// Get the `Some(&Value)` associated to `key`. Return `None` if not found. #[inline] - pub fn get(&self, key: &K) -> Option<&Value> + pub fn get(&self, key: &K) -> Option<&MetadataValueBox> where Name: Borrow, { @@ -204,9 +346,9 @@ impl Metadata { pub fn nested_insert_with_limits( &mut self, path: &Path, - value: Value, + value: impl Into, limits: Limits, - ) -> Result, MetadataError> { + ) -> Result, MetadataError> { if self.0.len() >= limits.capacity as usize { return Err(MetadataError::MaxCapacity(SizeError { limits, @@ -221,7 +363,7 @@ impl Metadata { .get_mut(k) .ok_or_else(|| MetadataError::MissingSegment(k.clone()))? { - Value::LimitedMetadata(data) => data, + MetadataValueBox::LimitedMetadata(data) => data, _ => return Err(MetadataError::InvalidSegment(k.clone())), }; } @@ -236,9 +378,11 @@ impl Metadata { pub fn insert_with_limits( &mut self, key: Name, - value: Value, + value: impl Into, limits: Limits, - ) -> Result, MetadataError> { + ) -> Result, MetadataError> { + let value = value.into(); + if self.0.len() >= limits.capacity as usize && !self.0.contains_key(&key) { return Err(MetadataError::MaxCapacity(SizeError { limits, @@ -256,7 +400,7 @@ impl Metadata { /// `Some(value)` at the key if the key was previously in the /// map, else `None`. #[inline] - pub fn remove(&mut self, key: &K) -> Option + pub fn remove(&mut self, key: &K) -> Option where Name: Borrow, { @@ -267,12 +411,12 @@ impl Metadata { /// malformed, or incorrect (if e.g. any of interior path segments /// are not [`Metadata`] instances) return `None`. Else return the /// owned value corresponding to that path. - pub fn nested_remove(&mut self, path: &Path) -> Option { + pub fn nested_remove(&mut self, path: &Path) -> Option { let key = path.last()?; let mut map = &mut self.0; for k in path.iter().take(path.len() - 1) { map = match map.get_mut(k)? { - Value::LimitedMetadata(data) => &mut data.0, + MetadataValueBox::LimitedMetadata(data) => &mut data.0, _ => return None, }; } @@ -280,7 +424,11 @@ impl Metadata { } } -fn check_size_limits(key: &Name, value: Value, limits: Limits) -> Result<(), MetadataError> { +fn check_size_limits( + key: &Name, + value: MetadataValueBox, + limits: Limits, +) -> Result<(), MetadataError> { let entry_bytes: Vec = (key, value).encode(); let byte_size = entry_bytes.len(); if byte_size > limits.max_entry_len as usize { @@ -305,8 +453,6 @@ mod tests { use alloc::{borrow::ToOwned as _, vec}; use core::str::FromStr as _; - use iroha_macro::FromVariant; - use super::*; use crate::ParseError; @@ -323,7 +469,7 @@ mod tests { let empty_path = vec![]; assert!(metadata.nested_get(&empty_path).is_none()); assert!(metadata - .nested_insert_with_limits(&empty_path, "0".to_owned().into(), Limits::new(12, 12)) + .nested_insert_with_limits(&empty_path, "0".to_owned(), Limits::new(12, 12)) .is_err()); #[cfg(feature = "transparent_api")] assert!(metadata.nested_remove(&empty_path).is_none()); @@ -336,12 +482,12 @@ mod tests { let limits = Limits::new(1024, 1024); // TODO: If we allow a `unsafe`, we could create the path. metadata - .insert_with_limits(Name::from_str("0")?, Metadata::new().into(), limits) + .insert_with_limits(Name::from_str("0")?, Metadata::new(), limits) .expect("Valid"); metadata .nested_insert_with_limits( &[Name::from_str("0")?, Name::from_str("1")?], - Metadata::new().into(), + Metadata::new(), limits, ) .expect("Valid"); @@ -351,11 +497,11 @@ mod tests { Name::from_str("2")?, ]; metadata - .nested_insert_with_limits(&path, "Hello World".to_owned().into(), limits) + .nested_insert_with_limits(&path, "Hello World".to_owned(), limits) .expect("Valid"); assert_eq!( *metadata.nested_get(&path).expect("Valid"), - Value::from("Hello World".to_owned()) + MetadataValueBox::from("Hello World".to_owned()) ); assert_eq!(metadata.nested_len(), 6); // Three nested path segments. metadata.nested_remove(&path); @@ -367,10 +513,10 @@ mod tests { fn non_existent_path_segment_fails() -> Result<(), TestError> { let mut metadata = Metadata::new(); let limits = Limits::new(10, 15); - metadata.insert_with_limits(Name::from_str("0")?, Metadata::new().into(), limits)?; + metadata.insert_with_limits(Name::from_str("0")?, Metadata::new(), limits)?; metadata.nested_insert_with_limits( &[Name::from_str("0")?, Name::from_str("1")?], - Metadata::new().into(), + Metadata::new(), limits, )?; let path = vec![ @@ -378,14 +524,14 @@ mod tests { Name::from_str("1")?, Name::from_str("2")?, ]; - metadata.nested_insert_with_limits(&path, "Hello World".to_owned().into(), limits)?; + metadata.nested_insert_with_limits(&path, "Hello World".to_owned(), limits)?; let bad_path = vec![ Name::from_str("0")?, Name::from_str("3")?, Name::from_str("2")?, ]; assert!(metadata - .nested_insert_with_limits(&bad_path, "Hello World".to_owned().into(), limits) + .nested_insert_with_limits(&bad_path, "Hello World".to_owned(), limits) .is_err()); assert!(metadata.nested_get(&bad_path).is_none()); #[cfg(feature = "transparent_api")] @@ -398,11 +544,11 @@ mod tests { let mut metadata = Metadata::new(); let limits = Limits::new(10, 14); // TODO: If we allow a `unsafe`, we could create the path. - metadata.insert_with_limits(Name::from_str("0")?, Metadata::new().into(), limits)?; + metadata.insert_with_limits(Name::from_str("0")?, Metadata::new(), limits)?; metadata .nested_insert_with_limits( &[Name::from_str("0")?, Name::from_str("1")?], - Metadata::new().into(), + Metadata::new(), limits, ) .expect("Valid"); @@ -412,7 +558,7 @@ mod tests { Name::from_str("2")?, ]; let failing_insert = - metadata.nested_insert_with_limits(&path, "Hello World".to_owned().into(), limits); + metadata.nested_insert_with_limits(&path, "Hello World".to_owned(), limits); assert!(failing_insert.is_err()); Ok(()) @@ -423,10 +569,10 @@ mod tests { let mut metadata = Metadata::new(); let limits = Limits::new(10, 5); assert!(metadata - .insert_with_limits(Name::from_str("1")?, "2".to_owned().into(), limits) + .insert_with_limits(Name::from_str("1")?, "2".to_owned(), limits) .is_ok()); assert!(metadata - .insert_with_limits(Name::from_str("1")?, "23456".to_owned().into(), limits) + .insert_with_limits(Name::from_str("1")?, "23456".to_owned(), limits) .is_err()); Ok(()) } @@ -437,16 +583,16 @@ mod tests { let mut metadata = Metadata::new(); let limits = Limits::new(2, 5); assert!(metadata - .insert_with_limits(Name::from_str("1")?, "0".to_owned().into(), limits) + .insert_with_limits(Name::from_str("1")?, "0".to_owned(), limits) .is_ok()); assert!(metadata - .insert_with_limits(Name::from_str("2")?, "0".to_owned().into(), limits) + .insert_with_limits(Name::from_str("2")?, "0".to_owned(), limits) .is_ok()); assert!(metadata - .insert_with_limits(Name::from_str("2")?, "1".to_owned().into(), limits) + .insert_with_limits(Name::from_str("2")?, "1".to_owned(), limits) .is_ok()); assert!(metadata - .insert_with_limits(Name::from_str("3")?, "0".to_owned().into(), limits) + .insert_with_limits(Name::from_str("3")?, "0".to_owned(), limits) .is_err()); Ok(()) } diff --git a/data_model/src/peer.rs b/data_model/src/peer.rs index f5da00a8bb5..695d61823f0 100644 --- a/data_model/src/peer.rs +++ b/data_model/src/peer.rs @@ -16,7 +16,7 @@ use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::{Identifiable, PublicKey, Registered, Value}; +use crate::{Identifiable, PublicKey, Registered}; #[model] pub mod model { @@ -113,15 +113,6 @@ impl Registered for Peer { type With = Self; } -impl FromIterator for Value { - fn from_iter>(iter: T) -> Self { - iter.into_iter() - .map(Into::into) - .collect::>() - .into() - } -} - /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{Peer, PeerId}; diff --git a/data_model/src/permission.rs b/data_model/src/permission.rs index fc2dc765858..a8ccc715d31 100644 --- a/data_model/src/permission.rs +++ b/data_model/src/permission.rs @@ -50,7 +50,7 @@ pub mod model { /// Token identifier pub definition_id: PermissionTokenId, /// JSON encoded token payload - pub payload: StringWithJson, + pub payload: JsonString, } /// Description of tokens defined in the executor @@ -85,7 +85,7 @@ pub mod model { /// String containing serialized valid JSON. /// This string is guaranteed to parse as JSON #[derive(Debug, Clone, Eq, Encode, Decode)] - pub struct StringWithJson(pub(super) String); + pub struct JsonString(pub(super) String); } // TODO: Use getset to derive this @@ -112,7 +112,7 @@ impl PermissionToken { pub fn from_str_unchecked(definition_id: PermissionTokenId, payload: &str) -> Self { Self { definition_id, - payload: StringWithJson(payload.to_owned()), + payload: JsonString(payload.to_owned()), } } @@ -120,7 +120,7 @@ impl PermissionToken { pub fn new(definition_id: PermissionTokenId, payload: &serde_json::Value) -> Self { Self { definition_id, - payload: StringWithJson::new(payload), + payload: JsonString::new(payload), } } @@ -143,20 +143,20 @@ impl core::fmt::Display for PermissionToken { } } -impl StringWithJson { - /// Construct [`StringWithJson`] +impl JsonString { + /// Construct [`JsonString`] pub fn new(payload: &serde_json::Value) -> Self { Self(payload.to_string()) } } -impl PartialEq for StringWithJson { +impl PartialEq for JsonString { fn eq(&self, other: &Self) -> bool { serde_json::from_str::(&self.0).unwrap() == serde_json::from_str::(&other.0).unwrap() } } -impl<'de> serde::de::Deserialize<'de> for StringWithJson { +impl<'de> serde::de::Deserialize<'de> for JsonString { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -166,7 +166,7 @@ impl<'de> serde::de::Deserialize<'de> for StringWithJson { } } -impl serde::ser::Serialize for StringWithJson { +impl serde::ser::Serialize for JsonString { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -176,13 +176,13 @@ impl serde::ser::Serialize for StringWithJson { } } -impl iroha_schema::TypeId for StringWithJson { +impl iroha_schema::TypeId for JsonString { fn id() -> iroha_schema::Ident { - "StringWithJson".to_owned() + "JsonString".to_owned() } } -impl IntoSchema for StringWithJson { +impl IntoSchema for JsonString { fn type_name() -> iroha_schema::Ident { ::id() } @@ -194,13 +194,13 @@ impl IntoSchema for StringWithJson { } } -impl PartialOrd for StringWithJson { +impl PartialOrd for JsonString { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for StringWithJson { +impl Ord for JsonString { fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.0.cmp(&other.0) } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index 8fe52246a37..9f3e402f8fd 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -4,9 +4,8 @@ #[cfg(not(feature = "std"))] use alloc::{ - boxed::Box, format, - string::{String, ToString as _}, + string::{String, ToString}, vec, vec::Vec, }; @@ -16,7 +15,7 @@ pub use cursor::ForwardCursor; use derive_more::{Constructor, Display}; use iroha_crypto::{PublicKey, SignatureOf}; use iroha_data_model_derive::{model, EnumRef}; -use iroha_macro::FromVariant; +use iroha_primitives::{numeric::Numeric, small::SmallVec}; use iroha_schema::IntoSchema; use iroha_version::prelude::*; pub use pagination::Pagination; @@ -31,15 +30,18 @@ use self::{ }; use crate::{ account::{Account, AccountId}, - block::SignedBlock, + block::{BlockHeader, SignedBlock}, events::TriggeringFilterBox, + metadata::MetadataValueBox, seal, transaction::{SignedTransaction, TransactionPayload, TransactionValue}, - Identifiable, Value, + IdBox, Identifiable, IdentifiableBox, }; pub mod cursor; pub mod pagination; +#[cfg(feature = "http")] +pub mod predicate; pub mod sorting; const FETCH_SIZE: &str = "fetch_size"; @@ -103,7 +105,7 @@ pub type QueryId = String; /// Trait for typesafe query output pub trait Query: Into + seal::Sealed { /// Output type of query - type Output: Into + TryFrom; + type Output: Into + TryFrom; /// [`Encode`] [`Self`] as [`QueryBox`]. /// @@ -115,6 +117,7 @@ pub trait Query: Into + seal::Sealed { pub mod model { use getset::Getters; use iroha_crypto::HashOf; + use iroha_macro::FromVariant; use strum::EnumDiscriminants; use super::*; @@ -191,47 +194,64 @@ pub mod model { FindAllParameters(FindAllParameters), } - /// Output of [`FindAllTransactions`] query + /// Sized container for all possible [`Query::Output`]s #[derive( Debug, Clone, - PartialOrd, - Ord, PartialEq, Eq, - Getters, + PartialOrd, + Ord, + FromVariant, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - #[getset(get = "pub")] - #[ffi_type] - pub struct TransactionQueryOutput { - /// The hash of the block to which `tx` belongs to - pub block_hash: HashOf, - /// Transaction - #[getset(skip)] - pub transaction: Box, + #[allow(missing_docs)] + pub enum QueryOutputBox { + Id(IdBox), + Identifiable(IdentifiableBox), + Transaction(TransactionQueryOutput), + PermissionToken(crate::permission::PermissionToken), + PermissionTokenSchema(crate::permission::PermissionTokenSchema), + LimitedMetadata(MetadataValueBox), + Numeric(Numeric), + BlockHeader(BlockHeader), + Block(crate::block::SignedBlock), + + Vec( + #[skip_from] + #[skip_try_from] + Vec, + ), } - /// Type returned from [`Metadata`] queries + /// Output of [`FindAllTransactions`] query #[derive( Debug, Clone, - PartialEq, - Eq, PartialOrd, Ord, + PartialEq, + Eq, + Getters, Decode, Encode, Deserialize, Serialize, IntoSchema, )] + #[getset(get = "pub")] #[ffi_type] - pub struct MetadataValue(pub Value); + pub struct TransactionQueryOutput { + /// The hash of the block to which `tx` belongs to + pub block_hash: HashOf, + /// Transaction + #[getset(skip)] + pub transaction: TransactionValue, + } /// Request type clients (like http clients or wasm) can send to a query endpoint. #[derive(Debug, Clone, Encode, Decode, Serialize, Deserialize)] @@ -260,6 +280,46 @@ pub mod model { } } +impl From for QueryOutputBox { + fn from(value: u32) -> Self { + Self::Numeric(value.into()) + } +} + +impl From for QueryOutputBox { + fn from(value: u64) -> Self { + Self::Numeric(value.into()) + } +} + +impl TryFrom for u32 { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: QueryOutputBox) -> Result { + use iroha_macro::error::ErrorTryFromEnum; + + let QueryOutputBox::Numeric(numeric) = value else { + return Err(ErrorTryFromEnum::default()); + }; + + numeric.try_into().map_err(|_| ErrorTryFromEnum::default()) + } +} + +impl TryFrom for u64 { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: QueryOutputBox) -> Result { + use iroha_macro::error::ErrorTryFromEnum; + + let QueryOutputBox::Numeric(numeric) = value else { + return Err(ErrorTryFromEnum::default()); + }; + + numeric.try_into().map_err(|_| ErrorTryFromEnum::default()) + } +} + macro_rules! impl_query { ($($ty:ty => $output:ty),+ $(,)?) => { $( impl Query for $ty { @@ -281,7 +341,7 @@ impl_query! { FindPermissionTokensByAccountId => Vec, FindAllAccounts => Vec, FindAccountById => crate::account::Account, - FindAccountKeyValueByIdAndKey => MetadataValue, + FindAccountKeyValueByIdAndKey => MetadataValueBox, FindAccountsByName => Vec, FindAccountsByDomainId => Vec, FindAccountsWithAsset => Vec, @@ -294,18 +354,18 @@ impl_query! { FindAssetsByAssetDefinitionId => Vec, FindAssetsByDomainId => Vec, FindAssetsByDomainIdAndAssetDefinitionId => Vec, - FindAssetQuantityById => crate::Numeric, - FindTotalAssetQuantityByAssetDefinitionId => crate::Numeric, - FindAssetKeyValueByIdAndKey => MetadataValue, - FindAssetDefinitionKeyValueByIdAndKey => MetadataValue, + FindAssetQuantityById => Numeric, + FindTotalAssetQuantityByAssetDefinitionId => Numeric, + FindAssetKeyValueByIdAndKey => MetadataValueBox, + FindAssetDefinitionKeyValueByIdAndKey => MetadataValueBox, FindAllDomains => Vec, FindDomainById => crate::domain::Domain, - FindDomainKeyValueByIdAndKey => MetadataValue, + FindDomainKeyValueByIdAndKey => MetadataValueBox, FindAllPeers => Vec, FindAllParameters => Vec, FindAllActiveTriggerIds => Vec, FindTriggerById => crate::trigger::Trigger, - FindTriggerKeyValueByIdAndKey => MetadataValue, + FindTriggerKeyValueByIdAndKey => MetadataValueBox, FindTriggersByDomainId => Vec>, FindAllTransactions => Vec, FindTransactionsByAccountId => Vec, @@ -316,30 +376,140 @@ impl_query! { } impl Query for QueryBox { - type Output = Value; + type Output = QueryOutputBox; fn encode_as_query_box(&self) -> Vec { self.encode() } } -impl From for Value { - #[inline] - fn from(source: MetadataValue) -> Self { - source.0 +impl core::fmt::Display for QueryOutputBox { + // TODO: Maybe derive + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + QueryOutputBox::Id(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::Identifiable(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::Transaction(_) => write!(f, "TransactionQueryOutput"), + QueryOutputBox::PermissionToken(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::PermissionTokenSchema(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::Block(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::BlockHeader(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::Numeric(v) => core::fmt::Display::fmt(&v, f), + QueryOutputBox::LimitedMetadata(v) => core::fmt::Display::fmt(&v, f), + + QueryOutputBox::Vec(v) => { + // TODO: Remove so we can derive. + let list_of_display: Vec<_> = v.iter().map(ToString::to_string).collect(); + // this prints with quotation marks, which is fine 90% + // of the time, and helps delineate where a display of + // one value stops and another one begins. + write!(f, "{list_of_display:?}") + } + } + } +} + +// TODO: The following macros looks very similar. Try to generalize them under one macro +macro_rules! from_and_try_from_value_idbox { + ( $($variant:ident( $ty:ty ),)+ $(,)? ) => { $( + impl TryFrom for $ty { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: QueryOutputBox) -> Result { + if let QueryOutputBox::Id(IdBox::$variant(id)) = value { + Ok(id) + } else { + Err(Self::Error::default()) + } + } + } + + impl From<$ty> for QueryOutputBox { + fn from(id: $ty) -> Self { + QueryOutputBox::Id(IdBox::$variant(id)) + } + })+ + }; +} + +macro_rules! from_and_try_from_value_identifiable { + ( $( $variant:ident( $ty:ty ), )+ $(,)? ) => { $( + impl TryFrom for $ty { + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: QueryOutputBox) -> Result { + if let QueryOutputBox::Identifiable(IdentifiableBox::$variant(id)) = value { + Ok(id) + } else { + Err(Self::Error::default()) + } + } + } + + impl From<$ty> for QueryOutputBox { + fn from(id: $ty) -> Self { + QueryOutputBox::Identifiable(IdentifiableBox::$variant(id)) + } + } )+ + }; +} + +from_and_try_from_value_idbox!( + PeerId(crate::peer::PeerId), + DomainId(crate::domain::DomainId), + AccountId(crate::account::AccountId), + AssetId(crate::asset::AssetId), + AssetDefinitionId(crate::asset::AssetDefinitionId), + TriggerId(crate::trigger::TriggerId), + RoleId(crate::role::RoleId), + ParameterId(crate::parameter::ParameterId), + // TODO: Should we wrap String with new type in order to convert like here? + //from_and_try_from_value_idbox!((DomainName(Name), ErrorValueTryFromDomainName),); +); + +from_and_try_from_value_identifiable!( + NewDomain(crate::domain::NewDomain), + NewAccount(crate::account::NewAccount), + NewAssetDefinition(crate::asset::NewAssetDefinition), + NewRole(crate::role::NewRole), + Peer(crate::peer::Peer), + Domain(crate::domain::Domain), + Account(crate::account::Account), + AssetDefinition(crate::asset::AssetDefinition), + Asset(crate::asset::Asset), + Trigger(crate::trigger::Trigger), + Role(crate::role::Role), + Parameter(crate::parameter::Parameter), +); + +impl> From> for QueryOutputBox { + fn from(values: Vec) -> QueryOutputBox { + QueryOutputBox::Vec(values.into_iter().map(Into::into).collect()) } } -impl From for MetadataValue { - #[inline] - fn from(source: Value) -> Self { - Self(source) +impl TryFrom for Vec +where + QueryOutputBox: TryInto, +{ + type Error = iroha_macro::error::ErrorTryFromEnum; + + fn try_from(value: QueryOutputBox) -> Result { + if let QueryOutputBox::Vec(vec) = value { + return vec + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .map_err(|_e| Self::Error::default()); + } + + Err(Self::Error::default()) } } -impl AsRef for TransactionQueryOutput { - fn as_ref(&self) -> &SignedTransaction { - &self.transaction.value +impl AsRef for TransactionQueryOutput { + fn as_ref(&self) -> &TransactionValue { + &self.transaction } } @@ -467,7 +637,7 @@ pub mod account { use derive_more::Display; use parity_scale_codec::Encode; - use super::{MetadataValue, Query, QueryType}; + use super::{MetadataValueBox, Query, QueryType}; use crate::prelude::*; queries! { @@ -489,7 +659,7 @@ pub mod account { pub id: AccountId, } - /// [`FindAccountKeyValueByIdAndKey`] Iroha Query finds a [`Value`] + /// [`FindAccountKeyValueByIdAndKey`] Iroha Query finds an [`MetadataValue`] /// of the key-value metadata pair in the specified account. #[derive(Display)] #[display(fmt = "Find metadata value with `{key}` key in `{id}` account")] @@ -560,7 +730,7 @@ pub mod asset { use iroha_primitives::numeric::Numeric; use parity_scale_codec::Encode; - use super::{MetadataValue, Query, QueryType}; + use super::{MetadataValueBox, Query, QueryType}; use crate::prelude::*; queries! { @@ -685,7 +855,7 @@ pub mod asset { pub id: AssetDefinitionId, } - /// [`FindAssetKeyValueByIdAndKey`] Iroha Query gets [`AssetId`] and key as input and finds [`Value`] + /// [`FindAssetKeyValueByIdAndKey`] Iroha Query gets [`AssetId`] and key as input and finds [`MetadataValue`] /// of the key-value pair stored in this asset. #[derive(Display)] #[display(fmt = "Find metadata value with `{key}` key in `{id}` asset")] @@ -697,7 +867,7 @@ pub mod asset { pub key: Name, } - /// [`FindAssetDefinitionKeyValueByIdAndKey`] Iroha Query gets [`AssetDefinitionId`] and key as input and finds [`Value`] + /// [`FindAssetDefinitionKeyValueByIdAndKey`] Iroha Query gets [`AssetDefinitionId`] and key as input and finds [`MetadataValue`] /// of the key-value pair stored in this asset definition. #[derive(Display)] #[display(fmt = "Find metadata value with `{key}` key in `{id}` asset definition")] @@ -733,7 +903,7 @@ pub mod domain { use derive_more::Display; use parity_scale_codec::Encode; - use super::{MetadataValue, Query, QueryType}; + use super::{MetadataValueBox, Query, QueryType}; use crate::prelude::*; queries! { @@ -754,7 +924,7 @@ pub mod domain { pub id: DomainId, } - /// [`FindDomainKeyValueByIdAndKey`] Iroha Query finds a [`Value`] of the key-value metadata pair + /// [`FindDomainKeyValueByIdAndKey`] Iroha Query finds a [`MetadataValue`] of the key-value metadata pair /// in the specified domain. #[derive(Display)] #[display(fmt = "Find metadata value with key `{key}` in `{id}` domain")] @@ -813,12 +983,12 @@ pub mod trigger { use derive_more::Display; use parity_scale_codec::Encode; - use super::{MetadataValue, Query, QueryType}; + use super::{MetadataValueBox, Query, QueryType}; use crate::{ domain::prelude::*, prelude::InstructionBox, trigger::{Trigger, TriggerId}, - Executable, Identifiable, Name, Value, + Executable, Identifiable, Name, }; queries! { @@ -933,14 +1103,13 @@ pub mod block { #![allow(clippy::missing_inline_in_public_items)] #[cfg(not(feature = "std"))] - use alloc::{boxed::Box, format, string::String, vec::Vec}; + use alloc::{format, string::String, vec::Vec}; use derive_more::Display; use iroha_crypto::HashOf; use parity_scale_codec::{Decode, Encode}; - use super::{Query, QueryType}; - use crate::block::SignedBlock; + use super::{Query, SignedBlock}; queries! { /// [`FindAllBlocks`] Iroha Query lists all blocks sorted by @@ -981,10 +1150,11 @@ pub mod http { use getset::Getters; use iroha_data_model_derive::model; + use predicate::PredicateBox; pub use self::model::*; use super::*; - use crate::{account::AccountId, predicate::PredicateBox}; + use crate::account::AccountId; declare_versioned_with_scale!(SignedQuery 1..2, Debug, Clone, iroha_macro::FromVariant, IntoSchema); @@ -1173,7 +1343,7 @@ pub mod error { pub use self::model::*; use super::*; - use crate::{block::SignedBlock, executor, permission, prelude::*}; + use crate::{executor, permission, prelude::*}; #[model] pub mod model { @@ -1270,11 +1440,11 @@ pub mod error { /// The prelude re-exports most commonly used traits, structs and macros from this crate. #[allow(ambiguous_glob_reexports)] pub mod prelude { - #[cfg(feature = "http")] - pub use super::http::*; pub use super::{ account::prelude::*, asset::prelude::*, block::prelude::*, domain::prelude::*, peer::prelude::*, permission::prelude::*, role::prelude::*, transaction::*, trigger::prelude::*, FetchSize, QueryBox, QueryId, TransactionQueryOutput, }; + #[cfg(feature = "http")] + pub use super::{http::*, predicate::PredicateTrait}; } diff --git a/data_model/src/predicate.rs b/data_model/src/query/predicate.rs similarity index 65% rename from data_model/src/predicate.rs rename to data_model/src/query/predicate.rs index 9469e1650ff..532243869d4 100644 --- a/data_model/src/predicate.rs +++ b/data_model/src/query/predicate.rs @@ -2,10 +2,254 @@ #[cfg(not(feature = "std"))] use alloc::vec; -use core::{fmt::Display, ops::Not}; +use core::{ + fmt::Display, + ops::{ControlFlow, Not}, +}; + +use iroha_data_model_derive::{PartiallyTaggedDeserialize, PartiallyTaggedSerialize}; use super::*; -use crate::{IdBox, Name, Value}; +use crate::{IdBox, Name}; + +/// Trait for boolean-like values +/// +/// [`or`](`Self::or`) and [`and`](`Self::and`) must satisfy De Morgan's laws, commutativity and associativity +/// [`Not`](`core::ops::Not`) implementation should satisfy double negation elimintation. +/// +/// Short-circuiting behaviour for `and` and `or` can be controlled by returning +/// `ControlFlow::Break` when subsequent application of the same operation +/// won't change the end result, no matter what operands. +/// +/// When implementing, it's recommended to generate exhaustive tests with +/// [`test_conformity`](`Self::test_conformity`). +pub trait PredicateSymbol +where + Self: Sized + core::ops::Not, +{ + /// Conjunction (e.g. boolean and) + #[must_use] + fn and(self, other: Self) -> ControlFlow; + /// Disjunction (e.g. boolean or) + #[must_use] + fn or(self, other: Self) -> ControlFlow; + + #[doc(hidden)] + #[must_use] + fn unwrapped_and(self, other: Self) -> Self { + match self.and(other) { + ControlFlow::Continue(val) | ControlFlow::Break(val) => val, + } + } + + #[doc(hidden)] + #[must_use] + fn unwrapped_or(self, other: Self) -> Self { + match self.or(other) { + ControlFlow::Continue(val) | ControlFlow::Break(val) => val, + } + } + + /// Given a list of all possible values of a type implementing [`PredicateSymbol`] + /// which are different in predicate context, exhaustively tests for: + /// - commutativity of `and` and `or` + /// - associativity of `and` and `or` + /// - De Mornan duality of `and` and `or` + /// - double negation elimination + /// + /// # Examples + /// + /// ``` + /// use iroha_data_model::query::predicate::PredicateSymbol; + /// + /// fn test() { + /// PredicateSymbol::test_conformity(vec![true, false]); + /// } + /// ``` + /// + fn test_conformity(values: Vec) + where + Self: PartialEq + Clone, + { + Self::test_conformity_with_eq(values, ::eq); + } + + /// Same as [`test_conformity`](`PredicateSymbol::test_conformity`), but + /// if type implementing [`PredicateSymbol`] carries some internal state + /// that isn't associative, one can provide custom `shallow_eq` function + /// that will be called instead of [`PartialEq::eq`] + /// + /// # Examples + /// + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// use iroha_data_model::query::predicate::PredicateSymbol; + /// + /// #[derive(Clone, PartialEq)] + /// enum Check { + /// Good, + /// // Encapsulates reason for badness which + /// // doesn't behave associatively + /// // (but if we ignore it, Check as a whole does) + /// Bad(String), + /// } + /// + /// impl core::ops::Not for Check { + /// type Output = Self; + /// fn not(self) -> Self { + /// // ... + /// todo!() + /// } + /// } + /// + /// impl PredicateSymbol for Check { + /// fn and(self, other: Self) -> ControlFlow { + /// // ... + /// todo!() + /// } + /// + /// fn or(self, other: Self) -> ControlFlow { + /// // ... + /// todo!() + /// } + /// } + /// + /// fn shallow_eq(left: &Check, right: &Check) -> bool { + /// match (left, right) { + /// (Check::Good, Check::Good) | (Check::Bad(_), Check::Bad(_)) => true, + /// _ => false + /// } + /// } + /// + /// fn test() { + /// let good = Check::Good; + /// let bad = Check::Bad("example".to_owned()); + /// // Would fail some assertions, since derived PartialEq is "deep" + /// // PredicateSymbol::test_conformity(vec![good, bad]); + /// + /// // Works as expected + /// PredicateSymbol::test_conformity_with_eq(vec![good, bad], shallow_eq); + /// } + /// ``` + fn test_conformity_with_eq(values: Vec, shallow_eq: impl FnMut(&Self, &Self) -> bool) + where + Self: Clone, + { + let mut eq = shallow_eq; + let values = values + .into_iter() + .map(|val| move || val.clone()) + .collect::>(); + + let typ = core::any::type_name::(); + + for a in &values { + assert!( + eq(&a().not().not(), &a()), + "Double negation elimination doesn't hold for {typ}", + ); + } + + for a in &values { + for b in &values { + assert!( + eq( + &PredicateSymbol::unwrapped_and(a(), b()), + &PredicateSymbol::unwrapped_and(b(), a()) + ), + "Commutativity doesn't hold for `PredicateSymbol::and` implementation for {typ}" + ); + + assert!( + eq( + &PredicateSymbol::unwrapped_or(a(), b()), + &PredicateSymbol::unwrapped_or(b(), a()) + ), + "Commutativity doesn't hold for `PredicateSymbol::or` implementation for {typ}" + ); + + assert!( + eq( + &PredicateSymbol::unwrapped_or(!a(), !b()), + &!PredicateSymbol::unwrapped_and(a(), b()) + ), + "De Morgan's law doesn't hold for {typ}", + ); + + assert!( + eq( + &PredicateSymbol::unwrapped_and(!a(), !b()), + &!PredicateSymbol::unwrapped_or(a(), b()) + ), + "De Morgan's law doesn't hold for {typ}", + ); + } + } + + for a in &values { + for b in &values { + for c in &values { + assert!( + eq( + &PredicateSymbol::unwrapped_and( + PredicateSymbol::unwrapped_and(a(), b()), + c() + ), + &PredicateSymbol::unwrapped_and( + a(), + PredicateSymbol::unwrapped_and(b(), c()), + ), + ), + "Associativity doesn't hold for `PredicateSymbol::or` implementation for {typ}", + ); + + assert!( + eq( + &PredicateSymbol::unwrapped_or( + PredicateSymbol::unwrapped_or(a(), b()), + c() + ), + &PredicateSymbol::unwrapped_or( + a(), + PredicateSymbol::unwrapped_or(b(), c()), + ), + ), + "Associativity doesn't hold for `PredicateSymbol::and` implementation for {typ}", + ); + } + } + } + } +} + +impl PredicateSymbol for bool { + fn and(self, other: Self) -> ControlFlow { + if self && other { + ControlFlow::Continue(true) + } else { + ControlFlow::Break(false) + } + } + + fn or(self, other: Self) -> ControlFlow { + if self || other { + ControlFlow::Break(true) + } else { + ControlFlow::Continue(false) + } + } +} + +/// Trait for generic predicates. +pub trait PredicateTrait { + /// Type the predicate evaluates to. + type EvaluatesTo: PredicateSymbol; + + /// The result of applying the predicate to a value. + fn applies(&self, input: T) -> Self::EvaluatesTo; +} mod nontrivial { use super::*; @@ -88,7 +332,7 @@ macro_rules! nontrivial { // couldn't find a way to do it without polluting everything // downstream with explicit lifetimes, since we would need to // store PhantomData here, and `Input`s are most often -// references (e.g. &Value). +// references (e.g. &QueryOutputBox). pub enum GenericPredicateBox

{ /// Logically `&&` the results of applying the predicates. And(NonTrivial), @@ -105,7 +349,7 @@ impl

Display for GenericPredicateBox

where P: Display, { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { GenericPredicateBox::And(predicates) => { write!(f, "AND(")?; @@ -219,19 +463,19 @@ where } } -/// Predicate combinator for predicates operating on `Value` -pub type PredicateBox = GenericPredicateBox; +/// Predicate combinator for predicates operating on `QueryOutputBox` +pub type PredicateBox = GenericPredicateBox; impl Default for PredicateBox { fn default() -> Self { - PredicateBox::Raw(value::ValuePredicate::Pass) + PredicateBox::Raw(value::QueryOutputPredicate::Pass) } } #[cfg(test)] pub mod test { - use super::{value, PredicateBox}; - use crate::{PredicateSymbol, PredicateTrait as _, ToValue}; + use super::{value, PredicateBox, PredicateSymbol, PredicateTrait as _}; + use crate::metadata::MetadataValueBox; #[test] fn boolean_predicate_symbol_conformity() { @@ -240,10 +484,10 @@ pub mod test { #[test] fn pass() { - let t = PredicateBox::new(value::ValuePredicate::Pass); + let t = PredicateBox::new(value::QueryOutputPredicate::Pass); let f = t.clone().negate(); - let v_t = true.to_value(); - let v_f = false.to_value(); + let v_t = MetadataValueBox::from(true).into(); + let v_f = MetadataValueBox::from(false).into(); println!("t: {t:?}, f: {f:?}"); assert!(t.applies(&v_t)); @@ -254,9 +498,9 @@ pub mod test { #[test] fn truth_table() { - let t = PredicateBox::new(value::ValuePredicate::Pass); + let t = PredicateBox::new(value::QueryOutputPredicate::Pass); let f = t.clone().negate(); - let v = true.to_value(); + let v = MetadataValueBox::from(true).into(); assert!(!PredicateBox::and(t.clone(), f.clone()).applies(&v)); assert!(PredicateBox::and(t.clone(), t.clone()).applies(&v)); @@ -372,6 +616,7 @@ pub mod string { mod id_box { use super::*; + use crate::peer::PeerId; #[test] fn simple_name_wrappers() { @@ -496,7 +741,7 @@ pub mod string { #[test] fn peer_id() { let (public_key, _) = iroha_crypto::KeyPair::generate().into(); - let id = IdBox::PeerId(peer::PeerId::new(socket_addr!(127.0.0.1:123), public_key)); + let id = IdBox::PeerId(PeerId::new(socket_addr!(127.0.0.1:123), public_key)); assert!(StringPredicate::contains("123").applies(&id)); } } @@ -563,6 +808,7 @@ pub mod numerical { use iroha_primitives::numeric::Numeric; use super::*; + use crate::query::QueryOutputBox; /// A lower-inclusive range predicate. #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] @@ -747,13 +993,13 @@ pub mod numerical { } } - impl PredicateTrait<&Value> for SemiRange { + impl PredicateTrait<&QueryOutputBox> for SemiRange { type EvaluatesTo = bool; #[inline] - fn applies(&self, input: &Value) -> Self::EvaluatesTo { + fn applies(&self, input: &QueryOutputBox) -> Self::EvaluatesTo { match input { - Value::Numeric(quantity) => match self { + QueryOutputBox::Numeric(quantity) => match self { SemiRange::Numeric(predicate) => predicate.applies(*quantity), }, _ => false, @@ -761,13 +1007,13 @@ pub mod numerical { } } - impl PredicateTrait<&Value> for Range { + impl PredicateTrait<&QueryOutputBox> for Range { type EvaluatesTo = bool; #[inline] - fn applies(&self, input: &Value) -> Self::EvaluatesTo { + fn applies(&self, input: &QueryOutputBox) -> Self::EvaluatesTo { match input { - Value::Numeric(quantity) => match self { + QueryOutputBox::Numeric(quantity) => match self { Range::Numeric(predicate) => predicate.applies(*quantity), }, _ => false, @@ -788,13 +1034,13 @@ pub mod numerical { let pred = SemiRange::Numeric((numeric!(1), numeric!(100)).into()); println!("semi_interval range predicate: {pred:?}"); - assert!(pred.applies(&Value::Numeric(numeric!(1)))); - assert!(!pred.applies(&Value::Numeric(numeric!(0)))); - assert!(pred.applies(&Value::Numeric(numeric!(99)))); - assert!(!pred.applies(&Value::Numeric(numeric!(100)))); - assert!(!pred.applies(&Value::Numeric(numeric!(0.99)))); - assert!(pred.applies(&Value::Numeric(numeric!(99.9999)))); - assert!(pred.applies(&Value::Numeric(numeric!(99.9_999_999_999)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(1)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(0)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(99)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(100)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(0.99)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(99.9999)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(99.9_999_999_999)))); } #[test] @@ -803,20 +1049,20 @@ pub mod numerical { let pred = Range::Numeric((numeric!(1), numeric!(100)).into()); println!("semi_interval range predicate: {pred:?}"); - assert!(pred.applies(&Value::Numeric(numeric!(1)))); - assert!(!pred.applies(&Value::Numeric(numeric!(0)))); - assert!(pred.applies(&Value::Numeric(numeric!(100)))); - assert!(!pred.applies(&Value::Numeric(numeric!(101)))); - assert!(!pred.applies(&Value::Numeric(numeric!(0.99)))); - assert!(pred.applies(&Value::Numeric(numeric!(99.9999)))); - assert!(!pred.applies(&Value::Numeric(numeric!(100.000000001)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(1)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(0)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(100)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(101)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(0.99)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(99.9999)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(100.000000001)))); } { let pred = Range::Numeric((numeric!(127), numeric!(127)).into()); - assert!(pred.applies(&Value::Numeric(numeric!(127)))); - assert!(!pred.applies(&Value::Numeric(numeric!(126)))); - assert!(!pred.applies(&Value::Numeric(numeric!(128)))); + assert!(pred.applies(&QueryOutputBox::Numeric(numeric!(127)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(126)))); + assert!(!pred.applies(&QueryOutputBox::Numeric(numeric!(128)))); } } @@ -824,11 +1070,11 @@ pub mod numerical { fn invalid_types_false() { { let pred = SemiRange::Numeric(SemiInterval::ending(numeric!(100))); - assert!(!pred.applies(&Value::Vec(Vec::new()))); + assert!(!pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { let pred = Range::Numeric(Interval::ending(numeric!(100))); - assert!(!pred.applies(&Value::Vec(Vec::new()))); + assert!(!pred.applies(&QueryOutputBox::Vec(Vec::new()))); } } @@ -837,163 +1083,114 @@ pub mod numerical { { let pred = SemiRange::Numeric(SemiInterval::starting(Numeric::ZERO)); // Technically the maximum itself is never included in the semi range. - assert!(!pred.applies(&Numeric::MAX.to_value())); + assert!(!pred.applies(&Numeric::MAX.into())); } { let pred = SemiRange::Numeric(SemiInterval::ending(numeric!(100))); - assert!(pred.applies(&numeric!(1).to_value())); - assert!(pred.applies(&numeric!(99).to_value())); - assert!(!pred.applies(&numeric!(100).to_value())); + assert!(pred.applies(&numeric!(1).into())); + assert!(pred.applies(&numeric!(99).into())); + assert!(!pred.applies(&numeric!(100).into())); } { let pred = Range::Numeric(Interval::starting(Numeric::ZERO)); // Technically the maximum itself is included in the range. - assert!(pred.applies(&Numeric::MAX.to_value())); + assert!(pred.applies(&Numeric::MAX.into())); } { let pred = Range::Numeric(Interval::ending(numeric!(100))); - assert!(pred.applies(&numeric!(1).to_value())); - assert!(pred.applies(&numeric!(100).to_value())); - assert!(!pred.applies(&numeric!(101).to_value())); + assert!(pred.applies(&numeric!(1).into())); + assert!(pred.applies(&numeric!(100).into())); + assert!(!pred.applies(&numeric!(101).into())); } } } } pub mod value { - //! raw predicates applied to `Value`. + //! raw predicates applied to `QueryOutputBox`. use super::*; + use crate::query::QueryOutputBox; - /// A predicate designed for general processing of `Value`. + /// A predicate designed for general processing of `QueryOutputBox`. #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] - pub enum ValuePredicate { + pub enum QueryOutputPredicate { /// Apply predicate to the [`Identifiable::Id`] and/or [`IdBox`]. Identifiable(string::StringPredicate), /// Apply predicate to the container. Container(Container), - /// Apply predicate to the [`::to_string`](ToString::to_string()) representation. + /// Apply predicate to the [`::to_string`](ToString::to_string()) representation. Display(string::StringPredicate), /// Apply predicate to the numerical value. Numerical(numerical::SemiRange), /// Timestamp (currently for [`SignedBlock`] only). TimeStamp(numerical::SemiInterval), - /// IpAddress enumerable by `u32` - Ipv4Addr(ip_addr::Ipv4Predicate), - /// IpAddress extended to use wide range `u128` enumerable addresses. - Ipv6Addr(ip_addr::Ipv6Predicate), /// Always return true. Pass, } - impl PredicateTrait<&Value> for ValuePredicate { + impl PredicateTrait<&QueryOutputBox> for QueryOutputPredicate { type EvaluatesTo = bool; - fn applies(&self, input: &Value) -> Self::EvaluatesTo { + fn applies(&self, input: &QueryOutputBox) -> Self::EvaluatesTo { // Large jump table. Do not inline. match self { - ValuePredicate::Identifiable(pred) => match input { - Value::String(s) => pred.applies(s), - Value::Name(n) => pred.applies(n), - Value::Id(id_box) => pred.applies(id_box), - Value::Identifiable(identifiable_box) => { + QueryOutputPredicate::Identifiable(pred) => match input { + QueryOutputBox::Id(id_box) => pred.applies(id_box), + QueryOutputBox::Identifiable(identifiable_box) => { pred.applies(&identifiable_box.id_box()) } _ => false, }, - ValuePredicate::Container(Container::Any(pred)) => match input { - Value::Vec(vec) => vec.iter().any(|val| pred.applies(val)), - Value::LimitedMetadata(map) => { - map.iter().map(|(_, val)| val).any(|val| pred.applies(val)) - } + QueryOutputPredicate::Container(Container::Any(pred)) => match input { + QueryOutputBox::Vec(vec) => vec.iter().any(|val| pred.applies(val)), _ => false, }, - ValuePredicate::Container(Container::All(pred)) => match input { - Value::Vec(vec) => vec.iter().all(|val| pred.applies(val)), - Value::LimitedMetadata(map) => { - map.iter().map(|(_, val)| val).all(|val| pred.applies(val)) - } + QueryOutputPredicate::Container(Container::All(pred)) => match input { + QueryOutputBox::Vec(vec) => vec.iter().all(|val| pred.applies(val)), _ => false, }, - ValuePredicate::Container(Container::AtIndex(AtIndex { + QueryOutputPredicate::Container(Container::AtIndex(AtIndex { index: idx, predicate: pred, })) => match input { - Value::Vec(vec) => vec + QueryOutputBox::Vec(vec) => vec .get(*idx as usize) // Safe, since this is only executed server-side and servers are 100% going to be 64-bit. .map_or(false, |val| pred.applies(val)), _ => false, }, - ValuePredicate::Container(Container::ValueOfKey(ValueOfKey { - key, - predicate: pred, - })) => { - match input { - Value::LimitedMetadata(map) => { - map.get(key).map_or(false, |val| pred.applies(val)) - } - _ => false, // TODO: Do we need more? + QueryOutputPredicate::Numerical(pred) => pred.applies(input), + QueryOutputPredicate::Display(pred) => pred.applies(&input.to_string()), + QueryOutputPredicate::TimeStamp(pred) => match input { + QueryOutputBox::Block(block) => { + pred.applies(block.header().timestamp().as_millis()) } - } - ValuePredicate::Container(Container::HasKey(key)) => match input { - Value::LimitedMetadata(map) => map.contains(key), _ => false, }, - ValuePredicate::Numerical(pred) => pred.applies(input), - ValuePredicate::Display(pred) => pred.applies(&input.to_string()), - ValuePredicate::TimeStamp(pred) => match input { - Value::Block(block) => pred.applies(block.header().timestamp().as_millis()), - _ => false, - }, - ValuePredicate::Ipv4Addr(pred) => match input { - Value::Ipv4Addr(addr) => pred.applies(*addr), - _ => false, - }, - ValuePredicate::Ipv6Addr(pred) => match input { - Value::Ipv6Addr(addr) => pred.applies(*addr), - _ => false, - }, - ValuePredicate::Pass => true, + QueryOutputPredicate::Pass => true, } } } - impl ValuePredicate { + impl QueryOutputPredicate { /// Construct [`Predicate::Container`] variant. #[inline] #[must_use] - pub fn any(pred: impl Into) -> Self { + pub fn any(pred: impl Into) -> Self { Self::Container(Container::Any(Box::new(pred.into()))) } /// Construct [`Predicate::Container`] variant. #[inline] #[must_use] - pub fn all(pred: impl Into) -> Self { + pub fn all(pred: impl Into) -> Self { Self::Container(Container::All(Box::new(pred.into()))) } /// Construct [`Predicate::Container`] variant. #[inline] #[must_use] - pub fn has_key(key: Name) -> Self { - Self::Container(Container::HasKey(key)) - } - - /// Construct [`Predicate::Container`] variant. - #[inline] - #[must_use] - pub fn value_of(key: Name, pred: impl Into) -> Self { - Self::Container(Container::ValueOfKey(ValueOfKey { - key, - predicate: Box::new(pred.into()), - })) - } - - /// Construct [`Predicate::Container`] variant. - #[inline] - #[must_use] - pub fn at_index(index: u32, pred: impl Into) -> Self { + pub fn at_index(index: u32, pred: impl Into) -> Self { Self::Container(Container::AtIndex(AtIndex { index, predicate: Box::new(pred.into()), @@ -1005,36 +1202,23 @@ pub mod value { #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub struct AtIndex { index: u32, - predicate: Box, - } - - /// A predicate that targets the particular `key` of a collection. - #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] - pub struct ValueOfKey { - key: Name, - predicate: Box, + predicate: Box, } /// Predicate that targets specific elements or groups; useful for - /// working with containers. Currently only - /// [`Metadata`](crate::metadata::Metadata) and [`Vec`] are - /// supported. + /// working with containers. Currently only [`Vec`] is supported. #[derive(Debug, Clone, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema)] pub enum Container { /// Forward to [`Iterator::any`] - Any(Box), + Any(Box), /// Forward to [`Iterator::all`] - All(Box), + All(Box), /// Apply predicate to the [`Value`] element at the index. AtIndex(AtIndex), - /// Apply the predicate to the [`Value`] keyed by the index. - ValueOfKey(ValueOfKey), - /// Forward to [`Metadata::contains`](crate::metadata::Metadata::contains()). - HasKey(Name), } - impl From for PredicateBox { - fn from(value: ValuePredicate) -> Self { + impl From for PredicateBox { + fn from(value: QueryOutputPredicate) -> Self { PredicateBox::Raw(value) } } @@ -1042,271 +1226,112 @@ pub mod value { #[cfg(test)] mod test { use iroha_crypto::KeyPair; - use iroha_primitives::{ - addr::socket_addr, - numeric::{numeric, Numeric}, - }; - use peer::Peer; - use prelude::Metadata; + use iroha_primitives::{addr::socket_addr, numeric::numeric}; use super::*; - use crate::account::Account; + use crate::{ + account::{Account, AccountId}, + domain::{Domain, DomainId}, + metadata::{Metadata, MetadataValueBox}, + peer::{Peer, PeerId}, + }; #[test] fn typing() { { - let pred = - ValuePredicate::Identifiable(string::StringPredicate::is("alice@wonderland")); + let pred = QueryOutputPredicate::Identifiable(string::StringPredicate::is( + "alice@wonderland", + )); println!("{pred:?}"); - assert!(pred.applies(&Value::String("alice@wonderland".to_owned()))); - assert!(pred.applies(&Value::Id(IdBox::AccountId( + assert!(pred.applies(&QueryOutputBox::Id(IdBox::AccountId( "alice@wonderland".parse().expect("Valid") )))); assert!( - pred.applies(&Value::Identifiable(IdentifiableBox::NewAccount( + pred.applies(&QueryOutputBox::Identifiable(IdentifiableBox::NewAccount( Account::new( "alice@wonderland".parse().expect("Valid"), - KeyPair::generate().into_raw_parts().0, + KeyPair::generate().into_raw_parts().0 ) ))) ); - assert!(!pred.applies(&Value::Name("alice".parse().expect("Valid")))); - assert!(!pred.applies(&Value::Vec(Vec::new()))); + assert!(!pred.applies( + &MetadataValueBox::from("alice".parse::().expect("Valid")).into() + )); + assert!(!pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { - let pred = ValuePredicate::Pass; + let pred = QueryOutputPredicate::Pass; println!("{pred:?}"); - assert!(pred.applies(&Value::String("alice@wonderland".to_owned()))); + assert!(pred.applies(&MetadataValueBox::from("alice@wonderland".to_owned()).into())); } { - let pred = ValuePredicate::TimeStamp(numerical::SemiInterval::starting(0)); + let pred = QueryOutputPredicate::TimeStamp(numerical::SemiInterval::starting(0)); println!("{pred:?}"); - assert!(!pred.applies(&Value::String("alice@wonderland".to_owned()))); + assert!( + !pred.applies(&MetadataValueBox::from("alice@wonderland".to_owned()).into()) + ); } { let key_pair = iroha_crypto::KeyPair::generate(); let (public_key, _) = key_pair.into(); - let pred = ValuePredicate::Display(string::StringPredicate::is("alice@wonderland")); + let pred = + QueryOutputPredicate::Display(string::StringPredicate::is("alice@wonderland")); println!("{pred:?}"); assert!( - !pred.applies(&Value::Identifiable(IdentifiableBox::Peer(Peer { - id: peer::PeerId::new(socket_addr!(127.0.0.1:123), public_key) + !pred.applies(&QueryOutputBox::Identifiable(IdentifiableBox::Peer(Peer { + id: PeerId::new(socket_addr!(127.0.0.1:123), public_key) }))) ); } - let pred = ValuePredicate::Numerical(numerical::SemiRange::Numeric( + let pred = QueryOutputPredicate::Numerical(numerical::SemiRange::Numeric( (numeric!(0), numeric!(42)).into(), )); - assert!(!pred.applies(&Value::String("alice".to_owned()))); - assert!(pred.applies(&numeric!(41).to_value())); + assert!(!pred.applies(&MetadataValueBox::from("alice".to_owned()).into())); + assert!(pred.applies(&numeric!(41).into())); } #[test] fn container_vec() { - let list = Value::Vec(vec![ - Value::String("alice".to_owned()), - Value::Name("alice_at_wonderland".parse().expect("Valid")), - Value::String("aliceee!".to_owned()), + let list = QueryOutputBox::Vec(vec![ + QueryOutputBox::Identifiable( + Domain::new("alice".parse::().unwrap()).into(), + ), + QueryOutputBox::Id("alice@wonderland".parse::().unwrap().into()), + QueryOutputBox::Id("aliceee!".parse::().unwrap().into()), ]); - let meta = Value::LimitedMetadata(Metadata::default()); - let alice = Value::Name("alice".parse().expect("Valid")); - let alice_pred = ValuePredicate::Display(string::StringPredicate::contains("alice")); + let alice_pred = + QueryOutputPredicate::Display(string::StringPredicate::contains("alice")); { - let pred = ValuePredicate::any(alice_pred.clone()); + let pred = QueryOutputPredicate::any(alice_pred.clone()); println!("{pred:?}"); assert!(pred.applies(&list)); - assert!(!pred.applies(&Value::Vec(Vec::new()))); - assert!(!pred.applies(&meta)); - assert!(!pred.applies(&alice)); + assert!(!pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { - let pred = ValuePredicate::all(alice_pred.clone()); + let pred = QueryOutputPredicate::all(alice_pred.clone()); println!("{pred:?}"); assert!(pred.applies(&list)); - assert!(pred.applies(&Value::Vec(Vec::new()))); - assert!(pred.applies(&meta)); // Not bug. Same convention as std lib. - assert!(!pred.applies(&alice)); + assert!(pred.applies(&QueryOutputBox::Vec(Vec::new()))); } { let alice_id_pred = - ValuePredicate::Identifiable(string::StringPredicate::contains("alice")); - let pred = ValuePredicate::all(alice_id_pred); + QueryOutputPredicate::Identifiable(string::StringPredicate::contains("alice")); + let pred = QueryOutputPredicate::all(alice_id_pred); println!("{pred:?}"); assert!(pred.applies(&list)); - assert!(pred.applies(&Value::Vec(Vec::new()))); - assert!(pred.applies(&meta)); // Not bug. Same convention as std lib. - assert!(!pred.applies(&alice)); + assert!(pred.applies(&QueryOutputBox::Vec(Vec::new()))); } - assert!(ValuePredicate::at_index(0, alice_pred.clone()).applies(&list)); + assert!(QueryOutputPredicate::at_index(0, alice_pred.clone()).applies(&list)); - let idx_pred = ValuePredicate::at_index(3, alice_pred); // Should be out of bounds. + let idx_pred = QueryOutputPredicate::at_index(3, alice_pred); // Should be out of bounds. println!("{idx_pred:?}"); assert!(!idx_pred.applies(&list)); - assert!(!idx_pred.applies(&meta)); - assert!(!idx_pred.applies(&alice)); - - let has_key = ValuePredicate::has_key("alice".parse().expect("Valid")); - println!("{has_key:?}"); - assert!(!has_key.applies(&list)); - assert!(!has_key.applies(&meta)); - // TODO: case with non-empty meta - - let value_key = ValuePredicate::value_of("alice".parse().expect("Valid"), has_key); - println!("{value_key:?}"); - assert!(!value_key.applies(&list)); - assert!(!value_key.applies(&meta)); - // TODO: case with non-empty meta - } - } -} - -pub mod ip_addr { - //! Predicates for IP address processing. - use iroha_primitives::addr::{Ipv4Addr, Ipv6Addr}; - - use super::{numerical::Interval as Mask, *}; - - /// A Predicate containing independent octuplet masks to be - /// applied to all elements of an IP version 4 address. - #[derive( - Debug, Clone, Copy, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema, - )] - pub struct Ipv4Predicate([Mask; 4]); - - impl PredicateTrait for Ipv4Predicate { - type EvaluatesTo = bool; - - fn applies(&self, input: Ipv4Addr) -> Self::EvaluatesTo { - self.0 - .iter() - .copied() - .zip(input) - .all(|(myself, other)| myself.applies(other)) - } - } - - impl Ipv4Predicate { - /// Construct a new predicate. - pub fn new( - octet_0: impl Into>, - octet_1: impl Into>, - octet_2: impl Into>, - octet_3: impl Into>, - ) -> Self { - Self([ - octet_0.into(), - octet_1.into(), - octet_2.into(), - octet_3.into(), - ]) - } - } - - /// A Predicate containing independent _hexadecuplets_ (u16 - /// groups) masks to be applied to all elements of an IP version 6 - /// address. - #[derive( - Debug, Clone, Copy, PartialEq, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema, - )] - pub struct Ipv6Predicate([Mask; 8]); - - impl PredicateTrait for Ipv6Predicate { - type EvaluatesTo = bool; - - fn applies(&self, input: Ipv6Addr) -> Self::EvaluatesTo { - self.0 - .iter() - .copied() - .zip(input) - .all(|(myself, other)| myself.applies(other)) - } - } - - // Could do this with a macro, but it doesn't seem to shorten much. - #[allow(clippy::too_many_arguments)] - impl Ipv6Predicate { - /// Construct a new predicate. The 8 arguments must match a - /// mask that filters on all 8 of the _hexadecuplets_ (u16 - /// groups) in a normal IP version 6 address. - pub fn new( - hexadecuplet_0: impl Into>, - hexadecuplet_1: impl Into>, - hexadecuplet_2: impl Into>, - hexadecuplet_3: impl Into>, - hexadecuplet_4: impl Into>, - hexadecuplet_5: impl Into>, - hexadecuplet_6: impl Into>, - hexadecuplet_7: impl Into>, - ) -> Self { - Self([ - hexadecuplet_0.into(), - hexadecuplet_1.into(), - hexadecuplet_2.into(), - hexadecuplet_3.into(), - hexadecuplet_4.into(), - hexadecuplet_5.into(), - hexadecuplet_6.into(), - hexadecuplet_7.into(), - ]) - } - } - - #[cfg(test)] - mod test { - use super::*; - - #[test] - fn ipv4_filter_example() { - { - let pred = Ipv4Predicate::new(127, 0, 0, (0, 10)); - println!("{pred:?}"); - assert!(pred.applies(Ipv4Addr::from([127, 0, 0, 1]))); - assert!(pred.applies(Ipv4Addr::from([127, 0, 0, 3]))); - assert!(pred.applies(Ipv4Addr::from([127, 0, 0, 4]))); - assert!(pred.applies(Ipv4Addr::from([127, 0, 0, 10]))); - assert!(!pred.applies(Ipv4Addr::from([127, 0, 0, 11]))); - assert!(!pred.applies(Ipv4Addr::from([125, 0, 0, 1]))); - assert!(!pred.applies(Ipv4Addr::from([128, 0, 0, 1]))); - assert!(!pred.applies(Ipv4Addr::from([127, 1, 0, 1]))); - assert!(!pred.applies(Ipv4Addr::from([127, 0, 1, 1]))); - } - - { - let pred = Ipv4Predicate::new(Mask::starting(0), 0, 0, (0, 10)); - println!("{pred:?}"); - assert!(pred.applies(Ipv4Addr::from([0, 0, 0, 1]))); - assert!(pred.applies(Ipv4Addr::from([255, 0, 0, 1]))); - assert!(pred.applies(Ipv4Addr::from([127, 0, 0, 4]))); - assert!(pred.applies(Ipv4Addr::from([127, 0, 0, 10]))); - assert!(pred.applies(Ipv4Addr::from([128, 0, 0, 1]))); - assert!(pred.applies(Ipv4Addr::from([128, 0, 0, 1]))); - assert!(!pred.applies(Ipv4Addr::from([127, 0, 0, 11]))); - assert!(pred.applies(Ipv4Addr::from([126, 0, 0, 1]))); - assert!(pred.applies(Ipv4Addr::from([128, 0, 0, 1]))); - assert!(!pred.applies(Ipv4Addr::from([127, 1, 0, 1]))); - assert!(!pred.applies(Ipv4Addr::from([127, 0, 1, 1]))); - } - } - - #[test] - fn ipv6_filter_example() { - let pred = Ipv6Predicate::new(12700, 0, 0, (0, 10), 0, 0, 0, 0); - println!("{pred:?}"); - assert!(pred.applies(Ipv6Addr::from([12700, 0, 0, 1, 0, 0, 0, 0]))); - assert!(pred.applies(Ipv6Addr::from([12700, 0, 0, 3, 0, 0, 0, 0]))); - assert!(pred.applies(Ipv6Addr::from([12700, 0, 0, 4, 0, 0, 0, 0]))); - assert!(pred.applies(Ipv6Addr::from([12700, 0, 0, 10, 0, 0, 0, 0]))); - assert!(!pred.applies(Ipv6Addr::from([12700, 0, 0, 11, 0, 0, 0, 0]))); - assert!(!pred.applies(Ipv6Addr::from([12500, 0, 0, 1, 0, 0, 0, 0]))); - assert!(!pred.applies(Ipv6Addr::from([12800, 0, 0, 1, 0, 0, 0, 0]))); - assert!(!pred.applies(Ipv6Addr::from([12700, 1, 0, 1, 0, 0, 0, 0]))); - assert!(!pred.applies(Ipv6Addr::from([12700, 0, 1, 1, 0, 0, 0, 0]))); } } } diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index 692470af82f..6e729ccd1d7 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -237,18 +237,6 @@ } ] }, - "Array, 8>": { - "Array": { - "type": "Interval", - "len": 8 - } - }, - "Array, 4>": { - "Array": { - "type": "Interval", - "len": 4 - } - }, "Array": { "Array": { "type": "u16", @@ -573,45 +561,24 @@ }, { "name": "predicate", - "type": "ValuePredicate" - } - ] - }, - "BatchedResponse": { - "Enum": [ - { - "tag": "V1", - "discriminant": 1, - "type": "BatchedResponseV1" + "type": "QueryOutputPredicate" } ] }, - "BatchedResponse>": { + "BatchedResponse": { "Enum": [ { "tag": "V1", "discriminant": 1, - "type": "BatchedResponseV1>" + "type": "BatchedResponseV1" } ] }, - "BatchedResponseV1": { + "BatchedResponseV1": { "Struct": [ { "name": "batch", - "type": "Value" - }, - { - "name": "cursor", - "type": "ForwardCursor" - } - ] - }, - "BatchedResponseV1>": { - "Struct": [ - { - "name": "batch", - "type": "Vec" + "type": "QueryOutputBox" }, { "name": "cursor", @@ -656,7 +623,7 @@ }, { "name": "commit_topology", - "type": "UniqueVec" + "type": "Vec" }, { "name": "transactions", @@ -763,27 +730,17 @@ { "tag": "Any", "discriminant": 0, - "type": "ValuePredicate" + "type": "QueryOutputPredicate" }, { "tag": "All", "discriminant": 1, - "type": "ValuePredicate" + "type": "QueryOutputPredicate" }, { "tag": "AtIndex", "discriminant": 2, "type": "AtIndex" - }, - { - "tag": "ValueOfKey", - "discriminant": 3, - "type": "ValueOfKey" - }, - { - "tag": "HasKey", - "discriminant": 4, - "type": "Name" } ] }, @@ -1770,27 +1727,27 @@ } ] }, - "GenericPredicateBox": { + "GenericPredicateBox": { "Enum": [ { "tag": "And", "discriminant": 0, - "type": "NonTrivial>" + "type": "NonTrivial>" }, { "tag": "Or", "discriminant": 1, - "type": "NonTrivial>" + "type": "NonTrivial>" }, { "tag": "Not", "discriminant": 2, - "type": "GenericPredicateBox" + "type": "GenericPredicateBox" }, { "tag": "Raw", "discriminant": 3, - "type": "ValuePredicate" + "type": "QueryOutputPredicate" } ] }, @@ -1853,20 +1810,6 @@ "HashOf>": "Hash", "HashOf": "Hash", "HashOf": "Hash", - "HashValue": { - "Enum": [ - { - "tag": "Transaction", - "discriminant": 0, - "type": "HashOf" - }, - { - "tag": "Block", - "discriminant": 1, - "type": "HashOf" - } - ] - }, "IdBox": { "Enum": [ { @@ -2213,49 +2156,6 @@ } ] }, - "Integer": { - "Enum": [ - { - "tag": "U32", - "discriminant": 0, - "type": "u32" - }, - { - "tag": "U64", - "discriminant": 1, - "type": "u64" - }, - { - "tag": "U128", - "discriminant": 2, - "type": "u128" - } - ] - }, - "Interval": { - "Struct": [ - { - "name": "start", - "type": "u16" - }, - { - "name": "limit", - "type": "u16" - } - ] - }, - "Interval": { - "Struct": [ - { - "name": "start", - "type": "u8" - }, - { - "name": "limit", - "type": "u8" - } - ] - }, "InvalidParameterError": { "Enum": [ { @@ -2271,9 +2171,8 @@ }, "IpfsPath": "String", "Ipv4Addr": "Array", - "Ipv4Predicate": "Array, 4>", "Ipv6Addr": "Array", - "Ipv6Predicate": "Array, 8>", + "JsonString": "String", "LengthLimits": { "Struct": [ { @@ -2370,7 +2269,7 @@ "MerkleTree": { "Vec": "HashOf" }, - "Metadata": "SortedMap", + "Metadata": "SortedMap", "MetadataChanged": { "Struct": [ { @@ -2383,7 +2282,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -2399,7 +2298,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -2415,7 +2314,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -2431,7 +2330,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -2463,6 +2362,45 @@ } ] }, + "MetadataValueBox": { + "Enum": [ + { + "tag": "Bool", + "discriminant": 0, + "type": "bool" + }, + { + "tag": "String", + "discriminant": 1, + "type": "String" + }, + { + "tag": "Name", + "discriminant": 2, + "type": "Name" + }, + { + "tag": "Bytes", + "discriminant": 3, + "type": "Vec" + }, + { + "tag": "Numeric", + "discriminant": 4, + "type": "Numeric" + }, + { + "tag": "LimitedMetadata", + "discriminant": 5, + "type": "Metadata" + }, + { + "tag": "Vec", + "discriminant": 6, + "type": "Vec" + } + ] + }, "Mint": { "Struct": [ { @@ -2558,18 +2496,6 @@ } ] }, - "Mismatch": { - "Struct": [ - { - "name": "expected", - "type": "AssetDefinitionId" - }, - { - "name": "actual", - "type": "AssetDefinitionId" - } - ] - }, "Mismatch": { "Struct": [ { @@ -2582,18 +2508,6 @@ } ] }, - "Mismatch": { - "Struct": [ - { - "name": "expected", - "type": "Value" - }, - { - "name": "actual", - "type": "Value" - } - ] - }, "Name": "String", "NewAccount": { "Struct": [ @@ -2667,7 +2581,7 @@ } ] }, - "NonTrivial>": "Vec>", + "NonTrivial>": "Vec>", "NonZero": "u32", "NonZero": "u64", "NotificationEvent": { @@ -2775,7 +2689,7 @@ }, { "name": "val", - "type": "Value" + "type": "ParameterValueBox" } ] }, @@ -2787,6 +2701,30 @@ } ] }, + "ParameterValueBox": { + "Enum": [ + { + "tag": "TransactionLimits", + "discriminant": 0, + "type": "TransactionLimits" + }, + { + "tag": "MetadataLimits", + "discriminant": 1, + "type": "Limits" + }, + { + "tag": "LengthLimits", + "discriminant": 2, + "type": "LengthLimits" + }, + { + "tag": "Numeric", + "discriminant": 3, + "type": "Numeric" + } + ] + }, "Peer": { "Struct": [ { @@ -2853,7 +2791,7 @@ }, { "name": "payload", - "type": "StringWithJson" + "type": "JsonString" } ] }, @@ -3215,6 +3153,93 @@ } ] }, + "QueryOutputBox": { + "Enum": [ + { + "tag": "Id", + "discriminant": 0, + "type": "IdBox" + }, + { + "tag": "Identifiable", + "discriminant": 1, + "type": "IdentifiableBox" + }, + { + "tag": "Transaction", + "discriminant": 2, + "type": "TransactionQueryOutput" + }, + { + "tag": "PermissionToken", + "discriminant": 3, + "type": "PermissionToken" + }, + { + "tag": "PermissionTokenSchema", + "discriminant": 4, + "type": "PermissionTokenSchema" + }, + { + "tag": "LimitedMetadata", + "discriminant": 5, + "type": "MetadataValueBox" + }, + { + "tag": "Numeric", + "discriminant": 6, + "type": "Numeric" + }, + { + "tag": "BlockHeader", + "discriminant": 7, + "type": "BlockHeader" + }, + { + "tag": "Block", + "discriminant": 8, + "type": "SignedBlock" + }, + { + "tag": "Vec", + "discriminant": 9, + "type": "Vec" + } + ] + }, + "QueryOutputPredicate": { + "Enum": [ + { + "tag": "Identifiable", + "discriminant": 0, + "type": "StringPredicate" + }, + { + "tag": "Container", + "discriminant": 1, + "type": "Container" + }, + { + "tag": "Display", + "discriminant": 2, + "type": "StringPredicate" + }, + { + "tag": "Numerical", + "discriminant": 3, + "type": "SemiRange" + }, + { + "tag": "TimeStamp", + "discriminant": 4, + "type": "SemiInterval" + }, + { + "tag": "Pass", + "discriminant": 5 + } + ] + }, "QueryPayload": { "Struct": [ { @@ -3227,7 +3252,7 @@ }, { "name": "filter", - "type": "GenericPredicateBox" + "type": "GenericPredicateBox" } ] }, @@ -3338,45 +3363,6 @@ } ] }, - "RegistrableBox": { - "Enum": [ - { - "tag": "Peer", - "discriminant": 0, - "type": "Peer" - }, - { - "tag": "Domain", - "discriminant": 1, - "type": "NewDomain" - }, - { - "tag": "Account", - "discriminant": 2, - "type": "NewAccount" - }, - { - "tag": "AssetDefinition", - "discriminant": 3, - "type": "NewAssetDefinition" - }, - { - "tag": "Asset", - "discriminant": 4, - "type": "Asset" - }, - { - "tag": "Trigger", - "discriminant": 5, - "type": "Trigger" - }, - { - "tag": "Role", - "discriminant": 6, - "type": "NewRole" - } - ] - }, "RemoveKeyValue": { "Struct": [ { @@ -3674,7 +3660,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -3690,7 +3676,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -3706,7 +3692,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -3722,7 +3708,7 @@ }, { "name": "value", - "type": "Value" + "type": "MetadataValueBox" } ] }, @@ -3957,10 +3943,10 @@ "value": "Asset" } }, - "SortedMap": { + "SortedMap": { "Map": { "key": "Name", - "value": "Value" + "value": "MetadataValueBox" } }, "SortedVec": { @@ -4000,7 +3986,6 @@ } ] }, - "StringWithJson": "String", "TimeEvent": { "Struct": [ { @@ -4074,7 +4059,7 @@ }, { "name": "metadata", - "type": "SortedMap" + "type": "SortedMap" } ] }, @@ -4390,29 +4375,18 @@ "discriminant": 0, "type": "Mismatch" }, - { - "tag": "ParameterValueType", - "discriminant": 1, - "type": "Mismatch" - }, - { - "tag": "AssetDefinitionId", - "discriminant": 2, - "type": "Mismatch" - }, { "tag": "NumericAssetValueTypeExpected", - "discriminant": 3, + "discriminant": 1, "type": "AssetValueType" }, { "tag": "StoreAssetValueTypeExpected", - "discriminant": 4, + "discriminant": 2, "type": "AssetValueType" } ] }, - "UniqueVec": "Vec", "Unregister": { "Struct": [ { @@ -4508,15 +4482,6 @@ } ] }, - "UpgradableBox": { - "Enum": [ - { - "tag": "Executor", - "discriminant": 0, - "type": "Executor" - } - ] - }, "Upgrade": { "Struct": [ { @@ -4552,194 +4517,18 @@ } ] }, - "Value": { - "Enum": [ - { - "tag": "Bool", - "discriminant": 0, - "type": "bool" - }, - { - "tag": "String", - "discriminant": 1, - "type": "String" - }, - { - "tag": "Name", - "discriminant": 2, - "type": "Name" - }, - { - "tag": "Vec", - "discriminant": 3, - "type": "Vec" - }, - { - "tag": "LimitedMetadata", - "discriminant": 4, - "type": "Metadata" - }, - { - "tag": "MetadataLimits", - "discriminant": 5, - "type": "Limits" - }, - { - "tag": "TransactionLimits", - "discriminant": 6, - "type": "TransactionLimits" - }, - { - "tag": "LengthLimits", - "discriminant": 7, - "type": "LengthLimits" - }, - { - "tag": "Id", - "discriminant": 8, - "type": "IdBox" - }, - { - "tag": "Identifiable", - "discriminant": 9, - "type": "IdentifiableBox" - }, - { - "tag": "PublicKey", - "discriminant": 10, - "type": "PublicKey" - }, - { - "tag": "SignatureCheckCondition", - "discriminant": 11, - "type": "SignatureCheckCondition" - }, - { - "tag": "TransactionQueryOutput", - "discriminant": 12, - "type": "TransactionQueryOutput" - }, - { - "tag": "PermissionToken", - "discriminant": 13, - "type": "PermissionToken" - }, - { - "tag": "PermissionTokenSchema", - "discriminant": 14, - "type": "PermissionTokenSchema" - }, - { - "tag": "Hash", - "discriminant": 15, - "type": "HashValue" - }, - { - "tag": "Block", - "discriminant": 16, - "type": "SignedBlock" - }, - { - "tag": "BlockHeader", - "discriminant": 17, - "type": "BlockHeader" - }, - { - "tag": "Ipv4Addr", - "discriminant": 18, - "type": "Ipv4Addr" - }, - { - "tag": "Ipv6Addr", - "discriminant": 19, - "type": "Ipv6Addr" - }, - { - "tag": "Numeric", - "discriminant": 20, - "type": "Numeric" - }, - { - "tag": "Integer", - "discriminant": 21, - "type": "Integer" - }, - { - "tag": "Executor", - "discriminant": 22, - "type": "Executor" - }, - { - "tag": "LogLevel", - "discriminant": 23, - "type": "Level" - } - ] - }, - "ValueOfKey": { - "Struct": [ - { - "name": "key", - "type": "Name" - }, - { - "name": "predicate", - "type": "ValuePredicate" - } - ] - }, - "ValuePredicate": { - "Enum": [ - { - "tag": "Identifiable", - "discriminant": 0, - "type": "StringPredicate" - }, - { - "tag": "Container", - "discriminant": 1, - "type": "Container" - }, - { - "tag": "Display", - "discriminant": 2, - "type": "StringPredicate" - }, - { - "tag": "Numerical", - "discriminant": 3, - "type": "SemiRange" - }, - { - "tag": "TimeStamp", - "discriminant": 4, - "type": "SemiInterval" - }, - { - "tag": "Ipv4Addr", - "discriminant": 5, - "type": "Ipv4Predicate" - }, - { - "tag": "Ipv6Addr", - "discriminant": 6, - "type": "Ipv6Predicate" - }, - { - "tag": "Pass", - "discriminant": 7 - } - ] - }, "Vec": { "Vec": "Event" }, - "Vec>": { - "Vec": "GenericPredicateBox" + "Vec>": { + "Vec": "GenericPredicateBox" }, "Vec": { "Vec": "InstructionBox" }, + "Vec": { + "Vec": "MetadataValueBox" + }, "Vec": { "Vec": "Name" }, @@ -4749,15 +4538,12 @@ "Vec": { "Vec": "PublicKey" }, - "Vec": { - "Vec": "SignedTransaction" + "Vec": { + "Vec": "QueryOutputBox" }, "Vec": { "Vec": "TransactionValue" }, - "Vec": { - "Vec": "Value" - }, "Vec>": { "Vec": "Vec" }, diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index afa9ad2242e..e6c9dcaffc1 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -29,6 +29,7 @@ pub static GENESIS_ACCOUNT_ID: Lazy = /// Genesis transaction #[derive(Debug, Clone)] +#[repr(transparent)] pub struct GenesisTransaction(pub SignedTransaction); /// [`GenesisNetwork`] contains initial transactions and genesis setup related parameters. diff --git a/primitives/numeric/src/lib.rs b/primitives/numeric/src/lib.rs index f21c0421c3e..ab4fb96bee0 100644 --- a/primitives/numeric/src/lib.rs +++ b/primitives/numeric/src/lib.rs @@ -9,6 +9,7 @@ extern crate alloc; use alloc::{format, string::String, string::ToString, vec, vec::Vec}; use core::str::FromStr; +use derive_more::Display; use parity_scale_codec::{Decode, Encode}; use rust_decimal::{prelude::ToPrimitive, Decimal}; use serde::{Deserialize, Serialize}; @@ -23,7 +24,7 @@ use serde_with::{DeserializeFromStr, SerializeDisplay}; /// If more rich functionality is required (e.g. in smartcontract) /// it's suggested to convert this type into proper decimal type (like `rust_decimal`, `bigdecimal`, `u128`, ...), /// perform necessary operations, and then convert back into `Numeric` when sending isi to iroha. -#[derive(Clone, Copy, Debug, derive_more::Display, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct Numeric { inner: Decimal, @@ -61,7 +62,7 @@ pub struct NumericSpec { } /// Error occurred during creation of [`Numeric`] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, displaydoc::Display)] +#[derive(Debug, Clone, Copy, displaydoc::Display)] #[cfg_attr(feature = "std", derive(thiserror::Error))] pub enum NumericError { /// Mantissa exceeds allowed range @@ -74,6 +75,11 @@ pub enum NumericError { Malformed, } +/// The error type returned when a numeric conversion fails. +#[derive(Debug, Clone, Copy, displaydoc::Display)] +#[cfg_attr(feature = "std", derive(thiserror::Error))] +pub struct TryFromNumericError; + /// Error occurred while checking if number satisfy given spec #[derive(Clone, Copy, Debug, displaydoc::Display)] #[cfg_attr(feature = "std", derive(thiserror::Error))] @@ -189,15 +195,15 @@ impl Numeric { .and_then(|inner| inner.is_sign_positive().then_some(Self { inner })) } - /// Check if number is zero - pub const fn is_zero(&self) -> bool { - self.inner.is_zero() - } - /// Convert [`Numeric`] to [`f64`] with possible loss in precision pub fn to_f64(self) -> f64 { self.inner.to_f64().expect("never fails") } + + /// Check if number is zero + pub const fn is_zero(&self) -> bool { + self.inner.is_zero() + } } impl From for Numeric { @@ -212,6 +218,22 @@ impl From for Numeric { } } +impl TryFrom for u32 { + type Error = TryFromNumericError; + + fn try_from(value: Numeric) -> Result { + value.inner.try_into().map_err(|_| TryFromNumericError) + } +} + +impl TryFrom for u64 { + type Error = TryFromNumericError; + + fn try_from(value: Numeric) -> Result { + value.inner.try_into().map_err(|_| TryFromNumericError) + } +} + impl NumericSpec { /// Check if given numeric satisfy constrains /// diff --git a/primitives/src/unique_vec.rs b/primitives/src/unique_vec.rs index 728d920370e..2fa03d69ce0 100644 --- a/primitives/src/unique_vec.rs +++ b/primitives/src/unique_vec.rs @@ -44,6 +44,9 @@ macro_rules! unique_vec { Decode, IntoSchema, )] +#[repr(transparent)] +#[serde(transparent)] +#[schema(transparent)] pub struct UniqueVec(Vec); impl UniqueVec { diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index e37b4768151..f049e614482 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -4,7 +4,7 @@ use iroha_crypto::MerkleTree; use iroha_data_model::{ block::stream::{BlockMessage, BlockSubscriptionRequest}, - query::error::QueryExecutionFail, + query::QueryOutputBox, BatchedResponse, }; use iroha_genesis::RawGenesisBlock; @@ -17,9 +17,6 @@ macro_rules! types { macro_rules! map_all_schema_types { ($callback:ident) => {{ $( $callback!($t); )+ - - #[cfg(target_arch = "aarch64")] - $callback!(Box); }} } } @@ -41,22 +38,26 @@ pub fn build_schemas() -> MetaMap { } schemas! { - QueryExecutionFail, - BlockMessage, - BlockSubscriptionRequest, + // Transaction + SignedTransaction, + + // Query + response + SignedQuery, + BatchedResponse, + + // Event stream EventMessage, EventSubscriptionRequest, - BatchedResponse, - BatchedResponse>, - SignedQuery, - // Never referenced, but present in type signature. Like `PhantomData` - MerkleTree, - RegistrableBox, - UpgradableBox, + // Block stream + BlockMessage, + BlockSubscriptionRequest, // SDK devs want to know how to read serialized genesis block RawGenesisBlock, + + // Never referenced, but present in type signature. Like `PhantomData` + MerkleTree, } } @@ -92,23 +93,29 @@ types!( BTreeMap, BTreeMap, BTreeMap, - BTreeMap, + BTreeMap, BTreeSet, BTreeSet, - BatchedResponse, - BatchedResponse>, - BatchedResponseV1, - BatchedResponseV1>, + BTreeSet>, + BTreeSet>, + BatchedResponse, + BatchedResponseV1, BlockHeader, BlockMessage, + BlockPayload, BlockRejectionReason, BlockSubscriptionRequest, - Box>, - Box, - Box, + Box>, + Box, + Burn>, + Burn, + Burn, BurnBox, + ChainId, ConfigurationEvent, ConstString, + ConstVec, + ConstVec, Container, DataEntityFilter, DataEvent, @@ -118,6 +125,7 @@ types!( DomainEventFilter, DomainFilter, DomainId, + DomainOwnerChanged, Duration, Event, EventMessage, @@ -194,6 +202,8 @@ types!( FindTriggerKeyValueByIdAndKey, FindTriggersByDomainId, ForwardCursor, + Grant, + Grant, GrantBox, Hash, HashOf>, @@ -202,24 +212,35 @@ types!( IdBox, IdentifiableBox, InstructionBox, + InstructionEvaluationError, + InstructionExecutionError, InstructionExecutionFail, - Interval, - Interval, + InstructionType, + InvalidParameterError, IpfsPath, Ipv4Addr, - Ipv4Predicate, Ipv6Addr, - Ipv6Predicate, LengthLimits, + Level, + Log, + MathError, MerkleTree, Metadata, MetadataChanged, MetadataChanged, MetadataChanged, MetadataChanged, + MetadataError, MetadataLimits, + MetadataValueBox, + Mint>, + Mint, + Mint, + Mint, MintBox, + MintabilityError, Mintable, + Mismatch, Name, NewAccount, NewAssetDefinition, @@ -227,20 +248,26 @@ types!( NewParameter, NewRole, NonTrivial, + NonZeroU32, NonZeroU64, + NotificationEvent, NotificationEventFilter, - Integer, Numeric, + NumericSpec, + Option, Option, Option, Option, Option>>, Option>, Option, + Option, + Option, Option, Option, Option, Option, + Option, Option, Option, OriginFilter, @@ -252,6 +279,7 @@ types!( OriginFilter, Parameter, ParameterId, + ParameterValueBox, Peer, PeerEvent, PeerEventFilter, @@ -271,11 +299,26 @@ types!( PublicKey, QueryBox, QueryExecutionFail, + QueryOutputBox, + QueryOutputPredicate, QueryPayload, + Register, + Register, + Register, + Register, + Register, + Register, + Register>, RegisterBox, - RegistrableBox, + RemoveKeyValue, + RemoveKeyValue, + RemoveKeyValue, + RemoveKeyValue, RemoveKeyValueBox, Repeats, + RepetitionError, + Revoke, + Revoke, RevokeBox, Role, RoleEvent, @@ -285,23 +328,35 @@ types!( SemiInterval, SemiInterval, SemiRange, + SetKeyValue, + SetKeyValue, + SetKeyValue, + SetKeyValue, SetKeyValueBox, SetParameter, Signature, SignatureCheckCondition, + SignatureOf, SignatureOf, SignatureOf, + SignatureWrapperOf, SignatureWrapperOf, + SignaturesOf, SignaturesOf, SignedBlock, SignedBlockV1, - SignedBlockWrapper, SignedQuery, SignedQueryV1, SignedTransaction, SignedTransactionV1, + SizeError, + SocketAddr, + SocketAddrHost, + SocketAddrV4, + SocketAddrV6, String, StringPredicate, + JsonString, TimeEvent, TimeEventFilter, TimeInterval, @@ -312,9 +367,15 @@ types!( TransactionQueryOutput, TransactionRejectionReason, TransactionValue, + Transfer, + Transfer, + Transfer, + Transfer, TransferBox, Trigger, + TriggerCompletedEvent, TriggerCompletedEventFilter, + TriggerCompletedOutcome, TriggerCompletedOutcomeType, TriggerEvent, TriggerEventFilter, @@ -322,23 +383,29 @@ types!( TriggerId, TriggerNumberOfExecutionsChanged, TriggeringFilterBox, + TypeError, + UniqueVec, + Unregister, + Unregister, + Unregister, + Unregister, + Unregister, + Unregister, + Unregister>, UnregisterBox, - UpgradableBox, + Upgrade, ValidationFail, - Value, - ValueOfKey, - ValuePredicate, Vec, Vec, + Vec, + Vec, Vec, Vec, - Vec, - Vec, + Vec, + Vec, Vec, WasmExecutionFail, WasmSmartContract, - [Interval; 8], - [Interval; 4], [u16; 8], [u8; 32], [u8; 4], @@ -352,7 +419,7 @@ types!( #[cfg(test)] mod tests { - use core::num::NonZeroU64; + use core::num::{NonZeroU32, NonZeroU64}; use std::{ collections::{BTreeMap, BTreeSet, HashMap, HashSet}, time::Duration, @@ -365,31 +432,42 @@ mod tests { block::{ error::BlockRejectionReason, stream::{BlockMessage, BlockSubscriptionRequest}, - BlockHeader, SignedBlock, SignedBlockV1, + BlockHeader, BlockPayload, SignedBlock, SignedBlockV1, }, domain::NewDomain, executor::Executor, ipfs::IpfsPath, - predicate::{ - ip_addr::{Ipv4Predicate, Ipv6Predicate}, - numerical::{Interval, SemiInterval, SemiRange}, - string::StringPredicate, - value::{AtIndex, Container, ValueOfKey, ValuePredicate}, - GenericPredicateBox, NonTrivial, PredicateBox, + isi::{ + error::{ + InstructionEvaluationError, InstructionExecutionError, InvalidParameterError, + MathError, MintabilityError, Mismatch, RepetitionError, TypeError, + }, + InstructionType, }, + metadata::{MetadataError, MetadataValueBox, SizeError}, + parameter::ParameterValueBox, + permission::JsonString, prelude::*, query::{ error::{FindError, QueryExecutionFail}, - ForwardCursor, + predicate::{ + numerical::{SemiInterval, SemiRange}, + string::StringPredicate, + value::{AtIndex, Container, QueryOutputPredicate}, + GenericPredicateBox, NonTrivial, PredicateBox, + }, + ForwardCursor, QueryOutputBox, }, transaction::{error::TransactionLimitError, SignedTransactionV1, TransactionLimits}, - BatchedResponse, BatchedResponseV1, SignedBlockWrapper, + BatchedResponse, BatchedResponseV1, Level, }; - use iroha_genesis::RawGenesisBlock; use iroha_primitives::{ - addr::{Ipv4Addr, Ipv6Addr}, + addr::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrHost, SocketAddrV4, SocketAddrV6}, + const_vec::ConstVec, conststr::ConstString, + unique_vec::UniqueVec, }; + use iroha_schema::Compact; use super::IntoSchema; @@ -412,7 +490,19 @@ mod tests { } }}; } + map_all_schema_types!(insert_into_test_map); + + insert_into_test_map!(Compact); + insert_into_test_map!(Compact); + + // NOTE: Coming from genesis + insert_into_test_map!(Vec); + insert_into_test_map!(iroha_genesis::GenesisTransactionBuilder); + insert_into_test_map!(iroha_genesis::RawGenesisBlock); + insert_into_test_map!(iroha_genesis::ExecutorMode); + insert_into_test_map!(iroha_genesis::ExecutorPath); + map } @@ -447,10 +537,8 @@ mod tests { #[test] fn no_extra_or_missing_schemas() { - let exceptions: HashSet<_> = RawGenesisBlock::schema() - .into_iter() - .map(|(type_id, _)| type_id) - .collect(); + // NOTE: Skipping Box until [this PR](https://github.com/paritytech/parity-scale-codec/pull/565) is merged + let exceptions: [core::any::TypeId; 1] = [core::any::TypeId::of::>()]; let schemas_types = super::build_schemas() .into_iter() diff --git a/smart_contract/executor/src/default.rs b/smart_contract/executor/src/default.rs index e5680e6f87e..41a4ab12b46 100644 --- a/smart_contract/executor/src/default.rs +++ b/smart_contract/executor/src/default.rs @@ -918,7 +918,9 @@ pub mod asset_definition { } pub mod asset { - use iroha_smart_contract::data_model::{isi::Instruction, metadata::Metadata}; + use iroha_smart_contract::data_model::{ + asset::AssetValue, isi::Instruction, metadata::Metadata, + }; use iroha_smart_contract_utils::Encode; use permission::{asset::is_asset_owner, asset_definition::is_asset_definition_owner}; @@ -993,7 +995,7 @@ pub mod asset { fn validate_mint_asset(executor: &mut V, authority: &AccountId, isi: &Mint) where V: Validate + ?Sized, - Q: Into, + Q: Into, Mint: Instruction + Encode, { let asset_id = isi.destination_id(); @@ -1035,7 +1037,7 @@ pub mod asset { fn validate_burn_asset(executor: &mut V, authority: &AccountId, isi: &Burn) where V: Validate + ?Sized, - Q: Into, + Q: Into, Burn: Instruction + Encode, { let asset_id = isi.destination_id(); @@ -1082,7 +1084,7 @@ pub mod asset { isi: &Transfer, ) where V: Validate + ?Sized, - Q: Into, + Q: Into, Transfer: Instruction + Encode, { let asset_id = isi.source_id(); diff --git a/smart_contract/src/lib.rs b/smart_contract/src/lib.rs index a3d6d281fea..b6663381a2b 100644 --- a/smart_contract/src/lib.rs +++ b/smart_contract/src/lib.rs @@ -11,12 +11,11 @@ use data_model::smart_contract::payloads; use data_model::{ isi::Instruction, prelude::*, - query::{cursor::ForwardCursor, sorting::Sorting, Pagination, Query}, + query::{cursor::ForwardCursor, sorting::Sorting, Pagination, Query, QueryOutputBox}, BatchedResponse, }; use derive_more::Display; pub use iroha_data_model as data_model; -use iroha_macro::error::ErrorTryFromEnum; pub use iroha_smart_contract_derive::main; pub use iroha_smart_contract_utils::{debug, error, info, log, warn}; use iroha_smart_contract_utils::{ @@ -181,7 +180,7 @@ impl ExecuteQueryOnHost for Q where Q: Query + Encode, Q::Output: DecodeAll, - >::Error: core::fmt::Debug, + >::Error: core::fmt::Debug, { type Output = Q::Output; @@ -227,7 +226,7 @@ impl QueryWithParameters<'_, Q> where Q: Query + Encode, Q::Output: DecodeAll, - >::Error: core::fmt::Debug, + >::Error: core::fmt::Debug, { /// Apply sorting to a query #[must_use] @@ -264,7 +263,7 @@ where // Safety: - `host_execute_query` doesn't take ownership of it's pointer parameter // - ownership of the returned result is transferred into `_decode_from_raw` - let res: Result, ValidationFail> = unsafe { + let res: Result, ValidationFail> = unsafe { decode_with_length_prefix_from_raw(encode_and_execute( &QueryRequest::Query(self), host_execute_query, @@ -297,15 +296,15 @@ impl QueryOutputCursor { } } -impl QueryOutputCursor { - /// Same as [`into_inner()`](Self::into_inner) but collects all values of [`Value::Vec`] +impl QueryOutputCursor { + /// Same as [`into_inner()`](Self::into_inner) but collects all values of [`QueryOutputBox::Vec`] /// in case if there are some cached results left on the host side. /// /// # Errors /// /// May fail due to the same reasons [`QueryOutputCursorIterator`] can fail to iterate. - pub fn collect(self) -> Result>> { - let Value::Vec(v) = self.batch else { + pub fn collect(self) -> Result { + let QueryOutputBox::Vec(v) = self.batch else { return Ok(self.batch); }; @@ -317,12 +316,12 @@ impl QueryOutputCursor { cursor .into_iter() .collect::, _>>() - .map(Value::Vec) + .map(QueryOutputBox::Vec) } } -impl> IntoIterator for QueryOutputCursor> { - type Item = Result>>; +impl> IntoIterator for QueryOutputCursor> { + type Item = Result; type IntoIter = QueryOutputCursorIterator; fn into_iter(self) -> Self::IntoIter { @@ -346,8 +345,8 @@ pub struct QueryOutputCursorIterator { cursor: ForwardCursor, } -impl> QueryOutputCursorIterator { - fn next_batch(&self) -> Result>> { +impl> QueryOutputCursorIterator { + fn next_batch(&self) -> Result { #[cfg(not(test))] use host::execute_query as host_execute_query; #[cfg(test)] @@ -355,14 +354,14 @@ impl> QueryOutputCursorIterator { // Safety: - `host_execute_query` doesn't take ownership of it's pointer parameter // - ownership of the returned result is transferred into `_decode_from_raw` - let res: Result, ValidationFail> = unsafe { + let res: Result, ValidationFail> = unsafe { decode_with_length_prefix_from_raw(encode_and_execute( &QueryRequest::::Cursor(&self.cursor), host_execute_query, )) }; let (value, cursor) = res?.into(); - let vec = Vec::::try_from(value)?; + let vec = Vec::::try_from(value).expect("Host returned unexpected output type"); Ok(Self { iter: vec.into_iter(), cursor, @@ -370,8 +369,8 @@ impl> QueryOutputCursorIterator { } } -impl> Iterator for QueryOutputCursorIterator { - type Item = Result>>; +impl> Iterator for QueryOutputCursorIterator { + type Item = Result; fn next(&mut self) -> Option { if let Some(item) = self.iter.next() { @@ -393,11 +392,9 @@ impl> Iterator for QueryOutputCursorIterator { /// Error iterating other query results. #[derive(Debug, Display, iroha_macro::FromVariant)] -pub enum QueryOutputCursorError { +pub enum QueryOutputCursorError { /// Validation error on the host side during next batch retrieval. Validation(ValidationFail), - /// Host returned unexpected output type. - Conversion(ErrorTryFromEnum), } /// Get payload for smart contract `main()` entrypoint. @@ -484,10 +481,11 @@ mod tests { } } - const QUERY_RESULT: Result, ValidationFail> = Ok(QueryOutputCursor { - batch: Value::Numeric(numeric!(1234)), - cursor: ForwardCursor::new(None, None), - }); + const QUERY_RESULT: Result, ValidationFail> = + Ok(QueryOutputCursor { + batch: QueryOutputBox::Numeric(numeric!(1234)), + cursor: ForwardCursor::new(None, None), + }); const ISI_RESULT: Result<(), ValidationFail> = Ok(()); fn get_test_instruction() -> InstructionBox { @@ -524,11 +522,12 @@ mod tests { let query = query_request.unwrap_query().0; assert_eq!(query, get_test_query()); - let response: Result, ValidationFail> = Ok(BatchedResponseV1::new( - QUERY_RESULT.unwrap().into_raw_parts().0, - ForwardCursor::new(None, None), - ) - .into()); + let response: Result, ValidationFail> = + Ok(BatchedResponseV1::new( + QUERY_RESULT.unwrap().into_raw_parts().0, + ForwardCursor::new(None, None), + ) + .into()); ManuallyDrop::new(encode_with_length_prefix(&response)).as_ptr() } diff --git a/tools/kagami/src/genesis.rs b/tools/kagami/src/genesis.rs index 87f29c7f4ce..965b88d6609 100644 --- a/tools/kagami/src/genesis.rs +++ b/tools/kagami/src/genesis.rs @@ -123,11 +123,7 @@ impl TryFrom for ExecutorMode { #[allow(clippy::too_many_lines)] pub fn generate_default(executor: ExecutorMode) -> color_eyre::Result { let mut meta = Metadata::new(); - meta.insert_with_limits( - "key".parse()?, - "value".to_owned().into(), - Limits::new(1024, 1024), - )?; + meta.insert_with_limits("key".parse()?, "value".to_owned(), Limits::new(1024, 1024))?; let mut genesis = RawGenesisBlockBuilder::default() .domain_with_metadata("wonderland".parse()?, meta.clone()) @@ -184,22 +180,40 @@ pub fn generate_default(executor: ExecutorMode) -> color_eyre::Result DumpDecodedMap { macro_rules! insert_into_map { ($t:ty) => {{ let type_id = <$t as iroha_schema::TypeId>::id(); + #[allow(trivial_casts)] map.insert(type_id, <$t as DumpDecoded>::dump_decoded as DumpDecodedPtr) }}; @@ -218,8 +230,8 @@ mod tests { let mut metadata = Metadata::new(); metadata .insert_with_limits( - "hat".parse().unwrap(), - Value::Name("white".parse().unwrap()), + "hat".parse().expect("Valid"), + "white".parse::().unwrap(), limits, ) .expect("Valid"); @@ -238,11 +250,7 @@ mod tests { let limits = MetadataLimits::new(256, 256); let mut metadata = Metadata::new(); metadata - .insert_with_limits( - "Is_Jabberwocky_alive".parse().expect("Valid"), - Value::Bool(true), - limits, - ) + .insert_with_limits("Is_Jabberwocky_alive".parse().expect("Valid"), true, limits) .expect("Valid"); let domain = Domain::new("wonderland".parse().expect("Valid")) .with_logo( diff --git a/torii/src/routing.rs b/torii/src/routing.rs index 54599a6fb82..02c1a9685c0 100644 --- a/torii/src/routing.rs +++ b/torii/src/routing.rs @@ -20,7 +20,7 @@ use iroha_data_model::{ }, prelude::*, query::{ - cursor::ForwardCursor, http, sorting::Sorting, Pagination, QueryRequest, + cursor::ForwardCursor, http, sorting::Sorting, Pagination, QueryOutputBox, QueryRequest, QueryWithParameters, }, BatchedResponse, @@ -104,7 +104,7 @@ pub async fn handle_queries( sumeragi: SumeragiHandle, query_request: http::ClientQueryRequest, -) -> Result>> { +) -> Result>> { let handle = task::spawn_blocking(move || match query_request.0 { QueryRequest::Query(QueryWithParameters { query: signed_query,