Fixing delegatecall

This commit is contained in:
Tomusdrw
2016-01-20 16:52:22 +01:00
parent 98b49e0234
commit aa0760597b
7 changed files with 151 additions and 39 deletions

View File

@@ -26,7 +26,7 @@ pub enum MessageCallResult {
Failed
}
/// TODO [debris] Please document me
/// Externalities interface for EVMs
pub trait Ext {
/// Returns a value for given key.
fn storage_at(&self, key: &H256) -> H256;
@@ -61,6 +61,18 @@ pub trait Ext {
code_address: &Address,
output: &mut [u8]) -> MessageCallResult;
/// Delegate Message call.
///
/// Returns Err, if we run out of gas.
/// Otherwise returns call_result which contains gas left
/// and true if subcall was successfull.
fn delegatecall(&mut self,
gas: &U256,
value: &U256,
data: &[u8],
code_address: &Address,
output: &mut [u8]) -> MessageCallResult;
/// Returns code at given address
fn extcode(&self, address: &Address) -> Bytes;

View File

@@ -564,17 +564,50 @@ impl Interpreter {
}
};
},
instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL => {
instructions::DELEGATECALL => {
let call_gas = stack.pop_back();
let code_address = stack.pop_back();
let code_address = u256_to_address(&code_address);
let value = params.value;
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.delegatecall(&call_gas, &value, 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");
let call_gas = stack.pop_back();
let code_address = stack.pop_back();
let code_address = u256_to_address(&code_address);
let is_delegatecall = instruction == instructions::DELEGATECALL;
let value = match is_delegatecall {
true => params.value,
false => stack.pop_back()
};
let value = stack.pop_back();
let address = match instruction == instructions::CALL {
true => &code_address,
@@ -586,12 +619,12 @@ impl Interpreter {
let out_off = stack.pop_back();
let out_size = stack.pop_back();
let call_gas = call_gas + match !is_delegatecall && value > U256::zero() {
let call_gas = call_gas + match value > U256::zero() {
true => U256::from(ext.schedule().call_stipend),
false => U256::zero()
};
let can_call = (is_delegatecall || ext.balance(&params.address) >= value) && ext.depth() < ext.schedule().max_depth;
let can_call = ext.balance(&params.address) >= value && ext.depth() < ext.schedule().max_depth;
if !can_call {
stack.push(U256::zero());

View File

@@ -69,6 +69,15 @@ impl Ext for FakeExt {
unimplemented!();
}
fn delegatecall(&mut self,
_gas: &U256,
_value: &U256,
_data: &[u8],
_address: &Address,
_output: &mut [u8]) -> MessageCallResult {
unimplemented!();
}
fn extcode(&self, address: &Address) -> Bytes {
self.codes.get(address).unwrap_or(&Bytes::new()).clone()
}
@@ -110,7 +119,7 @@ fn test_stack_underflow() {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "01600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -137,7 +146,7 @@ fn test_add(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -157,7 +166,7 @@ fn test_sha3(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "6000600020600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -177,7 +186,7 @@ fn test_address(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "30600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -198,7 +207,7 @@ fn test_origin(factory: super::Factory) {
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let code = "32600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.origin = origin.clone();
params.gas = U256::from(100_000);
@@ -220,7 +229,7 @@ fn test_sender(factory: super::Factory) {
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let code = "33600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
@@ -254,7 +263,7 @@ fn test_extcodecopy(factory: super::Factory) {
let code = "333b60006000333c600051600055".from_hex().unwrap();
let sender_code = "6005600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
@@ -276,7 +285,7 @@ fn test_log_empty(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "60006000a0".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -307,7 +316,7 @@ fn test_log_sender(factory: super::Factory) {
let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
let code = "60ff6000533360206000a1".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.sender = sender.clone();
params.gas = U256::from(100_000);
@@ -332,7 +341,7 @@ fn test_blockhash(factory: super::Factory) {
let code = "600040600055".from_hex().unwrap();
let blockhash = H256::from_str("123400000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -354,7 +363,7 @@ fn test_calldataload(factory: super::Factory) {
let code = "600135600055".from_hex().unwrap();
let data = "0123ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(100_000);
params.code = Some(code);
@@ -376,7 +385,7 @@ fn test_author(factory: super::Factory) {
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "41600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
@@ -396,7 +405,7 @@ fn test_timestamp(factory: super::Factory) {
let timestamp = 0x1234;
let code = "42600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
@@ -416,7 +425,7 @@ fn test_number(factory: super::Factory) {
let number = 0x1234;
let code = "43600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
@@ -436,7 +445,7 @@ fn test_difficulty(factory: super::Factory) {
let difficulty = U256::from(0x1234);
let code = "44600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();
@@ -456,7 +465,7 @@ fn test_gas_limit(factory: super::Factory) {
let gas_limit = U256::from(0x1234);
let code = "45600055".from_hex().unwrap();
let mut params = ActionParams::new();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(code);
let mut ext = FakeExt::new();