Implementing CALLs

This commit is contained in:
Tomusdrw 2016-01-14 00:39:59 +01:00
parent b3bf8b4034
commit d06857737e
2 changed files with 48 additions and 12 deletions

View File

@ -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<u8> {
fn size(&self) -> usize {
@ -106,6 +108,12 @@ impl Memory for Vec<u8> {
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
));
},
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 {
&params.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
));
},
// CALL, CALLCODE, DELEGATECALL
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 => {

View File

@ -131,7 +131,7 @@ impl<'a> Ext for TestExt<'a> {
self.ext.extcode(address)
}
fn log(&mut self, topics: Vec<H256>, data: Bytes) {
fn log(&mut self, topics: Vec<H256>, data: &[u8]) {
self.ext.log(topics, data)
}