WASM Runtime refactoring (#6596)
* refactoring to new pwasm-std * pass reference * remove ref * missing underscores
This commit is contained in:
parent
ec1a892f44
commit
4260910db6
@ -1 +1 @@
|
||||
Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a
|
||||
Subproject commit c8129ce2f36c26ed634eda786960978a28e28d0e
|
@ -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
|
||||
}
|
||||
}
|
@ -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",
|
||||
&[],
|
||||
|
@ -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()
|
||||
|
@ -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<PtrError> 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<WasmPtr, InterpreterError> {
|
||||
pub fn write_descriptor(&mut self, input: &[u8]) -> Result<WasmPtr, InterpreterError> {
|
||||
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<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)
|
||||
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||
{
|
||||
@ -691,6 +712,18 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> 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)?)
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user