Skip to content

Instantly share code, notes, and snippets.

@pepyakin
Last active January 2, 2018 15:44
Show Gist options
  • Save pepyakin/74c5600c09b3b20326ab3f55dc1324fd to your computer and use it in GitHub Desktop.
Save pepyakin/74c5600c09b3b20326ab3f55dc1324fd to your computer and use it in GitHub Desktop.
#![feature(prelude_import)]
#![no_std]
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Temporary crate for contracts implementations.
//!
//! This will be replaced with WASM contracts stored on-chain.
//! ** NOTE ***
//! This is entirely deprecated with the idea of a single-module Wasm module for state transition.
//! The dispatch table should be replaced with the specific functions needed:
//! - execute_block(bytes)
//! - init_block(PrevBlock?) -> InProgressBlock
//! - add_transaction(InProgressBlock) -> InProgressBlock
//! I leave it as is for now as it might be removed before this is ever done.
#![warn(missing_docs)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
extern crate polkadot_primitives as primitives;
extern crate polkadot_serializer as serializer;
extern crate polkadot_state_machine as state_machine;
extern crate serde;
extern crate parity_wasm;
extern crate byteorder;
#[macro_use]
extern crate error_chain;
#[macro_use]
mod wasm_utils {
//! Rust implementation of Polkadot contracts.
use std::sync::Arc;
use std::collections::HashMap;
pub use std::result;
pub use parity_wasm::elements::{ValueType, Module};
pub use parity_wasm::interpreter::{RuntimeValue, UserFunctionDescriptor, UserFunctionExecutor,
UserDefinedElements, env_native_module, DummyUserError,
ExecutionParams, UserError};
pub use parity_wasm::builder;
use parity_wasm::interpreter;
pub type Error = interpreter::Error<DummyUserError>;
pub type MemoryInstance = interpreter::MemoryInstance<DummyUserError>;
pub type ModuleInstance = interpreter::ModuleInstance<DummyUserError>;
pub type CallerContext<'a> = interpreter::CallerContext<'a, DummyUserError>;
pub trait ConvertibleToWasm {
const VALUE_TYPE: ValueType;
type NativeType;
fn to_runtime_value(self) -> RuntimeValue;
}
impl ConvertibleToWasm for i32 {
type NativeType = i32;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I32(self)
}
}
impl ConvertibleToWasm for u32 {
type NativeType = u32;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I32(self as i32)
}
}
impl ConvertibleToWasm for i64 {
type NativeType = i64;
const VALUE_TYPE: ValueType = ValueType::I64;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I64(self)
}
}
impl ConvertibleToWasm for u64 {
type NativeType = u64;
const VALUE_TYPE: ValueType = ValueType::I64;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I64(self as i64)
}
}
impl ConvertibleToWasm for f32 {
type NativeType = f32;
const VALUE_TYPE: ValueType = ValueType::F32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::F32(self)
}
}
impl ConvertibleToWasm for f64 {
type NativeType = f64;
const VALUE_TYPE: ValueType = ValueType::F64;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::F64(self)
}
}
impl ConvertibleToWasm for isize {
type NativeType = i32;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I32(self as i32)
}
}
impl ConvertibleToWasm for usize {
type NativeType = u32;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I32(self as u32 as i32)
}
}
impl<T> ConvertibleToWasm for *const T {
type NativeType = u32;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I32(self as isize as i32)
}
}
impl<T> ConvertibleToWasm for *mut T {
type NativeType = u32;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_runtime_value(self) -> RuntimeValue {
RuntimeValue::I32(self as isize as i32)
}
}
#[macro_export]
macro_rules! convert_args(( ) => ( [ ] ) ; ( $ ( $ t : ty ) , * ) => (
[
$ (
{
use $ crate :: wasm_utils :: ConvertibleToWasm ;
< $ t > :: VALUE_TYPE } , ) * ] ) ;);
#[macro_export]
macro_rules! convert_fn(( $ name : ident ( $ ( $ params : ty ) , * ) ) =>
(
$ crate :: wasm_utils :: UserFunctionDescriptor ::
Static (
stringify ! ( $ name ) , & convert_args ! (
$ ( $ params ) , * ) , None ) ) ; (
$ name : ident ( $ ( $ params : ty ) , * ) -> $
returns : ty ) => (
$ crate :: wasm_utils :: UserFunctionDescriptor ::
Static (
stringify ! ( $ name ) , & convert_args ! (
$ ( $ params ) , * ) , Some (
{
use $ crate :: wasm_utils :: ConvertibleToWasm ; <
$ returns > :: VALUE_TYPE } ) ) ) ;);
#[macro_export]
macro_rules! reverse_params((
$ body : tt , $ self : ident , $ context :
ident , $ ( $ names : ident : $ params : ty )
, * ) => (
reverse_params ! (
$ body $ self $ context [
$ ( $ names : $ params ) , * ] ) ; ) ; (
$ body : tt $ self : ident $ context : ident [
] $ ( $ names : ident : $ params : ty ) , * )
=> (
{
$ (
let $ names : < $ params as $ crate ::
wasm_utils :: ConvertibleToWasm > ::
NativeType = match $ context . value_stack .
pop_as ( ) {
Ok ( value ) => value , Err ( error ) =>
return Err ( error . into ( ) ) , } ; ) * $
body } ) ; (
$ body : tt $ self : ident $ context : ident [
$ name : ident : $ param : ty $ (
, $ names : ident : $ params : ty ) * ] $ (
$ reversed_names : ident : $ reversed_params :
ty ) , * ) => (
reverse_params ! (
$ body $ self $ context [
$ ( $ names : $ params ) , * ] $ name : $
param $ (
, $ reversed_names : $ reversed_params ) * ) ;
) ;);
#[macro_export]
macro_rules! marshall((
$ context : ident , $ self : ident , (
$ ( $ names : ident : $ params : ty ) , * ) -> $
returns : ty => $ body : tt ) => (
{
let r : < $ returns as $ crate :: wasm_utils ::
ConvertibleToWasm > :: NativeType = reverse_params !
(
$ body , $ self , $ context , $ ( $ names : $ params
) , * ) ; Ok (
Some (
{
use $ crate :: wasm_utils :: ConvertibleToWasm ; r .
to_runtime_value ( ) } ) ) } ) ; (
$ context : ident , $ self : ident , (
$ ( $ names : ident : $ params : ty ) , * ) => $
body : tt ) => (
{
reverse_params ! (
$ body , $ self , $ context , $ ( $ names : $ params
) , * ) ; Ok ( None ) } ));
#[macro_export]
macro_rules! dispatch((
$ objectname : ident , $ (
$ name : ident (
$ ( $ names : ident : $ params : ty ) , * ) $ (
-> $ returns : ty ) * => $ body : tt ) , * ) => (
fn execute (
& mut self , name : & str , context : $ crate ::
wasm_utils :: CallerContext ) -> $ crate ::
wasm_utils :: result :: Result < Option < $ crate ::
wasm_utils :: RuntimeValue > , $ crate :: wasm_utils
:: Error > {
let $ objectname = self ; match name {
$ (
stringify ! ( $ name ) => marshall ! (
context , $ objectname , (
$ ( $ names : $ params ) , * ) $ ( -> $ returns ) *
=> $ body ) , ) * _ => panic ! ( ) } } ) ;);
#[macro_export]
macro_rules! signatures((
$ (
$ name : ident ( $ ( $ params : ty ) , * ) $ (
-> $ returns : ty ) * ) , * ) => (
const SIGNATURES : & 'static [
$ crate :: wasm_utils :: UserFunctionDescriptor ]
= & [
$ (
convert_fn ! (
$ name ( $ ( $ params ) , * ) $ ( -> $ returns ) *
) , ) * ] ; ) ;);
pub trait IntoUserDefinedElements {
fn into_user_defined_elements(&mut self) -> UserDefinedElements<DummyUserError>;
}
#[macro_export]
macro_rules! impl_function_executor((
$ objectname : ident : $ structname :
ty , $ (
$ name : ident (
$ ( $ names : ident : $ params : ty )
, * ) $ ( -> $ returns : ty ) * => $
body : tt ) , * => $ ( $ pre : tt ) +
) => (
impl $ ( $ pre ) + $ crate ::
wasm_utils :: UserFunctionExecutor < $
crate :: wasm_utils :: DummyUserError
> for $ structname {
dispatch ! (
$ objectname , $ (
$ name ( $ ( $ names : $ params ) , *
) $ ( -> $ returns ) * => $ body ) , *
) ; } impl $ ( $ pre ) + $ structname
{
signatures ! (
$ (
$ name ( $ ( $ params ) , * ) $ (
-> $ returns ) * ) , * ) ; } impl $ (
$ pre ) + $ crate :: wasm_utils ::
IntoUserDefinedElements for $
structname {
fn into_user_defined_elements (
& mut self ) -> UserDefinedElements <
$ crate :: wasm_utils ::
DummyUserError > {
$ crate :: wasm_utils ::
UserDefinedElements {
executor : Some ( self ) , globals :
HashMap :: new ( ) , functions : ::
std :: borrow :: Cow :: from (
Self :: SIGNATURES ) , } } } ) ;);
struct DummyUserFunctionExecutor;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::clone::Clone for DummyUserFunctionExecutor {
#[inline]
fn clone(&self) -> DummyUserFunctionExecutor {
match *self {
DummyUserFunctionExecutor => DummyUserFunctionExecutor,
}
}
}
impl<E: UserError> interpreter::UserFunctionExecutor<E> for DummyUserFunctionExecutor {
fn execute(
&mut self,
_name: &str,
_context: interpreter::CallerContext<E>,
) -> result::Result<Option<interpreter::RuntimeValue>, interpreter::Error<E>> {
{
::rt::begin_panic("not yet implemented", &("src/wasm_utils.rs", 160u32, 2u32))
}
}
}
pub trait AddModuleWithoutFullDependentInstance {
fn add_module_by_sigs(
&self,
name: &str,
module: Module,
functions: HashMap<&str, &'static [UserFunctionDescriptor]>,
) -> result::Result<
Arc<interpreter::ModuleInstance<DummyUserError>>,
interpreter::Error<DummyUserError>,
>;
fn params_with_external<'a, 'b: 'a>(
&'b self,
externals_name: &str,
externals: &'a mut IntoUserDefinedElements,
) -> ExecutionParams<'a, DummyUserError>;
}
impl AddModuleWithoutFullDependentInstance for interpreter::ProgramInstance<DummyUserError> {
fn add_module_by_sigs(
&self,
name: &str,
module: Module,
functions: HashMap<&str, &'static [UserFunctionDescriptor]>,
) -> result::Result<
Arc<interpreter::ModuleInstance<DummyUserError>>,
interpreter::Error<DummyUserError>,
> {
let mut dufe = ::vec::from_elem(DummyUserFunctionExecutor, functions.len());
let dufe_refs = dufe.iter_mut().collect::<Vec<_>>();
let fake_module_map =
functions.into_iter().zip(dufe_refs.into_iter()).map(|((dep_mod_name,
functions),
dufe)|
{
let fake_module =
Arc::new(interpreter::env_native_module(self.module(dep_mod_name).unwrap(),
UserDefinedElements{executor:
Some(dufe),
globals:
HashMap::new(),
functions:
::std::borrow::Cow::from(functions),}).unwrap());
let fake_module:
Arc<interpreter::ModuleInstanceInterface<_>> =
fake_module;
(dep_mod_name.into(),
fake_module)
}).collect::<HashMap<_,
_>>();
self.add_module(name, module, Some(&fake_module_map))
}
fn params_with_external<'a, 'b: 'a>(
&'b self,
externals_name: &str,
externals: &'a mut IntoUserDefinedElements,
) -> ExecutionParams<'a, DummyUserError> {
interpreter::ExecutionParams::with_external(
externals_name.into(),
Arc::new(
interpreter::env_native_module(
self.module(externals_name).unwrap(),
externals.into_user_defined_elements(),
).unwrap(),
),
)
}
}
#[macro_export]
macro_rules! map(( $ ( $ name : expr => $ value : expr ) , * ) => (
vec ! [ $ ( ( $ name , $ value ) ) , * ] . into_iter ( )
. collect ( ) ));
}
mod wasm_executor {
//! Rust implementation of Polkadot contracts.
use parity_wasm::{deserialize_buffer, ModuleInstanceInterface, ProgramInstance};
use parity_wasm::interpreter::ItemIndex;
use parity_wasm::RuntimeValue::{I32, I64};
use std::collections::HashMap;
use primitives::contract::CallData;
use state_machine::{Externalities, CodeExecutor};
use error::{Error, ErrorKind, Result};
use std::sync::Arc;
use wasm_utils::{ModuleInstance, MemoryInstance, UserDefinedElements,
AddModuleWithoutFullDependentInstance};
struct Heap {
end: u32,
}
impl Heap {
fn new() -> Self {
Heap { end: 1024 }
}
fn allocate(&mut self, size: u32) -> u32 {
let r = self.end;
self.end += size;
r
}
fn deallocate(&mut self, _offset: u32) {}
}
struct FunctionExecutor<'e, E: Externalities + 'e> {
heap: Heap,
memory: Arc<MemoryInstance>,
ext: &'e mut E,
}
impl<'e, E: Externalities> FunctionExecutor<'e, E> {
fn new(m: &Arc<ModuleInstance>, e: &'e mut E) -> Self {
FunctionExecutor {
heap: Heap::new(),
memory: Arc::clone(&m.memory(ItemIndex::Internal(0)).unwrap()),
ext: e,
}
}
}
impl<'e, E: Externalities + 'e> ::wasm_utils::UserFunctionExecutor<::wasm_utils::DummyUserError>
for FunctionExecutor<'e, E> {
fn execute(
&mut self,
name: &str,
context: ::wasm_utils::CallerContext,
) -> ::wasm_utils::result::Result<Option<::wasm_utils::RuntimeValue>, ::wasm_utils::Error> {
let this = self;
match name {
"imported" => {
let r: <u64 as ::wasm_utils::ConvertibleToWasm>::NativeType =
{
let n:
<u64 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
::io::_print(::std::fmt::Arguments::new_v1_formatted(
&["imported ", "\n"],
&match (&n,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(
__arg0,
::std::fmt::Debug::fmt,
),
]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
));
n + 1
}
};
Ok(Some({
use wasm_utils::ConvertibleToWasm;
r.to_runtime_value()
}))
}
"ext_memcpy" => {
let r:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
{
let count:
<usize as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let src:
<*const u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let dest:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
this.memory.copy_nonoverlapping(src as usize,
dest as usize,
count as
usize).unwrap();
::io::_print(::std::fmt::Arguments::new_v1_formatted(&["memcpy ",
" from ",
", ",
" bytes\n"],
&match (&dest,
&src,
&count)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
},
&[::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(0usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(1usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(2usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},}]));
dest
}
};
Ok(Some({
use wasm_utils::ConvertibleToWasm;
r.to_runtime_value()
}))
}
"ext_memmove" => {
let r:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
{
let count:
<usize as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let src:
<*const u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let dest:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
::io::_print(::std::fmt::Arguments::new_v1_formatted(&["memmove ",
" from ",
", ",
" bytes\n"],
&match (&dest,
&src,
&count)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
},
&[::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(0usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(1usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(2usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},}]));
dest
}
};
Ok(Some({
use wasm_utils::ConvertibleToWasm;
r.to_runtime_value()
}))
}
"ext_memset" => {
let r:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
{
let count:
<usize as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let val:
<i32 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let dest:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
::io::_print(::std::fmt::Arguments::new_v1_formatted(&["memset ",
" with ",
", ",
" bytes\n"],
&match (&dest,
&val,
&count)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
},
&[::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(0usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(1usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(2usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},}]));
dest
}
};
Ok(Some({
use wasm_utils::ConvertibleToWasm;
r.to_runtime_value()
}))
}
"ext_malloc" => {
let r:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
{
let size:
<usize as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
let r = this.heap.allocate(size);
::io::_print(::std::fmt::Arguments::new_v1_formatted(&["malloc ",
" bytes at ",
"\n"],
&match (&size,
&r)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
},
&[::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(0usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::At(1usize),
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},}]));
r
}
};
Ok(Some({
use wasm_utils::ConvertibleToWasm;
r.to_runtime_value()
}))
}
"ext_free" => {
{
let addr:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
this.heap.deallocate(addr);
::io::_print(::std::fmt::Arguments::new_v1_formatted(
&["free ", "\n"],
&match (&addr,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(
__arg0,
::std::fmt::Display::fmt,
),
]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
))
}
};
Ok(None)
}
"set_storage" => {
{
let value_len:
<i32 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let value_data:
<*const u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let key_len:
<i32 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let key_data:
<*const u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
if let (Ok(key), Ok(value)) =
(
this.memory.get(key_data, key_len as usize),
this.memory.get(value_data, value_len as usize),
)
{
this.ext.set_storage(0, key, value);
}
}
};
Ok(None)
}
"get_allocated_storage" => {
let r:
<*mut u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
{
let written_out:
<*mut i32 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let key_len:
<i32 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
let key_data:
<*const u8 as
::wasm_utils::ConvertibleToWasm>::NativeType =
match context.value_stack.pop_as() {
Ok(value) => value,
Err(error) => return Err(error.into()),
};
{
let (offset, written) =
if let Ok(key) =
this.memory.get(key_data,
key_len as usize) {
if let Ok(value) =
this.ext.storage(0, &key) {
let offset =
this.heap.allocate(value.len()
as u32)
as u32;
let _ =
this.memory.set(offset,
value);
(offset, value.len() as u32)
} else { (0, 0) }
} else { (0, 0) };
if written > 0 {
use byteorder::{LittleEndian, ByteOrder};
let mut r = [0u8; 4];
LittleEndian::write_u32(&mut r, written);
let _ = this.memory.set(written_out, &r);
}
offset as u32
}
};
Ok(Some({
use wasm_utils::ConvertibleToWasm;
r.to_runtime_value()
}))
}
_ => {
::rt::begin_panic("explicit panic", &("src/wasm_executor.rs", 64u32, 0u32))
}
}
}
}
impl<'e, E: Externalities + 'e> FunctionExecutor<'e, E> {
const SIGNATURES: &'static [::wasm_utils::UserFunctionDescriptor] =
&[
::wasm_utils::UserFunctionDescriptor::Static(
"imported",
&[
{
use wasm_utils::ConvertibleToWasm;
<u64>::VALUE_TYPE
},
],
Some({
use wasm_utils::ConvertibleToWasm;
<u64>::VALUE_TYPE
}),
),
::wasm_utils::UserFunctionDescriptor::Static(
"ext_memcpy",
&[
{
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<*const u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<usize>::VALUE_TYPE
},
],
Some({
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
}),
),
::wasm_utils::UserFunctionDescriptor::Static(
"ext_memmove",
&[
{
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<*const u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<usize>::VALUE_TYPE
},
],
Some({
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
}),
),
::wasm_utils::UserFunctionDescriptor::Static(
"ext_memset",
&[
{
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<i32>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<usize>::VALUE_TYPE
},
],
Some({
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
}),
),
::wasm_utils::UserFunctionDescriptor::Static(
"ext_malloc",
&[
{
use wasm_utils::ConvertibleToWasm;
<usize>::VALUE_TYPE
},
],
Some({
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
}),
),
::wasm_utils::UserFunctionDescriptor::Static(
"ext_free",
&[
{
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
},
],
None,
),
::wasm_utils::UserFunctionDescriptor::Static(
"set_storage",
&[
{
use wasm_utils::ConvertibleToWasm;
<*const u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<i32>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<*const u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<i32>::VALUE_TYPE
},
],
None,
),
::wasm_utils::UserFunctionDescriptor::Static(
"get_allocated_storage",
&[
{
use wasm_utils::ConvertibleToWasm;
<*const u8>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<i32>::VALUE_TYPE
},
{
use wasm_utils::ConvertibleToWasm;
<*mut i32>::VALUE_TYPE
},
],
Some({
use wasm_utils::ConvertibleToWasm;
<*mut u8>::VALUE_TYPE
}),
),
];
}
impl<'e, E: Externalities + 'e> ::wasm_utils::IntoUserDefinedElements for FunctionExecutor<'e, E> {
fn into_user_defined_elements(
&mut self,
) -> UserDefinedElements<::wasm_utils::DummyUserError> {
::wasm_utils::UserDefinedElements {
executor: Some(self),
globals: HashMap::new(),
functions: ::std::borrow::Cow::from(Self::SIGNATURES),
}
}
}
/// Dummy rust executor for contracts.
///
/// Instead of actually executing the provided code it just
/// dispatches the calls to pre-defined hardcoded implementations in rust.
pub struct WasmExecutor;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::fmt::Debug for WasmExecutor {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
WasmExecutor => {
let mut builder = __arg_0.debug_tuple("WasmExecutor");
builder.finish()
}
}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::default::Default for WasmExecutor {
#[inline]
fn default() -> WasmExecutor {
WasmExecutor
}
}
impl CodeExecutor for WasmExecutor {
type Error = Error;
fn call<E: Externalities>(
&self,
ext: &mut E,
method: &str,
data: &CallData,
) -> Result<u64> {
let code = match ext.code() {
Ok(e) => e.to_owned(),
Err(e) => Err(ErrorKind::Externalities(Box::new(e)))?,
};
let program = ProgramInstance::new().unwrap();
let module = deserialize_buffer(code).expect("Failed to load module");
let module = program
.add_module_by_sigs(
"test",
module,
<[_]>::into_vec(box [("env", FunctionExecutor::<E>::SIGNATURES)])
.into_iter()
.collect(),
)
.expect("Failed to initialize module");
let mut fec = FunctionExecutor::new(&module, ext);
let size = data.0.len() as u32;
let offset = fec.heap.allocate(size);
module
.memory(ItemIndex::Internal(0))
.unwrap()
.set(offset, &data.0)
.unwrap();
let r = module
.execute_export(
method,
program
.params_with_external("env", &mut fec)
.add_argument(I32(offset as i32))
.add_argument(I32(size as i32)),
)
.map_err(|_| ErrorKind::Runtime.into())
.and_then(|i| if let Some(I64(r)) = i {
Ok(r as u64)
} else {
Err(ErrorKind::InvalidReturn.into())
});
r
}
}
}
pub mod error {
//! Rust executor possible errors.
use serializer;
use state_machine;
/// The Error type.
///
/// This tuple struct is made of two elements:
///
/// - an `ErrorKind` which is used to determine the type of the error.
/// - An internal `State`, not meant for direct use outside of `error_chain`
/// internals, containing:
/// - a backtrace, generated when the error is created.
/// - an error chain, used for the implementation of `Error::cause()`.
pub struct Error(
/// The kind of the error.
pub ErrorKind,
/// Contains the error chain and the backtrace.
#[doc(hidden)]
pub ::State
);
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::fmt::Debug for Error {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Error(ref __self_0_0, ref __self_0_1) => {
let mut builder = __arg_0.debug_tuple("Error");
let _ = builder.field(&&(*__self_0_0));
let _ = builder.field(&&(*__self_0_1));
builder.finish()
}
}
}
}
impl ::ChainedError for Error {
type ErrorKind = ErrorKind;
fn new(kind: ErrorKind, state: ::State) -> Error {
Error(kind, state)
}
fn from_kind(kind: Self::ErrorKind) -> Self {
Self::from_kind(kind)
}
fn with_chain<E, K>(error: E, kind: K) -> Self
where
E: ::std::error::Error + Send + 'static,
K: Into<Self::ErrorKind>,
{
Self::with_chain(error, kind)
}
fn kind(&self) -> &Self::ErrorKind {
self.kind()
}
fn iter(&self) -> ::Iter {
::Iter::new(Some(self))
}
fn chain_err<F, EK>(self, error: F) -> Self
where
F: FnOnce() -> EK,
EK: Into<ErrorKind>,
{
self.chain_err(error)
}
fn backtrace(&self) -> Option<&::Backtrace> {
self.backtrace()
}
#[allow(unknown_lints, unused_doc_comment)]
fn extract_backtrace(
e: &(::std::error::Error + Send + 'static),
) -> Option<::std::sync::Arc<::Backtrace>> {
if let Some(e) = e.downcast_ref::<Error>() {
return e.1.backtrace.clone();
}
None
}
}
#[allow(dead_code)]
impl Error {
/// Constructs an error from a kind, and generates a backtrace.
pub fn from_kind(kind: ErrorKind) -> Error {
Error(kind, ::State::default())
}
/// Constructs a chained error from another error and a kind, and generates a backtrace.
pub fn with_chain<E, K>(error: E, kind: K) -> Error
where
E: ::std::error::Error + Send + 'static,
K: Into<ErrorKind>,
{
Error::with_boxed_chain(Box::new(error), kind)
}
/// Construct a chained error from another boxed error and a kind, and generates a backtrace
pub fn with_boxed_chain<K>(error: Box<::std::error::Error + Send>, kind: K) -> Error
where
K: Into<ErrorKind>,
{
Error(kind.into(), ::State::new::<Error>(error))
}
/// Returns the kind of the error.
pub fn kind(&self) -> &ErrorKind {
&self.0
}
/// Iterates over the error chain.
pub fn iter(&self) -> ::Iter {
::ChainedError::iter(self)
}
/// Returns the backtrace associated with this error.
pub fn backtrace(&self) -> Option<&::Backtrace> {
self.1.backtrace()
}
/// Extends the error chain with a new entry.
pub fn chain_err<F, EK>(self, error: F) -> Error
where
F: FnOnce() -> EK,
EK: Into<ErrorKind>,
{
Error::with_chain(self, Self::from_kind(error().into()))
}
}
impl ::std::error::Error for Error {
fn description(&self) -> &str {
self.0.description()
}
#[allow(unknown_lints, unused_doc_comment)]
fn cause(&self) -> Option<&::std::error::Error> {
match self.1.next_error {
Some(ref c) => Some(&**c),
None => {
match self.0 {
#[doc = "Unserializable Data"]
ErrorKind::InvalidData(ref foreign_err) => foreign_err.cause(),
_ => None,
}
}
}
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::std::fmt::Display::fmt(&self.0, f)
}
}
#[doc = "Unserializable Data"]
impl From<serializer::Error> for Error {
fn from(e: serializer::Error) -> Self {
Error::from_kind(ErrorKind::InvalidData(e))
}
}
impl From<ErrorKind> for Error {
fn from(e: ErrorKind) -> Self {
Error::from_kind(e)
}
}
impl<'a> From<&'a str> for Error {
fn from(s: &'a str) -> Self {
Error::from_kind(s.into())
}
}
impl From<String> for Error {
fn from(s: String) -> Self {
Error::from_kind(s.into())
}
}
impl ::std::ops::Deref for Error {
type Target = ErrorKind;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[doc = r" The kind of an error."]
pub enum ErrorKind {
#[doc = r" A convenient variant for String."]
Msg(String),
#[doc = "Unserializable Data"]
InvalidData(serializer::Error),
#[doc = r" Method is not found"]
MethodNotFound(String),
#[doc = r" Code is invalid (expected single byte)"]
InvalidCode(Vec<u8>),
#[doc = r" Externalities have failed."]
Externalities(Box<state_machine::Error>),
#[doc = r" Invalid return type."]
InvalidReturn,
#[doc = r" Runtime failed."]
Runtime,
#[doc(hidden)]
__Nonexhaustive {},
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::fmt::Debug for ErrorKind {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match (&*self,) {
(&ErrorKind::Msg(ref __self_0),) => {
let mut builder = __arg_0.debug_tuple("Msg");
let _ = builder.field(&&(*__self_0));
builder.finish()
}
(&ErrorKind::InvalidData(ref __self_0),) => {
let mut builder = __arg_0.debug_tuple("InvalidData");
let _ = builder.field(&&(*__self_0));
builder.finish()
}
(&ErrorKind::MethodNotFound(ref __self_0),) => {
let mut builder = __arg_0.debug_tuple("MethodNotFound");
let _ = builder.field(&&(*__self_0));
builder.finish()
}
(&ErrorKind::InvalidCode(ref __self_0),) => {
let mut builder = __arg_0.debug_tuple("InvalidCode");
let _ = builder.field(&&(*__self_0));
builder.finish()
}
(&ErrorKind::Externalities(ref __self_0),) => {
let mut builder = __arg_0.debug_tuple("Externalities");
let _ = builder.field(&&(*__self_0));
builder.finish()
}
(&ErrorKind::InvalidReturn,) => {
let mut builder = __arg_0.debug_tuple("InvalidReturn");
builder.finish()
}
(&ErrorKind::Runtime,) => {
let mut builder = __arg_0.debug_tuple("Runtime");
builder.finish()
}
(&ErrorKind::__Nonexhaustive {},) => {
let mut builder = __arg_0.debug_struct("__Nonexhaustive");
builder.finish()
}
}
}
}
#[allow(unknown_lints, unused, unused_doc_comment)]
impl ::std::fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
#[doc = r" A convenient variant for String."]
ErrorKind::Msg(ref s) => {
let display_fn =
|_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1_formatted(
&[""],
&match (&s,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(
__arg0,
::std::fmt::Display::fmt,
),
]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
))
};
display_fn(self, fmt)
}
#[doc = "Unserializable Data"]
ErrorKind::InvalidData(ref err) => {
let display_fn =
|_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1_formatted(
&[""],
&match (&err,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(
__arg0,
::std::fmt::Display::fmt,
),
]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
))
};
display_fn(self, fmt)
}
#[doc = r" Method is not found"]
ErrorKind::MethodNotFound(ref t) => {
let display_fn =
|_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1_formatted(
&["Method not found: \'", "\'"],
&match (&t,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(
__arg0,
::std::fmt::Display::fmt,
),
]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
))
};
display_fn(self, fmt)
}
#[doc = r" Code is invalid (expected single byte)"]
ErrorKind::InvalidCode(ref c) => {
let display_fn = |_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1_formatted(
&["Invalid Code: "],
&match (&c,) {
(__arg0,) => {
[::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
))
};
display_fn(self, fmt)
}
#[doc = r" Externalities have failed."]
ErrorKind::Externalities(ref e) => {
let display_fn =
|_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1_formatted(
&["Externalities error: "],
&match (&e,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(
__arg0,
::std::fmt::Display::fmt,
),
]
}
},
&[
::std::fmt::rt::v1::Argument {
position: ::std::fmt::rt::v1::Position::At(0usize),
format: ::std::fmt::rt::v1::FormatSpec {
fill: ' ',
align: ::std::fmt::rt::v1::Alignment::Unknown,
flags: 0u32,
precision: ::std::fmt::rt::v1::Count::Implied,
width: ::std::fmt::rt::v1::Count::Implied,
},
},
],
))
};
display_fn(self, fmt)
}
#[doc = r" Invalid return type."]
ErrorKind::InvalidReturn => {
let display_fn = |_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1(
&["Invalid type returned (should be u64)"],
&match () {
()
=>
[],
},
))
};
display_fn(self, fmt)
}
#[doc = r" Runtime failed."]
ErrorKind::Runtime => {
let display_fn = |_, f: &mut ::std::fmt::Formatter| {
f.write_fmt(::std::fmt::Arguments::new_v1(
&["Runtime error"],
&match () {
()
=>
[],
},
))
};
display_fn(self, fmt)
}
_ => Ok(()),
}
}
}
#[allow(unknown_lints, unused, unused_doc_comment)]
impl ErrorKind {
/// A string describing the error kind.
pub fn description(&self) -> &str {
match *self {
#[doc = r" A convenient variant for String."]
ErrorKind::Msg(ref s) => &s,
#[doc = "Unserializable Data"]
ErrorKind::InvalidData(ref err) => ::std::error::Error::description(err),
#[doc = r" Method is not found"]
ErrorKind::MethodNotFound(ref t) => "method not found",
#[doc = r" Code is invalid (expected single byte)"]
ErrorKind::InvalidCode(ref c) => "invalid code",
#[doc = r" Externalities have failed."]
ErrorKind::Externalities(ref e) => "externalities failure",
#[doc = r" Invalid return type."]
ErrorKind::InvalidReturn => "u64 was not returned",
#[doc = r" Runtime failed."]
ErrorKind::Runtime => "runtime failure",
_ => "",
}
}
}
impl<'a> From<&'a str> for ErrorKind {
fn from(s: &'a str) -> Self {
ErrorKind::Msg(s.to_string())
}
}
impl From<String> for ErrorKind {
fn from(s: String) -> Self {
ErrorKind::Msg(s)
}
}
impl From<Error> for ErrorKind {
fn from(e: Error) -> Self {
e.0
}
}
/// Additional methods for `Result`, for easy interaction with this crate.
pub trait ResultExt<T> {
/// If the `Result` is an `Err` then `chain_err` evaluates the closure,
/// which returns *some type that can be converted to `ErrorKind`*, boxes
/// the original error to store as the cause, then returns a new error
/// containing the original error.
fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, Error>
where
F: FnOnce() -> EK,
EK: Into<ErrorKind>;
}
impl<T, E> ResultExt<T> for ::std::result::Result<T, E>
where
E: ::std::error::Error + Send + 'static,
{
fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, Error>
where
F: FnOnce() -> EK,
EK: Into<ErrorKind>,
{
self.map_err(move |e| {
let state = ::State::new::<Error>(Box::new(e));
::ChainedError::new(callback().into(), state)
})
}
}
impl<T> ResultExt<T> for ::std::option::Option<T> {
fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, Error>
where
F: FnOnce() -> EK,
EK: Into<ErrorKind>,
{
self.ok_or_else(move || ::ChainedError::from_kind(callback().into()))
}
}
/// Convenient wrapper around `std::Result`.
#[allow(unused)]
pub type Result<T> = ::std::result::Result<T, Error>;
}
/// Creates new RustExecutor for contracts.
pub fn executor() -> wasm_executor::WasmExecutor {
wasm_executor::WasmExecutor::default()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment