Skip to content

Commit

Permalink
perf: Don't validate transactions inside WASM (#4995)
Browse files Browse the repository at this point in the history
Signed-off-by: Dmitry Murzin <[email protected]>
  • Loading branch information
dima74 authored Aug 22, 2024
1 parent 76dafdc commit 9e8c35d
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 18 deletions.
27 changes: 17 additions & 10 deletions data_model/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -336,10 +330,13 @@ mod candidate {

impl SignedBlockCandidate {
fn validate(self) -> Result<SignedBlockV1, &'static str> {
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 {
Expand All @@ -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() {
Expand Down Expand Up @@ -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");
}
Expand All @@ -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;

Expand Down
9 changes: 9 additions & 0 deletions data_model/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
8 changes: 5 additions & 3 deletions data_model/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -116,9 +118,9 @@ impl<'de> Deserialize<'de> for Name {
impl Decode for Name {
fn decode<I: Input>(input: &mut I) -> Result<Self, parity_scale_codec::Error> {
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))
}
}

Expand Down
12 changes: 7 additions & 5 deletions data_model/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,13 @@ mod candidate {

impl SignedQueryCandidate {
fn validate(self) -> Result<SignedQueryV1, &'static str> {
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,
Expand Down
4 changes: 4 additions & 0 deletions data_model/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,9 @@ mod candidate {

impl SignedTransactionCandidate {
fn validate(self) -> Result<SignedTransactionV1, &'static str> {
#[cfg(not(target_family = "wasm"))]
self.validate_instructions()?;
#[cfg(not(target_family = "wasm"))]
self.validate_signature()?;

Ok(SignedTransactionV1 {
Expand All @@ -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() {
Expand All @@ -354,6 +357,7 @@ mod candidate {
Ok(())
}

#[cfg(not(target_family = "wasm"))]
fn validate_signature(&self) -> Result<(), &'static str> {
let TransactionSignature(signature) = &self.signature;

Expand Down
Binary file modified defaults/executor.wasm
Binary file not shown.

0 comments on commit 9e8c35d

Please sign in to comment.