Merge pull request #111 from gavofyork/evm_factory_parametrized
Parametrizing evm::Factory
This commit is contained in:
commit
8366c9d44f
@ -2,6 +2,7 @@ use common::*;
|
||||
use block::Block;
|
||||
use spec::Spec;
|
||||
use evm::Schedule;
|
||||
use evm::Factory;
|
||||
|
||||
/// 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.
|
||||
@ -22,6 +23,9 @@ pub trait Engine : Sync + Send {
|
||||
/// Get the general parameters of the chain.
|
||||
fn spec(&self) -> &Spec;
|
||||
|
||||
/// Get current EVM factory
|
||||
fn vm_factory(&self) -> &Factory;
|
||||
|
||||
/// Get the EVM schedule for the given `env_info`.
|
||||
fn schedule(&self, env_info: &EnvInfo) -> Schedule;
|
||||
|
||||
|
@ -3,16 +3,22 @@ use block::*;
|
||||
use spec::*;
|
||||
use engine::*;
|
||||
use evm::Schedule;
|
||||
use evm::Factory;
|
||||
|
||||
/// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum
|
||||
/// mainnet chains in the Olympic, Frontier and Homestead eras.
|
||||
pub struct Ethash {
|
||||
spec: Spec,
|
||||
factory: Factory
|
||||
}
|
||||
|
||||
impl Ethash {
|
||||
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`.
|
||||
fn extra_info(&self, _header: &Header) -> HashMap<String, String> { HashMap::new() }
|
||||
fn spec(&self) -> &Spec { &self.spec }
|
||||
|
||||
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.
|
||||
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
||||
|
@ -1,25 +1,99 @@
|
||||
//! Evm factory.
|
||||
|
||||
use std::fmt;
|
||||
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.
|
||||
pub struct Factory;
|
||||
pub struct Factory {
|
||||
evm : VMType
|
||||
}
|
||||
|
||||
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")]
|
||||
pub fn create() -> Box<Evm> {
|
||||
fn jit() -> Box<Evm> {
|
||||
Box::new(super::jit::JitEvm)
|
||||
}
|
||||
|
||||
/// Returns native rust evm
|
||||
#[cfg(not(feature = "jit"))]
|
||||
pub fn create() -> Box<Evm> {
|
||||
Box::new(super::interpreter::Interpreter)
|
||||
fn jit() -> Box<Evm> {
|
||||
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]
|
||||
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));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -3,6 +3,7 @@
|
||||
pub mod ext;
|
||||
pub mod evm;
|
||||
pub mod interpreter;
|
||||
#[macro_use]
|
||||
pub mod factory;
|
||||
pub mod schedule;
|
||||
mod instructions;
|
||||
@ -16,3 +17,4 @@ pub use self::evm::{Evm, Error, Result};
|
||||
pub use self::ext::Ext;
|
||||
pub use self::factory::Factory;
|
||||
pub use self::schedule::Schedule;
|
||||
pub use self::factory::VMType;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use common::*;
|
||||
use evm;
|
||||
use evm::{Ext, Schedule};
|
||||
use evm::{Ext, Schedule, Factory, VMType};
|
||||
|
||||
struct FakeLogEntry {
|
||||
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}
|
||||
fn test_add(vm : Box<super::Evm>) {
|
||||
fn test_add(factory: super::Factory) {
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
|
||||
|
||||
@ -148,6 +134,7 @@ fn test_add(vm : Box<super::Evm>) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -156,7 +143,7 @@ fn test_add(vm : Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "6000600020600055".from_hex().unwrap();
|
||||
|
||||
@ -167,6 +154,7 @@ fn test_sha3(vm: Box<super::Evm>) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -175,7 +163,7 @@ fn test_sha3(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "30600055".from_hex().unwrap();
|
||||
|
||||
@ -186,6 +174,7 @@ fn test_address(vm: Box<super::Evm>) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -194,7 +183,7 @@ fn test_address(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
|
||||
let code = "32600055".from_hex().unwrap();
|
||||
@ -207,6 +196,7 @@ fn test_origin(vm: Box<super::Evm>) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -215,7 +205,7 @@ fn test_origin(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
|
||||
let code = "33600055".from_hex().unwrap();
|
||||
@ -228,6 +218,7 @@ fn test_sender(vm: Box<super::Evm>) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -236,7 +227,7 @@ fn test_sender(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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
|
||||
// 3b - extcodesize
|
||||
// 60 00 - push 0
|
||||
@ -262,6 +253,7 @@ fn test_extcodecopy(vm: Box<super::Evm>) {
|
||||
ext.codes.insert(sender, sender_code);
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &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}
|
||||
fn test_log_empty(vm: Box<super::Evm>) {
|
||||
fn test_log_empty(factory: super::Factory) {
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").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 gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &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}
|
||||
fn test_log_sender(vm: Box<super::Evm>) {
|
||||
fn test_log_sender(factory: super::Factory) {
|
||||
// 60 ff - push ff
|
||||
// 60 00 - push 00
|
||||
// 53 - mstore
|
||||
@ -312,6 +305,7 @@ fn test_log_sender(vm: Box<super::Evm>) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &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}
|
||||
fn test_blockhash(vm: Box<super::Evm>) {
|
||||
fn test_blockhash(factory: super::Factory) {
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
let code = "600040600055".from_hex().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());
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -344,7 +339,7 @@ fn test_blockhash(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "600135600055".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 gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -366,7 +362,7 @@ fn test_calldataload(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "41600055".from_hex().unwrap();
|
||||
|
||||
@ -377,6 +373,7 @@ fn test_author(vm: Box<super::Evm>) {
|
||||
ext.info.author = author;
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -385,7 +382,7 @@ fn test_author(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "42600055".from_hex().unwrap();
|
||||
|
||||
@ -396,6 +393,7 @@ fn test_timestamp(vm: Box<super::Evm>) {
|
||||
ext.info.timestamp = timestamp;
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -404,7 +402,7 @@ fn test_timestamp(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "43600055".from_hex().unwrap();
|
||||
|
||||
@ -415,6 +413,7 @@ fn test_number(vm: Box<super::Evm>) {
|
||||
ext.info.number = number;
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
@ -423,7 +422,7 @@ fn test_number(vm: Box<super::Evm>) {
|
||||
}
|
||||
|
||||
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 code = "44600055".from_hex().unwrap();
|
||||
|
||||
@ -434,6 +433,7 @@ fn test_difficulty(vm: Box<super::Evm>) {
|
||||
ext.info.difficulty = difficulty;
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &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}
|
||||
fn test_gas_limit(vm: Box<super::Evm>) {
|
||||
fn test_gas_limit(factory: super::Factory) {
|
||||
let gas_limit = U256::from(0x1234);
|
||||
let code = "45600055".from_hex().unwrap();
|
||||
|
||||
@ -453,6 +453,7 @@ fn test_gas_limit(vm: Box<super::Evm>) {
|
||||
ext.info.gas_limit = gas_limit;
|
||||
|
||||
let gas_left = {
|
||||
let vm = factory.create();
|
||||
vm.exec(¶ms, &mut ext).unwrap()
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
use common::*;
|
||||
use state::*;
|
||||
use engine::*;
|
||||
use evm::{self, Schedule, Factory, Ext};
|
||||
use evm::{self, Schedule, Ext};
|
||||
|
||||
/// Returns new address created from address and given nonce.
|
||||
pub fn contract_address(address: &Address, nonce: &U256) -> Address {
|
||||
@ -196,8 +196,7 @@ impl<'a> Executive<'a> {
|
||||
} else if params.code.len() > 0 {
|
||||
// if destination is a contract, do normal message call
|
||||
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::Return(output));
|
||||
let evm = Factory::create();
|
||||
evm.exec(¶ms, &mut ext)
|
||||
self.engine.vm_factory().create().exec(¶ms, &mut ext)
|
||||
} else {
|
||||
// otherwise, nothing
|
||||
Ok(params.gas)
|
||||
@ -214,8 +213,7 @@ impl<'a> Executive<'a> {
|
||||
self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value);
|
||||
|
||||
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract);
|
||||
let evm = Factory::create();
|
||||
evm.exec(¶ms, &mut ext)
|
||||
self.engine.vm_factory().create().exec(¶ms, &mut ext)
|
||||
}
|
||||
|
||||
/// Finalizes the transaction (does refunds and suicides).
|
||||
@ -496,15 +494,19 @@ mod tests {
|
||||
use engine::*;
|
||||
use spec::*;
|
||||
use evm::Schedule;
|
||||
use evm::Factory;
|
||||
use evm::factory::VMType;
|
||||
|
||||
struct TestEngine {
|
||||
factory: Factory,
|
||||
spec: Spec,
|
||||
max_depth: usize
|
||||
}
|
||||
|
||||
impl TestEngine {
|
||||
fn new(max_depth: usize) -> TestEngine {
|
||||
fn new(max_depth: usize, factory: Factory) -> TestEngine {
|
||||
TestEngine {
|
||||
factory: factory,
|
||||
spec: ethereum::new_frontier_test(),
|
||||
max_depth: max_depth
|
||||
}
|
||||
@ -514,6 +516,9 @@ mod tests {
|
||||
impl Engine for TestEngine {
|
||||
fn name(&self) -> &str { "TestEngine" }
|
||||
fn spec(&self) -> &Spec { &self.spec }
|
||||
fn vm_factory(&self) -> &Factory {
|
||||
&self.factory
|
||||
}
|
||||
fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
|
||||
let mut schedule = Schedule::new_frontier();
|
||||
schedule.max_depth = self.max_depth;
|
||||
@ -528,9 +533,9 @@ mod tests {
|
||||
assert_eq!(expected_address, contract_address(&address, &U256::from(88)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
// 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 address = contract_address(&sender, &U256::zero());
|
||||
let mut params = ActionParams::new();
|
||||
@ -542,7 +547,7 @@ mod tests {
|
||||
let mut state = State::new_temp();
|
||||
state.add_balance(&sender, &U256::from(0x100u64));
|
||||
let info = EnvInfo::new();
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
let gas_left = {
|
||||
@ -560,8 +565,8 @@ mod tests {
|
||||
// TODO: just test state root.
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_contract() {
|
||||
evm_test!{test_create_contract: test_create_contract_jit, test_create_contract_int}
|
||||
fn test_create_contract(factory: Factory) {
|
||||
// code:
|
||||
//
|
||||
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||
@ -600,7 +605,7 @@ mod tests {
|
||||
let mut state = State::new_temp();
|
||||
state.add_balance(&sender, &U256::from(100));
|
||||
let info = EnvInfo::new();
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
let gas_left = {
|
||||
@ -613,8 +618,8 @@ mod tests {
|
||||
assert_eq!(substate.contracts_created.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_contract_value_too_high() {
|
||||
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(factory: Factory) {
|
||||
// code:
|
||||
//
|
||||
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||
@ -653,7 +658,7 @@ mod tests {
|
||||
let mut state = State::new_temp();
|
||||
state.add_balance(&sender, &U256::from(100));
|
||||
let info = EnvInfo::new();
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
let gas_left = {
|
||||
@ -665,8 +670,8 @@ mod tests {
|
||||
assert_eq!(substate.contracts_created.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_contract_without_max_depth() {
|
||||
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(factory: Factory) {
|
||||
// code:
|
||||
//
|
||||
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||
@ -704,7 +709,7 @@ mod tests {
|
||||
let mut state = State::new_temp();
|
||||
state.add_balance(&sender, &U256::from(100));
|
||||
let info = EnvInfo::new();
|
||||
let engine = TestEngine::new(1024);
|
||||
let engine = TestEngine::new(1024, factory);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
{
|
||||
@ -716,8 +721,8 @@ mod tests {
|
||||
assert_eq!(substate.contracts_created[0], next_address);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aba_calls() {
|
||||
evm_test!{test_aba_calls: test_aba_calls_jit, test_aba_calls_int}
|
||||
fn test_aba_calls(factory: Factory) {
|
||||
// 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));
|
||||
|
||||
let info = EnvInfo::new();
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recursive_bomb1() {
|
||||
evm_test!{test_recursive_bomb1: test_recursive_bomb1_jit, test_recursive_bomb1_int}
|
||||
fn test_recursive_bomb1(factory: Factory) {
|
||||
// 60 01 - push 1
|
||||
// 60 00 - push 0
|
||||
// 54 - sload
|
||||
@ -804,7 +809,7 @@ mod tests {
|
||||
let mut state = State::new_temp();
|
||||
state.init_code(&address, code.clone());
|
||||
let info = EnvInfo::new();
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
let gas_left = {
|
||||
@ -817,8 +822,8 @@ mod tests {
|
||||
assert_eq!(state.storage_at(&address, &H256::from(&U256::one())), H256::from(&U256::from(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transact_simple() {
|
||||
evm_test!{test_transact_simple: test_transact_simple_jit, test_transact_simple_int}
|
||||
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 keypair = KeyPair::create().unwrap();
|
||||
t.sign(&keypair.secret());
|
||||
@ -829,7 +834,7 @@ mod tests {
|
||||
state.add_balance(&sender, &U256::from(18));
|
||||
let mut info = EnvInfo::new();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
|
||||
let executed = {
|
||||
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_used, U256::from(20_025));
|
||||
assert_eq!(executed.refunded, U256::from(79_975));
|
||||
assert_eq!(executed.cumulative_gas_used, U256::from(20_025));
|
||||
assert_eq!(executed.gas_used, U256::from(41_301));
|
||||
assert_eq!(executed.refunded, U256::from(58_699));
|
||||
assert_eq!(executed.cumulative_gas_used, U256::from(41_301));
|
||||
assert_eq!(executed.logs.len(), 0);
|
||||
assert_eq!(executed.out_of_gas, false);
|
||||
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)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transact_invalid_sender() {
|
||||
evm_test!{test_transact_invalid_sender: test_transact_invalid_sender_jit, test_transact_invalid_sender_int}
|
||||
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 mut state = State::new_temp();
|
||||
let mut info = EnvInfo::new();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||
@ -869,8 +874,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transact_invalid_nonce() {
|
||||
evm_test!{test_transact_invalid_nonce: test_transact_invalid_nonce_jit, test_transact_invalid_nonce_int}
|
||||
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 keypair = KeyPair::create().unwrap();
|
||||
t.sign(&keypair.secret());
|
||||
@ -880,7 +885,7 @@ mod tests {
|
||||
state.add_balance(&sender, &U256::from(17));
|
||||
let mut info = EnvInfo::new();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||
@ -894,8 +899,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transact_gas_limit_reached() {
|
||||
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(factory: Factory) {
|
||||
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();
|
||||
t.sign(&keypair.secret());
|
||||
@ -906,7 +911,7 @@ mod tests {
|
||||
let mut info = EnvInfo::new();
|
||||
info.gas_used = U256::from(20_000);
|
||||
info.gas_limit = U256::from(100_000);
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||
@ -920,8 +925,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_enough_cash() {
|
||||
evm_test!{test_not_enough_cash: test_not_enough_cash_jit, test_not_enough_cash_int}
|
||||
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 keypair = KeyPair::create().unwrap();
|
||||
t.sign(&keypair.secret());
|
||||
@ -931,7 +936,7 @@ mod tests {
|
||||
state.add_balance(&sender, &U256::from(100_017));
|
||||
let mut info = EnvInfo::new();
|
||||
info.gas_limit = U256::from(100_000);
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, factory);
|
||||
|
||||
let res = {
|
||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||
|
@ -88,6 +88,8 @@ extern crate env_logger;
|
||||
|
||||
pub mod common;
|
||||
pub mod basic_types;
|
||||
#[macro_use]
|
||||
pub mod evm;
|
||||
pub mod executive;
|
||||
pub mod error;
|
||||
pub mod log_entry;
|
||||
@ -105,7 +107,6 @@ pub mod spec;
|
||||
pub mod views;
|
||||
pub mod blockchain;
|
||||
pub mod extras;
|
||||
pub mod evm;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -1,20 +1,29 @@
|
||||
use engine::Engine;
|
||||
use spec::Spec;
|
||||
use evm::Schedule;
|
||||
use evm::Factory;
|
||||
use env_info::EnvInfo;
|
||||
|
||||
/// An engine which does not provide any consensus mechanism.
|
||||
pub struct NullEngine {
|
||||
spec: Spec,
|
||||
factory: Factory
|
||||
}
|
||||
|
||||
impl NullEngine {
|
||||
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 {
|
||||
fn vm_factory(&self) -> &Factory {
|
||||
&self.factory
|
||||
}
|
||||
fn name(&self) -> &str { "NullEngine" }
|
||||
fn spec(&self) -> &Spec { &self.spec }
|
||||
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }
|
||||
|
@ -4,17 +4,19 @@ use executive::*;
|
||||
use spec::*;
|
||||
use engine::*;
|
||||
use evm;
|
||||
use evm::{Schedule, Ext, Factory};
|
||||
use evm::{Schedule, Ext, Factory, VMType};
|
||||
use ethereum;
|
||||
|
||||
struct TestEngine {
|
||||
vm_factory: Factory,
|
||||
spec: Spec,
|
||||
max_depth: usize
|
||||
}
|
||||
|
||||
impl TestEngine {
|
||||
fn new(max_depth: usize) -> TestEngine {
|
||||
fn new(max_depth: usize, vm_type: VMType) -> TestEngine {
|
||||
TestEngine {
|
||||
vm_factory: Factory::new(vm_type),
|
||||
spec: ethereum::new_frontier_test(),
|
||||
max_depth: max_depth
|
||||
}
|
||||
@ -24,6 +26,7 @@ impl TestEngine {
|
||||
impl Engine for TestEngine {
|
||||
fn name(&self) -> &str { "TestEngine" }
|
||||
fn spec(&self) -> &Spec { &self.spec }
|
||||
fn vm_factory(&self) -> &Factory { &self.vm_factory }
|
||||
fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
|
||||
let mut schedule = Schedule::new_frontier();
|
||||
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> {
|
||||
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 mut failed = Vec::new();
|
||||
for (name, test) in json.as_object().unwrap() {
|
||||
// sync io is usefull when something crashes in jit
|
||||
//::std::io::stdout().write(&name.as_bytes());
|
||||
//::std::io::stdout().write(b"\n");
|
||||
//::std::io::stdout().flush();
|
||||
// ::std::io::stdout().write(&name.as_bytes());
|
||||
// ::std::io::stdout().write(b"\n");
|
||||
// ::std::io::stdout().flush();
|
||||
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, 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
|
||||
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();
|
||||
});
|
||||
|
||||
let engine = TestEngine::new(0);
|
||||
let engine = TestEngine::new(0, vm.clone());
|
||||
|
||||
// params
|
||||
let mut params = ActionParams::new();
|
||||
@ -219,7 +234,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
let (res, callcreates) = {
|
||||
let ex = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
|
||||
let mut test_ext = TestExt::new(ex);
|
||||
let evm = Factory::create();
|
||||
let evm = engine.vm_factory().create();
|
||||
let res = evm.exec(¶ms, &mut test_ext);
|
||||
(res, test_ext.callcreates)
|
||||
};
|
||||
|
@ -1,6 +1,5 @@
|
||||
use super::test_common::*;
|
||||
use state::*;
|
||||
use executive::*;
|
||||
use ethereum;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
|
Loading…
Reference in New Issue
Block a user