From 148ec3731cef789746017cedc41984a99cf87c10 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 3 Nov 2017 14:20:54 +0300 Subject: [PATCH] [beta] Add hint in ActionParams for splitting code/data (#6968) * Action params and embedded params handling * fix namespaces --- Cargo.lock | 9 +++++---- ethcore/src/executive.rs | 2 ++ ethcore/src/externalities.rs | 3 +++ ethcore/src/machine.rs | 3 ++- ethcore/src/spec/spec.rs | 3 ++- ethcore/src/tests/evm.rs | 4 +++- ethcore/vm/src/action_params.rs | 14 +++++++++++++- ethcore/vm/src/lib.rs | 2 +- ethcore/wasm/Cargo.toml | 2 +- ethcore/wasm/src/lib.rs | 28 +++++++++++++++++++++++++--- ethcore/wasm/src/tests.rs | 27 +++++++++++++++++++++++++++ 11 files changed, 84 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29655346e..a9c8f9aac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ dependencies = [ "ethcore-logger 1.8.0", "ethcore-util 1.8.2", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.15.1 (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)", ] @@ -2401,7 +2401,7 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.14.5" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3583,7 +3583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-utils" version = "0.1.0" -source = "git+https://github.com/paritytech/wasm-utils#6a39db802eb6b67a0c4e5cf50741f965e217335a" +source = "git+https://github.com/paritytech/wasm-utils#3d59f7ca0661317bc66894a26b2a5a319fa5d229" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3591,7 +3591,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.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3816,6 +3816,7 @@ dependencies = [ "checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "" "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git?branch=beta)" = "" "checksum parity-wasm 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4502e18417d96bd8e72fca9ea4cc18f4d80288ff565582d10aefe86f18b4fc3" +"checksum parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95f6243c2d6fadf903b5edfd0011817efc20522ce5f360abf4648c24ea87581a" "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" diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 2a70689db..8e47035c4 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -309,6 +309,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { code: Some(Arc::new(t.data.clone())), data: None, call_type: CallType::None, + params_type: vm::ParamsType::Embedded, }; let mut out = if output_from_create { Some(vec![]) } else { None }; (self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new)) @@ -326,6 +327,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { code_hash: Some(self.state.code_hash(address)?), data: Some(t.data.clone()), call_type: CallType::Call, + params_type: vm::ParamsType::Separate, }; let mut out = vec![]; (self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out) diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index c7cf62276..ff7805299 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -171,6 +171,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> code_hash: Some(code_hash), data: Some(H256::from(number).to_vec()), call_type: CallType::Call, + params_type: vm::ParamsType::Separate, }; let mut output = H256::new(); @@ -219,6 +220,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> code_hash: code_hash, data: None, call_type: CallType::None, + params_type: vm::ParamsType::Embedded, }; if !self.static_flag { @@ -276,6 +278,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> code_hash: Some(code_hash), data: Some(data.to_vec()), call_type: call_type, + params_type: vm::ParamsType::Separate, }; if let Some(value) = value { diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 2536384e6..783dc8cc0 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -35,7 +35,7 @@ use tx_filter::TransactionFilter; use bigint::prelude::U256; use bytes::BytesRef; use util::Address; -use vm::{CallType, ActionParams, ActionValue}; +use vm::{CallType, ActionParams, ActionValue, ParamsType}; use vm::{EnvInfo, Schedule, CreateContractAddress}; /// Parity tries to round block.gas_limit to multiple of this constant @@ -149,6 +149,7 @@ impl EthereumMachine { code_hash: Some(state.code_hash(&contract_address)?), data: data, call_type: CallType::Call, + params_type: ParamsType::Separate, }; let mut ex = Executive::new(&mut state, &env_info, self); let mut substate = Substate::new(); diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index a1696c47b..451cb13f2 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -30,7 +30,7 @@ use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; use rustc_hex::FromHex; use util::*; -use vm::{EnvInfo, CallType, ActionValue, ActionParams}; +use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType}; use super::genesis::Genesis; use super::seal::Generic as GenericSeal; @@ -504,6 +504,7 @@ impl Spec { code: Some(Arc::new(constructor.clone())), data: None, call_type: CallType::None, + params_type: ParamsType::Embedded, }; let mut substate = Substate::new(); diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 021ab444e..830fcb5d7 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use hash::keccak; -use vm::{EnvInfo, ActionParams, ActionValue, CallType}; +use vm::{EnvInfo, ActionParams, ActionValue, CallType, ParamsType}; use evm::{Factory, VMType}; use executive::Executive; use state::Substate; @@ -45,6 +45,7 @@ fn test_blockhash_eip210(factory: Factory) { code_hash: Some(blockhash_contract_code_hash), data: Some(H256::from(i - 1).to_vec()), call_type: CallType::Call, + params_type: ParamsType::Separate, }; let mut ex = Executive::new(&mut state, &env_info, &machine); let mut substate = Substate::new(); @@ -67,6 +68,7 @@ fn test_blockhash_eip210(factory: Factory) { code_hash: Some(get_prev_hash_code_hash), data: None, call_type: CallType::Call, + params_type: ParamsType::Separate, }; let mut ex = Executive::new(&mut state, &env_info, &machine); let mut substate = Substate::new(); diff --git a/ethcore/vm/src/action_params.rs b/ethcore/vm/src/action_params.rs index f87b1e558..cf914126f 100644 --- a/ethcore/vm/src/action_params.rs +++ b/ethcore/vm/src/action_params.rs @@ -35,6 +35,15 @@ pub enum ActionValue { Apparent(U256) } +/// Type of the way parameters encoded +#[derive(Clone, Debug)] +pub enum ParamsType { + /// Parameters are included in code + Embedded, + /// Parameters are passed in data section + Separate, +} + impl ActionValue { /// Returns action value as U256. pub fn value(&self) -> U256 { @@ -81,7 +90,8 @@ pub struct ActionParams { pub data: Option, /// Type of call pub call_type: CallType, - + /// Param types encoding + pub params_type: ParamsType, } impl Default for ActionParams { @@ -99,6 +109,7 @@ impl Default for ActionParams { code: None, data: None, call_type: CallType::None, + params_type: ParamsType::Separate, } } } @@ -118,6 +129,7 @@ impl From for ActionParams { gas_price: t.gas_price.into(), value: ActionValue::Transfer(t.value.into()), call_type: match address.is_zero() { true => CallType::None, false => CallType::Call }, // TODO @debris is this correct? + params_type: ParamsType::Separate, } } } diff --git a/ethcore/vm/src/lib.rs b/ethcore/vm/src/lib.rs index 56a380597..1f88bf625 100644 --- a/ethcore/vm/src/lib.rs +++ b/ethcore/vm/src/lib.rs @@ -35,7 +35,7 @@ mod error; pub mod tests; -pub use action_params::{ActionParams, ActionValue}; +pub use action_params::{ActionParams, ActionValue, ParamsType}; pub use call_type::CallType; pub use env_info::{EnvInfo, LastHashes}; pub use schedule::{Schedule, CleanDustMode}; diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index 1b18a5c2a..380ffdfcf 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -8,7 +8,7 @@ byteorder = "1.0" ethcore-util = { path = "../../util" } ethcore-bigint = { path = "../../util/bigint" } log = "0.3" -parity-wasm = "0.14" +parity-wasm = "0.15" wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } vm = { path = "../vm" } ethcore-logger = { path = "../../logger" } diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index df5a4c043..70601144d 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -115,7 +115,18 @@ impl vm::Vm for WasmInterpreter { &self.program, ); - let mut cursor = ::std::io::Cursor::new(&*code); + let (mut cursor, data_position) = match params.params_type { + vm::ParamsType::Embedded => { + let module_size = parity_wasm::peek_size(&*code); + ( + ::std::io::Cursor::new(&code[..module_size]), + module_size + ) + }, + vm::ParamsType::Separate => { + (::std::io::Cursor::new(&code[..]), 0) + }, + }; let contract_module = wasm_utils::inject_gas_counter( elements::Module::deserialize( @@ -134,8 +145,19 @@ impl vm::Vm for WasmInterpreter { let static_segment_cost = data_section_length * runtime.ext().schedule().wasm.static_region as u64; runtime.charge(|_| static_segment_cost).map_err(Error)?; - let d_ptr = runtime.write_descriptor(¶ms.data.unwrap_or_default()) - .map_err(Error)?; + let d_ptr = { + match params.params_type { + vm::ParamsType::Embedded => { + runtime.write_descriptor( + if data_position < code.len() { &code[data_position..] } else { &[] } + ).map_err(Error)? + }, + vm::ParamsType::Separate => { + runtime.write_descriptor(¶ms.data.unwrap_or_default()) + .map_err(Error)? + } + } + }; { let execution_params = runtime.execution_params() diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index 57b5ab6a8..c9174f288 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -677,3 +677,30 @@ fn externs() { assert_eq!(gas_left, U256::from(91_857)); } + +#[test] +fn embedded_keccak() { + + ::ethcore_logger::init_log(); + let mut code = load_sample!("keccak.wasm"); + code.extend_from_slice(b"something"); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.params_type = vm::ParamsType::Embedded; + + 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!("keccak should return payload"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + } + }; + + assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); + assert_eq!(gas_left, U256::from(80_452)); +} \ No newline at end of file