WASM Runtime refactoring (#6596)

* refactoring to new pwasm-std

* pass reference

* remove ref

* missing underscores
This commit is contained in:
Nikolay Volf 2017-10-04 13:15:59 +02:00 committed by Arkadiy Paronyan
parent ec1a892f44
commit 4260910db6
6 changed files with 102 additions and 113 deletions

@ -1 +1 @@
Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a Subproject commit c8129ce2f36c26ed634eda786960978a28e28d0e

View File

@ -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
}
}

View File

@ -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",
&[], &[],

View File

@ -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(&params.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()

View File

@ -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)?)

View File

@ -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));
} }