Merge pull request #80 from gavofyork/evm_tests

evm tests cleanup
This commit is contained in:
Arkadiy Paronyan 2016-01-11 22:41:57 +01:00
commit 5036735e2c
8 changed files with 379 additions and 393 deletions

View File

@ -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,

View File

@ -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()
}
}

View File

@ -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;
}

View File

@ -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<u8>,
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<u8>
struct RuntimeData {
gas: U256,
gas_price: U256,
call_data: Vec<u8>,
address: Address,
caller: Address,
origin: Address,
call_value: U256,
author: Address,
difficulty: U256,
gas_limit: U256,
number: u64,
timestamp: u64,
code: Vec<u8>
}
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<evmjit::RuntimeDataHandle> 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;
@ -329,7 +329,7 @@ impl evm::Evm for JitEvm {
data.code = params.code.clone();
// TODO:
data.coinbase = Address::new();
data.author = Address::new();
data.difficulty = U256::zero();
data.gas_limit = U256::zero();
data.number = 0;
@ -357,359 +357,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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &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, &params, &mut substate, OutputPolicy::InitContract);
let evm = JitEvm;
let _res = evm.exec(&params, &mut ext);
//assert_eq!(evm.exec(&params, &mut ext), Result::Stop {});
}
assert_eq!(state.storage_at(&address, &H256::new()), H256::from_str("23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23").unwrap());
}
}

View File

@ -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;

View File

@ -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,
}
}
}
}

325
src/evm/tests.rs Normal file
View File

@ -0,0 +1,325 @@
use common::*;
use evm;
use evm::{Ext, Schedule, Factory};
struct FakeLogEntry {
topics: Vec<H256>,
data: Bytes
}
/// Fake externalities test structure.
///
/// Can't do recursive calls.
#[derive(Default)]
struct FakeExt {
store: HashMap<H256, H256>,
balances: HashMap<Address, U256>,
blockhashes: HashMap<U256, H256>,
codes: HashMap<Address, Bytes>,
logs: Vec<FakeLogEntry>,
suicide: HashSet<Address>,
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<Address>), 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<u64, evm::Error> {
unimplemented!();
}
fn extcode(&self, address: &Address) -> Vec<u8> {
self.codes.get(address).unwrap_or(&Bytes::new()).clone()
}
fn log(&mut self, topics: Vec<H256>, data: Bytes) {
self.logs.push(FakeLogEntry {
topics: topics,
data: data
});
}
fn ret(&mut self, _gas: u64, _data: &[u8]) -> result::Result<u64, evm::Error> {
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(&params, &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(&params, &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(&params, &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(&params, &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(&params, &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(&params, &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(&params, &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(&params, &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(&params, &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(&params, &mut ext).unwrap()
};
assert_eq!(gas_left, U256::from(79_991));
assert_eq!(ext.store.get(&H256::new()).unwrap(), &H256::from_str("23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23").unwrap());
}

View File

@ -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<Address>,
/// 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<Executed, ExecutionError>;
/// 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)
}
@ -93,7 +89,7 @@ impl<'a> Executive<'a> {
}
}
/// This funtion should be used to execute transaction.
/// Executes transaction.
pub fn transact(&mut self, t: &Transaction) -> ExecutionResult {
// TODO: validate transaction signature ?/ sender
@ -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() {