diff --git a/data_model/src/block.rs b/data_model/src/block.rs index 1cbfeb543e0..705aff16b93 100644 --- a/data_model/src/block.rs +++ b/data_model/src/block.rs @@ -318,15 +318,9 @@ impl BlockSignature { } mod candidate { - #[cfg(not(feature = "std"))] - use alloc::collections::BTreeSet; - #[cfg(feature = "std")] - use std::collections::BTreeSet; - use parity_scale_codec::Input; use super::*; - use crate::isi::InstructionBox; #[derive(Decode, Deserialize)] struct SignedBlockCandidate { @@ -336,10 +330,13 @@ mod candidate { impl SignedBlockCandidate { fn validate(self) -> Result { - self.validate_signatures()?; - self.validate_header()?; - if self.payload.header.height.get() == 1 { - self.validate_genesis()?; + #[cfg(not(target_family = "wasm"))] + { + self.validate_signatures()?; + self.validate_header()?; + if self.payload.header.height.get() == 1 { + self.validate_genesis()?; + } } Ok(SignedBlockV1 { @@ -348,7 +345,10 @@ mod candidate { }) } + #[cfg(not(target_family = "wasm"))] fn validate_genesis(&self) -> Result<(), &'static str> { + use crate::isi::InstructionBox; + let transactions = self.payload.transactions.as_slice(); for transaction in transactions { if transaction.error.is_some() { @@ -382,7 +382,13 @@ mod candidate { Ok(()) } + #[cfg(not(target_family = "wasm"))] fn validate_signatures(&self) -> Result<(), &'static str> { + #[cfg(not(feature = "std"))] + use alloc::collections::BTreeSet; + #[cfg(feature = "std")] + use std::collections::BTreeSet; + if self.signatures.is_empty() && self.payload.header.height.get() != 1 { return Err("Block missing signatures"); } @@ -401,6 +407,7 @@ mod candidate { Ok(()) } + #[cfg(not(target_family = "wasm"))] fn validate_header(&self) -> Result<(), &'static str> { let actual_txs_hash = self.payload.header.transactions_hash; diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index 7a52f92d86e..1c6c659d910 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -1,5 +1,14 @@ //! Iroha Data Model contains structures for Domains, Peers, Accounts and Assets with simple, //! non-specific functions like serialization. +//! +//! ## Note about WASM and deserialization +//! Some structs performs validation during deserialization. +//! (e.g. [`transaction::candidate::SignedTransactionCandidate`]). +//! However such validation was disabled when compiled to WASM, +//! Validation at WASM side is not necessary, +//! because validation was already performed on host side, +//! and host is a trusted entity. +//! This gives about 50% performance boost, see #4995. // Clippy bug #![allow(clippy::items_after_test_module)] diff --git a/data_model/src/name.rs b/data_model/src/name.rs index bf87b77a275..a0b46cd8a97 100644 --- a/data_model/src/name.rs +++ b/data_model/src/name.rs @@ -105,9 +105,11 @@ impl<'de> Deserialize<'de> for Name { where D: serde::Deserializer<'de>, { + #[cfg(not(target_family = "wasm"))] use serde::de::Error as _; let candidate = ConstString::deserialize(deserializer)?; + #[cfg(not(target_family = "wasm"))] Self::validate_str(&candidate).map_err(D::Error::custom)?; Ok(Self(candidate)) @@ -116,9 +118,9 @@ impl<'de> Deserialize<'de> for Name { impl Decode for Name { fn decode(input: &mut I) -> Result { let name = ConstString::decode(input)?; - Self::validate_str(&name) - .map(|()| Self(name)) - .map_err(|error| error.reason.into()) + #[cfg(not(target_family = "wasm"))] + Self::validate_str(&name).map_err(|error| parity_scale_codec::Error::from(error.reason))?; + Ok(Self(name)) } } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index d79b9a60c5a..32878184256 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -375,11 +375,13 @@ mod candidate { impl SignedQueryCandidate { fn validate(self) -> Result { - let QuerySignature(signature) = &self.signature; - - signature - .verify(&self.payload.authority.signatory, &self.payload) - .map_err(|_| "Query request signature is not valid")?; + #[cfg(not(target_family = "wasm"))] + { + let QuerySignature(signature) = &self.signature; + signature + .verify(&self.payload.authority.signatory, &self.payload) + .map_err(|_| "Query request signature is not valid")?; + } Ok(SignedQueryV1 { payload: self.payload, diff --git a/data_model/src/transaction.rs b/data_model/src/transaction.rs index ef57fe45b11..e1efd11e902 100644 --- a/data_model/src/transaction.rs +++ b/data_model/src/transaction.rs @@ -335,7 +335,9 @@ mod candidate { impl SignedTransactionCandidate { fn validate(self) -> Result { + #[cfg(not(target_family = "wasm"))] self.validate_instructions()?; + #[cfg(not(target_family = "wasm"))] self.validate_signature()?; Ok(SignedTransactionV1 { @@ -344,6 +346,7 @@ mod candidate { }) } + #[cfg(not(target_family = "wasm"))] fn validate_instructions(&self) -> Result<(), &'static str> { if let Executable::Instructions(instructions) = &self.payload.instructions { if instructions.is_empty() { @@ -354,6 +357,7 @@ mod candidate { Ok(()) } + #[cfg(not(target_family = "wasm"))] fn validate_signature(&self) -> Result<(), &'static str> { let TransactionSignature(signature) = &self.signature; diff --git a/defaults/executor.wasm b/defaults/executor.wasm index 6933f17e8ad..89ec026fae2 100644 Binary files a/defaults/executor.wasm and b/defaults/executor.wasm differ