2016-01-07 21:29:36 +01:00
|
|
|
use util::hash::*;
|
|
|
|
use util::uint::*;
|
2016-01-07 23:33:54 +01:00
|
|
|
use util::rlp::*;
|
|
|
|
use util::sha3::*;
|
2016-01-07 19:05:44 +01:00
|
|
|
use state::*;
|
|
|
|
use env_info::*;
|
|
|
|
use engine::*;
|
|
|
|
use transaction::*;
|
2016-01-08 00:16:15 +01:00
|
|
|
use evm::{VmFactory, ExtFace, Ext, RuntimeData};
|
2016-01-07 23:33:54 +01:00
|
|
|
|
2016-01-08 00:16:15 +01:00
|
|
|
pub fn contract_address(address: &Address, nonce: &U256) -> Address {
|
2016-01-07 23:33:54 +01:00
|
|
|
let mut stream = RlpStream::new_list(2);
|
|
|
|
stream.append(address);
|
|
|
|
stream.append(nonce);
|
|
|
|
From::from(stream.out().sha3())
|
|
|
|
}
|
2016-01-07 19:05:44 +01:00
|
|
|
|
|
|
|
pub enum ExecutiveResult {
|
|
|
|
Ok
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Executive<'a> {
|
|
|
|
state: &'a mut State,
|
|
|
|
info: &'a EnvInfo,
|
|
|
|
engine: &'a Engine,
|
2016-01-08 00:16:15 +01:00
|
|
|
depth: usize
|
2016-01-07 19:05:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Executive<'a> {
|
2016-01-08 00:16:15 +01:00
|
|
|
pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self {
|
2016-01-07 19:05:44 +01:00
|
|
|
Executive {
|
|
|
|
state: state,
|
|
|
|
info: info,
|
|
|
|
engine: engine,
|
2016-01-08 00:16:15 +01:00
|
|
|
depth: depth
|
2016-01-07 19:05:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn exec(&mut self, transaction: &Transaction) -> ExecutiveResult {
|
|
|
|
// TODO: validate that we have enough funds
|
|
|
|
|
2016-01-07 21:29:36 +01:00
|
|
|
self.state.inc_nonce(&transaction.sender());
|
|
|
|
|
2016-01-07 19:05:44 +01:00
|
|
|
match transaction.kind() {
|
|
|
|
TransactionKind::MessageCall => self.call(transaction),
|
2016-01-07 23:33:54 +01:00
|
|
|
TransactionKind::ContractCreation => self.create(&transaction.sender(),
|
|
|
|
&transaction.value,
|
|
|
|
&transaction.gas_price,
|
|
|
|
&transaction.gas,
|
|
|
|
&transaction.data,
|
|
|
|
&transaction.sender())
|
2016-01-07 19:05:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn call(&mut self, transaction: &Transaction) -> ExecutiveResult {
|
|
|
|
ExecutiveResult::Ok
|
|
|
|
}
|
|
|
|
|
2016-01-07 23:33:54 +01:00
|
|
|
fn create(&mut self, sender: &Address, endowment: &U256, gas_price: &U256, gas: &U256, init: &[u8], origin: &Address) -> ExecutiveResult {
|
2016-01-08 00:16:15 +01:00
|
|
|
let new_address = contract_address(&sender, &(self.state.nonce(sender) - U256::one()));
|
2016-01-08 12:50:06 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
let mut ext = Ext::new(self.state, self.info, self.engine, self.depth, new_address.clone());
|
|
|
|
let mut data = RuntimeData::new();
|
|
|
|
|
|
|
|
// TODO: init runtime data
|
|
|
|
data.gas = *gas;
|
|
|
|
data.gas_price = *gas_price;
|
|
|
|
|
|
|
|
let evm = VmFactory::create();
|
|
|
|
evm.exec(data, &mut ext);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.state.transfer_balance(sender, &new_address, endowment);
|
2016-01-07 19:05:44 +01:00
|
|
|
ExecutiveResult::Ok
|
|
|
|
}
|
|
|
|
}
|
2016-01-07 23:33:54 +01:00
|
|
|
|
|
|
|
#[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)));
|
|
|
|
}
|
|
|
|
}
|