Merging CALL & DELEGATECALL branches

This commit is contained in:
Tomusdrw 2016-01-25 23:59:50 +01:00
parent 58bda2209c
commit 16f2fa33ee
5 changed files with 29 additions and 52 deletions

View File

@ -57,7 +57,7 @@ pub trait Ext {
gas: &U256, gas: &U256,
sender_address: &Address, sender_address: &Address,
receive_address: &Address, receive_address: &Address,
value: Option<&U256>, value: Option<U256>,
data: &[u8], data: &[u8],
code_address: &Address, code_address: &Address,
output: &mut [u8]) -> MessageCallResult; output: &mut [u8]) -> MessageCallResult;

View File

@ -566,66 +566,43 @@ impl Interpreter {
} }
}; };
}, },
instructions::DELEGATECALL => { instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL => {
let call_gas = stack.pop_back();
let code_address = stack.pop_back();
let code_address = u256_to_address(&code_address);
let in_off = stack.pop_back();
let in_size = stack.pop_back();
let out_off = stack.pop_back();
let out_size = stack.pop_back();
let can_call = ext.depth() < ext.schedule().max_depth;
if !can_call {
stack.push(U256::zero());
return Ok(InstructionResult::UnusedGas(call_gas));
}
let call_result = {
// we need to write and read from memory in the same time
// and we don't want to copy
let input = unsafe { ::std::mem::transmute(mem.read_slice(in_off, in_size)) };
let output = mem.writeable_slice(out_off, out_size);
ext.call(&call_gas, &params.sender, &params.address, None, input, &code_address, output)
};
return match call_result {
MessageCallResult::Success(gas_left) => {
stack.push(U256::one());
Ok(InstructionResult::UnusedGas(gas_left))
},
MessageCallResult::Failed => {
stack.push(U256::zero());
Ok(InstructionResult::Ok)
}
};
},
instructions::CALL | instructions::CALLCODE => {
assert!(ext.schedule().call_value_transfer_gas > ext.schedule().call_stipend, "overflow possible"); assert!(ext.schedule().call_value_transfer_gas > ext.schedule().call_stipend, "overflow possible");
let call_gas = stack.pop_back(); let call_gas = stack.pop_back();
let code_address = stack.pop_back(); let code_address = stack.pop_back();
let code_address = u256_to_address(&code_address); let code_address = u256_to_address(&code_address);
let value = stack.pop_back(); let value = match instruction == instructions::DELEGATECALL {
true => None,
false => Some(stack.pop_back())
};
let in_off = stack.pop_back(); let in_off = stack.pop_back();
let in_size = stack.pop_back(); let in_size = stack.pop_back();
let out_off = stack.pop_back(); let out_off = stack.pop_back();
let out_size = stack.pop_back(); let out_size = stack.pop_back();
let call_gas = call_gas + match value > U256::zero() { // Add stipend (only CALL|CALLCODE when value > 0)
let call_gas = call_gas + value.map_or_else(U256::zero, |val| match val > U256::zero() {
true => U256::from(ext.schedule().call_stipend), true => U256::from(ext.schedule().call_stipend),
false => U256::zero() false => U256::zero()
});
// Get sender & receive addresses, check if we have balance
let (sender_address, receive_address, has_balance) = match instruction {
instructions::CALL => {
let has_balance = ext.balance(&params.address) >= value.unwrap();
(&params.address, &code_address, has_balance)
},
instructions::CALLCODE => {
let has_balance = ext.balance(&params.address) >= value.unwrap();
(&params.address, &params.address, has_balance)
},
instructions::DELEGATECALL => (&params.sender, &params.address, true),
_ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction))
}; };
let (sender_address, receive_address) = match instruction == instructions::CALL { let can_call = has_balance && ext.depth() < ext.schedule().max_depth;
true => (&params.address, &code_address),
false => (&params.address, &params.address)
};
let can_call = ext.balance(&params.address) >= value && ext.depth() < ext.schedule().max_depth;
if !can_call { if !can_call {
stack.push(U256::zero()); stack.push(U256::zero());
return Ok(InstructionResult::UnusedGas(call_gas)); return Ok(InstructionResult::UnusedGas(call_gas));
@ -636,7 +613,7 @@ impl Interpreter {
// and we don't want to copy // and we don't want to copy
let input = unsafe { ::std::mem::transmute(mem.read_slice(in_off, in_size)) }; let input = unsafe { ::std::mem::transmute(mem.read_slice(in_off, in_size)) };
let output = mem.writeable_slice(out_off, out_size); let output = mem.writeable_slice(out_off, out_size);
ext.call(&call_gas, sender_address, receive_address, Some(&value), input, &code_address, output) ext.call(&call_gas, sender_address, receive_address, value, input, &code_address, output)
}; };
return match call_result { return match call_result {

View File

@ -63,7 +63,7 @@ impl Ext for FakeExt {
_gas: &U256, _gas: &U256,
_sender_address: &Address, _sender_address: &Address,
_receive_address: &Address, _receive_address: &Address,
_value: Option<&U256>, _value: Option<U256>,
_data: &[u8], _data: &[u8],
_code_address: &Address, _code_address: &Address,
_output: &mut [u8]) -> MessageCallResult { _output: &mut [u8]) -> MessageCallResult {

View File

@ -138,7 +138,7 @@ impl<'a> Ext for Externalities<'a> {
gas: &U256, gas: &U256,
sender_address: &Address, sender_address: &Address,
receive_address: &Address, receive_address: &Address,
value: Option<&U256>, value: Option<U256>,
data: &[u8], data: &[u8],
code_address: &Address, code_address: &Address,
output: &mut [u8]) -> MessageCallResult { output: &mut [u8]) -> MessageCallResult {
@ -156,7 +156,7 @@ impl<'a> Ext for Externalities<'a> {
}; };
if let Some(value) = value { if let Some(value) = value {
params.value = ActionValue::Transfer(value.clone()); params.value = ActionValue::Transfer(value);
} }
let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth);

View File

@ -103,7 +103,7 @@ impl<'a> Ext for TestExt<'a> {
gas: &U256, gas: &U256,
_sender_address: &Address, _sender_address: &Address,
receive_address: &Address, receive_address: &Address,
value: Option<&U256>, value: Option<U256>,
data: &[u8], data: &[u8],
_code_address: &Address, _code_address: &Address,
_output: &mut [u8]) -> MessageCallResult { _output: &mut [u8]) -> MessageCallResult {
@ -111,7 +111,7 @@ impl<'a> Ext for TestExt<'a> {
data: data.to_vec(), data: data.to_vec(),
destination: Some(receive_address.clone()), destination: Some(receive_address.clone()),
gas_limit: *gas, gas_limit: *gas,
value: *value.unwrap() value: value.unwrap()
}); });
MessageCallResult::Success(*gas) MessageCallResult::Success(*gas)
} }