Merging CALL & DELEGATECALL branches
This commit is contained in:
parent
58bda2209c
commit
16f2fa33ee
@ -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;
|
||||||
|
@ -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, ¶ms.sender, ¶ms.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(¶ms.address) >= value.unwrap();
|
||||||
|
(¶ms.address, &code_address, has_balance)
|
||||||
|
},
|
||||||
|
instructions::CALLCODE => {
|
||||||
|
let has_balance = ext.balance(¶ms.address) >= value.unwrap();
|
||||||
|
(¶ms.address, ¶ms.address, has_balance)
|
||||||
|
},
|
||||||
|
instructions::DELEGATECALL => (¶ms.sender, ¶ms.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 => (¶ms.address, &code_address),
|
|
||||||
false => (¶ms.address, ¶ms.address)
|
|
||||||
};
|
|
||||||
|
|
||||||
let can_call = ext.balance(¶ms.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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user