diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index d9d6133c1..f25e60e30 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit d9d6133c1bc5dca4c74c9eb758a39546a0d46b45 +Subproject commit f25e60e300ade96aba2adffb3ebca8e5b4965720 diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 5b9689537..eb679d72d 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -577,16 +577,18 @@ impl<'a, 'b> Runtime<'a, 'b> { // let len = context.value_stack.pop_as::()? as u32; - let cx = context.value_stack.pop_as::()? as u32; let ct = context.value_stack.pop_as::()? as u32; + let cx = context.value_stack.pop_as::()? as u32; self.charge(|schedule| schedule.wasm.mem_cmp as u64 * len as u64)?; - let cx = self.memory.get(cx, len as usize)?; let ct = self.memory.get(ct, len as usize)?; + let cx = self.memory.get(cx, len as usize)?; + let result = unsafe { memcmp(cx.as_ptr() as *const c_void, ct.as_ptr() as *const c_void, len as usize) }; + Ok(Some(Into::into(result))) } diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index 981078305..7930c813a 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -29,6 +29,34 @@ macro_rules! load_sample { } } +macro_rules! reqrep_test { + ($name: expr, $input: expr) => { + reqrep_test!($name, $input, vm::EnvInfo::default(), HashMap::new()) + }; + ($name: expr, $input: expr, $info: expr, $block_hashes: expr) => { + { + ::ethcore_logger::init_log(); + let code = load_sample!($name); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.data = Some($input); + + let mut fake_ext = FakeExt::new(); + fake_ext.info = $info; + fake_ext.blockhashes = $block_hashes; + + let mut interpreter = wasm_interpreter(); + interpreter.exec(params, &mut fake_ext) + .map(|result| match result { + GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + }) + } + }; +} + fn test_finalize(res: Result) -> Result { match res { Ok(GasLeft::Known(gas)) => Ok(gas), @@ -491,6 +519,36 @@ fn keccak() { assert_eq!(gas_left, U256::from(81_067)); } +// memcmp test. +#[test] +fn memcmp() { + ::ethcore_logger::init_log(); + + let (gas_left, result) = reqrep_test! { + "memcmp.wasm", + vec![1u8, 1, 1] + }.expect("Interpreter to execute without any errors"); + + assert_eq!(0i32, LittleEndian::read_i32(&result)); + assert_eq!(gas_left, U256::from(96610)); + + let (gas_left, result) = reqrep_test! { + "memcmp.wasm", + vec![1u8, 1, 3, 1] + }.expect("Interpreter to execute without any errors"); + + assert_eq!(2i32, LittleEndian::read_i32(&result)); + assert_eq!(gas_left, U256::from(96610)); + + let (gas_left, result) = reqrep_test! { + "memcmp.wasm", + vec![1u8, 1, 0] + }.expect("Interpreter to execute without any errors"); + + assert_eq!(-1i32, LittleEndian::read_i32(&result)); + assert_eq!(gas_left, U256::from(96610)); +} + // memcpy test. #[test] fn memcpy() { @@ -580,34 +638,6 @@ fn memset() { assert_eq!(gas_left, U256::from(71_921)); } -macro_rules! reqrep_test { - ($name: expr, $input: expr) => { - reqrep_test!($name, $input, vm::EnvInfo::default(), HashMap::new()) - }; - ($name: expr, $input: expr, $info: expr, $block_hashes: expr) => { - { - ::ethcore_logger::init_log(); - let code = load_sample!($name); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some($input); - - let mut fake_ext = FakeExt::new(); - fake_ext.info = $info; - fake_ext.blockhashes = $block_hashes; - - let mut interpreter = wasm_interpreter(); - interpreter.exec(params, &mut fake_ext) - .map(|result| match result { - GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); }, - GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), - }) - } - }; -} - // math_* tests check the ability of wasm contract to perform big integer operations // - addition // - multiplication