Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ded8fdb
Adds benchmark for direct/indirect wasm function calls
bkchr Feb 13, 2019
a8052d1
Store the benchmark function pointer in a `Cell`
bkchr Feb 14, 2019
456ddac
Add some documentation
bkchr Feb 14, 2019
c9a5b11
Make function implementations exchangeable
bkchr Feb 25, 2019
0638c55
Add parachain stub
bkchr Feb 26, 2019
7bb9d20
Add macro for registering the `validate_block` function
bkchr Feb 26, 2019
3d650b9
Make all functions replace-able by unimplemented
bkchr Mar 1, 2019
b41e6d0
Some more refactoring
bkchr Mar 1, 2019
b1c99b8
Adds tests for executing empty parachain block
bkchr Mar 4, 2019
2524f95
Work on a new test with empty witness data
bkchr Mar 4, 2019
4e6e32d
Don't exchange `ext_print_*` stuff
bkchr Mar 5, 2019
603897b
Some cleanup and one more function for `validate_block`
bkchr Mar 5, 2019
c1630ea
More tests and more functions
bkchr Mar 5, 2019
e4962c9
Merge branch 'master' into bkchr-validate_block
bkchr Mar 5, 2019
ab63852
Fixes after merging master
bkchr Mar 5, 2019
eeab2ce
Use `parity-codec` `derive` feature
bkchr Mar 5, 2019
481749d
CHange implementation of `wasm-nice-panic-message`
bkchr Mar 6, 2019
73f282f
Move `parachain` stuff to cumulus
bkchr Mar 6, 2019
8090c35
devops-parity updated wasm runtime blobs 98cfecb1 and merged in maste…
devops-parity Mar 6, 2019
e1124fb
Merge remote-tracking branch 'origin/master' into bkchr-validate_block
bkchr Mar 7, 2019
dd09ee6
Updated wasm files
bkchr Mar 7, 2019
d0b1f5a
Merge branch 'master' into bkchr-validate_block
bkchr Mar 11, 2019
9e20490
Integrate feedback
bkchr Mar 11, 2019
ea99855
Switch to `ExchangeableFunction` struct
bkchr Mar 11, 2019
682eafa
More fixes
bkchr Mar 11, 2019
c0131c2
Merge remote-tracking branch 'origin/master' into bkchr-validate_block
bkchr Mar 13, 2019
f958f0f
Switch to Cell and panic on multiple replaces
bkchr Mar 14, 2019
99823e8
Increase `impl_version`
bkchr Mar 14, 2019
b382c7f
Fix shifting
bkchr Mar 14, 2019
7f390ce
Make the API more verbose of `ExchangeableFunction`
bkchr Mar 14, 2019
a8e8b0b
devops-parity updated wasm runtime blobs 99191521 and merged in maste…
devops-parity Mar 14, 2019
3800235
Increase `impl_version`
bkchr Mar 14, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 78 additions & 22 deletions core/executor/src/wasm_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use secp256k1;
use wasmi::{
Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef,
};
use wasmi::RuntimeValue::{I32, I64};
use wasmi::RuntimeValue::{I32, I64, self};
use wasmi::memory_units::{Pages};
use state_machine::Externalities;
use crate::error::{Error, ErrorKind, Result};
Expand Down Expand Up @@ -393,10 +393,12 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
.map_err(|_| UserError("Invalid attempt to get parent_hash in ext_storage_changes_root"))?;
parent_hash.as_mut().copy_from_slice(&raw_parent_hash[..]);
let r = this.ext.storage_changes_root(parent_hash, parent_number);
if let Some(ref r) = r {
if let Some(r) = r {
this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?;
Ok(1)
} else {
Ok(0)
}
Ok(if r.is_some() { 1u32 } else { 0u32 })
},
ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => {
let values = (0..lens_len)
Expand Down Expand Up @@ -637,17 +639,19 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
///
/// Executes the provided code in a sandboxed wasm runtime.
#[derive(Debug, Clone)]
pub struct WasmExecutor {
}
pub struct WasmExecutor;

impl WasmExecutor {

/// Create a new instance.
pub fn new() -> Self {
WasmExecutor{}
WasmExecutor
}

/// Call a given method in the given code.
///
/// Signature of this method needs to be `(I32, I32) -> I64`.
///
/// This should be used for tests only.
pub fn call<E: Externalities<Blake2Hasher>>(
&self,
Expand All @@ -656,12 +660,34 @@ impl WasmExecutor {
code: &[u8],
method: &str,
data: &[u8],
) -> Result<Vec<u8>> {
) -> Result<Vec<u8>> {
let module = ::wasmi::Module::from_buffer(code)?;
let module = self.prepare_module(ext, heap_pages, &module)?;
self.call_in_wasm_module(ext, &module, method, data)
}

/// Call a given method with a custom signature in the given code.
///
/// This should be used for tests only.
pub fn call_with_custom_signature<
E: Externalities<Blake2Hasher>,
F: FnOnce(&mut FnMut(&[u8]) -> Result<u32>) -> Result<Vec<RuntimeValue>>,
FR: FnOnce(Option<RuntimeValue>, &MemoryRef) -> Result<Option<R>>,
R,
>(
&self,
ext: &mut E,
heap_pages: usize,
code: &[u8],
method: &str,
create_parameters: F,
filter_result: FR,
) -> Result<R> {
let module = wasmi::Module::from_buffer(code)?;
let module = self.prepare_module(ext, heap_pages, &module)?;
self.call_in_wasm_module_with_custom_signature(ext, &module, method, create_parameters, filter_result)
}

fn get_mem_instance(module: &ModuleRef) -> Result<MemoryRef> {
Ok(module
.export_by_name("memory")
Expand All @@ -679,6 +705,40 @@ impl WasmExecutor {
method: &str,
data: &[u8],
) -> Result<Vec<u8>> {
self.call_in_wasm_module_with_custom_signature(
ext,
module_instance,
method,
|alloc| {
let offset = alloc(data)?;
Ok(vec![I32(offset as i32), I32(data.len() as i32)])
},
|res, memory| {
if let Some(I64(r)) = res {
let offset = r as u32;
let length = (r as u64 >> 32) as usize;
memory.get(offset, length).map_err(|_| ErrorKind::Runtime.into()).map(Some)
} else {
Ok(None)
}
}
)
}

/// Call a given method in the given wasm-module runtime.
fn call_in_wasm_module_with_custom_signature<
E: Externalities<Blake2Hasher>,
F: FnOnce(&mut FnMut(&[u8]) -> Result<u32>) -> Result<Vec<RuntimeValue>>,
FR: FnOnce(Option<RuntimeValue>, &MemoryRef) -> Result<Option<R>>,
R,
>(
&self,
ext: &mut E,
module_instance: &ModuleRef,
method: &str,
create_parameters: F,
filter_result: FR,
) -> Result<R> {
// extract a reference to a linear memory, optional reference to a table
// and then initialize FunctionExecutor.
let memory = Self::get_mem_instance(module_instance)?;
Expand All @@ -689,26 +749,22 @@ impl WasmExecutor {
let low = memory.lowest_used();
let used_mem = memory.used_size();
let mut fec = FunctionExecutor::new(memory.clone(), table, ext)?;
let size = data.len() as u32;
let offset = fec.heap.allocate(size).map_err(|_| ErrorKind::Runtime)?;
memory.set(offset, &data)?;
let parameters = create_parameters(&mut |data: &[u8]| {
let offset = fec.heap.allocate(data.len() as u32).map_err(|_| ErrorKind::Runtime)?;
memory.set(offset, &data)?;
Ok(offset)
})?;

let result = module_instance.invoke_export(
method,
&[
I32(offset as i32),
I32(size as i32)
],
&parameters,
&mut fec
);
let result = match result {
Ok(Some(I64(r))) => {
let offset = r as u32;
let length = (r >> 32) as u32 as usize;
memory.get(offset, length)
.map_err(|_| ErrorKind::Runtime.into())
Ok(val) => match filter_result(val, &memory)? {
Some(val) => Ok(val),
None => Err(ErrorKind::InvalidReturn.into()),
},
Ok(_) => Err(ErrorKind::InvalidReturn.into()),
Err(e) => {
trace!(target: "wasm-executor", "Failed to execute code with {} pages", memory.current_size().0);
Err(e.into())
Expand Down Expand Up @@ -738,7 +794,7 @@ impl WasmExecutor {
module,
&ImportsBuilder::new()
.with_resolver("env", FunctionExecutor::<E>::resolver())
)?;
)?;

// extract a reference to a linear memory, optional reference to a table
// and then initialize FunctionExecutor.
Expand All @@ -759,7 +815,7 @@ impl WasmExecutor {
#[cfg(test)]
mod tests {
use super::*;

use parity_codec::Encode;

use state_machine::TestExternalities;
Expand Down
15 changes: 14 additions & 1 deletion core/sr-api-macros/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

use criterion::Criterion;
use criterion::{Criterion, criterion_group, criterion_main};
use test_client::runtime::TestAPI;
use runtime_primitives::{generic::BlockId, traits::ProvideRuntimeApi};
use state_machine::ExecutionStrategy;

fn sr_api_benchmark(c: &mut Criterion) {
c.bench_function("add one with same runtime api", |b| {
Expand Down Expand Up @@ -50,6 +51,18 @@ fn sr_api_benchmark(c: &mut Criterion) {

b.iter_with_large_drop(|| client.runtime_api().benchmark_vector_add_one(&block_id, &data))
});

c.bench_function("calling function by function pointer in wasm", |b| {
let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm);
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
b.iter(|| client.runtime_api().benchmark_indirect_call(&block_id).unwrap())
});

c.bench_function("calling function in wasm", |b| {
let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm);
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
b.iter(|| client.runtime_api().benchmark_direct_call(&block_id).unwrap())
});
}

criterion_group!(benches, sr_api_benchmark);
Expand Down
1 change: 1 addition & 0 deletions core/sr-io/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ std = [
]
nightly = []
strict = []
wasm-nice-panic-message = []
Loading