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

View File

@ -310,12 +310,12 @@ impl evm::Evm for JitEvm {
let mut data = RuntimeData::new(); let mut data = RuntimeData::new();
data.gas = params.gas; data.gas = params.gas;
data.gas_price = params.gas_price; 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.address = params.address.clone();
data.caller = params.sender.clone(); data.caller = params.sender.clone();
data.origin = params.origin.clone(); data.origin = params.origin.clone();
data.call_value = params.value; 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.author = ext.env_info().author.clone();
data.difficulty = ext.env_info().difficulty; data.difficulty = ext.env_info().difficulty;

View File

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

View File

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