pwasm-std update (#7018)
This commit is contained in:
		
							parent
							
								
									df49b4b065
								
							
						
					
					
						commit
						bcdfc50a0b
					
				
							
								
								
									
										8
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -2253,7 +2253,7 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "parity-wasm"
 | 
			
		||||
version = "0.15.1"
 | 
			
		||||
version = "0.15.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
@ -3417,7 +3417,7 @@ dependencies = [
 | 
			
		||||
 "ethcore-logger 1.9.0",
 | 
			
		||||
 "ethcore-util 1.9.0",
 | 
			
		||||
 "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "vm 0.1.0",
 | 
			
		||||
 "wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
 | 
			
		||||
]
 | 
			
		||||
@ -3433,7 +3433,7 @@ dependencies = [
 | 
			
		||||
 "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -3647,7 +3647,7 @@ dependencies = [
 | 
			
		||||
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
 | 
			
		||||
"checksum parity-ui-old-precompiled 1.8.0 (git+https://github.com/paritytech/js-precompiled.git?branch=v1)" = "<none>"
 | 
			
		||||
"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/paritytech/js-precompiled.git)" = "<none>"
 | 
			
		||||
"checksum parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95f6243c2d6fadf903b5edfd0011817efc20522ce5f360abf4648c24ea87581a"
 | 
			
		||||
"checksum parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8431a184ad88cfbcd71a792aaca319cc7203a94300c26b8dce2d0df0681ea87d"
 | 
			
		||||
"checksum parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81451bfab101d186f8fc4a0aa13cb5539b31b02c4ed96425a0842e2a413daba6"
 | 
			
		||||
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
 | 
			
		||||
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
 | 
			
		||||
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
Subproject commit 94b7877b5826a53627b8732ea0feb45869dd04ab
 | 
			
		||||
Subproject commit 9a1fcbf0d4e73bea437577e807bc38c7ba243d80
 | 
			
		||||
@ -127,12 +127,14 @@ pub struct WasmCosts {
 | 
			
		||||
	pub mul: u32,
 | 
			
		||||
	/// Memory (load/store) operations multiplier.
 | 
			
		||||
	pub mem: u32,
 | 
			
		||||
	/// Memory copy operation.
 | 
			
		||||
	/// Memory copy operation, per byte.
 | 
			
		||||
	pub mem_copy: u32,
 | 
			
		||||
	/// Memory move operation, per byte.
 | 
			
		||||
	pub mem_move: u32,
 | 
			
		||||
	/// Memory set operation, per byte.
 | 
			
		||||
	pub mem_set: u32,
 | 
			
		||||
	/// Static region charge, per byte.
 | 
			
		||||
	pub static_region: u32,
 | 
			
		||||
	/// General static query of u64 value from env-info
 | 
			
		||||
	pub static_u64: u32,
 | 
			
		||||
	/// General static query of U256 value from env-info
 | 
			
		||||
	pub static_u256: u32,
 | 
			
		||||
	/// General static query of Address value from env-info
 | 
			
		||||
@ -147,11 +149,9 @@ impl Default for WasmCosts {
 | 
			
		||||
			mul: 4,
 | 
			
		||||
			mem: 2,
 | 
			
		||||
			mem_copy: 1,
 | 
			
		||||
			mem_move: 1,
 | 
			
		||||
			mem_set: 1,
 | 
			
		||||
			static_region: 1,
 | 
			
		||||
 | 
			
		||||
			// due to runtime issues, this can be slow
 | 
			
		||||
			static_u64: 32,
 | 
			
		||||
 | 
			
		||||
			static_u256: 64,
 | 
			
		||||
			static_address: 40,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -38,12 +38,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
 | 
			
		||||
		None,
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_malloc",
 | 
			
		||||
		"_ext_malloc",
 | 
			
		||||
		&[I32],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_free",
 | 
			
		||||
		"_ext_free",
 | 
			
		||||
		&[I32],
 | 
			
		||||
		None,
 | 
			
		||||
	),
 | 
			
		||||
@ -92,6 +92,21 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
 | 
			
		||||
		&[I32; 3],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_ext_memcpy",
 | 
			
		||||
		&[I32; 3],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_ext_memset",
 | 
			
		||||
		&[I32; 3],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_ext_memmove",
 | 
			
		||||
		&[I32; 3],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_panic",
 | 
			
		||||
		&[I32; 2],
 | 
			
		||||
@ -99,7 +114,7 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_blockhash",
 | 
			
		||||
		&[I32; 3],
 | 
			
		||||
		&[I64, I32],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
@ -130,12 +145,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
 | 
			
		||||
	Static(
 | 
			
		||||
		"_timestamp",
 | 
			
		||||
		&[],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
		Some(I64),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_blocknumber",
 | 
			
		||||
		&[],
 | 
			
		||||
		Some(I32),
 | 
			
		||||
		Some(I64),
 | 
			
		||||
	),
 | 
			
		||||
	Static(
 | 
			
		||||
		"_difficulty",
 | 
			
		||||
@ -162,8 +177,8 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
 | 
			
		||||
 | 
			
		||||
	Static(
 | 
			
		||||
		"_llvm_bswap_i64",
 | 
			
		||||
		&[I32; 2],
 | 
			
		||||
		Some(I32)
 | 
			
		||||
		&[I64],
 | 
			
		||||
		Some(I64)
 | 
			
		||||
	),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -560,32 +560,67 @@ impl<'a, 'b> Runtime<'a, 'b> {
 | 
			
		||||
	fn mem_copy(&mut self, context: InterpreterCallerContext)
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		//
 | 
			
		||||
		// method signature:
 | 
			
		||||
		//   fn memcpy(dest: *const u8, src: *const u8, len: u32) -> *mut u8;
 | 
			
		||||
		//
 | 
			
		||||
 | 
			
		||||
		let len = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let dst = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let src = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let dst = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
 | 
			
		||||
		self.charge(|schedule| schedule.wasm.mem_copy as u64 * len as u64)?;
 | 
			
		||||
 | 
			
		||||
		let mem = self.memory().get(src, len as usize)?;
 | 
			
		||||
		self.memory().set(dst, &mem)?;
 | 
			
		||||
		self.memory().copy_nonoverlapping(src as usize, dst as usize, len as usize)?;
 | 
			
		||||
 | 
			
		||||
		Ok(Some(0i32.into()))
 | 
			
		||||
		Ok(Some(Into::into(dst as i32)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn bswap_32(x: u32) -> u32 {
 | 
			
		||||
		x >> 24 | x >> 8 & 0xff00 | x << 8 & 0xff0000 | x << 24
 | 
			
		||||
	fn mem_move(&mut self, context: InterpreterCallerContext)
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		//
 | 
			
		||||
		// method signature:
 | 
			
		||||
		//   fn memmove(dest: *const u8, src: *const u8, len: u32) -> *mut u8;
 | 
			
		||||
		//
 | 
			
		||||
 | 
			
		||||
		let len = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let src = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let dst = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
 | 
			
		||||
		self.charge(|schedule| schedule.wasm.mem_move as u64 * len as u64)?;
 | 
			
		||||
 | 
			
		||||
		self.memory().copy(src as usize, dst as usize, len as usize)?;
 | 
			
		||||
 | 
			
		||||
		Ok(Some(Into::into(dst as i32)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn mem_set(&mut self, context: InterpreterCallerContext)
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		//
 | 
			
		||||
		// method signature:
 | 
			
		||||
		//   fn memset(dest: *const u8, c: u32, len: u32) -> *mut u8;
 | 
			
		||||
		//
 | 
			
		||||
 | 
			
		||||
		let len = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let c = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let dst = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
 | 
			
		||||
		self.charge(|schedule| schedule.wasm.mem_set as u64 * len as u64)?;
 | 
			
		||||
 | 
			
		||||
		self.memory().clear(dst as usize, c as u8, len as usize)?;
 | 
			
		||||
 | 
			
		||||
		Ok(Some(Into::into(dst as i32)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn bitswap_i64(&mut self, context: InterpreterCallerContext)
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		let x1 = context.value_stack.pop_as::<i32>()?;
 | 
			
		||||
		let x2 = context.value_stack.pop_as::<i32>()?;
 | 
			
		||||
		let x = context.value_stack.pop_as::<i64>()?;
 | 
			
		||||
		let result = x.swap_bytes();
 | 
			
		||||
 | 
			
		||||
		let result = ((Runtime::bswap_32(x2 as u32) as u64) << 32
 | 
			
		||||
			| Runtime::bswap_32(x1 as u32) as u64) as i64;
 | 
			
		||||
 | 
			
		||||
		self.return_i64(result)
 | 
			
		||||
		Ok(Some(result.into()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn user_panic(&mut self, context: InterpreterCallerContext)
 | 
			
		||||
@ -606,13 +641,10 @@ impl<'a, 'b> Runtime<'a, 'b> {
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let block_hi = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let block_lo = context.value_stack.pop_as::<i32>()? as u32;
 | 
			
		||||
		let block_num = context.value_stack.pop_as::<i64>()? as u64;
 | 
			
		||||
 | 
			
		||||
		self.charge(|schedule| schedule.blockhash_gas as u64)?;
 | 
			
		||||
 | 
			
		||||
		let block_num = (block_hi as u64) << 32 | block_lo as u64;
 | 
			
		||||
 | 
			
		||||
		trace!("Requesting block hash for block #{}", block_num);
 | 
			
		||||
		let hash = self.ext.blockhash(&U256::from(block_num));
 | 
			
		||||
 | 
			
		||||
@ -694,14 +726,14 @@ impl<'a, 'b> Runtime<'a, 'b> {
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		let timestamp = self.ext.env_info().timestamp as i64;
 | 
			
		||||
		self.return_i64(timestamp)
 | 
			
		||||
		Ok(Some(timestamp.into()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn block_number(&mut self, _context: InterpreterCallerContext)
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		let block_number: u64 = self.ext.env_info().number.into();
 | 
			
		||||
		self.return_i64(block_number as i64)
 | 
			
		||||
		let block_number = self.ext.env_info().number as i64;
 | 
			
		||||
		Ok(Some(block_number.into()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn difficulty(&mut self, context: InterpreterCallerContext)
 | 
			
		||||
@ -726,25 +758,6 @@ impl<'a, 'b> Runtime<'a, 'b> {
 | 
			
		||||
		Ok(None)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn return_i64(&mut self, val: i64) -> Result<Option<interpreter::RuntimeValue>, InterpreterError> {
 | 
			
		||||
		self.charge(|schedule| schedule.wasm.static_u64 as u64)?;
 | 
			
		||||
 | 
			
		||||
		let uval = val as u64;
 | 
			
		||||
		let hi = (uval >> 32) as i32;
 | 
			
		||||
		let lo = (uval << 32 >> 32) as i32;
 | 
			
		||||
 | 
			
		||||
		let target = self.instance.module("contract").ok_or(UserTrap::Other)?;
 | 
			
		||||
		target.execute_export(
 | 
			
		||||
			"setTempRet0",
 | 
			
		||||
			self.execution_params().add_argument(
 | 
			
		||||
				interpreter::RuntimeValue::I32(hi).into()
 | 
			
		||||
			),
 | 
			
		||||
		)?;
 | 
			
		||||
		Ok(Some(
 | 
			
		||||
			(lo).into()
 | 
			
		||||
		))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub fn execution_params(&mut self) -> interpreter::ExecutionParams<UserTrap> {
 | 
			
		||||
		use super::env;
 | 
			
		||||
 | 
			
		||||
@ -812,10 +825,10 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
 | 
			
		||||
		-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
 | 
			
		||||
	{
 | 
			
		||||
		match name {
 | 
			
		||||
			"_malloc" => {
 | 
			
		||||
			"_ext_malloc" => {
 | 
			
		||||
				self.malloc(context)
 | 
			
		||||
			},
 | 
			
		||||
			"_free" => {
 | 
			
		||||
			"_ext_free" => {
 | 
			
		||||
				// Since it is arena allocator, free does nothing
 | 
			
		||||
				// todo: update if changed
 | 
			
		||||
				self.user_noop(context)
 | 
			
		||||
@ -853,6 +866,15 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
 | 
			
		||||
			"_emscripten_memcpy_big" => {
 | 
			
		||||
				self.mem_copy(context)
 | 
			
		||||
			},
 | 
			
		||||
			"_ext_memcpy" => {
 | 
			
		||||
				self.mem_copy(context)
 | 
			
		||||
			},
 | 
			
		||||
			"_ext_memmove" => {
 | 
			
		||||
				self.mem_move(context)
 | 
			
		||||
			},
 | 
			
		||||
			"_ext_memset" => {
 | 
			
		||||
				self.mem_set(context)
 | 
			
		||||
			},
 | 
			
		||||
			"_llvm_bswap_i64" => {
 | 
			
		||||
				self.bitswap_i64(context)
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
@ -60,7 +60,7 @@ fn empty() {
 | 
			
		||||
		test_finalize(interpreter.exec(params, &mut ext)).unwrap()
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_976));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_982));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This test checks if the contract deserializes payload header properly.
 | 
			
		||||
@ -89,7 +89,6 @@ fn logger() {
 | 
			
		||||
		test_finalize(interpreter.exec(params, &mut ext)).unwrap()
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(15_177));
 | 
			
		||||
	let address_val: H256 = address.into();
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
 | 
			
		||||
@ -113,6 +112,7 @@ fn logger() {
 | 
			
		||||
		U256::from(1_000_000_000),
 | 
			
		||||
		"Logger sets 0x04 key to the trasferred value"
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(19_143));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
 | 
			
		||||
@ -142,13 +142,12 @@ fn identity() {
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_695));
 | 
			
		||||
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		Address::from_slice(&result),
 | 
			
		||||
		sender,
 | 
			
		||||
		"Idenity test contract does not return the sender passed"
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_844));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
 | 
			
		||||
@ -176,12 +175,12 @@ fn dispersion() {
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(96_543));
 | 
			
		||||
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		result,
 | 
			
		||||
		vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_469));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
@ -205,12 +204,11 @@ fn suicide_not() {
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(96_822));
 | 
			
		||||
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		result,
 | 
			
		||||
		vec![0u8]
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_724));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
@ -241,8 +239,8 @@ fn suicide() {
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(96_580));
 | 
			
		||||
	assert!(ext.suicides.contains(&refund));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_663));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
@ -272,7 +270,7 @@ fn create() {
 | 
			
		||||
	assert!(ext.calls.contains(
 | 
			
		||||
		&FakeCall {
 | 
			
		||||
			call_type: FakeCallType::Create,
 | 
			
		||||
			gas: U256::from(62_324),
 | 
			
		||||
			gas: U256::from(65_903),
 | 
			
		||||
			sender_address: None,
 | 
			
		||||
			receive_address: None,
 | 
			
		||||
			value: Some(1_000_000_000.into()),
 | 
			
		||||
@ -280,7 +278,7 @@ fn create() {
 | 
			
		||||
			code_address: None,
 | 
			
		||||
		}
 | 
			
		||||
	));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(62_289));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(65_896));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -314,7 +312,7 @@ fn call_code() {
 | 
			
		||||
	assert!(ext.calls.contains(
 | 
			
		||||
		&FakeCall {
 | 
			
		||||
			call_type: FakeCallType::Call,
 | 
			
		||||
			gas: U256::from(95_585),
 | 
			
		||||
			gas: U256::from(98_709),
 | 
			
		||||
			sender_address: Some(sender),
 | 
			
		||||
			receive_address: Some(receiver),
 | 
			
		||||
			value: None,
 | 
			
		||||
@ -322,11 +320,11 @@ fn call_code() {
 | 
			
		||||
			code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
 | 
			
		||||
		}
 | 
			
		||||
	));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(90_665));
 | 
			
		||||
 | 
			
		||||
	// siphash result
 | 
			
		||||
	let res = LittleEndian::read_u32(&result[..]);
 | 
			
		||||
	assert_eq!(res, 4198595614);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(93_851));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
@ -359,7 +357,7 @@ fn call_static() {
 | 
			
		||||
	assert!(ext.calls.contains(
 | 
			
		||||
		&FakeCall {
 | 
			
		||||
			call_type: FakeCallType::Call,
 | 
			
		||||
			gas: U256::from(95_585),
 | 
			
		||||
			gas: U256::from(98_709),
 | 
			
		||||
			sender_address: Some(sender),
 | 
			
		||||
			receive_address: Some(receiver),
 | 
			
		||||
			value: None,
 | 
			
		||||
@ -367,11 +365,12 @@ fn call_static() {
 | 
			
		||||
			code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
 | 
			
		||||
		}
 | 
			
		||||
	));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(90_665));
 | 
			
		||||
 | 
			
		||||
	// siphash result
 | 
			
		||||
	let res = LittleEndian::read_u32(&result[..]);
 | 
			
		||||
	assert_eq!(res, 317632590);
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(93_851));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Realloc test
 | 
			
		||||
@ -393,8 +392,8 @@ fn realloc() {
 | 
			
		||||
				GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
	assert_eq!(gas_left, U256::from(96_811));
 | 
			
		||||
	assert_eq!(result, vec![0u8; 2]);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_787));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests that contract's ability to read from a storage
 | 
			
		||||
@ -419,8 +418,8 @@ fn storage_read() {
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(96_645));
 | 
			
		||||
	assert_eq!(Address::from(&result[12..32]), address);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(99_702));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests keccak calculation
 | 
			
		||||
@ -446,9 +445,97 @@ fn keccak() {
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(80_452));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(84_520));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// memcpy test.
 | 
			
		||||
#[test]
 | 
			
		||||
fn memcpy() {
 | 
			
		||||
	::ethcore_logger::init_log();
 | 
			
		||||
	let code = load_sample!("mem.wasm");
 | 
			
		||||
 | 
			
		||||
	let mut test_payload = Vec::with_capacity(8192);
 | 
			
		||||
	for i in 0..8192 {
 | 
			
		||||
		test_payload.push((i % 255) as u8);
 | 
			
		||||
	}
 | 
			
		||||
	let mut data = vec![0u8];
 | 
			
		||||
	data.extend(&test_payload);
 | 
			
		||||
 | 
			
		||||
	let mut params = ActionParams::default();
 | 
			
		||||
	params.gas = U256::from(100_000);
 | 
			
		||||
	params.code = Some(Arc::new(code));
 | 
			
		||||
	params.data = Some(data);
 | 
			
		||||
	let mut ext = FakeExt::new();
 | 
			
		||||
 | 
			
		||||
	let (gas_left, result) = {
 | 
			
		||||
		let mut interpreter = wasm_interpreter();
 | 
			
		||||
		let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
 | 
			
		||||
		match result {
 | 
			
		||||
			GasLeft::Known(_) => { panic!("mem should return payload"); },
 | 
			
		||||
			GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(result, test_payload);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(75_324));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// memmove test.
 | 
			
		||||
#[test]
 | 
			
		||||
fn memmove() {
 | 
			
		||||
	::ethcore_logger::init_log();
 | 
			
		||||
	let code = load_sample!("mem.wasm");
 | 
			
		||||
 | 
			
		||||
	let mut test_payload = Vec::with_capacity(8192);
 | 
			
		||||
	for i in 0..8192 {
 | 
			
		||||
		test_payload.push((i % 255) as u8);
 | 
			
		||||
	}
 | 
			
		||||
	let mut data = vec![1u8];
 | 
			
		||||
	data.extend(&test_payload);
 | 
			
		||||
 | 
			
		||||
	let mut params = ActionParams::default();
 | 
			
		||||
	params.gas = U256::from(100_000);
 | 
			
		||||
	params.code = Some(Arc::new(code));
 | 
			
		||||
	params.data = Some(data);
 | 
			
		||||
	let mut ext = FakeExt::new();
 | 
			
		||||
 | 
			
		||||
	let (gas_left, result) = {
 | 
			
		||||
		let mut interpreter = wasm_interpreter();
 | 
			
		||||
		let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
 | 
			
		||||
		match result {
 | 
			
		||||
			GasLeft::Known(_) => { panic!("mem should return payload"); },
 | 
			
		||||
			GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(result, test_payload);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(75_324));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// memset test
 | 
			
		||||
#[test]
 | 
			
		||||
fn memset() {
 | 
			
		||||
	::ethcore_logger::init_log();
 | 
			
		||||
	let code = load_sample!("mem.wasm");
 | 
			
		||||
 | 
			
		||||
	let mut params = ActionParams::default();
 | 
			
		||||
	params.gas = U256::from(100_000);
 | 
			
		||||
	params.code = Some(Arc::new(code));
 | 
			
		||||
	params.data = Some(vec![2u8,  228u8]);
 | 
			
		||||
	let mut ext = FakeExt::new();
 | 
			
		||||
 | 
			
		||||
	let (gas_left, result) = {
 | 
			
		||||
		let mut interpreter = wasm_interpreter();
 | 
			
		||||
		let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
 | 
			
		||||
		match result {
 | 
			
		||||
			GasLeft::Known(_) => { panic!("mem should return payload"); },
 | 
			
		||||
			GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(result, vec![228u8; 8192]);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(75_324));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! reqrep_test {
 | 
			
		||||
	($name: expr, $input: expr) => {
 | 
			
		||||
@ -500,11 +587,11 @@ fn math_add() {
 | 
			
		||||
		}
 | 
			
		||||
	).expect("Interpreter to execute without any errors");
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(94_666));
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		U256::from_dec_str("1888888888888888888888888888887").unwrap(),
 | 
			
		||||
		(&result[..]).into()
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(98_576));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// multiplication
 | 
			
		||||
@ -522,11 +609,11 @@ fn math_mul() {
 | 
			
		||||
		}
 | 
			
		||||
	).expect("Interpreter to execute without any errors");
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(93_719));
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
 | 
			
		||||
		(&result[..]).into()
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(97_726));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// subtraction
 | 
			
		||||
@ -544,11 +631,11 @@ fn math_sub() {
 | 
			
		||||
		}
 | 
			
		||||
	).expect("Interpreter to execute without any errors");
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(94_718));
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		U256::from_dec_str("111111111111111111111111111111").unwrap(),
 | 
			
		||||
		(&result[..]).into()
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(98_568));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// subtraction with overflow
 | 
			
		||||
@ -566,7 +653,10 @@ fn math_sub_with_overflow() {
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	assert_eq!(result, Err(vm::Error::Wasm("Wasm runtime error: User(Panic(\"arithmetic operation overflow\"))".into())));
 | 
			
		||||
	match result {
 | 
			
		||||
		Err(vm::Error::Wasm(_)) => {},
 | 
			
		||||
		_ => panic!("Unexpected result {:?}", result),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
@ -583,11 +673,11 @@ fn math_div() {
 | 
			
		||||
		}
 | 
			
		||||
	).expect("Interpreter to execute without any errors");
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(86_996));
 | 
			
		||||
	assert_eq!(
 | 
			
		||||
		U256::from_dec_str("1125000").unwrap(),
 | 
			
		||||
		(&result[..]).into()
 | 
			
		||||
	);
 | 
			
		||||
	assert_eq!(gas_left, U256::from(91_564));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This test checks the ability of wasm contract to invoke
 | 
			
		||||
@ -675,7 +765,7 @@ fn externs() {
 | 
			
		||||
		"Gas limit requested and returned does not match"
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	assert_eq!(gas_left, U256::from(91_857));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(97_740));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
@ -701,7 +791,7 @@ fn embedded_keccak() {
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(80_452));
 | 
			
		||||
	assert_eq!(gas_left, U256::from(84_520));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// This test checks the correctness of log extern
 | 
			
		||||
@ -736,5 +826,5 @@ fn events() {
 | 
			
		||||
	assert_eq!(&log_entry.data, b"gnihtemos");
 | 
			
		||||
 | 
			
		||||
	assert_eq!(&result, b"gnihtemos");
 | 
			
		||||
	assert_eq!(gas_left, U256::from(78039));
 | 
			
		||||
}
 | 
			
		||||
	assert_eq!(gas_left, U256::from(82_721));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user