From d06857737e05165e4b16ecc8301b2d5bb20b8021 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Thu, 14 Jan 2016 00:39:59 +0100 Subject: [PATCH] Implementing CALLs --- src/evm/interpreter.rs | 58 ++++++++++++++++++++++++++++++++++-------- src/tests/executive.rs | 2 +- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/evm/interpreter.rs b/src/evm/interpreter.rs index d426bb5a7..da76ee95e 100644 --- a/src/evm/interpreter.rs +++ b/src/evm/interpreter.rs @@ -84,6 +84,8 @@ trait Memory { fn write_slice(&mut self, offset: U256, &[u8]); /// Retrieve part of the memory between offset and offset + size fn read_slice(&self, offset: U256, size: U256) -> &[u8]; + /// Retrieve writeable part of memory + fn writeable_slice(&mut self, offset: U256, size: U256) -> &mut[u8]; } impl Memory for Vec { fn size(&self) -> usize { @@ -106,6 +108,12 @@ impl Memory for Vec { val } + fn writeable_slice(&mut self, offset: U256, size: U256) -> &mut [u8] { + let off = offset.low_u64() as usize; + let s = size.low_u64() as usize; + &mut self[off..off+s] + } + fn write_slice(&mut self, offset: U256, slice: &[u8]) { let off = offset.low_u64() as usize; @@ -419,30 +427,59 @@ impl Interpreter { let init_off = stack.pop_back(); let init_size = stack.pop_back(); - // TODO [todr] Fix u64 for gas let contract_code = mem.read_slice(init_off, init_size); - // TODO [todr] Fix u64 for gasLeft let (gas_left, maybe_address) = try!( - ext.create(gas.low_u64(), &endowment, &contract_code) + ext.create(&gas, &endowment, &contract_code) ); match maybe_address { Some(address) => stack.push(address_to_u256(address)), None => stack.push(U256::zero()) } return Ok(InstructionResult::AdditionalGasCost( - gas - Gas::from(gas_left) + gas - gas_left )); }, - // CALL, CALLCODE, DELEGATECALL + instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL => { + let call_gas = stack.pop_back(); + let code_address = u256_to_address(&stack.pop_back()); + + let value = if instruction == instructions::DELEGATECALL { + params.value + } else { + stack.pop_back() + }; + + let address = if instruction == instructions::CALL { + &code_address + } else { + ¶ms.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 gas_left = { + // 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); + try!( + ext.call(&gas, &call_gas, address, &value, input, &code_address, output) + ) + }; + return Ok(InstructionResult::AdditionalGasCost( + gas - gas_left + )); + }, instructions::RETURN => { let init_off = stack.pop_back(); let init_size = stack.pop_back(); let return_code = mem.read_slice(init_off, init_size); - // TODO [todr] Fix u64 for gas - let gas_left = try!(ext.ret(gas.low_u64(), &return_code)); - // TODO [todr] Fix u64 for gasLeft + let gas_left = try!(ext.ret(&gas, &return_code)); return Ok(InstructionResult::StopExecutionWithGasCost( - gas - Gas::from(gas_left) + gas - gas_left )); }, instructions::STOP => { @@ -451,8 +488,7 @@ impl Interpreter { instructions::SUICIDE => { // TODO [todr] Suicide should have argument with address of contract that funds should be transfered to let address = stack.pop_back(); - // ext.suicide(Address::from(address)); - ext.suicide(); + ext.suicide(&u256_to_address(&address)); return Ok(InstructionResult::StopExecution); }, instructions::LOG0...instructions::LOG4 => { diff --git a/src/tests/executive.rs b/src/tests/executive.rs index cfe80dfc1..0a71aa3e4 100644 --- a/src/tests/executive.rs +++ b/src/tests/executive.rs @@ -131,7 +131,7 @@ impl<'a> Ext for TestExt<'a> { self.ext.extcode(address) } - fn log(&mut self, topics: Vec, data: Bytes) { + fn log(&mut self, topics: Vec, data: &[u8]) { self.ext.log(topics, data) }