pwasm-std update (#7018)
This commit is contained in:
parent
6ad5d559ca
commit
561e843207
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -2387,7 +2387,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-wasm"
|
name = "parity-wasm"
|
||||||
version = "0.15.1"
|
version = "0.15.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -3575,7 +3575,7 @@ dependencies = [
|
|||||||
"ethcore-logger 1.8.0",
|
"ethcore-logger 1.8.0",
|
||||||
"ethcore-util 1.8.3",
|
"ethcore-util 1.8.3",
|
||||||
"log 0.3.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)",
|
||||||
"vm 0.1.0",
|
"vm 0.1.0",
|
||||||
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
|
||||||
]
|
]
|
||||||
@ -3591,7 +3591,7 @@ dependencies = [
|
|||||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
@ -3815,7 +3815,7 @@ dependencies = [
|
|||||||
"checksum parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddaeb8543c6823e93dae65a25eb8083ebfeee8f0000031119d7a0055b2e8fc63"
|
"checksum parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddaeb8543c6823e93dae65a25eb8083ebfeee8f0000031119d7a0055b2e8fc63"
|
||||||
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
|
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
|
||||||
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git?branch=beta)" = "<none>"
|
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git?branch=beta)" = "<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 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 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"
|
"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,
|
pub mul: u32,
|
||||||
/// Memory (load/store) operations multiplier.
|
/// Memory (load/store) operations multiplier.
|
||||||
pub mem: u32,
|
pub mem: u32,
|
||||||
/// Memory copy operation.
|
/// Memory copy operation, per byte.
|
||||||
pub mem_copy: u32,
|
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.
|
/// Static region charge, per byte.
|
||||||
pub static_region: u32,
|
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
|
/// General static query of U256 value from env-info
|
||||||
pub static_u256: u32,
|
pub static_u256: u32,
|
||||||
/// General static query of Address value from env-info
|
/// General static query of Address value from env-info
|
||||||
@ -147,11 +149,9 @@ impl Default for WasmCosts {
|
|||||||
mul: 4,
|
mul: 4,
|
||||||
mem: 2,
|
mem: 2,
|
||||||
mem_copy: 1,
|
mem_copy: 1,
|
||||||
|
mem_move: 1,
|
||||||
|
mem_set: 1,
|
||||||
static_region: 1,
|
static_region: 1,
|
||||||
|
|
||||||
// due to runtime issues, this can be slow
|
|
||||||
static_u64: 32,
|
|
||||||
|
|
||||||
static_u256: 64,
|
static_u256: 64,
|
||||||
static_address: 40,
|
static_address: 40,
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
Static(
|
Static(
|
||||||
"_malloc",
|
"_ext_malloc",
|
||||||
&[I32],
|
&[I32],
|
||||||
Some(I32),
|
Some(I32),
|
||||||
),
|
),
|
||||||
Static(
|
Static(
|
||||||
"_free",
|
"_ext_free",
|
||||||
&[I32],
|
&[I32],
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
@ -92,6 +92,21 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
&[I32; 3],
|
&[I32; 3],
|
||||||
Some(I32),
|
Some(I32),
|
||||||
),
|
),
|
||||||
|
Static(
|
||||||
|
"_ext_memcpy",
|
||||||
|
&[I32; 3],
|
||||||
|
Some(I32),
|
||||||
|
),
|
||||||
|
Static(
|
||||||
|
"_ext_memset",
|
||||||
|
&[I32; 3],
|
||||||
|
Some(I32),
|
||||||
|
),
|
||||||
|
Static(
|
||||||
|
"_ext_memmove",
|
||||||
|
&[I32; 3],
|
||||||
|
Some(I32),
|
||||||
|
),
|
||||||
Static(
|
Static(
|
||||||
"_panic",
|
"_panic",
|
||||||
&[I32; 2],
|
&[I32; 2],
|
||||||
@ -99,7 +114,7 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
),
|
),
|
||||||
Static(
|
Static(
|
||||||
"_blockhash",
|
"_blockhash",
|
||||||
&[I32; 3],
|
&[I64, I32],
|
||||||
Some(I32),
|
Some(I32),
|
||||||
),
|
),
|
||||||
Static(
|
Static(
|
||||||
@ -130,12 +145,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
Static(
|
Static(
|
||||||
"_timestamp",
|
"_timestamp",
|
||||||
&[],
|
&[],
|
||||||
Some(I32),
|
Some(I64),
|
||||||
),
|
),
|
||||||
Static(
|
Static(
|
||||||
"_blocknumber",
|
"_blocknumber",
|
||||||
&[],
|
&[],
|
||||||
Some(I32),
|
Some(I64),
|
||||||
),
|
),
|
||||||
Static(
|
Static(
|
||||||
"_difficulty",
|
"_difficulty",
|
||||||
@ -162,8 +177,8 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
|||||||
|
|
||||||
Static(
|
Static(
|
||||||
"_llvm_bswap_i64",
|
"_llvm_bswap_i64",
|
||||||
&[I32; 2],
|
&[I64],
|
||||||
Some(I32)
|
Some(I64)
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -560,32 +560,67 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
|||||||
fn mem_copy(&mut self, context: InterpreterCallerContext)
|
fn mem_copy(&mut self, context: InterpreterCallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
-> 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 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 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)?;
|
self.charge(|schedule| schedule.wasm.mem_copy as u64 * len as u64)?;
|
||||||
|
|
||||||
let mem = self.memory().get(src, len as usize)?;
|
self.memory().copy_nonoverlapping(src as usize, dst as usize, len as usize)?;
|
||||||
self.memory().set(dst, &mem)?;
|
|
||||||
|
|
||||||
Ok(Some(0i32.into()))
|
Ok(Some(Into::into(dst as i32)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bswap_32(x: u32) -> u32 {
|
fn mem_move(&mut self, context: InterpreterCallerContext)
|
||||||
x >> 24 | x >> 8 & 0xff00 | x << 8 & 0xff0000 | x << 24
|
-> 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)
|
fn bitswap_i64(&mut self, context: InterpreterCallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
{
|
{
|
||||||
let x1 = context.value_stack.pop_as::<i32>()?;
|
let x = context.value_stack.pop_as::<i64>()?;
|
||||||
let x2 = context.value_stack.pop_as::<i32>()?;
|
let result = x.swap_bytes();
|
||||||
|
|
||||||
let result = ((Runtime::bswap_32(x2 as u32) as u64) << 32
|
Ok(Some(result.into()))
|
||||||
| Runtime::bswap_32(x1 as u32) as u64) as i64;
|
|
||||||
|
|
||||||
self.return_i64(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn user_panic(&mut self, context: InterpreterCallerContext)
|
fn user_panic(&mut self, context: InterpreterCallerContext)
|
||||||
@ -606,13 +641,10 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
|||||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
{
|
{
|
||||||
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
|
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
|
||||||
let block_hi = context.value_stack.pop_as::<i32>()? as u32;
|
let block_num = context.value_stack.pop_as::<i64>()? as u64;
|
||||||
let block_lo = context.value_stack.pop_as::<i32>()? as u32;
|
|
||||||
|
|
||||||
self.charge(|schedule| schedule.blockhash_gas 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);
|
trace!("Requesting block hash for block #{}", block_num);
|
||||||
let hash = self.ext.blockhash(&U256::from(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>
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
{
|
{
|
||||||
let timestamp = self.ext.env_info().timestamp as i64;
|
let timestamp = self.ext.env_info().timestamp as i64;
|
||||||
self.return_i64(timestamp)
|
Ok(Some(timestamp.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_number(&mut self, _context: InterpreterCallerContext)
|
fn block_number(&mut self, _context: InterpreterCallerContext)
|
||||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
{
|
{
|
||||||
let block_number: u64 = self.ext.env_info().number.into();
|
let block_number = self.ext.env_info().number as i64;
|
||||||
self.return_i64(block_number as i64)
|
Ok(Some(block_number.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn difficulty(&mut self, context: InterpreterCallerContext)
|
fn difficulty(&mut self, context: InterpreterCallerContext)
|
||||||
@ -726,25 +758,6 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
|||||||
Ok(None)
|
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> {
|
pub fn execution_params(&mut self) -> interpreter::ExecutionParams<UserTrap> {
|
||||||
use super::env;
|
use super::env;
|
||||||
|
|
||||||
@ -812,10 +825,10 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
|
|||||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||||
{
|
{
|
||||||
match name {
|
match name {
|
||||||
"_malloc" => {
|
"_ext_malloc" => {
|
||||||
self.malloc(context)
|
self.malloc(context)
|
||||||
},
|
},
|
||||||
"_free" => {
|
"_ext_free" => {
|
||||||
// Since it is arena allocator, free does nothing
|
// Since it is arena allocator, free does nothing
|
||||||
// todo: update if changed
|
// todo: update if changed
|
||||||
self.user_noop(context)
|
self.user_noop(context)
|
||||||
@ -853,6 +866,15 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
|
|||||||
"_emscripten_memcpy_big" => {
|
"_emscripten_memcpy_big" => {
|
||||||
self.mem_copy(context)
|
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" => {
|
"_llvm_bswap_i64" => {
|
||||||
self.bitswap_i64(context)
|
self.bitswap_i64(context)
|
||||||
},
|
},
|
||||||
|
@ -60,7 +60,7 @@ fn empty() {
|
|||||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
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.
|
// This test checks if the contract deserializes payload header properly.
|
||||||
@ -89,7 +89,6 @@ fn logger() {
|
|||||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(15_177));
|
|
||||||
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"),
|
||||||
@ -113,6 +112,7 @@ fn logger() {
|
|||||||
U256::from(1_000_000_000),
|
U256::from(1_000_000_000),
|
||||||
"Logger sets 0x04 key to the trasferred value"
|
"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.
|
// 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!(
|
assert_eq!(
|
||||||
Address::from_slice(&result),
|
Address::from_slice(&result),
|
||||||
sender,
|
sender,
|
||||||
"Idenity test contract does not return the sender passed"
|
"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
|
// 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!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
|
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
|
||||||
);
|
);
|
||||||
|
assert_eq!(gas_left, U256::from(99_469));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -205,12 +204,11 @@ fn suicide_not() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(96_822));
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
vec![0u8]
|
vec![0u8]
|
||||||
);
|
);
|
||||||
|
assert_eq!(gas_left, U256::from(99_724));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -241,8 +239,8 @@ fn suicide() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(96_580));
|
|
||||||
assert!(ext.suicides.contains(&refund));
|
assert!(ext.suicides.contains(&refund));
|
||||||
|
assert_eq!(gas_left, U256::from(99_663));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -272,7 +270,7 @@ fn create() {
|
|||||||
assert!(ext.calls.contains(
|
assert!(ext.calls.contains(
|
||||||
&FakeCall {
|
&FakeCall {
|
||||||
call_type: FakeCallType::Create,
|
call_type: FakeCallType::Create,
|
||||||
gas: U256::from(62_324),
|
gas: U256::from(65_903),
|
||||||
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()),
|
||||||
@ -280,7 +278,7 @@ fn create() {
|
|||||||
code_address: None,
|
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(
|
assert!(ext.calls.contains(
|
||||||
&FakeCall {
|
&FakeCall {
|
||||||
call_type: FakeCallType::Call,
|
call_type: FakeCallType::Call,
|
||||||
gas: U256::from(95_585),
|
gas: U256::from(98_709),
|
||||||
sender_address: Some(sender),
|
sender_address: Some(sender),
|
||||||
receive_address: Some(receiver),
|
receive_address: Some(receiver),
|
||||||
value: None,
|
value: None,
|
||||||
@ -322,11 +320,11 @@ fn call_code() {
|
|||||||
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
|
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
assert_eq!(gas_left, U256::from(90_665));
|
|
||||||
|
|
||||||
// siphash result
|
// siphash result
|
||||||
let res = LittleEndian::read_u32(&result[..]);
|
let res = LittleEndian::read_u32(&result[..]);
|
||||||
assert_eq!(res, 4198595614);
|
assert_eq!(res, 4198595614);
|
||||||
|
assert_eq!(gas_left, U256::from(93_851));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -359,7 +357,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(95_585),
|
gas: U256::from(98_709),
|
||||||
sender_address: Some(sender),
|
sender_address: Some(sender),
|
||||||
receive_address: Some(receiver),
|
receive_address: Some(receiver),
|
||||||
value: None,
|
value: None,
|
||||||
@ -367,11 +365,12 @@ fn call_static() {
|
|||||||
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
assert_eq!(gas_left, U256::from(90_665));
|
|
||||||
|
|
||||||
// siphash result
|
// siphash result
|
||||||
let res = LittleEndian::read_u32(&result[..]);
|
let res = LittleEndian::read_u32(&result[..]);
|
||||||
assert_eq!(res, 317632590);
|
assert_eq!(res, 317632590);
|
||||||
|
|
||||||
|
assert_eq!(gas_left, U256::from(93_851));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Realloc test
|
// Realloc test
|
||||||
@ -393,8 +392,8 @@ 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(96_811));
|
|
||||||
assert_eq!(result, vec![0u8; 2]);
|
assert_eq!(result, vec![0u8; 2]);
|
||||||
|
assert_eq!(gas_left, U256::from(99_787));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that contract's ability to read from a storage
|
// 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!(Address::from(&result[12..32]), address);
|
||||||
|
assert_eq!(gas_left, U256::from(99_702));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests keccak calculation
|
// Tests keccak calculation
|
||||||
@ -446,9 +445,97 @@ 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(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 {
|
macro_rules! reqrep_test {
|
||||||
($name: expr, $input: expr) => {
|
($name: expr, $input: expr) => {
|
||||||
@ -500,11 +587,11 @@ fn math_add() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(94_666));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
);
|
);
|
||||||
|
assert_eq!(gas_left, U256::from(98_576));
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiplication
|
// multiplication
|
||||||
@ -522,11 +609,11 @@ fn math_mul() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(93_719));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
);
|
);
|
||||||
|
assert_eq!(gas_left, U256::from(97_726));
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtraction
|
// subtraction
|
||||||
@ -544,11 +631,11 @@ fn math_sub() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(94_718));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
);
|
);
|
||||||
|
assert_eq!(gas_left, U256::from(98_568));
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtraction with overflow
|
// 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]
|
#[test]
|
||||||
@ -583,11 +673,11 @@ fn math_div() {
|
|||||||
}
|
}
|
||||||
).expect("Interpreter to execute without any errors");
|
).expect("Interpreter to execute without any errors");
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(86_996));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
U256::from_dec_str("1125000").unwrap(),
|
U256::from_dec_str("1125000").unwrap(),
|
||||||
(&result[..]).into()
|
(&result[..]).into()
|
||||||
);
|
);
|
||||||
|
assert_eq!(gas_left, U256::from(91_564));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test checks the ability of wasm contract to invoke
|
// This test checks the ability of wasm contract to invoke
|
||||||
@ -675,7 +765,7 @@ fn externs() {
|
|||||||
"Gas limit requested and returned does not match"
|
"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]
|
#[test]
|
||||||
@ -701,7 +791,7 @@ fn embedded_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(80_452));
|
assert_eq!(gas_left, U256::from(84_520));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This test checks the correctness of log extern
|
/// This test checks the correctness of log extern
|
||||||
@ -736,5 +826,5 @@ fn events() {
|
|||||||
assert_eq!(&log_entry.data, b"gnihtemos");
|
assert_eq!(&log_entry.data, b"gnihtemos");
|
||||||
|
|
||||||
assert_eq!(&result, 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