diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index fcac936bf..c8129ce2f 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a +Subproject commit c8129ce2f36c26ed634eda786960978a28e28d0e diff --git a/ethcore/wasm/src/call_args.rs b/ethcore/wasm/src/call_args.rs deleted file mode 100644 index 7fb50bff3..000000000 --- a/ethcore/wasm/src/call_args.rs +++ /dev/null @@ -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 . - -//! 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, -} - -impl CallArgs { - /// New contract call payload with known parameters - pub fn new(address: H160, sender: H160, origin: H160, value: U256, data: Vec) -> 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 - } -} diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index c32e3ed84..8f4fa264f 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -102,6 +102,26 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[ &[I32], None, ), + Static( + "_sender", + &[I32], + None, + ), + Static( + "_origin", + &[I32], + None, + ), + Static( + "_address", + &[I32], + None, + ), + Static( + "_value", + &[I32], + None, + ), Static( "_timestamp", &[], diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index 8eb14a91a..a68d40d86 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -27,7 +27,6 @@ extern crate wasm_utils; mod runtime; mod ptr; -mod call_args; mod result; #[cfg(test)] mod tests; @@ -107,7 +106,12 @@ impl vm::Vm for WasmInterpreter { env_memory, DEFAULT_STACK_SPACE, 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, ); @@ -121,15 +125,8 @@ impl vm::Vm for WasmInterpreter { })? ); - let d_ptr = runtime.write_descriptor( - call_args::CallArgs::new( - params.address, - params.sender, - params.origin, - params.value.value(), - params.data.unwrap_or(Vec::with_capacity(0)), - ) - ).map_err(|e| Error(e))?; + let d_ptr = runtime.write_descriptor(¶ms.data.unwrap_or_default()) + .map_err(Error)?; { let execution_params = runtime.execution_params() diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 8376d0f39..5e18ce216 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -28,7 +28,6 @@ use util::Address; use vm::CallType; use super::ptr::{WasmPtr, Error as PtrError}; -use super::call_args::CallArgs; /// User trap in native code #[derive(Debug, Clone, PartialEq)] @@ -97,17 +96,10 @@ impl From for UserTrap { } pub struct RuntimeContext { - address: Address, - sender: Address, -} - -impl RuntimeContext { - pub fn new(address: Address, sender: Address) -> Self { - RuntimeContext { - address: address, - sender: sender, - } - } + pub address: Address, + pub sender: Address, + pub origin: Address, + pub value: U256, } /// Runtime enviroment data for wasm contract execution @@ -442,10 +434,10 @@ impl<'a, 'b> Runtime<'a, 'b> { } /// Write call descriptor to wasm memory - pub fn write_descriptor(&mut self, call_args: CallArgs) -> Result { + pub fn write_descriptor(&mut self, input: &[u8]) -> Result { 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)?; // write call descriptor @@ -457,11 +449,7 @@ impl<'a, 'b> Runtime<'a, 'b> { self.memory.set(d_ptr, &d_buf)?; // write call args to memory - self.memory.set(args_ptr, &call_args.address)?; - 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)?; + self.memory.set(args_ptr, input)?; Ok(d_ptr.into()) } @@ -559,6 +547,39 @@ impl<'a, 'b> Runtime<'a, 'b> { Ok(None) } + fn sender(&mut self, context: InterpreterCallerContext) + -> Result, InterpreterError> + { + let return_ptr = context.value_stack.pop_as::()? as u32; + self.memory.set(return_ptr, &*self.context.sender)?; + Ok(None) + } + + fn address(&mut self, context: InterpreterCallerContext) + -> Result, InterpreterError> + { + let return_ptr = context.value_stack.pop_as::()? as u32; + self.memory.set(return_ptr, &*self.context.address)?; + Ok(None) + } + + fn origin(&mut self, context: InterpreterCallerContext) + -> Result, InterpreterError> + { + let return_ptr = context.value_stack.pop_as::()? as u32; + self.memory.set(return_ptr, &*self.context.origin)?; + Ok(None) + } + + fn value(&mut self, context: InterpreterCallerContext) + -> Result, InterpreterError> + { + let return_ptr = context.value_stack.pop_as::()? as u32; + let value: H256 = self.context.value.clone().into(); + self.memory.set(return_ptr, &*value)?; + Ok(None) + } + fn timestamp(&mut self, _context: InterpreterCallerContext) -> Result, InterpreterError> { @@ -691,6 +712,18 @@ impl<'a, 'b> interpreter::UserFunctionExecutor for Runtime<'a, 'b> { "_gaslimit" => { 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); Ok(self.unknown_trap(context)?) diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index 22eeb23f5..5a6be6e2a 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -88,7 +88,7 @@ fn logger() { }; 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(); assert_eq!( ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"), @@ -121,6 +121,8 @@ fn logger() { // if it has any result. #[test] fn identity() { + ::ethcore_logger::init_log(); + let code = load_sample!("identity.wasm"); 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!( 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!( 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!( 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)); } @@ -267,7 +269,7 @@ fn create() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Create, - gas: U256::from(98_908), + gas: U256::from(99_144), sender_address: None, receive_address: None, value: Some(1_000_000_000.into()), @@ -275,7 +277,7 @@ fn create() { 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( &FakeCall { call_type: FakeCallType::Call, - gas: U256::from(99_108), + gas: U256::from(99_138), sender_address: Some(sender), receive_address: Some(receiver), value: None, @@ -317,7 +319,7 @@ fn call_code() { code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()), } )); - assert_eq!(gas_left, U256::from(94_241)); + assert_eq!(gas_left, U256::from(94_269)); // siphash result let res = LittleEndian::read_u32(&result[..]); @@ -354,7 +356,7 @@ fn call_static() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, - gas: U256::from(99_108), + gas: U256::from(99_138), sender_address: Some(sender), receive_address: Some(receiver), value: None, @@ -362,7 +364,7 @@ fn call_static() { code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), } )); - assert_eq!(gas_left, U256::from(94_241)); + assert_eq!(gas_left, U256::from(94_269)); // siphash 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()), } }; - assert_eq!(gas_left, U256::from(99_562)); + assert_eq!(gas_left, U256::from(99_614)); 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); } @@ -441,7 +443,7 @@ fn keccak() { }; 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"); - assert_eq!(gas_left, U256::from(98177)); + assert_eq!(gas_left, U256::from(98_241)); assert_eq!( U256::from_dec_str("1888888888888888888888888888887").unwrap(), (&result[..]).into() @@ -517,7 +519,7 @@ fn math_mul() { } ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(97326)); + assert_eq!(gas_left, U256::from(97_390)); assert_eq!( U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), (&result[..]).into() @@ -539,7 +541,7 @@ fn math_sub() { } ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(98221)); + assert_eq!(gas_left, U256::from(98_285)); assert_eq!( U256::from_dec_str("111111111111111111111111111111").unwrap(), (&result[..]).into() @@ -578,7 +580,7 @@ fn math_div() { } ).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!( U256::from_dec_str("1125000").unwrap(), (&result[..]).into() @@ -670,5 +672,5 @@ fn externs() { "Gas limit requested and returned does not match" ); - assert_eq!(gas_left, U256::from(95_999)); + assert_eq!(gas_left, U256::from(96_284)); }