diff --git a/rust-evmjit/src/lib.rs b/rust-evmjit/src/lib.rs index 41270177f..670509d87 100644 --- a/rust-evmjit/src/lib.rs +++ b/rust-evmjit/src/lib.rs @@ -287,7 +287,7 @@ pub mod ffi { pub caller: JitI256, pub origin: JitI256, pub call_value: JitI256, - pub coinbase: JitI256, + pub author: JitI256, pub difficulty: JitI256, pub gas_limit: JitI256, pub number: u64, diff --git a/src/env_info.rs b/src/env_info.rs index 5df877970..8b9fe3349 100644 --- a/src/env_info.rs +++ b/src/env_info.rs @@ -36,3 +36,11 @@ impl EnvInfo { } } } + +/// TODO: it should be the other way around. +/// `new` should call `default`. +impl Default for EnvInfo { + fn default() -> Self { + EnvInfo::new() + } +} diff --git a/src/evm/ext.rs b/src/evm/ext.rs index f5ddaaaa6..b878c5819 100644 --- a/src/evm/ext.rs +++ b/src/evm/ext.rs @@ -3,8 +3,8 @@ use util::hash::*; use util::uint::*; use util::bytes::*; -use evm::Schedule; -use evm::Error; +use evm::{Schedule, Error}; +use env_info::*; // TODO: replace all u64 with u256 pub trait Ext { @@ -55,4 +55,7 @@ pub trait Ext { /// Returns schedule. fn schedule(&self) -> &Schedule; + + /// Returns environment info. + fn env_info(&self) -> &EnvInfo; } diff --git a/src/evm/jit.rs b/src/evm/jit.rs index 4b99bc655..3fb3bb40c 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -4,24 +4,24 @@ use evmjit; use evm; /// Ethcore representation of evmjit runtime data. -pub struct RuntimeData { - pub gas: U256, - pub gas_price: U256, - pub call_data: Vec, - pub address: Address, - pub caller: Address, - pub origin: Address, - pub call_value: U256, - pub coinbase: Address, - pub difficulty: U256, - pub gas_limit: U256, - pub number: u64, - pub timestamp: u64, - pub code: Vec +struct RuntimeData { + gas: U256, + gas_price: U256, + call_data: Vec, + address: Address, + caller: Address, + origin: Address, + call_value: U256, + author: Address, + difficulty: U256, + gas_limit: U256, + number: u64, + timestamp: u64, + code: Vec } impl RuntimeData { - pub fn new() -> RuntimeData { + fn new() -> RuntimeData { RuntimeData { gas: U256::zero(), gas_price: U256::zero(), @@ -30,7 +30,7 @@ impl RuntimeData { caller: Address::new(), origin: Address::new(), call_value: U256::zero(), - coinbase: Address::new(), + author: Address::new(), difficulty: U256::zero(), gas_limit: U256::zero(), number: 0, @@ -140,7 +140,7 @@ impl IntoJit for RuntimeData { data.caller = self.caller.into_jit(); data.origin = self.origin.into_jit(); data.call_value = self.call_value.into_jit(); - data.coinbase = self.coinbase.into_jit(); + data.author = self.author.into_jit(); data.difficulty = self.difficulty.into_jit(); data.gas_limit = self.gas_limit.into_jit(); data.number = self.number; @@ -328,12 +328,11 @@ impl evm::Evm for JitEvm { data.call_value = params.value; data.code = params.code.clone(); - // TODO: - data.coinbase = Address::new(); - data.difficulty = U256::zero(); - data.gas_limit = U256::zero(); - data.number = 0; - data.timestamp = 0; + data.author = ext.env_info().author.clone(); + data.difficulty = ext.env_info().difficulty; + data.gas_limit = ext.env_info().gas_limit; + data.number = ext.env_info().number; + data.timestamp = ext.env_info().timestamp; let mut context = unsafe { evmjit::ContextHandle::new(data.into_jit(), &mut ext_handle) }; let res = context.exec(); @@ -357,359 +356,3 @@ impl evm::Evm for JitEvm { } } -#[cfg(test)] -mod tests { - use super::*; - use common::*; - use evm::jit::{FromJit, IntoJit}; - use evm::{Evm,Schedule}; - use executive::*; - use state::*; - use engine::*; - use spec::*; - - struct TestEngine; - - impl TestEngine { - fn new() -> Self { TestEngine } - } - - impl Engine for TestEngine { - fn name(&self) -> &str { "TestEngine" } - fn spec(&self) -> &Spec { unimplemented!() } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() } - } - - #[test] - fn test_to_and_from_u256() { - use std::str::FromStr; - - let u = U256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap(); - let j = u.into_jit(); - let u2 = U256::from_jit(&j); - assert_eq!(u, u2); - } - - #[test] - fn test_to_and_from_h256() { - use std::str::FromStr; - - let h = H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap(); - let j: ::evmjit::I256 = h.clone().into_jit(); - let h2 = H256::from_jit(&j); - assert_eq!(h, h2); - } - - #[test] - fn test_to_and_from_address() { - use std::str::FromStr; - - let a = Address::from_str("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap(); - let j: ::evmjit::I256 = a.clone().into_jit(); - let a2 = Address::from_jit(&j); - assert_eq!(a, a2); - } - - #[test] - fn test_ext_add() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop); - } - - assert_eq!(state.storage_at(&address, &H256::new()), - H256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap()); - } - - #[test] - fn test_ext_sha3_0() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "6000600020600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(state.storage_at(&address, &H256::new()), - H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap()); - } - - #[test] - fn test_ext_sha3_1() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "6005600420600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(state.storage_at(&address, &H256::new()), - H256::from_str("c41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec").unwrap()); - } - - #[test] - fn test_origin() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.origin = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "32600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(Address::from(state.storage_at(&address, &H256::new())), address.clone()); - } - - #[test] - fn test_sender() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.sender = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "32600055".from_hex().unwrap(); - params.code = "33600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(Address::from(state.storage_at(&address, &H256::new())), address.clone()); - } - - #[test] - fn test_extcode_copy0() { - // 33 - sender - // 3b - extcodesize - // 60 00 - push 0 - // 60 00 - push 0 - // 33 - sender - // 3c - extcodecopy - // 60 00 - push 0 - // 51 - load word from memory - // 60 00 - push 0 - // 55 - sstore - - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address_code = "333b60006000333c600051600055".from_hex().unwrap(); - let sender_code = "6005600055".from_hex().unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.sender = sender.clone(); - params.origin = sender.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = address_code.clone(); - - let mut state = State::new_temp(); - state.init_code(&address, address_code); - state.init_code(&sender, sender_code); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(state.storage_at(&address, &H256::new()), - H256::from_str("6005600055000000000000000000000000000000000000000000000000000000").unwrap()); - } - - #[test] - fn test_balance() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.sender = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "3331600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - state.add_balance(&address, &U256::from(0x10)); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(state.storage_at(&address, &H256::new()), H256::from(&U256::from(0x10))); - } - - #[test] - fn test_empty_log() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "60006000a0".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - let logs = substate.logs(); - assert_eq!(logs.len(), 1); - let log = &logs[0]; - assert_eq!(log.address(), &address); - assert_eq!(log.topics().len(), 0); - assert_eq!(log.bloom(), H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); - } - - #[test] - fn test_log_with_one_topic() { - // 60 ff - push ff - // 60 00 - push 00 - // 53 - mstore - // 33 - sender - // 60 20 - push 20 - // 60 00 - push 0 - // a1 - log with 1 topic - - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.sender = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "60ff6000533360206000a1".from_hex().unwrap(); - - let mut state = State::new_temp(); - let info = EnvInfo::new(); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - let logs = substate.logs(); - assert_eq!(logs.len(), 1); - let log = &logs[0]; - assert_eq!(log.address(), &address); - assert_eq!(log.topics().len(), 1); - let topic = &log.topics()[0]; - assert_eq!(topic, &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()); - assert_eq!(topic, &H256::from(address.clone())); - assert_eq!(log.data(), &"ff00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()); - } - - #[test] - fn test_blockhash() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "600040600055".from_hex().unwrap(); - - let mut state = State::new_temp(); - let mut info = EnvInfo::new(); - info.number = 1; - info.last_hashes.push(H256::from(address.clone())); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(state.storage_at(&address, &H256::new()), H256::from(address.clone())); - } - - #[test] - fn test_calldataload() { - let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let mut params = ActionParams::new(); - params.address = address.clone(); - params.gas = U256::from(0x174876e800u64); - params.code = "600135600055".from_hex().unwrap(); - params.data = "0123ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23".from_hex().unwrap(); - - let mut state = State::new_temp(); - let mut info = EnvInfo::new(); - info.number = 1; - info.last_hashes.push(H256::from(address.clone())); - let engine = TestEngine::new(); - let mut substate = Substate::new(); - - { - let mut ext = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::InitContract); - let evm = JitEvm; - let _res = evm.exec(¶ms, &mut ext); - //assert_eq!(evm.exec(¶ms, &mut ext), Result::Stop {}); - } - - assert_eq!(state.storage_at(&address, &H256::new()), H256::from_str("23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23").unwrap()); - } -} diff --git a/src/evm/mod.rs b/src/evm/mod.rs index 9f5789dda..ee590c934 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -7,6 +7,9 @@ pub mod schedule; #[cfg(feature = "jit" )] mod jit; +#[cfg(test)] +mod tests; + pub use self::evm::{Evm, Error, Result}; pub use self::ext::Ext; pub use self::factory::Factory; diff --git a/src/evm/schedule.rs b/src/evm/schedule.rs index 552c2a576..0f46bba12 100644 --- a/src/evm/schedule.rs +++ b/src/evm/schedule.rs @@ -1,3 +1,5 @@ +//! Cost schedule and other parameterisations for the EVM. + /// Definition of the cost schedule and other parameterisations for the EVM. pub struct Schedule { pub exceptional_failed_code_deposit: bool, @@ -77,4 +79,4 @@ impl Schedule { copy_gas: 3, } } -} \ No newline at end of file +} diff --git a/src/evm/tests.rs b/src/evm/tests.rs new file mode 100644 index 000000000..7ee64e4cc --- /dev/null +++ b/src/evm/tests.rs @@ -0,0 +1,425 @@ +use common::*; +use evm; +use evm::{Ext, Schedule, Factory}; + +struct FakeLogEntry { + topics: Vec, + data: Bytes +} + +/// Fake externalities test structure. +/// +/// Can't do recursive calls. +#[derive(Default)] +struct FakeExt { + store: HashMap, + balances: HashMap, + blockhashes: HashMap, + codes: HashMap, + logs: Vec, + suicide: HashSet
, + info: EnvInfo +} + +impl FakeExt { + fn new() -> Self { FakeExt::default() } +} + +impl Ext for FakeExt { + fn sload(&self, key: &H256) -> H256 { + self.store.get(key).unwrap_or(&H256::new()).clone() + } + + fn sstore(&mut self, key: H256, value: H256) { + self.store.insert(key, value); + } + + fn balance(&self, _address: &Address) -> U256 { + unimplemented!(); + } + + fn blockhash(&self, number: &U256) -> H256 { + self.blockhashes.get(number).unwrap_or(&H256::new()).clone() + } + + fn create(&mut self, _gas: u64, _value: &U256, _code: &[u8]) -> result::Result<(u64, Option
), evm::Error> { + unimplemented!(); + } + + fn call(&mut self, + _gas: u64, + _call_gas: u64, + _receive_address: &Address, + _value: &U256, + _data: &[u8], + _code_address: &Address, + _output: &mut [u8]) -> result::Result { + unimplemented!(); + } + + fn extcode(&self, address: &Address) -> Vec { + self.codes.get(address).unwrap_or(&Bytes::new()).clone() + } + + fn log(&mut self, topics: Vec, data: Bytes) { + self.logs.push(FakeLogEntry { + topics: topics, + data: data + }); + } + + fn ret(&mut self, _gas: u64, _data: &[u8]) -> result::Result { + unimplemented!(); + } + + fn suicide(&mut self) { + unimplemented!(); + } + + fn schedule(&self) -> &Schedule { + unimplemented!(); + } + + fn env_info(&self) -> &EnvInfo { + &self.info + } +} + +#[test] +fn test_add() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_988)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap()); +} + +#[test] +fn test_sha3() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "6000600020600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_961)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap()); +} + +#[test] +fn test_address() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "30600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()); +} + +#[test] +fn test_origin() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); + let code = "32600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.origin = origin.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap()); +} + +#[test] +fn test_sender() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); + let code = "33600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.sender = sender.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap()); +} + +#[test] +fn test_extcodecopy() { + // 33 - sender + // 3b - extcodesize + // 60 00 - push 0 + // 60 00 - push 0 + // 33 - sender + // 3c - extcodecopy + // 60 00 - push 0 + // 51 - load word from memory + // 60 00 - push 0 + // 55 - sstore + + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); + let code = "333b60006000333c600051600055".from_hex().unwrap(); + let sender_code = "6005600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.sender = sender.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.codes.insert(sender, sender_code); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_935)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("6005600055000000000000000000000000000000000000000000000000000000").unwrap()); +} + +#[test] +fn test_log_empty() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "60006000a0".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(99_619)); + assert_eq!(ext.logs.len(), 1); + assert_eq!(ext.logs[0].topics.len(), 0); + assert_eq!(ext.logs[0].data, vec![]); +} + +#[test] +fn test_log_sender() { + // 60 ff - push ff + // 60 00 - push 00 + // 53 - mstore + // 33 - sender + // 60 20 - push 20 + // 60 00 - push 0 + // a1 - log with 1 topic + + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); + let code = "60ff6000533360206000a1".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.sender = sender.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(98_974)); + assert_eq!(ext.logs.len(), 1); + assert_eq!(ext.logs[0].topics.len(), 1); + assert_eq!(ext.logs[0].topics[0], H256::from_str("000000000000000000000000cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); + assert_eq!(ext.logs[0].data, "ff00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()); +} + +#[test] +fn test_blockhash() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "600040600055".from_hex().unwrap(); + let blockhash = H256::from_str("123400000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.blockhashes.insert(U256::zero(), blockhash.clone()); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_974)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash); +} + +#[test] +fn test_calldataload() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "600135600055".from_hex().unwrap(); + let data = "0123ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = code; + params.data = data; + let mut ext = FakeExt::new(); + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_991)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23").unwrap()); + +} + +#[test] +fn test_author() { + let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let code = "41600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.info.author = author; + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()); +} + +#[test] +fn test_timestamp() { + let timestamp = 0x1234; + let code = "42600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.info.timestamp = timestamp; + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); +} + +#[test] +fn test_number() { + let number = 0x1234; + let code = "43600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.info.number = number; + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); +} + +#[test] +fn test_difficulty() { + let difficulty = U256::from(0x1234); + let code = "44600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.info.difficulty = difficulty; + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); +} + +#[test] +fn test_gas_limit() { + let gas_limit = U256::from(0x1234); + let code = "45600055".from_hex().unwrap(); + + let mut params = ActionParams::new(); + params.gas = U256::from(100_000); + params.code = code; + let mut ext = FakeExt::new(); + ext.info.gas_limit = gas_limit; + + let gas_left = { + let vm = Factory::create(); + vm.exec(¶ms, &mut ext).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("0000000000000000000000000000000000000000000000000000000000001234").unwrap()); +} diff --git a/src/executive.rs b/src/executive.rs index 06a405c1d..81788c78d 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -14,7 +14,7 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address { /// State changes which should be applied in finalize, /// after transaction is fully executed. -pub struct Substate { +struct Substate { /// Any accounts that have suicided. suicides: HashSet
, /// Any logs. @@ -25,21 +25,16 @@ pub struct Substate { impl Substate { /// Creates new substate. - pub fn new() -> Self { + fn new() -> Self { Substate { suicides: HashSet::new(), logs: vec![], refunds_count: U256::zero(), } } - - // TODO: remove - pub fn logs(&self) -> &[LogEntry] { - &self.logs - } } -/// Transaction execution result. +/// Transaction execution receipt. pub struct Executed { /// Gas paid up front for execution of transaction. pub gas: U256, @@ -61,9 +56,10 @@ pub struct Executed { pub out_of_gas: bool, } +/// Transaction execution result. pub type ExecutionResult = Result; -/// Message-call/contract-creation executor; useful for executing transactions. +/// Transaction executor. pub struct Executive<'a> { state: &'a mut State, info: &'a EnvInfo, @@ -72,7 +68,7 @@ pub struct Executive<'a> { } impl<'a> Executive<'a> { - /// Creates new executive with depth equal 0. + /// Basic constructor. pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self { Executive::new_with_depth(state, info, engine, 0) } @@ -259,7 +255,7 @@ impl<'a> Executive<'a> { } /// Policy for handling output data on `RETURN` opcode. -pub enum OutputPolicy<'a> { +enum OutputPolicy<'a> { /// Return reference to fixed sized output. /// Used for message calls. Return(&'a mut [u8]), @@ -268,7 +264,7 @@ pub enum OutputPolicy<'a> { } /// Implementation of evm Externalities. -pub struct Externalities<'a> { +struct Externalities<'a> { state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, @@ -281,7 +277,7 @@ pub struct Externalities<'a> { impl<'a> Externalities<'a> { /// Basic `Externalities` constructor. - pub fn new(state: &'a mut State, + fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize, @@ -301,7 +297,7 @@ impl<'a> Externalities<'a> { } /// Creates `Externalities` from `Executive`. - pub fn from_executive(e: &'a mut Executive, params: &'a ActionParams, substate: &'a mut Substate, output: OutputPolicy<'a>) -> Self { + fn from_executive(e: &'a mut Executive, params: &'a ActionParams, substate: &'a mut Substate, output: OutputPolicy<'a>) -> Self { Self::new(e.state, e.info, e.engine, e.depth, params, substate, output) } } @@ -443,6 +439,10 @@ impl<'a> Ext for Externalities<'a> { fn schedule(&self) -> &Schedule { &self.schedule } + + fn env_info(&self) -> &EnvInfo { + &self.info + } } #[cfg(test)] @@ -452,6 +452,7 @@ mod tests { use state::*; use ethereum; use null_engine::*; + use super::Substate; #[test] fn test_contract_address() {