From ca31ab072f6ebe83372775b3f6243d8963401a47 Mon Sep 17 00:00:00 2001 From: Gauri Agarwal Date: Fri, 28 Jun 2019 16:26:59 -0700 Subject: [PATCH] Parallelizing Signature Verification in the Executor Signature Verification takes a significant amount of time (about 50% more time) and thus parallelizing it is expected to improve the performance of the code significantly. --- language/vm/vm_runtime/Cargo.toml | 1 + language/vm/vm_runtime/src/block_processor.rs | 37 +++++++++++++------ language/vm/vm_runtime/src/process_txn/mod.rs | 6 +-- .../vm/vm_runtime/src/process_txn/validate.rs | 7 ---- language/vm/vm_runtime/src/runtime.rs | 10 ++++- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/language/vm/vm_runtime/Cargo.toml b/language/vm/vm_runtime/Cargo.toml index 9e5a22ab29e3..009136b64aaa 100644 --- a/language/vm/vm_runtime/Cargo.toml +++ b/language/vm/vm_runtime/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" rental = "0.5.3" tiny-keccak = "1.4.2" proptest = "0.9" +rayon = "1.1" bytecode_verifier = { path = "../../bytecode_verifier" } canonical_serialization = { path = "../../../common/canonical_serialization" } diff --git a/language/vm/vm_runtime/src/block_processor.rs b/language/vm/vm_runtime/src/block_processor.rs index 46694f15be8c..8402870584f3 100644 --- a/language/vm/vm_runtime/src/block_processor.rs +++ b/language/vm/vm_runtime/src/block_processor.rs @@ -13,9 +13,12 @@ use crate::{ }; use config::config::VMPublishingOption; use logger::prelude::*; +use rayon::prelude::*; use state_view::StateView; use types::{ - transaction::{SignedTransaction, TransactionOutput, TransactionStatus}, + transaction::{ + SignatureCheckedTransaction, SignedTransaction, TransactionOutput, TransactionStatus, + }, vm_error::{ExecutionStatus, VMStatus, VMValidationStatus}, write_set::WriteSet, }; @@ -57,15 +60,27 @@ pub fn execute_block<'alloc>( let module_cache = BlockModuleCache::new(code_cache, ModuleFetcherImpl::new(data_view)); let mut data_cache = BlockDataCache::new(data_view); let mut result = vec![]; - for txn in txn_block.into_iter() { - let output = transaction_flow( - txn, - &module_cache, - script_cache, - &data_cache, - mode, - publishing_option, - ); + + let signature_verified_block: Vec> = txn_block + .into_par_iter() + .map(|txn| match txn.check_signature() { + Ok(t) => Ok(t), + Err(_) => Err(VMStatus::Validation(VMValidationStatus::InvalidSignature)), + }) + .collect(); + + for transaction in signature_verified_block { + let output = match transaction { + Ok(t) => transaction_flow( + t, + &module_cache, + script_cache, + &data_cache, + mode, + publishing_option, + ), + Err(vm_status) => ExecutedTransaction::discard_error_output(vm_status), + }; data_cache.push_write_set(&output.write_set()); result.push(output); } @@ -87,7 +102,7 @@ pub fn execute_block<'alloc>( /// include those newly published modules. This function will also update the `script_cache` to /// cache this `txn` fn transaction_flow<'alloc, P>( - txn: SignedTransaction, + txn: SignatureCheckedTransaction, module_cache: P, script_cache: &ScriptCache<'alloc>, data_cache: &BlockDataCache<'_>, diff --git a/language/vm/vm_runtime/src/process_txn/mod.rs b/language/vm/vm_runtime/src/process_txn/mod.rs index de22c0b1c6ad..5a0b03e3b24e 100644 --- a/language/vm/vm_runtime/src/process_txn/mod.rs +++ b/language/vm/vm_runtime/src/process_txn/mod.rs @@ -4,7 +4,7 @@ use crate::{ }; use config::config::VMPublishingOption; use std::marker::PhantomData; -use types::transaction::SignedTransaction; +use types::transaction::SignatureCheckedTransaction; use vm_cache_map::Arena; pub mod execute; @@ -21,7 +21,7 @@ where 'alloc: 'txn, P: ModuleCache<'alloc>, { - txn: SignedTransaction, + txn: SignatureCheckedTransaction, module_cache: P, data_cache: &'txn RemoteCache, allocator: &'txn Arena, @@ -35,7 +35,7 @@ where { /// Creates a new instance of `ProcessTransaction`. pub fn new( - txn: SignedTransaction, + txn: SignatureCheckedTransaction, module_cache: P, data_cache: &'txn RemoteCache, allocator: &'txn Arena, diff --git a/language/vm/vm_runtime/src/process_txn/validate.rs b/language/vm/vm_runtime/src/process_txn/validate.rs index b765b37307f9..90289feb360e 100644 --- a/language/vm/vm_runtime/src/process_txn/validate.rs +++ b/language/vm/vm_runtime/src/process_txn/validate.rs @@ -78,13 +78,6 @@ where allocator, .. } = process_txn; - let txn = match txn.check_signature() { - Ok(txn) => txn, - Err(_) => { - error!("[VM] Invalid signature"); - return Err(VMStatus::Validation(VMValidationStatus::InvalidSignature)); - } - }; let txn_state = match txn.payload() { TransactionPayload::Program(program) => { diff --git a/language/vm/vm_runtime/src/runtime.rs b/language/vm/vm_runtime/src/runtime.rs index 8c3b7745520f..b93d154044b5 100644 --- a/language/vm/vm_runtime/src/runtime.rs +++ b/language/vm/vm_runtime/src/runtime.rs @@ -18,7 +18,7 @@ use logger::prelude::*; use state_view::StateView; use types::{ transaction::{SignedTransaction, TransactionOutput}, - vm_error::VMStatus, + vm_error::{VMStatus, VMValidationStatus}, }; use vm_cache_map::Arena; @@ -73,7 +73,13 @@ impl<'alloc> VMRuntime<'alloc> { let data_cache = BlockDataCache::new(data_view); let arena = Arena::new(); - let process_txn = ProcessTransaction::new(txn, module_cache, &data_cache, &arena); + let signature_verified_txn = match txn.check_signature() { + Ok(t) => t, + Err(_) => return Some(VMStatus::Validation(VMValidationStatus::InvalidSignature)), + }; + + let process_txn = + ProcessTransaction::new(signature_verified_txn, module_cache, &data_cache, &arena); let mode = if data_view.is_genesis() { ValidationMode::Genesis } else {