WASM Runtime refactoring (#6596)
* refactoring to new pwasm-std * pass reference * remove ref * missing underscores
This commit is contained in:
parent
ec1a892f44
commit
4260910db6
@ -1 +1 @@
|
|||||||
Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a
|
Subproject commit c8129ce2f36c26ed634eda786960978a28e28d0e
|
@ -1,63 +0,0 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity 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.
|
|
||||||
|
|
||||||
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Wasm evm call arguments helper
|
|
||||||
|
|
||||||
use bigint::prelude::U256;
|
|
||||||
use bigint::hash::H160;
|
|
||||||
|
|
||||||
/// Input part of the wasm call descriptor
|
|
||||||
pub struct CallArgs {
|
|
||||||
/// Receiver of the transaction
|
|
||||||
pub address: [u8; 20],
|
|
||||||
|
|
||||||
/// Sender of the transaction
|
|
||||||
pub sender: [u8; 20],
|
|
||||||
|
|
||||||
/// Original transaction initiator
|
|
||||||
pub origin: [u8; 20],
|
|
||||||
|
|
||||||
/// Transfer value
|
|
||||||
pub value: [u8; 32],
|
|
||||||
|
|
||||||
/// call/create params
|
|
||||||
pub data: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CallArgs {
|
|
||||||
/// New contract call payload with known parameters
|
|
||||||
pub fn new(address: H160, sender: H160, origin: H160, value: U256, data: Vec<u8>) -> Self {
|
|
||||||
let mut descriptor = CallArgs {
|
|
||||||
address: [0u8; 20],
|
|
||||||
sender: [0u8; 20],
|
|
||||||
origin: [0u8; 20],
|
|
||||||
value: [0u8; 32],
|
|
||||||
data: data,
|
|
||||||
};
|
|
||||||
|
|
||||||
descriptor.address.copy_from_slice(&*address);
|
|
||||||
descriptor.sender.copy_from_slice(&*sender);
|
|
||||||
descriptor.origin.copy_from_slice(&*origin);
|
|
||||||
value.to_big_endian(&mut descriptor.value);
|
|
||||||
|
|
||||||
descriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Total call payload length in linear memory
|
|
||||||
pub fn len(&self) -> u32 {
|
|
||||||
self.data.len() as u32 + 92
|
|
||||||
}
|
|
||||||
}
|
|
@ -102,6 +102,26 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
&[I32],
|
&[I32],
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
Static(
|
||||||
|
"_sender",
|
||||||
|
&[I32],
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
Static(
|
||||||
|
"_origin",
|
||||||
|
&[I32],
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
Static(
|
||||||
|
"_address",
|
||||||
|
&[I32],
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
Static(
|
||||||
|
"_value",
|
||||||
|
&[I32],
|
||||||
|
None,
|
||||||
|
),
|
||||||
Static(
|
Static(
|
||||||
"_timestamp",
|
"_timestamp",
|
||||||
&[],
|
&[],
|
||||||
|
@ -27,7 +27,6 @@ extern crate wasm_utils;
|
|||||||
|
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod call_args;
|
|
||||||
mod result;
|
mod result;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@ -107,7 +106,12 @@ impl vm::Vm for WasmInterpreter {
|
|||||||
env_memory,
|
env_memory,
|
||||||
DEFAULT_STACK_SPACE,
|
DEFAULT_STACK_SPACE,
|
||||||
params.gas.low_u64(),
|
params.gas.low_u64(),
|
||||||
RuntimeContext::new(params.address, params.sender),
|
RuntimeContext {
|
||||||
|
address: params.address,
|
||||||
|
sender: params.sender,
|
||||||
|
origin: params.origin,
|
||||||
|
value: params.value.value(),
|
||||||
|
},
|
||||||
&self.program,
|
&self.program,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -121,15 +125,8 @@ impl vm::Vm for WasmInterpreter {
|
|||||||
})?
|
})?
|
||||||
);
|
);
|
||||||
|
|
||||||
let d_ptr = runtime.write_descriptor(
|
let d_ptr = runtime.write_descriptor(¶ms.data.unwrap_or_default())
|
||||||
call_args::CallArgs::new(
|
.map_err(Error)?;
|
||||||
params.address,
|
|
||||||
params.sender,
|
|
||||||
params.origin,
|
|
||||||
params.value.value(),
|
|
||||||
params.data.unwrap_or(Vec::with_capacity(0)),
|
|
||||||
)
|
|
||||||
).map_err(|e| Error(e))?;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let execution_params = runtime.execution_params()
|
let execution_params = runtime.execution_params()
|
||||||
|
@ -28,7 +28,6 @@ use util::Address;
|
|||||||
|
|
||||||
use vm::CallType;
|
use vm::CallType;
|
||||||
use super::ptr::{WasmPtr, Error as PtrError};
|
use super::ptr::{WasmPtr, Error as PtrError};
|
||||||
use super::call_args::CallArgs;
|
|
||||||
|
|
||||||
/// User trap in native code
|
/// User trap in native code
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -97,17 +96,10 @@ impl From<PtrError> for UserTrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct RuntimeContext {
|
pub struct RuntimeContext {
|
||||||
address: Address,
|
pub address: Address,
|
||||||
sender: Address,
|
pub sender: Address,
|
||||||
}
|
pub origin: Address,
|
||||||
|
pub value: U256,
|
||||||
impl RuntimeContext {
|
|
||||||
pub fn new(address: Address, sender: Address) -> Self {
|
|
||||||
RuntimeContext {
|
|
||||||
address: address,
|
|
||||||
sender: sender,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runtime enviroment data for wasm contract execution
|
/// Runtime enviroment data for wasm contract execution
|
||||||
@ -442,10 +434,10 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write call descriptor to wasm memory
|
/// Write call descriptor to wasm memory
|
||||||
pub fn write_descriptor(&mut self, call_args: CallArgs) -> Result<WasmPtr, InterpreterError> {
|
pub fn write_descriptor(&mut self, input: &[u8]) -> Result<WasmPtr, InterpreterError> {
|
||||||
let d_ptr = self.alloc(16)?;
|
let d_ptr = self.alloc(16)?;
|
||||||
|
|
||||||
let args_len = call_args.len();
|
let args_len = input.len() as u32;
|
||||||
let args_ptr = self.alloc(args_len)?;
|
let args_ptr = self.alloc(args_len)?;
|
||||||
|
|
||||||
// write call descriptor
|
// write call descriptor
|
||||||
@ -457,11 +449,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
|||||||
self.memory.set(d_ptr, &d_buf)?;
|
self.memory.set(d_ptr, &d_buf)?;
|
||||||
|
|
||||||
// write call args to memory
|
// write call args to memory
|
||||||
self.memory.set(args_ptr, &call_args.address)?;
|
self.memory.set(args_ptr, input)?;
|
||||||
self.memory.set(args_ptr+20, &call_args.sender)?;
|
|
||||||
self.memory.set(args_ptr+40, &call_args.origin)?;
|
|
||||||
self.memory.set(args_ptr+60, &call_args.value)?;
|
|
||||||
self.memory.set(args_ptr+92, &call_args.data)?;
|
|
||||||
|
|
||||||
Ok(d_ptr.into())
|
Ok(d_ptr.into())
|
||||||
}
|
}
|
||||||
@ -559,6 +547,39 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sender(&mut self, context: InterpreterCallerContext)
|
||||||
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
|
{
|
||||||
|
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
|
||||||
|
self.memory.set(return_ptr, &*self.context.sender)?;
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn address(&mut self, context: InterpreterCallerContext)
|
||||||
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
|
{
|
||||||
|
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
|
||||||
|
self.memory.set(return_ptr, &*self.context.address)?;
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin(&mut self, context: InterpreterCallerContext)
|
||||||
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
|
{
|
||||||
|
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
|
||||||
|
self.memory.set(return_ptr, &*self.context.origin)?;
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value(&mut self, context: InterpreterCallerContext)
|
||||||
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
|
{
|
||||||
|
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
|
||||||
|
let value: H256 = self.context.value.clone().into();
|
||||||
|
self.memory.set(return_ptr, &*value)?;
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
fn timestamp(&mut self, _context: InterpreterCallerContext)
|
fn timestamp(&mut self, _context: InterpreterCallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
{
|
{
|
||||||
@ -691,6 +712,18 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
|
|||||||
"_gaslimit" => {
|
"_gaslimit" => {
|
||||||
self.ext_gas_limit(context)
|
self.ext_gas_limit(context)
|
||||||
},
|
},
|
||||||
|
"_sender" => {
|
||||||
|
self.sender(context)
|
||||||
|
},
|
||||||
|
"_address" => {
|
||||||
|
self.address(context)
|
||||||
|
},
|
||||||
|
"_origin" => {
|
||||||
|
self.origin(context)
|
||||||
|
},
|
||||||
|
"_value" => {
|
||||||
|
self.value(context)
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
trace!(target: "wasm", "Trapped due to unhandled function: '{}'", name);
|
trace!(target: "wasm", "Trapped due to unhandled function: '{}'", name);
|
||||||
Ok(self.unknown_trap(context)?)
|
Ok(self.unknown_trap(context)?)
|
||||||
|
@ -88,7 +88,7 @@ fn logger() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
println!("ext.store: {:?}", ext.store);
|
println!("ext.store: {:?}", ext.store);
|
||||||
assert_eq!(gas_left, U256::from(98417));
|
assert_eq!(gas_left, U256::from(98_731));
|
||||||
let address_val: H256 = address.into();
|
let address_val: H256 = address.into();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
|
ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
|
||||||
@ -121,6 +121,8 @@ fn logger() {
|
|||||||
// if it has any result.
|
// if it has any result.
|
||||||
#[test]
|
#[test]
|
||||||
fn identity() {
|
fn identity() {
|
||||||
|
::ethcore_logger::init_log();
|
||||||
|
|
||||||
let code = load_sample!("identity.wasm");
|
let code = load_sample!("identity.wasm");
|
||||||
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||||
|
|
||||||
@ -139,7 +141,7 @@ fn identity() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(99_732));
|
assert_eq!(gas_left, U256::from(99_812));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::from_slice(&result),
|
Address::from_slice(&result),
|
||||||
@ -173,7 +175,7 @@ fn dispersion() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(99_421));
|
assert_eq!(gas_left, U256::from(99_474));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
@ -202,7 +204,7 @@ fn suicide_not() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(99_664));
|
assert_eq!(gas_left, U256::from(99_691));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
@ -236,7 +238,7 @@ fn suicide() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(99_420));
|
assert_eq!(gas_left, U256::from(99_490));
|
||||||
assert!(ext.suicides.contains(&refund));
|
assert!(ext.suicides.contains(&refund));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +269,7 @@ fn create() {
|
|||||||
assert!(ext.calls.contains(
|
assert!(ext.calls.contains(
|
||||||
&FakeCall {
|
&FakeCall {
|
||||||
call_type: FakeCallType::Create,
|
call_type: FakeCallType::Create,
|
||||||
gas: U256::from(98_908),
|
gas: U256::from(99_144),
|
||||||
sender_address: None,
|
sender_address: None,
|
||||||
receive_address: None,
|
receive_address: None,
|
||||||
value: Some(1_000_000_000.into()),
|
value: Some(1_000_000_000.into()),
|
||||||
@ -275,7 +277,7 @@ fn create() {
|
|||||||
code_address: None,
|
code_address: None,
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
assert_eq!(gas_left, U256::from(98_860));
|
assert_eq!(gas_left, U256::from(99_113));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -309,7 +311,7 @@ fn call_code() {
|
|||||||
assert!(ext.calls.contains(
|
assert!(ext.calls.contains(
|
||||||
&FakeCall {
|
&FakeCall {
|
||||||
call_type: FakeCallType::Call,
|
call_type: FakeCallType::Call,
|
||||||
gas: U256::from(99_108),
|
gas: U256::from(99_138),
|
||||||
sender_address: Some(sender),
|
sender_address: Some(sender),
|
||||||
receive_address: Some(receiver),
|
receive_address: Some(receiver),
|
||||||
value: None,
|
value: None,
|
||||||
@ -317,7 +319,7 @@ fn call_code() {
|
|||||||
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
|
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
assert_eq!(gas_left, U256::from(94_241));
|
assert_eq!(gas_left, U256::from(94_269));
|
||||||
|
|
||||||
// siphash result
|
// siphash result
|
||||||
let res = LittleEndian::read_u32(&result[..]);
|
let res = LittleEndian::read_u32(&result[..]);
|
||||||
@ -354,7 +356,7 @@ fn call_static() {
|
|||||||
assert!(ext.calls.contains(
|
assert!(ext.calls.contains(
|
||||||
&FakeCall {
|
&FakeCall {
|
||||||
call_type: FakeCallType::Call,
|
call_type: FakeCallType::Call,
|
||||||
gas: U256::from(99_108),
|
gas: U256::from(99_138),
|
||||||
sender_address: Some(sender),
|
sender_address: Some(sender),
|
||||||
receive_address: Some(receiver),
|
receive_address: Some(receiver),
|
||||||
value: None,
|
value: None,
|
||||||
@ -362,7 +364,7 @@ fn call_static() {
|
|||||||
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
assert_eq!(gas_left, U256::from(94_241));
|
assert_eq!(gas_left, U256::from(94_269));
|
||||||
|
|
||||||
// siphash result
|
// siphash result
|
||||||
let res = LittleEndian::read_u32(&result[..]);
|
let res = LittleEndian::read_u32(&result[..]);
|
||||||
@ -388,7 +390,7 @@ fn realloc() {
|
|||||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert_eq!(gas_left, U256::from(99_562));
|
assert_eq!(gas_left, U256::from(99_614));
|
||||||
assert_eq!(result, vec![0u8; 2]);
|
assert_eq!(result, vec![0u8; 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +416,7 @@ fn storage_read() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(99_673));
|
assert_eq!(gas_left, U256::from(99_695));
|
||||||
assert_eq!(Address::from(&result[12..32]), address);
|
assert_eq!(Address::from(&result[12..32]), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,7 +443,7 @@ fn keccak() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||||
assert_eq!(gas_left, U256::from(84003));
|
assert_eq!(gas_left, U256::from(84_026));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -495,7 +497,7 @@ fn math_add() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(98177));
|
assert_eq!(gas_left, U256::from(98_241));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
@ -517,7 +519,7 @@ fn math_mul() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(97326));
|
assert_eq!(gas_left, U256::from(97_390));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
@ -539,7 +541,7 @@ fn math_sub() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(98221));
|
assert_eq!(gas_left, U256::from(98_285));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
@ -578,7 +580,7 @@ fn math_div() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(91_562));
|
assert_eq!(gas_left, U256::from(91_574));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("1125000").unwrap(),
|
U256::from_dec_str("1125000").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
@ -670,5 +672,5 @@ fn externs() {
|
|||||||
"Gas limit requested and returned does not match"
|
"Gas limit requested and returned does not match"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(95_999));
|
assert_eq!(gas_left, U256::from(96_284));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user