Merge branch 'evm' of github.com:gavofyork/ethcore into evm

This commit is contained in:
Tomusdrw 2016-01-15 01:42:09 +01:00
commit e8b9ef202c
10 changed files with 214 additions and 94 deletions

View File

@ -2,6 +2,7 @@ use common::*;
use block::Block; use block::Block;
use spec::Spec; use spec::Spec;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. /// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based.
/// Provides hooks into each of the major parts of block import. /// Provides hooks into each of the major parts of block import.
@ -22,6 +23,9 @@ pub trait Engine : Sync + Send {
/// Get the general parameters of the chain. /// Get the general parameters of the chain.
fn spec(&self) -> &Spec; fn spec(&self) -> &Spec;
/// Get current EVM factory
fn vm_factory(&self) -> &Factory;
/// Get the EVM schedule for the given `env_info`. /// Get the EVM schedule for the given `env_info`.
fn schedule(&self, env_info: &EnvInfo) -> Schedule; fn schedule(&self, env_info: &EnvInfo) -> Schedule;

View File

@ -3,16 +3,22 @@ use block::*;
use spec::*; use spec::*;
use engine::*; use engine::*;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
/// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum /// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum
/// mainnet chains in the Olympic, Frontier and Homestead eras. /// mainnet chains in the Olympic, Frontier and Homestead eras.
pub struct Ethash { pub struct Ethash {
spec: Spec, spec: Spec,
factory: Factory
} }
impl Ethash { impl Ethash {
pub fn new_boxed(spec: Spec) -> Box<Engine> { pub fn new_boxed(spec: Spec) -> Box<Engine> {
Box::new(Ethash{spec: spec}) Box::new(Ethash{
spec: spec,
// TODO [todr] should this return any specific factory?
factory: Factory::default()
})
} }
} }
@ -27,7 +33,11 @@ impl Engine for Ethash {
/// Additional engine-specific information for the user/developer concerning `header`. /// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, _header: &Header) -> HashMap<String, String> { HashMap::new() } fn extra_info(&self, _header: &Header) -> HashMap<String, String> { HashMap::new() }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() } fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }
fn vm_factory(&self) -> &Factory {
&self.factory
}
/// Apply the block reward on finalisation of the block. /// Apply the block reward on finalisation of the block.
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).

View File

@ -1,25 +1,99 @@
//! Evm factory. //! Evm factory.
use std::fmt;
use evm::Evm; use evm::Evm;
#[derive(Clone)]
pub enum VMType {
Jit,
Interpreter
}
impl fmt::Display for VMType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
VMType::Jit => "JIT",
VMType::Interpreter => "INT"
})
}
}
impl VMType {
#[cfg(feature="jit")]
pub fn all() -> Vec<VMType> {
vec![VMType::Jit, VMType::Interpreter]
}
#[cfg(not(feature="jit"))]
pub fn all() -> Vec<VMType> {
vec![VMType::Interpreter]
}
}
/// Evm factory. Creates appropriate Evm. /// Evm factory. Creates appropriate Evm.
pub struct Factory; pub struct Factory {
evm : VMType
}
impl Factory { impl Factory {
/// Returns jit vm
pub fn create(&self) -> Box<Evm> {
match self.evm {
VMType::Jit => {
Factory::jit()
},
VMType::Interpreter => {
Box::new(super::interpreter::Interpreter)
}
}
}
pub fn new(evm: VMType) -> Factory {
Factory {
evm: evm
}
}
#[cfg(feature = "jit")] #[cfg(feature = "jit")]
pub fn create() -> Box<Evm> { fn jit() -> Box<Evm> {
Box::new(super::jit::JitEvm) Box::new(super::jit::JitEvm)
} }
/// Returns native rust evm
#[cfg(not(feature = "jit"))] #[cfg(not(feature = "jit"))]
pub fn create() -> Box<Evm> { fn jit() -> Box<Evm> {
Box::new(super::interpreter::Interpreter) unimplemented!()
}
/// Returns jitvm factory
#[cfg(feature = "jit")]
pub fn default() -> Factory {
Factory {
evm: VMType::Jit
}
}
/// Returns native rust evm factory
#[cfg(not(feature = "jit"))]
pub fn default() -> Factory {
Factory {
evm: VMType::Interpreter
}
} }
} }
#[test] #[test]
fn test_create_vm() { fn test_create_vm() {
let _vm = Factory::create(); let _vm = Factory::default().create();
} }
#[macro_export]
macro_rules! evm_test(
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit));
}
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter));
}
}
);

View File

@ -3,6 +3,7 @@
pub mod ext; pub mod ext;
pub mod evm; pub mod evm;
pub mod interpreter; pub mod interpreter;
#[macro_use]
pub mod factory; pub mod factory;
pub mod schedule; pub mod schedule;
mod instructions; mod instructions;
@ -16,3 +17,4 @@ pub use self::evm::{Evm, Error, Result};
pub use self::ext::Ext; pub use self::ext::Ext;
pub use self::factory::Factory; pub use self::factory::Factory;
pub use self::schedule::Schedule; pub use self::schedule::Schedule;
pub use self::factory::VMType;

View File

@ -1,6 +1,6 @@
use common::*; use common::*;
use evm; use evm;
use evm::{Ext, Schedule}; use evm::{Ext, Schedule, Factory, VMType};
struct FakeLogEntry { struct FakeLogEntry {
topics: Vec<H256>, topics: Vec<H256>,
@ -122,22 +122,8 @@ fn test_stack_underflow() {
}; };
} }
macro_rules! evm_test(
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Box::new(super::jit::JitEvm));
}
#[test]
fn $name_int() {
$name_test(Box::new(super::interpreter::Interpreter));
}
}
);
evm_test!{test_add: test_add_jit, test_add_int} evm_test!{test_add: test_add_jit, test_add_int}
fn test_add(vm : Box<super::Evm>) { fn test_add(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap(); let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
@ -148,6 +134,7 @@ fn test_add(vm : Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -156,7 +143,7 @@ fn test_add(vm : Box<super::Evm>) {
} }
evm_test!{test_sha3: test_sha3_jit, test_sha3_int} evm_test!{test_sha3: test_sha3_jit, test_sha3_int}
fn test_sha3(vm: Box<super::Evm>) { fn test_sha3(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "6000600020600055".from_hex().unwrap(); let code = "6000600020600055".from_hex().unwrap();
@ -167,6 +154,7 @@ fn test_sha3(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -175,7 +163,7 @@ fn test_sha3(vm: Box<super::Evm>) {
} }
evm_test!{test_address: test_address_jit, test_address_int} evm_test!{test_address: test_address_jit, test_address_int}
fn test_address(vm: Box<super::Evm>) { fn test_address(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "30600055".from_hex().unwrap(); let code = "30600055".from_hex().unwrap();
@ -186,6 +174,7 @@ fn test_address(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -194,7 +183,7 @@ fn test_address(vm: Box<super::Evm>) {
} }
evm_test!{test_origin: test_origin_jit, test_origin_int} evm_test!{test_origin: test_origin_jit, test_origin_int}
fn test_origin(vm: Box<super::Evm>) { fn test_origin(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let code = "32600055".from_hex().unwrap(); let code = "32600055".from_hex().unwrap();
@ -207,6 +196,7 @@ fn test_origin(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -215,7 +205,7 @@ fn test_origin(vm: Box<super::Evm>) {
} }
evm_test!{test_sender: test_sender_jit, test_sender_int} evm_test!{test_sender: test_sender_jit, test_sender_int}
fn test_sender(vm: Box<super::Evm>) { fn test_sender(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let code = "33600055".from_hex().unwrap(); let code = "33600055".from_hex().unwrap();
@ -228,6 +218,7 @@ fn test_sender(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -236,7 +227,7 @@ fn test_sender(vm: Box<super::Evm>) {
} }
evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int} evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int}
fn test_extcodecopy(vm: Box<super::Evm>) { fn test_extcodecopy(factory: super::Factory) {
// 33 - sender // 33 - sender
// 3b - extcodesize // 3b - extcodesize
// 60 00 - push 0 // 60 00 - push 0
@ -262,6 +253,7 @@ fn test_extcodecopy(vm: Box<super::Evm>) {
ext.codes.insert(sender, sender_code); ext.codes.insert(sender, sender_code);
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -270,7 +262,7 @@ fn test_extcodecopy(vm: Box<super::Evm>) {
} }
evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int} evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int}
fn test_log_empty(vm: Box<super::Evm>) { fn test_log_empty(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "60006000a0".from_hex().unwrap(); let code = "60006000a0".from_hex().unwrap();
@ -281,6 +273,7 @@ fn test_log_empty(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -291,7 +284,7 @@ fn test_log_empty(vm: Box<super::Evm>) {
} }
evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int} evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int}
fn test_log_sender(vm: Box<super::Evm>) { fn test_log_sender(factory: super::Factory) {
// 60 ff - push ff // 60 ff - push ff
// 60 00 - push 00 // 60 00 - push 00
// 53 - mstore // 53 - mstore
@ -312,6 +305,7 @@ fn test_log_sender(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -323,7 +317,7 @@ fn test_log_sender(vm: Box<super::Evm>) {
} }
evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int} evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int}
fn test_blockhash(vm: Box<super::Evm>) { fn test_blockhash(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600040600055".from_hex().unwrap(); let code = "600040600055".from_hex().unwrap();
let blockhash = H256::from_str("123400000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap(); let blockhash = H256::from_str("123400000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@ -336,6 +330,7 @@ fn test_blockhash(vm: Box<super::Evm>) {
ext.blockhashes.insert(U256::zero(), blockhash.clone()); ext.blockhashes.insert(U256::zero(), blockhash.clone());
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -344,7 +339,7 @@ fn test_blockhash(vm: Box<super::Evm>) {
} }
evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int} evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int}
fn test_calldataload(vm: Box<super::Evm>) { fn test_calldataload(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600135600055".from_hex().unwrap(); let code = "600135600055".from_hex().unwrap();
let data = "0123ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23".from_hex().unwrap(); let data = "0123ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23".from_hex().unwrap();
@ -357,6 +352,7 @@ fn test_calldataload(vm: Box<super::Evm>) {
let mut ext = FakeExt::new(); let mut ext = FakeExt::new();
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -366,7 +362,7 @@ fn test_calldataload(vm: Box<super::Evm>) {
} }
evm_test!{test_author: test_author_jit, test_author_int} evm_test!{test_author: test_author_jit, test_author_int}
fn test_author(vm: Box<super::Evm>) { fn test_author(factory: super::Factory) {
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "41600055".from_hex().unwrap(); let code = "41600055".from_hex().unwrap();
@ -377,6 +373,7 @@ fn test_author(vm: Box<super::Evm>) {
ext.info.author = author; ext.info.author = author;
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -385,7 +382,7 @@ fn test_author(vm: Box<super::Evm>) {
} }
evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int} evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int}
fn test_timestamp(vm: Box<super::Evm>) { fn test_timestamp(factory: super::Factory) {
let timestamp = 0x1234; let timestamp = 0x1234;
let code = "42600055".from_hex().unwrap(); let code = "42600055".from_hex().unwrap();
@ -396,6 +393,7 @@ fn test_timestamp(vm: Box<super::Evm>) {
ext.info.timestamp = timestamp; ext.info.timestamp = timestamp;
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -404,7 +402,7 @@ fn test_timestamp(vm: Box<super::Evm>) {
} }
evm_test!{test_number: test_number_jit, test_number_int} evm_test!{test_number: test_number_jit, test_number_int}
fn test_number(vm: Box<super::Evm>) { fn test_number(factory: super::Factory) {
let number = 0x1234; let number = 0x1234;
let code = "43600055".from_hex().unwrap(); let code = "43600055".from_hex().unwrap();
@ -415,6 +413,7 @@ fn test_number(vm: Box<super::Evm>) {
ext.info.number = number; ext.info.number = number;
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -423,7 +422,7 @@ fn test_number(vm: Box<super::Evm>) {
} }
evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int} evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int}
fn test_difficulty(vm: Box<super::Evm>) { fn test_difficulty(factory: super::Factory) {
let difficulty = U256::from(0x1234); let difficulty = U256::from(0x1234);
let code = "44600055".from_hex().unwrap(); let code = "44600055".from_hex().unwrap();
@ -434,6 +433,7 @@ fn test_difficulty(vm: Box<super::Evm>) {
ext.info.difficulty = difficulty; ext.info.difficulty = difficulty;
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };
@ -442,7 +442,7 @@ fn test_difficulty(vm: Box<super::Evm>) {
} }
evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int} evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int}
fn test_gas_limit(vm: Box<super::Evm>) { fn test_gas_limit(factory: super::Factory) {
let gas_limit = U256::from(0x1234); let gas_limit = U256::from(0x1234);
let code = "45600055".from_hex().unwrap(); let code = "45600055".from_hex().unwrap();
@ -453,6 +453,7 @@ fn test_gas_limit(vm: Box<super::Evm>) {
ext.info.gas_limit = gas_limit; ext.info.gas_limit = gas_limit;
let gas_left = { let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap() vm.exec(&params, &mut ext).unwrap()
}; };

View File

@ -2,7 +2,7 @@
use common::*; use common::*;
use state::*; use state::*;
use engine::*; use engine::*;
use evm::{self, Schedule, Factory, Ext}; use evm::{self, Schedule, Ext};
/// Returns new address created from address and given nonce. /// Returns new address created from address and given nonce.
pub fn contract_address(address: &Address, nonce: &U256) -> Address { pub fn contract_address(address: &Address, nonce: &U256) -> Address {
@ -196,8 +196,7 @@ impl<'a> Executive<'a> {
} else if params.code.len() > 0 { } else if params.code.len() > 0 {
// if destination is a contract, do normal message call // if destination is a contract, do normal message call
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::Return(output)); let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::Return(output));
let evm = Factory::create(); self.engine.vm_factory().create().exec(&params, &mut ext)
evm.exec(&params, &mut ext)
} else { } else {
// otherwise, nothing // otherwise, nothing
Ok(params.gas) Ok(params.gas)
@ -214,8 +213,7 @@ impl<'a> Executive<'a> {
self.state.transfer_balance(&params.sender, &params.address, &params.value); self.state.transfer_balance(&params.sender, &params.address, &params.value);
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract); let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract);
let evm = Factory::create(); self.engine.vm_factory().create().exec(&params, &mut ext)
evm.exec(&params, &mut ext)
} }
/// Finalizes the transaction (does refunds and suicides). /// Finalizes the transaction (does refunds and suicides).
@ -496,15 +494,19 @@ mod tests {
use engine::*; use engine::*;
use spec::*; use spec::*;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
use evm::factory::VMType;
struct TestEngine { struct TestEngine {
factory: Factory,
spec: Spec, spec: Spec,
max_depth: usize max_depth: usize
} }
impl TestEngine { impl TestEngine {
fn new(max_depth: usize) -> TestEngine { fn new(max_depth: usize, factory: Factory) -> TestEngine {
TestEngine { TestEngine {
factory: factory,
spec: ethereum::new_frontier_test(), spec: ethereum::new_frontier_test(),
max_depth: max_depth max_depth: max_depth
} }
@ -514,6 +516,9 @@ mod tests {
impl Engine for TestEngine { impl Engine for TestEngine {
fn name(&self) -> &str { "TestEngine" } fn name(&self) -> &str { "TestEngine" }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn vm_factory(&self) -> &Factory {
&self.factory
}
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
let mut schedule = Schedule::new_frontier(); let mut schedule = Schedule::new_frontier();
schedule.max_depth = self.max_depth; schedule.max_depth = self.max_depth;
@ -528,9 +533,9 @@ mod tests {
assert_eq!(expected_address, contract_address(&address, &U256::from(88))); assert_eq!(expected_address, contract_address(&address, &U256::from(88)));
} }
#[test]
// TODO: replace params with transactions! // TODO: replace params with transactions!
fn test_sender_balance() { evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int}
fn test_sender_balance(factory: Factory) {
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let address = contract_address(&sender, &U256::zero()); let address = contract_address(&sender, &U256::zero());
let mut params = ActionParams::new(); let mut params = ActionParams::new();
@ -542,7 +547,7 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(0x100u64)); state.add_balance(&sender, &U256::from(0x100u64));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
@ -560,8 +565,8 @@ mod tests {
// TODO: just test state root. // TODO: just test state root.
} }
#[test] evm_test!{test_create_contract: test_create_contract_jit, test_create_contract_int}
fn test_create_contract() { fn test_create_contract(factory: Factory) {
// code: // code:
// //
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes? // 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
@ -600,7 +605,7 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100)); state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
@ -613,8 +618,8 @@ mod tests {
assert_eq!(substate.contracts_created.len(), 0); assert_eq!(substate.contracts_created.len(), 0);
} }
#[test] evm_test!{test_create_contract_value_too_high: test_create_contract_value_too_high_jit, test_create_contract_value_too_high_int}
fn test_create_contract_value_too_high() { fn test_create_contract_value_too_high(factory: Factory) {
// code: // code:
// //
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes? // 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
@ -653,7 +658,7 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100)); state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
@ -665,8 +670,8 @@ mod tests {
assert_eq!(substate.contracts_created.len(), 0); assert_eq!(substate.contracts_created.len(), 0);
} }
#[test] evm_test!{test_create_contract_without_max_depth: test_create_contract_without_max_depth_jit, test_create_contract_without_max_depth_int}
fn test_create_contract_without_max_depth() { fn test_create_contract_without_max_depth(factory: Factory) {
// code: // code:
// //
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes? // 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
@ -704,7 +709,7 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100)); state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(1024); let engine = TestEngine::new(1024, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
{ {
@ -716,8 +721,8 @@ mod tests {
assert_eq!(substate.contracts_created[0], next_address); assert_eq!(substate.contracts_created[0], next_address);
} }
#[test] evm_test!{test_aba_calls: test_aba_calls_jit, test_aba_calls_int}
fn test_aba_calls() { fn test_aba_calls(factory: Factory) {
// 60 00 - push 0 // 60 00 - push 0
// 60 00 - push 0 // 60 00 - push 0
// 60 00 - push 0 // 60 00 - push 0
@ -762,7 +767,7 @@ mod tests {
state.add_balance(&sender, &U256::from(100_000)); state.add_balance(&sender, &U256::from(100_000));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
@ -774,8 +779,8 @@ mod tests {
assert_eq!(state.storage_at(&address_a, &H256::from(&U256::from(0x23))), H256::from(&U256::from(1))); assert_eq!(state.storage_at(&address_a, &H256::from(&U256::from(0x23))), H256::from(&U256::from(1)));
} }
#[test] evm_test!{test_recursive_bomb1: test_recursive_bomb1_jit, test_recursive_bomb1_int}
fn test_recursive_bomb1() { fn test_recursive_bomb1(factory: Factory) {
// 60 01 - push 1 // 60 01 - push 1
// 60 00 - push 0 // 60 00 - push 0
// 54 - sload // 54 - sload
@ -804,7 +809,7 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.init_code(&address, code.clone()); state.init_code(&address, code.clone());
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
@ -817,8 +822,8 @@ mod tests {
assert_eq!(state.storage_at(&address, &H256::from(&U256::one())), H256::from(&U256::from(1))); assert_eq!(state.storage_at(&address, &H256::from(&U256::one())), H256::from(&U256::from(1)));
} }
#[test] evm_test!{test_transact_simple: test_transact_simple_jit, test_transact_simple_int}
fn test_transact_simple() { fn test_transact_simple(factory: Factory) {
let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::zero()); let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::zero());
let keypair = KeyPair::create().unwrap(); let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret()); t.sign(&keypair.secret());
@ -829,7 +834,7 @@ mod tests {
state.add_balance(&sender, &U256::from(18)); state.add_balance(&sender, &U256::from(18));
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let executed = { let executed = {
let mut ex = Executive::new(&mut state, &info, &engine); let mut ex = Executive::new(&mut state, &info, &engine);
@ -837,9 +842,9 @@ mod tests {
}; };
assert_eq!(executed.gas, U256::from(100_000)); assert_eq!(executed.gas, U256::from(100_000));
assert_eq!(executed.gas_used, U256::from(20_025)); assert_eq!(executed.gas_used, U256::from(41_301));
assert_eq!(executed.refunded, U256::from(79_975)); assert_eq!(executed.refunded, U256::from(58_699));
assert_eq!(executed.cumulative_gas_used, U256::from(20_025)); assert_eq!(executed.cumulative_gas_used, U256::from(41_301));
assert_eq!(executed.logs.len(), 0); assert_eq!(executed.logs.len(), 0);
assert_eq!(executed.out_of_gas, false); assert_eq!(executed.out_of_gas, false);
assert_eq!(executed.contracts_created.len(), 0); assert_eq!(executed.contracts_created.len(), 0);
@ -849,14 +854,14 @@ mod tests {
assert_eq!(state.storage_at(&contract, &H256::new()), H256::from(&U256::from(1))); assert_eq!(state.storage_at(&contract, &H256::new()), H256::from(&U256::from(1)));
} }
#[test] evm_test!{test_transact_invalid_sender: test_transact_invalid_sender_jit, test_transact_invalid_sender_int}
fn test_transact_invalid_sender() { fn test_transact_invalid_sender(factory: Factory) {
let t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::zero()); let t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::zero());
let mut state = State::new_temp(); let mut state = State::new_temp();
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let mut ex = Executive::new(&mut state, &info, &engine);
@ -869,8 +874,8 @@ mod tests {
} }
} }
#[test] evm_test!{test_transact_invalid_nonce: test_transact_invalid_nonce_jit, test_transact_invalid_nonce_int}
fn test_transact_invalid_nonce() { fn test_transact_invalid_nonce(factory: Factory) {
let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::one()); let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::one());
let keypair = KeyPair::create().unwrap(); let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret()); t.sign(&keypair.secret());
@ -880,7 +885,7 @@ mod tests {
state.add_balance(&sender, &U256::from(17)); state.add_balance(&sender, &U256::from(17));
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let mut ex = Executive::new(&mut state, &info, &engine);
@ -894,8 +899,8 @@ mod tests {
} }
} }
#[test] evm_test!{test_transact_gas_limit_reached: test_transact_gas_limit_reached_jit, test_transact_gas_limit_reached_int}
fn test_transact_gas_limit_reached() { fn test_transact_gas_limit_reached(factory: Factory) {
let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(80_001), U256::zero(), U256::zero()); let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(80_001), U256::zero(), U256::zero());
let keypair = KeyPair::create().unwrap(); let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret()); t.sign(&keypair.secret());
@ -906,7 +911,7 @@ mod tests {
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_used = U256::from(20_000); info.gas_used = U256::from(20_000);
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let mut ex = Executive::new(&mut state, &info, &engine);
@ -920,8 +925,8 @@ mod tests {
} }
} }
#[test] evm_test!{test_not_enough_cash: test_not_enough_cash_jit, test_not_enough_cash_int}
fn test_not_enough_cash() { fn test_not_enough_cash(factory: Factory) {
let mut t = Transaction::new_create(U256::from(18), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::one(), U256::zero()); let mut t = Transaction::new_create(U256::from(18), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::one(), U256::zero());
let keypair = KeyPair::create().unwrap(); let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret()); t.sign(&keypair.secret());
@ -931,7 +936,7 @@ mod tests {
state.add_balance(&sender, &U256::from(100_017)); state.add_balance(&sender, &U256::from(100_017));
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let mut ex = Executive::new(&mut state, &info, &engine);

View File

@ -88,6 +88,8 @@ extern crate env_logger;
pub mod common; pub mod common;
pub mod basic_types; pub mod basic_types;
#[macro_use]
pub mod evm;
pub mod executive; pub mod executive;
pub mod error; pub mod error;
pub mod log_entry; pub mod log_entry;
@ -105,7 +107,6 @@ pub mod spec;
pub mod views; pub mod views;
pub mod blockchain; pub mod blockchain;
pub mod extras; pub mod extras;
pub mod evm;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View File

@ -1,20 +1,29 @@
use engine::Engine; use engine::Engine;
use spec::Spec; use spec::Spec;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
use env_info::EnvInfo; use env_info::EnvInfo;
/// An engine which does not provide any consensus mechanism. /// An engine which does not provide any consensus mechanism.
pub struct NullEngine { pub struct NullEngine {
spec: Spec, spec: Spec,
factory: Factory
} }
impl NullEngine { impl NullEngine {
pub fn new_boxed(spec: Spec) -> Box<Engine> { pub fn new_boxed(spec: Spec) -> Box<Engine> {
Box::new(NullEngine{spec: spec}) Box::new(NullEngine{
spec: spec,
// TODO [todr] should this return any specific factory?
factory: Factory::default()
})
} }
} }
impl Engine for NullEngine { impl Engine for NullEngine {
fn vm_factory(&self) -> &Factory {
&self.factory
}
fn name(&self) -> &str { "NullEngine" } fn name(&self) -> &str { "NullEngine" }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() } fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }

View File

@ -4,17 +4,19 @@ use executive::*;
use spec::*; use spec::*;
use engine::*; use engine::*;
use evm; use evm;
use evm::{Schedule, Ext, Factory}; use evm::{Schedule, Ext, Factory, VMType};
use ethereum; use ethereum;
struct TestEngine { struct TestEngine {
vm_factory: Factory,
spec: Spec, spec: Spec,
max_depth: usize max_depth: usize
} }
impl TestEngine { impl TestEngine {
fn new(max_depth: usize) -> TestEngine { fn new(max_depth: usize, vm_type: VMType) -> TestEngine {
TestEngine { TestEngine {
vm_factory: Factory::new(vm_type),
spec: ethereum::new_frontier_test(), spec: ethereum::new_frontier_test(),
max_depth: max_depth max_depth: max_depth
} }
@ -24,6 +26,7 @@ impl TestEngine {
impl Engine for TestEngine { impl Engine for TestEngine {
fn name(&self) -> &str { "TestEngine" } fn name(&self) -> &str { "TestEngine" }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn vm_factory(&self) -> &Factory { &self.vm_factory }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
let mut schedule = Schedule::new_frontier(); let mut schedule = Schedule::new_frontier();
schedule.max_depth = self.max_depth; schedule.max_depth = self.max_depth;
@ -153,16 +156,28 @@ impl<'a> Ext for TestExt<'a> {
} }
fn do_json_test(json_data: &[u8]) -> Vec<String> { fn do_json_test(json_data: &[u8]) -> Vec<String> {
let vms = VMType::all();
vms
.iter()
.flat_map(|vm| do_json_test_for(vm, json_data))
.collect()
}
fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
let mut failed = Vec::new(); let mut failed = Vec::new();
for (name, test) in json.as_object().unwrap() { for (name, test) in json.as_object().unwrap() {
// sync io is usefull when something crashes in jit // sync io is usefull when something crashes in jit
//::std::io::stdout().write(&name.as_bytes()); // ::std::io::stdout().write(&name.as_bytes());
//::std::io::stdout().write(b"\n"); // ::std::io::stdout().write(b"\n");
//::std::io::stdout().flush(); // ::std::io::stdout().flush();
let mut fail = false; let mut fail = false;
//let mut fail_unless = |cond: bool| if !cond && !fail { failed.push(name.to_string()); fail = true }; //let mut fail_unless = |cond: bool| if !cond && !fail { failed.push(name.to_string()); fail = true };
let mut fail_unless = |cond: bool, s: &str | if !cond && !fail { failed.push(name.to_string() + ": "+ s); fail = true }; let mut fail_unless = |cond: bool, s: &str | if !cond && !fail {
failed.push(format!("[{}] {}: {}", vm, name.to_string(), s));
fail = true
};
// test env // test env
let mut state = State::new_temp(); let mut state = State::new_temp();
@ -194,7 +209,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
info.timestamp = u256_from_json(&env["currentTimestamp"]).low_u64(); info.timestamp = u256_from_json(&env["currentTimestamp"]).low_u64();
}); });
let engine = TestEngine::new(0); let engine = TestEngine::new(0, vm.clone());
// params // params
let mut params = ActionParams::new(); let mut params = ActionParams::new();
@ -219,7 +234,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
let (res, callcreates) = { let (res, callcreates) = {
let ex = Externalities::new(&mut state, &info, &engine, 0, &params, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output))); let ex = Externalities::new(&mut state, &info, &engine, 0, &params, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
let mut test_ext = TestExt::new(ex); let mut test_ext = TestExt::new(ex);
let evm = Factory::create(); let evm = engine.vm_factory().create();
let res = evm.exec(&params, &mut test_ext); let res = evm.exec(&params, &mut test_ext);
(res, test_ext.callcreates) (res, test_ext.callcreates)
}; };

View File

@ -1,6 +1,5 @@
use super::test_common::*; use super::test_common::*;
use state::*; use state::*;
use executive::*;
use ethereum; use ethereum;
fn do_json_test(json_data: &[u8]) -> Vec<String> { fn do_json_test(json_data: &[u8]) -> Vec<String> {