Add hint in ActionParams for splitting code/data (#6957)

* Action params and embedded params handling

* fix namespaces
This commit is contained in:
Nikolay Volf 2017-11-02 14:49:57 +03:00 committed by Arkadiy Paronyan
parent 0a69d5ac4c
commit f72858ee0a
11 changed files with 84 additions and 14 deletions

10
Cargo.lock generated
View File

@ -7,7 +7,7 @@ dependencies = [
"ethcore-logger 1.9.0", "ethcore-logger 1.9.0",
"ethcore-util 1.9.0", "ethcore-util 1.9.0",
"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.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", "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)",
] ]
@ -2267,7 +2267,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-wasm" name = "parity-wasm"
version = "0.14.5" version = "0.15.1"
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)",
@ -3425,7 +3425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "wasm-utils" name = "wasm-utils"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/wasm-utils#6a39db802eb6b67a0c4e5cf50741f965e217335a" source = "git+https://github.com/paritytech/wasm-utils#3d59f7ca0661317bc66894a26b2a5a319fa5d229"
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)",
"clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3433,7 +3433,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.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]] [[package]]
@ -3647,7 +3647,7 @@ dependencies = [
"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-old-precompiled 1.8.0 (git+https://github.com/paritytech/js-precompiled.git?branch=v1)" = "<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-ui-precompiled 1.9.0 (git+https://github.com/paritytech/js-precompiled.git)" = "<none>"
"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 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"

View File

@ -309,6 +309,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
code: Some(Arc::new(t.data.clone())), code: Some(Arc::new(t.data.clone())),
data: None, data: None,
call_type: CallType::None, call_type: CallType::None,
params_type: vm::ParamsType::Embedded,
}; };
let mut out = if output_from_create { Some(vec![]) } else { None }; 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)) (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)?), code_hash: Some(self.state.code_hash(address)?),
data: Some(t.data.clone()), data: Some(t.data.clone()),
call_type: CallType::Call, call_type: CallType::Call,
params_type: vm::ParamsType::Separate,
}; };
let mut out = vec![]; let mut out = vec![];
(self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out) (self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out)

View File

@ -171,6 +171,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
code_hash: Some(code_hash), code_hash: Some(code_hash),
data: Some(H256::from(number).to_vec()), data: Some(H256::from(number).to_vec()),
call_type: CallType::Call, call_type: CallType::Call,
params_type: vm::ParamsType::Separate,
}; };
let mut output = H256::new(); 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, code_hash: code_hash,
data: None, data: None,
call_type: CallType::None, call_type: CallType::None,
params_type: vm::ParamsType::Embedded,
}; };
if !self.static_flag { 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), code_hash: Some(code_hash),
data: Some(data.to_vec()), data: Some(data.to_vec()),
call_type: call_type, call_type: call_type,
params_type: vm::ParamsType::Separate,
}; };
if let Some(value) = value { if let Some(value) = value {

View File

@ -35,7 +35,7 @@ use tx_filter::TransactionFilter;
use bigint::prelude::U256; use bigint::prelude::U256;
use bytes::BytesRef; use bytes::BytesRef;
use util::Address; use util::Address;
use vm::{CallType, ActionParams, ActionValue}; use vm::{CallType, ActionParams, ActionValue, ParamsType};
use vm::{EnvInfo, Schedule, CreateContractAddress}; use vm::{EnvInfo, Schedule, CreateContractAddress};
/// Parity tries to round block.gas_limit to multiple of this constant /// 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)?), code_hash: Some(state.code_hash(&contract_address)?),
data: data, data: data,
call_type: CallType::Call, call_type: CallType::Call,
params_type: ParamsType::Separate,
}; };
let mut ex = Executive::new(&mut state, &env_info, self); let mut ex = Executive::new(&mut state, &env_info, self);
let mut substate = Substate::new(); let mut substate = Substate::new();

View File

@ -30,7 +30,7 @@ use parking_lot::RwLock;
use rlp::{Rlp, RlpStream}; use rlp::{Rlp, RlpStream};
use rustc_hex::FromHex; use rustc_hex::FromHex;
use util::*; use util::*;
use vm::{EnvInfo, CallType, ActionValue, ActionParams}; use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType};
use super::genesis::Genesis; use super::genesis::Genesis;
use super::seal::Generic as GenericSeal; use super::seal::Generic as GenericSeal;
@ -504,6 +504,7 @@ impl Spec {
code: Some(Arc::new(constructor.clone())), code: Some(Arc::new(constructor.clone())),
data: None, data: None,
call_type: CallType::None, call_type: CallType::None,
params_type: ParamsType::Embedded,
}; };
let mut substate = Substate::new(); let mut substate = Substate::new();

View File

@ -2,7 +2,7 @@
use std::sync::Arc; use std::sync::Arc;
use hash::keccak; use hash::keccak;
use vm::{EnvInfo, ActionParams, ActionValue, CallType}; use vm::{EnvInfo, ActionParams, ActionValue, CallType, ParamsType};
use evm::{Factory, VMType}; use evm::{Factory, VMType};
use executive::Executive; use executive::Executive;
use state::Substate; use state::Substate;
@ -45,6 +45,7 @@ fn test_blockhash_eip210(factory: Factory) {
code_hash: Some(blockhash_contract_code_hash), code_hash: Some(blockhash_contract_code_hash),
data: Some(H256::from(i - 1).to_vec()), data: Some(H256::from(i - 1).to_vec()),
call_type: CallType::Call, call_type: CallType::Call,
params_type: ParamsType::Separate,
}; };
let mut ex = Executive::new(&mut state, &env_info, &machine); let mut ex = Executive::new(&mut state, &env_info, &machine);
let mut substate = Substate::new(); let mut substate = Substate::new();
@ -67,6 +68,7 @@ fn test_blockhash_eip210(factory: Factory) {
code_hash: Some(get_prev_hash_code_hash), code_hash: Some(get_prev_hash_code_hash),
data: None, data: None,
call_type: CallType::Call, call_type: CallType::Call,
params_type: ParamsType::Separate,
}; };
let mut ex = Executive::new(&mut state, &env_info, &machine); let mut ex = Executive::new(&mut state, &env_info, &machine);
let mut substate = Substate::new(); let mut substate = Substate::new();

View File

@ -35,6 +35,15 @@ pub enum ActionValue {
Apparent(U256) 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 { impl ActionValue {
/// Returns action value as U256. /// Returns action value as U256.
pub fn value(&self) -> U256 { pub fn value(&self) -> U256 {
@ -81,7 +90,8 @@ pub struct ActionParams {
pub data: Option<Bytes>, pub data: Option<Bytes>,
/// Type of call /// Type of call
pub call_type: CallType, pub call_type: CallType,
/// Param types encoding
pub params_type: ParamsType,
} }
impl Default for ActionParams { impl Default for ActionParams {
@ -99,6 +109,7 @@ impl Default for ActionParams {
code: None, code: None,
data: None, data: None,
call_type: CallType::None, call_type: CallType::None,
params_type: ParamsType::Separate,
} }
} }
} }
@ -118,6 +129,7 @@ impl From<ethjson::vm::Transaction> for ActionParams {
gas_price: t.gas_price.into(), gas_price: t.gas_price.into(),
value: ActionValue::Transfer(t.value.into()), value: ActionValue::Transfer(t.value.into()),
call_type: match address.is_zero() { true => CallType::None, false => CallType::Call }, // TODO @debris is this correct? call_type: match address.is_zero() { true => CallType::None, false => CallType::Call }, // TODO @debris is this correct?
params_type: ParamsType::Separate,
} }
} }
} }

View File

@ -35,7 +35,7 @@ mod error;
pub mod tests; pub mod tests;
pub use action_params::{ActionParams, ActionValue}; pub use action_params::{ActionParams, ActionValue, ParamsType};
pub use call_type::CallType; pub use call_type::CallType;
pub use env_info::{EnvInfo, LastHashes}; pub use env_info::{EnvInfo, LastHashes};
pub use schedule::{Schedule, CleanDustMode}; pub use schedule::{Schedule, CleanDustMode};

View File

@ -8,7 +8,7 @@ byteorder = "1.0"
ethcore-util = { path = "../../util" } ethcore-util = { path = "../../util" }
ethcore-bigint = { path = "../../util/bigint" } ethcore-bigint = { path = "../../util/bigint" }
log = "0.3" log = "0.3"
parity-wasm = "0.14" parity-wasm = "0.15"
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
vm = { path = "../vm" } vm = { path = "../vm" }
ethcore-logger = { path = "../../logger" } ethcore-logger = { path = "../../logger" }

View File

@ -115,7 +115,18 @@ impl vm::Vm for WasmInterpreter {
&self.program, &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( let contract_module = wasm_utils::inject_gas_counter(
elements::Module::deserialize( 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; let static_segment_cost = data_section_length * runtime.ext().schedule().wasm.static_region as u64;
runtime.charge(|_| static_segment_cost).map_err(Error)?; runtime.charge(|_| static_segment_cost).map_err(Error)?;
let d_ptr = runtime.write_descriptor(&params.data.unwrap_or_default()) let d_ptr = {
.map_err(Error)?; 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(&params.data.unwrap_or_default())
.map_err(Error)?
}
}
};
{ {
let execution_params = runtime.execution_params() let execution_params = runtime.execution_params()

View File

@ -677,3 +677,30 @@ fn externs() {
assert_eq!(gas_left, U256::from(91_857)); 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));
}