callcode builtins are working

This commit is contained in:
debris 2016-01-15 15:00:28 +01:00
parent ec7e80ff13
commit ed0e243506
4 changed files with 53 additions and 41 deletions

View File

@ -9,6 +9,9 @@ use util::bytes::*;
#[derive(Clone, Debug)]
pub struct ActionParams {
/// Address of currently executed code.
pub code_address: Address,
/// Receive address. Usually equal to code_address,
/// except when called using CALLCODE.
pub address: Address,
/// Sender of current part of the transaction.
pub sender: Address,
@ -21,22 +24,23 @@ pub struct ActionParams {
/// Transaction value.
pub value: U256,
/// Code being executed.
pub code: Bytes,
pub code: Option<Bytes>,
/// Input data.
pub data: Bytes
pub data: Option<Bytes>
}
impl ActionParams {
pub fn new() -> ActionParams {
ActionParams {
code_address: Address::new(),
address: Address::new(),
sender: Address::new(),
origin: Address::new(),
gas: U256::zero(),
gas_price: U256::zero(),
value: U256::zero(),
code: vec![],
data: vec![],
code: None,
data: None
}
}
}

View File

@ -310,12 +310,12 @@ impl evm::Evm for JitEvm {
let mut data = RuntimeData::new();
data.gas = params.gas;
data.gas_price = params.gas_price;
data.call_data = params.data.clone();
data.call_data = params.data.clone().unwrap_or(vec![]);
data.address = params.address.clone();
data.caller = params.sender.clone();
data.origin = params.origin.clone();
data.call_value = params.value;
data.code = params.code.clone();
data.code = params.code.clone().unwrap_or(vec![]);
data.author = ext.env_info().author.clone();
data.difficulty = ext.env_info().difficulty;

View File

@ -93,7 +93,7 @@ fn test_add() {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -113,7 +113,7 @@ fn test_sha3() {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -133,7 +133,7 @@ fn test_address() {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -155,7 +155,7 @@ fn test_origin() {
params.address = address.clone();
params.origin = origin.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -177,7 +177,7 @@ fn test_sender() {
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -211,7 +211,7 @@ fn test_extcodecopy() {
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.codes.insert(sender, sender_code);
@ -232,7 +232,7 @@ fn test_log_empty() {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -264,7 +264,7 @@ fn test_log_sender() {
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
let gas_left = {
@ -288,7 +288,7 @@ fn test_blockhash() {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.blockhashes.insert(U256::zero(), blockhash.clone());
@ -310,8 +310,8 @@ fn test_calldataload() {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code;
params.data = data;
params.code = Some(code);
params.data = Some(data);
let mut ext = FakeExt::new();
let gas_left = {
@ -331,7 +331,7 @@ fn test_author() {
let mut params = ActionParams::new();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.info.author = author;
@ -351,7 +351,7 @@ fn test_timestamp() {
let mut params = ActionParams::new();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.info.timestamp = timestamp;
@ -371,7 +371,7 @@ fn test_number() {
let mut params = ActionParams::new();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.info.number = number;
@ -391,7 +391,7 @@ fn test_difficulty() {
let mut params = ActionParams::new();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.info.difficulty = difficulty;
@ -411,7 +411,7 @@ fn test_gas_limit() {
let mut params = ActionParams::new();
params.gas = U256::from(100_000);
params.code = code;
params.code = Some(code);
let mut ext = FakeExt::new();
ext.info.gas_limit = gas_limit;

View File

@ -150,28 +150,31 @@ impl<'a> Executive<'a> {
let res = match t.action() {
&Action::Create => {
let new_address = contract_address(&sender, &nonce);
let params = ActionParams {
address: contract_address(&sender, &nonce),
code_address: new_address.clone(),
address: new_address,
sender: sender.clone(),
origin: sender.clone(),
gas: init_gas,
gas_price: t.gas_price,
value: t.value,
code: t.data.clone(),
data: vec![],
code: Some(t.data.clone()),
data: None,
};
self.create(&params, &mut substate)
},
&Action::Call(ref address) => {
let params = ActionParams {
code_address: address.clone(),
address: address.clone(),
sender: sender.clone(),
origin: sender.clone(),
gas: init_gas,
gas_price: t.gas_price,
value: t.value,
code: self.state.code(address).unwrap_or(vec![]),
data: t.data.clone(),
code: self.state.code(address),
data: Some(t.data.clone()),
};
// TODO: move output upstream
let mut out = vec![];
@ -194,12 +197,14 @@ impl<'a> Executive<'a> {
// at first, transfer value to destination
self.state.transfer_balance(&params.sender, &params.address, &params.value);
if self.engine.is_builtin(&params.address) {
if self.engine.is_builtin(&params.code_address) {
let default = [];
let data = if let &Some(ref d) = &params.data { d as &[u8] } else { &default as &[u8] };
// if destination is builtin, try to execute it
let cost = self.engine.cost_of_builtin(&params.address, &params.data);
let cost = self.engine.cost_of_builtin(&params.code_address, &data);
match cost <= params.gas {
true => {
self.engine.execute_builtin(&params.address, &params.data, &mut output);
self.engine.execute_builtin(&params.code_address, &data, &mut output);
Ok(params.gas - cost)
},
// just drain the whole gas
@ -208,7 +213,7 @@ impl<'a> Executive<'a> {
Err(evm::Error::OutOfGas)
}
}
} else if params.code.len() > 0 {
} else if params.code.is_some() {
// if destination is a contract, do normal message call
// part of substate that may be reverted
@ -411,14 +416,15 @@ impl<'a> Ext for Externalities<'a> {
// prepare the params
let params = ActionParams {
code_address: address.clone(),
address: address.clone(),
sender: self.params.address.clone(),
origin: self.params.origin.clone(),
gas: *gas,
gas_price: self.params.gas_price.clone(),
value: value.clone(),
code: code.to_vec(),
data: vec![],
code: Some(code.to_vec()),
data: None
};
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
@ -440,6 +446,7 @@ impl<'a> Ext for Externalities<'a> {
let mut gas_cost = *call_gas;
let mut call_gas = *call_gas;
// TODO: move gas calculation out!
let is_call = receive_address == code_address;
if is_call && !self.state.exists(&code_address) {
gas_cost = gas_cost + U256::from(self.schedule.call_new_account_gas);
@ -463,14 +470,15 @@ impl<'a> Ext for Externalities<'a> {
}
let params = ActionParams {
code_address: code_address.clone(),
address: receive_address.clone(),
sender: self.params.address.clone(),
origin: self.params.origin.clone(),
gas: call_gas,
gas_price: self.params.gas_price.clone(),
value: value.clone(),
code: self.state.code(code_address).unwrap_or(vec![]),
data: data.to_vec(),
code: self.state.code(code_address),
data: Some(data.to_vec()),
};
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
@ -591,7 +599,7 @@ mod tests {
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
params.code = "3331600055".from_hex().unwrap();
params.code = Some("3331600055".from_hex().unwrap());
params.value = U256::from(0x7);
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(0x100u64));
@ -649,7 +657,7 @@ mod tests {
params.sender = sender.clone();
params.origin = sender.clone();
params.gas = U256::from(100_000);
params.code = code.clone();
params.code = Some(code.clone());
params.value = U256::from(100);
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100));
@ -702,7 +710,7 @@ mod tests {
params.sender = sender.clone();
params.origin = sender.clone();
params.gas = U256::from(100_000);
params.code = code.clone();
params.code = Some(code.clone());
params.value = U256::from(100);
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100));
@ -753,7 +761,7 @@ mod tests {
params.sender = sender.clone();
params.origin = sender.clone();
params.gas = U256::from(100_000);
params.code = code.clone();
params.code = Some(code.clone());
params.value = U256::from(100);
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100));
@ -807,7 +815,7 @@ mod tests {
params.address = address_a.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
params.code = code_a.clone();
params.code = Some(code_a.clone());
params.value = U256::from(100_000);
let mut state = State::new_temp();
@ -854,7 +862,7 @@ mod tests {
let mut params = ActionParams::new();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = code.clone();
params.code = Some(code.clone());
let mut state = State::new_temp();
state.init_code(&address, code.clone());
let info = EnvInfo::new();