From f407c99394ea9a17a6653ef33ab66858238cdd18 Mon Sep 17 00:00:00 2001 From: Daniil Polyakov Date: Wed, 24 May 2023 13:28:19 +0300 Subject: [PATCH] [fix] #3233: Remove duplicated error messages Signed-off-by: Daniil Polyakov --- Cargo.lock | 20 + Cargo.toml | 2 + cli/src/torii/mod.rs | 35 +- cli/src/torii/routing.rs | 30 +- client/src/client.rs | 55 +- client/tests/integration/events/data.rs | 3 +- client/tests/integration/offline_peers.rs | 2 +- client/tests/integration/permissions.rs | 8 +- client/tests/integration/queries/asset.rs | 8 +- client/tests/integration/queries/role.rs | 4 +- client/tests/integration/query_errors.rs | 4 +- .../src/lib.rs | 11 +- .../smartcontracts/mint_rose/src/lib.rs | 4 +- .../validator_with_admin/src/lib.rs | 13 +- .../integration/triggers/by_call_trigger.rs | 28 +- .../integration/triggers/time_trigger.rs | 2 +- client/tests/wasm/utils.rs | 7 +- configs/peer/validator.wasm | Bin 561267 -> 597151 bytes core/Cargo.toml | 1 + core/src/smartcontracts/isi/account.rs | 57 +- core/src/smartcontracts/isi/domain.rs | 19 +- core/src/smartcontracts/isi/mod.rs | 4 +- core/src/smartcontracts/isi/permissions.rs | 12 +- core/src/smartcontracts/isi/triggers/mod.rs | 28 +- core/src/smartcontracts/isi/world.rs | 53 +- core/src/smartcontracts/mod.rs | 6 +- core/src/smartcontracts/wasm.rs | 581 ++++++++---------- core/src/tx.rs | 53 +- core/src/validator.rs | 49 +- core/src/wsv.rs | 2 +- data_model/src/asset.rs | 1 + data_model/src/evaluate.rs | 148 +++-- data_model/src/events/pipeline.rs | 18 +- data_model/src/isi.rs | 282 ++++++--- data_model/src/lib.rs | 116 +++- data_model/src/metadata.rs | 94 +-- data_model/src/name.rs | 31 +- data_model/src/query.rs | 73 ++- data_model/src/transaction.rs | 86 ++- data_model/src/validator.rs | 24 +- default_validator/src/lib.rs | 2 +- docs/source/references/schema.json | 463 +++++++++++++- .../ui_fail/fallible_transmute_mut_ref.stderr | 4 +- .../tests/ui_fail/non_robust_repr_c.stderr | 2 +- schema/gen/src/lib.rs | 2 +- schema/src/lib.rs | 23 + wasm/src/debug.rs | 6 +- wasm/src/lib.rs | 70 ++- wasm/src/log.rs | 14 +- wasm/validator/derive/src/entrypoint.rs | 6 +- wasm/validator/derive/src/lib.rs | 6 +- wasm/validator/derive/src/token.rs | 8 +- wasm/validator/derive/src/validate.rs | 2 +- wasm/validator/src/default.rs | 145 +++-- wasm/validator/src/lib.rs | 45 +- wasm/validator/src/permission.rs | 57 +- wasm_codec/Cargo.toml | 14 + wasm_codec/derive/Cargo.toml | 16 + wasm_codec/derive/src/lib.rs | 384 ++++++++++++ wasm_codec/src/lib.rs | 149 +++++ 60 files changed, 2387 insertions(+), 1005 deletions(-) create mode 100644 wasm_codec/Cargo.toml create mode 100644 wasm_codec/derive/Cargo.toml create mode 100644 wasm_codec/derive/src/lib.rs create mode 100644 wasm_codec/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 0e4df2a4767..c816489a98b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2814,6 +2814,7 @@ dependencies = [ "iroha_primitives", "iroha_telemetry", "iroha_version", + "iroha_wasm_codec", "itertools", "once_cell", "parity-scale-codec", @@ -2828,6 +2829,16 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "iroha_core_wasm_codec_derive" +version = "2.0.0-pre-rc.16" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "iroha_crypto" version = "2.0.0-pre-rc.16" @@ -3167,6 +3178,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "iroha_wasm_codec" +version = "2.0.0-pre-rc.16" +dependencies = [ + "iroha_core_wasm_codec_derive", + "parity-scale-codec", + "wasmtime", +] + [[package]] name = "is-terminal" version = "0.4.7" diff --git a/Cargo.toml b/Cargo.toml index f562efb64c1..be2bf19bef4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,8 @@ members = [ "tools/parity_scale_decoder", "version", "version/derive", + "wasm_codec", + "wasm_codec/derive", "wasm_builder", ] diff --git a/cli/src/torii/mod.rs b/cli/src/torii/mod.rs index dd4089550de..c0b6a0b3f8a 100644 --- a/cli/src/torii/mod.rs +++ b/cli/src/torii/mod.rs @@ -47,7 +47,7 @@ pub struct Torii { pub enum Error { /// Failed to execute or validate query #[error("Failed to execute or validate query")] - Query(#[from] iroha_data_model::query::error::QueryExecutionFailure), + Query(#[from] iroha_data_model::ValidationFail), /// Failed to accept transaction #[error("Failed to accept transaction: {0}")] AcceptTransaction(#[from] iroha_data_model::transaction::error::AcceptTransactionFailure), @@ -67,16 +67,29 @@ pub enum Error { } /// Status code for query error response. -pub(crate) const fn query_status_code( - query_error: &iroha_data_model::query::error::QueryExecutionFailure, -) -> StatusCode { - use iroha_data_model::query::error::QueryExecutionFailure::*; +pub(crate) fn query_status_code(validation_error: &iroha_data_model::ValidationFail) -> StatusCode { + use iroha_data_model::{ + isi::error::InstructionExecutionFailure, query::error::QueryExecutionFailure::*, + ValidationFail::*, + }; - match query_error { - Evaluate(_) | Conversion(_) => StatusCode::BAD_REQUEST, - Signature(_) | Unauthorized => StatusCode::UNAUTHORIZED, - Permission(_) => StatusCode::FORBIDDEN, - Find(_) => StatusCode::NOT_FOUND, + match validation_error { + NotPermitted(_) => StatusCode::FORBIDDEN, + QueryFailed(query_error) + | InstructionFailed(InstructionExecutionFailure::Query(query_error)) => match query_error { + Evaluate(_) | Conversion(_) => StatusCode::BAD_REQUEST, + Signature(_) | Unauthorized => StatusCode::UNAUTHORIZED, + Find(_) => StatusCode::NOT_FOUND, + }, + TooComplex => StatusCode::UNPROCESSABLE_ENTITY, + InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR, + InstructionFailed(error) => { + iroha_logger::error!( + ?error, + "Query validation failed with unexpected error. This means a bug inside Runtime Validator", + ); + StatusCode::INTERNAL_SERVER_ERROR + } } } @@ -93,7 +106,7 @@ impl Reply for Error { } impl Error { - const fn status_code(&self) -> StatusCode { + fn status_code(&self) -> StatusCode { use Error::*; match self { Query(e) => query_status_code(e), diff --git a/cli/src/torii/routing.rs b/cli/src/torii/routing.rs index 08197299f68..3dc78969544 100644 --- a/cli/src/torii/routing.rs +++ b/cli/src/torii/routing.rs @@ -32,6 +32,7 @@ use iroha_data_model::{ query::error::QueryExecutionFailure, transaction::InBlock, }; +use iroha_logger::prelude::*; #[cfg(feature = "telemetry")] use iroha_telemetry::metrics::Status; use pagination::{paginate, Paginate}; @@ -66,19 +67,23 @@ impl VerifiedQuery { pub fn validate( self, wsv: &mut WorldStateView, - ) -> Result<(ValidQueryRequest, PredicateBox), QueryExecutionFailure> { - let account_has_public_key = wsv.map_account(&self.payload.account_id, |account| { - account.signatories.contains(self.signature.public_key()) - })?; + ) -> Result<(ValidQueryRequest, PredicateBox), ValidationFail> { + let account_has_public_key = wsv + .map_account(&self.payload.account_id, |account| { + account.signatories.contains(self.signature.public_key()) + }) + .map_err(QueryExecutionFailure::from)?; if !account_has_public_key { return Err(QueryExecutionFailure::Signature(String::from( "Signature public key doesn't correspond to the account.", - ))); + )) + .into()); } - wsv.validator_view() - .clone() // Cloning validator is a cheap operation - .validate(wsv, &self.payload.account_id, self.payload.query.clone()) - .map_err(|err| QueryExecutionFailure::Permission(err.to_string()))?; + wsv.validator_view().clone().validate( + wsv, + &self.payload.account_id, + self.payload.query.clone(), + )?; Ok(( ValidQueryRequest::new(self.payload.query), self.payload.filter, @@ -135,12 +140,12 @@ pub(crate) async fn handle_queries( request: VersionedSignedQuery, ) -> Result> { let VersionedSignedQuery::V1(request) = request; - let request: VerifiedQuery = request.try_into()?; + let request: VerifiedQuery = request.try_into().map_err(ValidationFail::from)?; let (result, filter) = { let mut wsv = sumeragi.wsv_clone(); let (valid_request, filter) = request.validate(&mut wsv)?; - let original_result = valid_request.execute(&wsv)?; + let original_result = valid_request.execute(&wsv).map_err(ValidationFail::from)?; (filter.filter(original_result), filter) }; @@ -155,7 +160,8 @@ pub(crate) async fn handle_queries( let total = total .try_into() - .map_err(|e: TryFromIntError| QueryExecutionFailure::Conversion(e.to_string()))?; + .map_err(|e: TryFromIntError| QueryExecutionFailure::Conversion(e.to_string())) + .map_err(ValidationFail::from)?; let result = QueryResult(result); let paginated_result = PaginatedQueryResult { result, diff --git a/client/src/client.rs b/client/src/client.rs index a209dece0b7..262322aa948 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -15,7 +15,7 @@ use iroha_config::{client::Configuration, torii::uri, GetConfiguration, PostConf use iroha_crypto::{HashOf, KeyPair}; use iroha_data_model::{ block::VersionedCommittedBlock, predicate::PredicateBox, prelude::*, - query::error::QueryExecutionFailure, transaction::TransactionPayload, + transaction::TransactionPayload, }; use iroha_logger::prelude::*; use iroha_telemetry::metrics::Status; @@ -81,14 +81,15 @@ where StatusCode::BAD_REQUEST | StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN - | StatusCode::NOT_FOUND => { - let res = QueryExecutionFailure::decode_all(&mut resp.body().as_ref()); + | StatusCode::NOT_FOUND + | StatusCode::UNPROCESSABLE_ENTITY => { + let res = ValidationFail::decode_all(&mut resp.body().as_ref()); let err = res.wrap_err( "Failed to decode error-response from Iroha. \ You are likely using a version of the client library \ that is incompatible with the version of the peer software", )?; - Err(ClientQueryError::QueryError(err)) + Err(ClientQueryError::Validation(err)) } _ => Err(ResponseReport::with_msg("Unexpected query response", resp).into()), } @@ -103,19 +104,12 @@ where /// Different errors as a result of query response handling #[derive(Debug, thiserror::Error)] pub enum ClientQueryError { - /// Certain Iroha query error - #[error("Query error: {0}")] - QueryError(QueryExecutionFailure), + /// Query validation error + #[error("Query validation error")] + Validation(#[from] ValidationFail), /// Some other error - #[error("Other error: {0}")] - Other(eyre::Error), -} - -impl From for ClientQueryError { - #[inline] - fn from(err: eyre::Error) -> Self { - Self::Other(err) - } + #[error("Other error")] + Other(#[from] eyre::Error), } impl From for ClientQueryError { @@ -518,8 +512,8 @@ impl Client { if let Event::Pipeline(this_event) = event? { match this_event.status() { PipelineStatus::Validating => {} - PipelineStatus::Rejected(reason) => { - return Err(reason.clone()).wrap_err("Transaction rejected") + PipelineStatus::Rejected(ref reason) => { + return Err(reason.clone().into()); } PipelineStatus::Committed => return Ok(hash.transmute()), } @@ -1184,8 +1178,8 @@ pub mod stream_api { fn drop(&mut self) { let mut close = || -> eyre::Result<()> { self.stream.close(None)?; - let mes = self.stream.read_message()?; - if !mes.is_close() { + let msg = self.stream.read_message()?; + if !msg.is_close() { return Err(eyre!( "Server hasn't sent `Close` message for websocket handshake" )); @@ -1245,8 +1239,8 @@ pub mod stream_api { pub async fn close(mut self) { let close = async { self.stream.close(None).await?; - if let Some(mes) = self.stream.next().await { - if !mes?.is_close() { + if let Some(msg) = self.stream.next().await { + if !msg?.is_close() { eyre::bail!("Server hasn't sent `Close` message for websocket handshake"); } } @@ -1718,6 +1712,7 @@ mod tests { #[cfg(test)] mod query_errors_handling { use http::Response; + use iroha_data_model::{query::error::QueryExecutionFailure, ValidationFail}; use super::*; @@ -1727,24 +1722,24 @@ mod tests { let responses = vec![ ( StatusCode::UNAUTHORIZED, - QueryExecutionFailure::Signature("whatever".to_owned()), - ), - ( - StatusCode::FORBIDDEN, - QueryExecutionFailure::Permission("whatever".to_owned()), + ValidationFail::QueryFailed(QueryExecutionFailure::Signature( + "whatever".to_owned(), + )), ), + (StatusCode::UNPROCESSABLE_ENTITY, ValidationFail::TooComplex), ( StatusCode::NOT_FOUND, // Here should be `Find`, but actually handler doesn't care - QueryExecutionFailure::Evaluate("whatever".to_owned()), + ValidationFail::QueryFailed(QueryExecutionFailure::Evaluate( + "whatever".to_owned(), + )), ), ]; - for (status_code, err) in responses { let resp = Response::builder().status(status_code).body(err.encode())?; match sut.handle(resp) { - Err(ClientQueryError::QueryError(actual)) => { + Err(ClientQueryError::Validation(actual)) => { // PartialEq isn't implemented, so asserting by encoded repr assert_eq!(actual.encode(), err.encode()); } diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 03b2a43e7ac..13c1c1ca291 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -63,7 +63,8 @@ fn wasm_execution_should_produce_events() -> Result<()> { // It's expected that hex values are of even length write!( isi_calls, - "(call $exec_isi (i32.const {ptr_offset}) (i32.const {ptr_len}))", + "(call $exec_isi (i32.const {ptr_offset}) (i32.const {ptr_len})) + drop", ptr_offset = ptr_offset / 2, ptr_len = ptr_len / 2, )?; diff --git a/client/tests/integration/offline_peers.rs b/client/tests/integration/offline_peers.rs index c7bb1c50fa3..13ed021b960 100644 --- a/client/tests/integration/offline_peers.rs +++ b/client/tests/integration/offline_peers.rs @@ -10,7 +10,7 @@ use test_network::*; use tokio::runtime::Runtime; #[test] -fn genesis_block_is_commited_with_some_offline_peers() -> Result<()> { +fn genesis_block_is_committed_with_some_offline_peers() -> Result<()> { // Given let rt = Runtime::test(); diff --git a/client/tests/integration/permissions.rs b/client/tests/integration/permissions.rs index 573d47c5dfa..63ff41e4d39 100644 --- a/client/tests/integration/permissions.rs +++ b/client/tests/integration/permissions.rs @@ -92,7 +92,9 @@ fn permissions_disallow_asset_transfer() { //Then assert!(matches!( rejection_reason, - &PipelineRejectionReason::Transaction(TransactionRejectionReason::NotPermitted(_)) + &PipelineRejectionReason::Transaction(TransactionRejectionReason::Validation( + ValidationFail::NotPermitted(_) + )) )); let alice_assets = get_assets(&mut iroha_client, &alice_id); assert_eq!(alice_assets, alice_start_assets); @@ -146,7 +148,9 @@ fn permissions_disallow_asset_burn() { //Then assert!(matches!( rejection_reason, - &PipelineRejectionReason::Transaction(TransactionRejectionReason::NotPermitted(_)) + &PipelineRejectionReason::Transaction(TransactionRejectionReason::Validation( + ValidationFail::NotPermitted(_) + )) )); let alice_assets = get_assets(&mut iroha_client, &alice_id); diff --git a/client/tests/integration/queries/asset.rs b/client/tests/integration/queries/asset.rs index bd336733066..67a6dd5baf0 100644 --- a/client/tests/integration/queries/asset.rs +++ b/client/tests/integration/queries/asset.rs @@ -144,7 +144,9 @@ fn find_asset_total_quantity() -> Result<()> { )); assert!(matches!( result, - Err(ClientQueryError::QueryError(QueryExecutionFailure::Find(_))) + Err(ClientQueryError::Validation(ValidationFail::QueryFailed( + QueryExecutionFailure::Find(_) + ))) )); } @@ -202,7 +204,9 @@ fn find_asset_total_quantity() -> Result<()> { )); assert!(matches!( result, - Err(ClientQueryError::QueryError(QueryExecutionFailure::Find(_))) + Err(ClientQueryError::Validation(ValidationFail::QueryFailed( + QueryExecutionFailure::Find(_) + ))) )); Ok(()) diff --git a/client/tests/integration/queries/role.rs b/client/tests/integration/queries/role.rs index 5da109a24a4..dee30326948 100644 --- a/client/tests/integration/queries/role.rs +++ b/client/tests/integration/queries/role.rs @@ -105,8 +105,8 @@ fn find_unregistered_role_by_id() { // Not found error assert!(matches!( found_role, - Err(client::ClientQueryError::QueryError( - QueryExecutionFailure::Find(_) + Err(client::ClientQueryError::Validation( + ValidationFail::QueryFailed(QueryExecutionFailure::Find(_)) )) )); } diff --git a/client/tests/integration/query_errors.rs b/client/tests/integration/query_errors.rs index 3f5da93b851..9b95d12f771 100644 --- a/client/tests/integration/query_errors.rs +++ b/client/tests/integration/query_errors.rs @@ -22,7 +22,9 @@ fn non_existent_account_is_specific_error() { .expect_err("Should error"); match err { - ClientQueryError::QueryError(QueryExecutionFailure::Find(err)) => match *err { + ClientQueryError::Validation(ValidationFail::QueryFailed(QueryExecutionFailure::Find( + err, + ))) => match *err { FindError::Domain(id) => assert_eq!(id.name.as_ref(), "regalia"), x => panic!("FindError::Domain expected, got {x:?}"), }, diff --git a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs index 2baca279a78..46761ab52f6 100644 --- a/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs +++ b/client/tests/integration/smartcontracts/create_nft_for_every_user_trigger/src/lib.rs @@ -16,7 +16,8 @@ use iroha_wasm::{data_model::prelude::*, prelude::*}; fn main() { iroha_wasm::info!("Executing trigger"); - let accounts = FindAllAccounts.execute(); + let accounts = FindAllAccounts.execute().dbg_unwrap(); + let limits = MetadataLimits::new(256, 256); for account in accounts { @@ -39,15 +40,17 @@ fn main() { let account_nft_id = ::Id::new(nft_id, account.id().clone()); let account_nft = Asset::new(account_nft_id, Metadata::new()); - RegisterBox::new(nft_definition).execute(); - RegisterBox::new(account_nft).execute(); + RegisterBox::new(nft_definition).execute().dbg_unwrap(); + RegisterBox::new(account_nft).execute().dbg_unwrap(); } iroha_wasm::info!("Smart contract executed successfully"); } fn generate_new_nft_id(account_id: &::Id) -> AssetDefinitionId { - let assets = FindAssetsByAccountId::new(account_id.clone()).execute(); + let assets = FindAssetsByAccountId::new(account_id.clone()) + .execute() + .dbg_unwrap(); let new_number = assets .into_iter() diff --git a/client/tests/integration/smartcontracts/mint_rose/src/lib.rs b/client/tests/integration/smartcontracts/mint_rose/src/lib.rs index 89f33a28c3e..990a448dcce 100644 --- a/client/tests/integration/smartcontracts/mint_rose/src/lib.rs +++ b/client/tests/integration/smartcontracts/mint_rose/src/lib.rs @@ -18,5 +18,7 @@ fn main(authority: ::Id) { .dbg_expect("Failed to parse `rose#wonderland` asset definition id"); let rose_id = ::Id::new(rose_definition_id, authority); - MintBox::new(1_u32, rose_id).execute(); + MintBox::new(1_u32, rose_id) + .execute() + .dbg_expect("Failed to mint rose"); } diff --git a/client/tests/integration/smartcontracts/validator_with_admin/src/lib.rs b/client/tests/integration/smartcontracts/validator_with_admin/src/lib.rs index 1d743ecbc00..90b2a55abff 100644 --- a/client/tests/integration/smartcontracts/validator_with_admin/src/lib.rs +++ b/client/tests/integration/smartcontracts/validator_with_admin/src/lib.rs @@ -3,7 +3,7 @@ #![no_std] use iroha_validator::{ - data_model::evaluate::{Error, ExpressionEvaluator}, + data_model::evaluate::{EvaluationError, ExpressionEvaluator}, parse, prelude::*, }; @@ -91,16 +91,19 @@ impl Visit for CustomValidator { } impl Validate for CustomValidator { - fn verdict(&self) -> &Verdict { + fn verdict(&self) -> &Result { self.0.verdict() } - fn deny(&mut self, reason: DenialReason) { + fn deny(&mut self, reason: ValidationFail) { self.0.deny(reason); } } impl ExpressionEvaluator for CustomValidator { - fn evaluate(&self, expression: &E) -> Result { + fn evaluate( + &self, + expression: &E, + ) -> core::result::Result { self.0.evaluate(expression) } } @@ -108,7 +111,7 @@ impl ExpressionEvaluator for CustomValidator { /// Allow operation if authority is `admin@admin` and if not, /// fallback to [`DefaultValidator::validate()`]. #[entrypoint(params = "[authority, operation]")] -pub fn validate(authority: AccountId, operation: NeedsValidationBox) -> Verdict { +pub fn validate(authority: AccountId, operation: NeedsValidationBox) -> Result { let mut validator = CustomValidator(DefaultValidator::new()); match operation { diff --git a/client/tests/integration/triggers/by_call_trigger.rs b/client/tests/integration/triggers/by_call_trigger.rs index 7a7f4c151f5..ef62487da46 100644 --- a/client/tests/integration/triggers/by_call_trigger.rs +++ b/client/tests/integration/triggers/by_call_trigger.rs @@ -4,7 +4,7 @@ use std::{str::FromStr as _, sync::mpsc, thread, time::Duration}; use eyre::{eyre, Result, WrapErr}; use iroha_client::client::{self, Client}; -use iroha_data_model::{prelude::*, trigger::OptimizedExecutable}; +use iroha_data_model::{prelude::*, query::error::FindError, trigger::OptimizedExecutable}; use iroha_genesis::GenesisNetwork; use iroha_logger::info; use test_network::*; @@ -182,16 +182,28 @@ fn trigger_should_not_be_executed_with_zero_repeats_count() -> Result<()> { let prev_asset_value = get_asset_value(&mut test_client, asset_id.clone())?; // Executing trigger first time - let execute_trigger = ExecuteTriggerBox::new(trigger_id); + let execute_trigger = ExecuteTriggerBox::new(trigger_id.clone()); test_client.submit_blocking(execute_trigger.clone())?; // Executing trigger second time - assert!(test_client - .submit_blocking(execute_trigger) - .expect_err("Error expected") - .root_cause() - .downcast_ref::() - .is_some()); + + // NOTE: Keep this for debugging purposes + // let error = test_client + // .submit_blocking(execute_trigger) + // .expect_err("Error expected"); + // iroha_logger::info!(?error); + + assert!(matches!( + test_client + .submit_blocking(execute_trigger) + .expect_err("Error expected") + .chain() + .last() + .expect("At least two error causes expected") + .downcast_ref::>() + .map(std::ops::Deref::deref), + Some(FindError::Trigger(id)) if *id == trigger_id + )); // Checking results let new_asset_value = get_asset_value(&mut test_client, asset_id)?; diff --git a/client/tests/integration/triggers/time_trigger.rs b/client/tests/integration/triggers/time_trigger.rs index 7250a1b3a2d..c152c4d8c95 100644 --- a/client/tests/integration/triggers/time_trigger.rs +++ b/client/tests/integration/triggers/time_trigger.rs @@ -258,7 +258,7 @@ fn mint_nft_for_every_user_every_1_sec() -> Result<()> { assert!( count >= EXPECTED_COUNT, - "{account_id} has {count} NFT, but at least {EXPECTED_COUNT} expected", + "{account_id} has {count} NFTs, but at least {EXPECTED_COUNT} expected", ); } diff --git a/client/tests/wasm/utils.rs b/client/tests/wasm/utils.rs index 0b643f04735..5aefbd7dd06 100644 --- a/client/tests/wasm/utils.rs +++ b/client/tests/wasm/utils.rs @@ -15,7 +15,7 @@ pub fn wasm_template(hex_val: &str) -> String { r#" ;; Import host function to execute instruction (import "iroha" "{execute_instruction}" - (func $exec_isi (param i32 i32))) + (func $exec_isi (param i32 i32) (result i32))) ;; Import host function to execute query (import "iroha" "{execute_query}" @@ -35,9 +35,14 @@ pub fn wasm_template(hex_val: &str) -> String { (global.set $mem_size (i32.add (global.get $mem_size) (local.get $size))) ) + + ;; Export mock deallocator to host. This allocator does nothing! + (func (export "{dealloc_fn_name}") (param $size i32) (param $len i32) + nop) "#, memory_name = "memory", alloc_fn_name = "_iroha_wasm_alloc", + dealloc_fn_name = "_iroha_wasm_dealloc", execute_instruction = "execute_instruction", execute_query = "execute_query", hex_val = escape_hex(hex_val), diff --git a/configs/peer/validator.wasm b/configs/peer/validator.wasm index 41f0d046e99be1f17cb9625dd1dd81edddf600f2..72feaff428792b9f5b8c2ec55eee736153c0b8b8 100644 GIT binary patch literal 597151 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