diff --git a/ethcore/wasm/run/res/sample-fixture.json b/ethcore/wasm/run/res/sample-fixture.json index 4f53eaa38..7be3e04be 100644 --- a/ethcore/wasm/run/res/sample-fixture.json +++ b/ethcore/wasm/run/res/sample-fixture.json @@ -1,7 +1,7 @@ [ { "caption": "Sample test", - "wasm": "./res/sample1.wasm", + "source": "./res/sample1.wasm", "address": "0x1000000000000000000000000000000000000001", "sender": "0x1000000000000000000000000000000000000002", "value": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -21,11 +21,25 @@ }, { "caption": "Keccak test", - "wasm": "./res/sample2.wasm", + "source": "./res/sample2.wasm", "payload": "0x736f6d657468696e67", "gasLimit": 100000, "asserts": [ { "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" } ] + }, + { + "caption": "Token total supply", + "source": { + "constructor": "./res/sample3.wasm", + "sender": "0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f", + "at": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "arguments": "0x0000000000000000000000000000000000000000000000000000000010000000" + }, + "payload": "0x18160ddd", + "gasLimit": 100000, + "asserts": [ + { "Return": "0x0000000000000000000000000000000000000000000000000000000010000000" } + ] } ] \ No newline at end of file diff --git a/ethcore/wasm/run/res/sample3.wasm b/ethcore/wasm/run/res/sample3.wasm new file mode 100644 index 000000000..1811215b4 Binary files /dev/null and b/ethcore/wasm/run/res/sample3.wasm differ diff --git a/ethcore/wasm/run/src/fixture.rs b/ethcore/wasm/run/src/fixture.rs index 0fd3a08e1..ba2da0670 100644 --- a/ethcore/wasm/run/src/fixture.rs +++ b/ethcore/wasm/run/src/fixture.rs @@ -3,11 +3,32 @@ use ethjson::uint::Uint; use ethjson::hash::{Address, H256}; use ethjson::bytes::Bytes; +#[derive(Deserialize)] +#[serde(untagged)] +pub enum Source { + Raw(Cow<'static, String>), + Constructor { + #[serde(rename="constructor")] + source: Cow<'static, String>, + arguments: Bytes, + sender: Address, + at: Address, + }, +} + +impl Source { + pub fn as_ref(&self) -> &str { + match *self { + Source::Raw(ref r) => r.as_ref(), + Source::Constructor { ref source, .. } => source.as_ref(), + } + } +} + #[derive(Deserialize)] pub struct Fixture { pub caption: Cow<'static, String>, - #[serde(rename="wasm")] - pub wasm_file: Cow<'static, String>, + pub source: Source, pub address: Option
, pub sender: Option
, pub value: Option, diff --git a/ethcore/wasm/run/src/runner.rs b/ethcore/wasm/run/src/runner.rs index edfc1ee4b..06a6b0469 100644 --- a/ethcore/wasm/run/src/runner.rs +++ b/ethcore/wasm/run/src/runner.rs @@ -1,6 +1,6 @@ -use fixture::{Fixture, Assert, CallLocator}; +use fixture::{Fixture, Assert, CallLocator, Source}; use wasm::WasmInterpreter; -use vm::{self, Vm, GasLeft, ActionParams, ActionValue}; +use vm::{self, Vm, GasLeft, ActionParams, ActionValue, ParamsType}; use vm::tests::FakeExt; use std::io::{self, Read}; use std::{fs, path, fmt}; @@ -19,6 +19,11 @@ fn wasm_interpreter() -> WasmInterpreter { WasmInterpreter::new().expect("wasm interpreter to create without errors") } +#[derive(Debug)] +pub enum SpecNonconformity { + Address, +} + #[derive(Debug)] pub enum Fail { Return { expected: Vec, actual: Vec }, @@ -27,6 +32,7 @@ pub enum Fail { Load(io::Error), NoCall(CallLocator), StorageMismatch { key: H256, expected: H256, actual: Option }, + Nonconformity(SpecNonconformity) } impl Fail { @@ -37,6 +43,10 @@ impl Fail { fn load(err: io::Error) -> Vec { vec![Fail::Load(err)] } + + fn nononformity(kind: SpecNonconformity) -> Vec { + vec![Fail::Nonconformity(kind)] + } } impl fmt::Display for Fail { @@ -52,6 +62,7 @@ impl fmt::Display for Fail { actual.to_hex(), actual.len() ), + UsedGas { expected, actual } => write!(f, "Expected to use gas: {}, but got actual gas used: {}", expected, actual), @@ -80,22 +91,69 @@ impl fmt::Display for Fail { key.as_ref().to_vec().to_hex(), expected.as_ref().to_vec().to_hex(), ), + + Nonconformity(SpecNonconformity::Address) => + write!(f, "Cannot use address when constructor is specified!"), } } } +pub fn construct( + ext: &mut vm::Ext, + source: Vec, + arguments: Vec, + sender: H160, + at: H160, +) -> Result, vm::Error> { + + let mut params = ActionParams::default(); + params.sender = sender; + params.address = at; + params.gas = U256::from(100_000_000); + params.data = Some(arguments); + params.code = Some(Arc::new(source)); + params.params_type = ParamsType::Separate; + + Ok( + match wasm_interpreter().exec(params, ext)? { + GasLeft::Known(_) => Vec::new(), + GasLeft::NeedsReturn { data, .. } => data.to_vec(), + } + ) +} + pub fn run_fixture(fixture: &Fixture) -> Vec { let mut params = ActionParams::default(); + let source = match load_code(fixture.source.as_ref()) { + Ok(code) => code, + Err(e) => { return Fail::load(e); }, + }; + + let mut ext = FakeExt::new(); params.code = Some(Arc::new( - match load_code(fixture.wasm_file.as_ref()) { - Ok(code) => code, - Err(e) => { return Fail::load(e); }, + if let Source::Constructor { ref arguments, ref sender, ref at, .. } = fixture.source { + match construct(&mut ext, source, arguments.clone().into(), sender.clone().into(), at.clone().into()) { + Ok(code) => code, + Err(e) => { return Fail::runtime(e); } + } + } else { + source } )); + if let Some(ref sender) = fixture.sender { + params.sender = sender.clone().into(); + } + if let Some(ref address) = fixture.address { + if let Source::Constructor { .. } = fixture.source { + return Fail::nononformity(SpecNonconformity::Address); + } + params.address = address.clone().into(); + } else if let Source::Constructor { ref at, .. } = fixture.source { + params.address = at.clone().into(); } if let Some(gas_limit) = fixture.gas_limit { @@ -110,7 +168,6 @@ pub fn run_fixture(fixture: &Fixture) -> Vec { params.value = ActionValue::Transfer(value.clone().into()) } - let mut ext = FakeExt::new(); if let Some(ref storage) = fixture.storage { for storage_entry in storage.iter() { let key: U256 = storage_entry.key.into(); diff --git a/logger/src/rotating.rs b/logger/src/rotating.rs index d11011f74..e67bdfaad 100644 --- a/logger/src/rotating.rs +++ b/logger/src/rotating.rs @@ -32,8 +32,8 @@ lazy_static! { builder.parse(&log); } - if builder.init().is_ok() { - println!("logger initialized"); + if !builder.init().is_ok() { + println!("logger initialization failed!"); } }; }