From 8335d401024e4efea74dcf458f4e5dea5e141dfd Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 7 Jan 2016 23:33:54 +0100 Subject: [PATCH] contract_address && ExtFace --- src/evm/evm.rs | 4 +- src/evm/executive.rs | 36 +++++++++++++- src/evm/ext.rs | 116 +++++++++++++++++++++++++------------------ src/evm/jit.rs | 6 +-- src/evm/mod.rs | 4 +- 5 files changed, 109 insertions(+), 57 deletions(-) diff --git a/src/evm/evm.rs b/src/evm/evm.rs index 9a9b8bc41..abd2d321d 100644 --- a/src/evm/evm.rs +++ b/src/evm/evm.rs @@ -1,6 +1,6 @@ //! Evm interface. -use evm::{RuntimeData, Ext}; +use evm::{RuntimeData, ExtFace}; #[derive(Debug, Eq, PartialEq)] pub enum ReturnCode { @@ -12,5 +12,5 @@ pub enum ReturnCode { } pub trait Evm { - fn exec(&self, data: RuntimeData, ext: &mut Ext) -> ReturnCode; + fn exec(&self, data: RuntimeData, ext: &mut ExtFace) -> ReturnCode; } diff --git a/src/evm/executive.rs b/src/evm/executive.rs index 1ab7a580d..616eacd56 100644 --- a/src/evm/executive.rs +++ b/src/evm/executive.rs @@ -1,9 +1,19 @@ use util::hash::*; use util::uint::*; +use util::rlp::*; +use util::sha3::*; use state::*; use env_info::*; use engine::*; use transaction::*; +use evm::VmFactory; + +fn contract_address(address: &Address, nonce: &U256) -> Address { + let mut stream = RlpStream::new_list(2); + stream.append(address); + stream.append(nonce); + From::from(stream.out().sha3()) +} pub enum ExecutiveResult { Ok @@ -33,7 +43,12 @@ impl<'a> Executive<'a> { match transaction.kind() { TransactionKind::MessageCall => self.call(transaction), - TransactionKind::ContractCreation => { unimplemented!(); }// self.create(&self.sender(), ) + TransactionKind::ContractCreation => self.create(&transaction.sender(), + &transaction.value, + &transaction.gas_price, + &transaction.gas, + &transaction.data, + &transaction.sender()) } } @@ -41,7 +56,24 @@ impl<'a> Executive<'a> { ExecutiveResult::Ok } - fn create(&mut self, address: &Address, endowment: &U256, gas_price: &U256, gas: &U256, init: &[u8], origin: &Address) -> ExecutiveResult { + fn create(&mut self, sender: &Address, endowment: &U256, gas_price: &U256, gas: &U256, init: &[u8], origin: &Address) -> ExecutiveResult { + let _new_address = contract_address(&sender, &(self.state.nonce(sender) - U256::one())); + let _evm = VmFactory::create(); + ExecutiveResult::Ok } } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use util::hash::*; + use util::uint::*; + + #[test] + fn test_contract_address() { + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + let contract_address = Address::from_str("3f09c73a5ed19289fb9bdc72f1742566df146f56").unwrap(); + assert_eq!(contract_address, super::contract_address(&address, &U256::from(88))); + } +} diff --git a/src/evm/ext.rs b/src/evm/ext.rs index 27fdc1028..a5e7f3c2f 100644 --- a/src/evm/ext.rs +++ b/src/evm/ext.rs @@ -27,6 +27,34 @@ impl SubState { } } +pub trait ExtFace { + /// Returns a value for given key. + fn sload(&self, key: &H256) -> H256; + + /// Stores a value for given key. + fn sstore(&mut self, key: H256, value: H256); + + /// Returns address balance. + fn balance(&self, address: &Address) -> U256; + + /// Returns the hash of one of the 256 most recent complete blocks. + fn blockhash(&self, number: &U256) -> H256; + + /// Creates new contract. + /// Returns new contract address and gas used. + fn create(&self, _gas: u64, _endowment: &U256, _code: &[u8]) -> (Address, u64); + + /// Calls existing contract. + /// Returns call output and gas used. + fn call(&self, _gas: u64, _call_gas: u64, _receive_address: &Address, _value: &U256, _data: &[u8], _code_address: &Address) -> Option<(Vec, u64)>; + + /// Returns code at given address + fn extcode(&self, address: &Address) -> Vec; + + /// Creates log entry with given topics and data + fn log(&mut self, topics: Vec, data: Bytes); +} + /// Externality interface for the Virtual Machine providing access to /// world state. /// @@ -62,55 +90,6 @@ impl Ext { } } - /// Returns a value for given key. - pub fn sload(&self, key: &H256) -> H256 { - self.state.storage_at(&self.address, key) - } - - /// Stores a value for given key. - pub fn sstore(&mut self, key: H256, value: H256) { - self.state.set_storage(&self.address, key, value) - } - - /// Returns address balance. - pub fn balance(&self, address: &Address) -> U256 { - self.state.balance(address) - } - - /// Returns the hash of one of the 256 most recent complete blocks. - pub fn blockhash(&self, number: &U256) -> H256 { - match *number < self.info.number { - false => H256::from(&U256::zero()), - true => { - let index = self.info.number - *number - U256::one(); - self.info.last_hashes[index.low_u32() as usize].clone() - } - } - } - - /// Creates new contract. - /// Returns new contract address and gas used. - pub fn create(&self, _gas: u64, _endowment: &U256, _code: &[u8]) -> (Address, u64) { - unimplemented!(); - } - - /// Calls existing contract. - /// Returns call output and gas used. - pub fn call(&self, _gas: u64, _call_gas: u64, _receive_address: &Address, _value: &U256, _data: &[u8], _code_address: &Address) -> Option<(Vec, u64)>{ - unimplemented!(); - } - - /// Returns code at given address - pub fn extcode(&self, address: &Address) -> Vec { - self.state.code(address).unwrap_or(vec![]) - } - - /// Creates log entry with given topics and data - pub fn log(&mut self, topics: Vec, data: Bytes) { - let address = self.address.clone(); - self.substate.logs.push(LogEntry::new(address, topics, data)); - } - /// Returns state // not sure if this is the best solution, but seems to be the easiest one, mk pub fn state(&self) -> &State { @@ -123,4 +102,43 @@ impl Ext { } } +impl ExtFace for Ext { + fn sload(&self, key: &H256) -> H256 { + self.state.storage_at(&self.address, key) + } + fn sstore(&mut self, key: H256, value: H256) { + self.state.set_storage(&self.address, key, value) + } + + fn balance(&self, address: &Address) -> U256 { + self.state.balance(address) + } + + fn blockhash(&self, number: &U256) -> H256 { + match *number < self.info.number { + false => H256::from(&U256::zero()), + true => { + let index = self.info.number - *number - U256::one(); + self.info.last_hashes[index.low_u32() as usize].clone() + } + } + } + + fn create(&self, _gas: u64, _endowment: &U256, _code: &[u8]) -> (Address, u64) { + unimplemented!(); + } + + fn call(&self, _gas: u64, _call_gas: u64, _receive_address: &Address, _value: &U256, _data: &[u8], _code_address: &Address) -> Option<(Vec, u64)>{ + unimplemented!(); + } + + fn extcode(&self, address: &Address) -> Vec { + self.state.code(address).unwrap_or(vec![]) + } + + fn log(&mut self, topics: Vec, data: Bytes) { + let address = self.address.clone(); + self.substate.logs.push(LogEntry::new(address, topics, data)); + } +} diff --git a/src/evm/jit.rs b/src/evm/jit.rs index 80e756bf1..8b9e344c0 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -120,11 +120,11 @@ impl IntoJit for evm::RuntimeData { } struct ExtAdapter<'a> { - ext: &'a mut evm::Ext + ext: &'a mut evm::ExtFace } impl<'a> ExtAdapter<'a> { - fn new(ext: &'a mut evm::Ext) -> Self { + fn new(ext: &'a mut evm::ExtFace) -> Self { ExtAdapter { ext: ext } @@ -262,7 +262,7 @@ impl From for evm::ReturnCode { pub struct JitEvm; impl evm::Evm for JitEvm { - fn exec(&self, data: evm::RuntimeData, ext: &mut evm::Ext) -> evm::ReturnCode { + fn exec(&self, data: evm::RuntimeData, ext: &mut evm::ExtFace) -> evm::ReturnCode { // Dirty hack. This is unsafe, but we interact with ffi, so it's justified. let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext)) }; let mut ext_handle = evmjit::ExtHandle::new(ext_adapter); diff --git a/src/evm/mod.rs b/src/evm/mod.rs index c3b6216e5..43f733483 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -10,6 +10,8 @@ pub mod executive; mod jit; pub use self::evm::{Evm, ReturnCode}; -pub use self::ext::Ext; +pub use self::ext::{ExtFace, Ext}; pub use self::runtime_data::RuntimeData; pub use self::logentry::LogEntry; +pub use self::vmfactory::VmFactory; +pub use self::executive::Executive;