Getting rid of RequiredMem enum

This commit is contained in:
Tomusdrw 2016-01-17 14:17:05 +01:00
parent c8d94c981b
commit 342c4e736d

View File

@ -243,15 +243,10 @@ impl<'a> CodeReader<'a> {
} }
} }
enum RequiredMem {
Mem(U256),
OutOfMemory
}
enum InstructionCost { enum InstructionCost {
Gas(U256), Gas(U256),
GasMem(U256, RequiredMem), GasMem(U256, U256),
GasMemCopy(U256, RequiredMem, U256) GasMemCopy(U256, U256, U256)
} }
enum InstructionResult { enum InstructionResult {
@ -381,31 +376,31 @@ impl Interpreter {
InstructionCost::Gas(U256::from(schedule.sload_gas)) InstructionCost::Gas(U256::from(schedule.sload_gas))
}, },
instructions::MSTORE => { instructions::MSTORE => {
InstructionCost::GasMem(default_gas, self.mem_needed_const(stack.peek(0), 32)) InstructionCost::GasMem(default_gas, try!(self.mem_needed_const(stack.peek(0), 32)))
}, },
instructions::MLOAD => { instructions::MLOAD => {
InstructionCost::GasMem(default_gas, self.mem_needed_const(stack.peek(0), 32)) InstructionCost::GasMem(default_gas, try!(self.mem_needed_const(stack.peek(0), 32)))
}, },
instructions::MSTORE8 => { instructions::MSTORE8 => {
InstructionCost::GasMem(default_gas, self.mem_needed_const(stack.peek(0), 1)) InstructionCost::GasMem(default_gas, try!(self.mem_needed_const(stack.peek(0), 1)))
}, },
instructions::RETURN => { instructions::RETURN => {
InstructionCost::GasMem(default_gas, self.mem_needed(stack.peek(0), stack.peek(1))) InstructionCost::GasMem(default_gas, try!(self.mem_needed(stack.peek(0), stack.peek(1))))
}, },
instructions::SHA3 => { instructions::SHA3 => {
let w = overflowing!(add_u256_usize(stack.peek(1), 31)); let w = overflowing!(add_u256_usize(stack.peek(1), 31));
let words = w >> 5; let words = w >> 5;
let gas = U256::from(schedule.sha3_gas) + (U256::from(schedule.sha3_word_gas) * words); let gas = U256::from(schedule.sha3_gas) + (U256::from(schedule.sha3_word_gas) * words);
InstructionCost::GasMem(gas, self.mem_needed(stack.peek(0), stack.peek(1))) InstructionCost::GasMem(gas, try!(self.mem_needed(stack.peek(0), stack.peek(1))))
}, },
instructions::CALLDATACOPY => { instructions::CALLDATACOPY => {
InstructionCost::GasMemCopy(default_gas, self.mem_needed(stack.peek(0), stack.peek(2)), stack.peek(2).clone()) InstructionCost::GasMemCopy(default_gas, try!(self.mem_needed(stack.peek(0), stack.peek(2))), stack.peek(2).clone())
}, },
instructions::CODECOPY => { instructions::CODECOPY => {
InstructionCost::GasMemCopy(default_gas, self.mem_needed(stack.peek(0), stack.peek(2)), stack.peek(2).clone()) InstructionCost::GasMemCopy(default_gas, try!(self.mem_needed(stack.peek(0), stack.peek(2))), stack.peek(2).clone())
}, },
instructions::EXTCODECOPY => { instructions::EXTCODECOPY => {
InstructionCost::GasMemCopy(default_gas, self.mem_needed(stack.peek(1), stack.peek(3)), stack.peek(3).clone()) InstructionCost::GasMemCopy(default_gas, try!(self.mem_needed(stack.peek(1), stack.peek(3))), stack.peek(3).clone())
}, },
instructions::JUMPDEST => { instructions::JUMPDEST => {
InstructionCost::Gas(U256::one()) InstructionCost::Gas(U256::one())
@ -416,13 +411,13 @@ impl Interpreter {
let data_gas = overflowing!(stack.peek(1).overflowing_mul(U256::from(schedule.log_data_gas))); let data_gas = overflowing!(stack.peek(1).overflowing_mul(U256::from(schedule.log_data_gas)));
let gas = overflowing!(data_gas.overflowing_add(U256::from(log_gas))); let gas = overflowing!(data_gas.overflowing_add(U256::from(log_gas)));
InstructionCost::GasMem(gas, self.mem_needed(stack.peek(0), stack.peek(1))) InstructionCost::GasMem(gas, try!(self.mem_needed(stack.peek(0), stack.peek(1))))
}, },
instructions::CALL | instructions::CALLCODE => { instructions::CALL | instructions::CALLCODE => {
let mut gas = overflowing!(add_u256_usize(stack.peek(0), schedule.call_gas)); let mut gas = overflowing!(add_u256_usize(stack.peek(0), schedule.call_gas));
let mem = self.mem_max( let mem = cmp::max(
self.mem_needed(stack.peek(5), stack.peek(6)), try!(self.mem_needed(stack.peek(5), stack.peek(6))),
self.mem_needed(stack.peek(3), stack.peek(4)) try!(self.mem_needed(stack.peek(3), stack.peek(4)))
); );
let address = u256_to_address(stack.peek(1)); let address = u256_to_address(stack.peek(1));
@ -439,15 +434,15 @@ impl Interpreter {
}, },
instructions::DELEGATECALL => { instructions::DELEGATECALL => {
let gas = overflowing!(add_u256_usize(stack.peek(0), schedule.call_gas)); let gas = overflowing!(add_u256_usize(stack.peek(0), schedule.call_gas));
let mem = self.mem_max( let mem = cmp::max(
self.mem_needed(stack.peek(4), stack.peek(5)), try!(self.mem_needed(stack.peek(4), stack.peek(5))),
self.mem_needed(stack.peek(2), stack.peek(3)) try!(self.mem_needed(stack.peek(2), stack.peek(3)))
); );
InstructionCost::GasMem(gas, mem) InstructionCost::GasMem(gas, mem)
}, },
instructions::CREATE => { instructions::CREATE => {
let gas = U256::from(schedule.create_gas); let gas = U256::from(schedule.create_gas);
let mem = self.mem_needed(stack.peek(1), stack.peek(2)); let mem = try!(self.mem_needed(stack.peek(1), stack.peek(2)));
InstructionCost::GasMem(gas, mem) InstructionCost::GasMem(gas, mem)
}, },
instructions::EXP => { instructions::EXP => {
@ -463,24 +458,18 @@ impl Interpreter {
InstructionCost::Gas(gas) => { InstructionCost::Gas(gas) => {
Ok((gas, 0)) Ok((gas, 0))
}, },
InstructionCost::GasMem(gas, mem_size) => match mem_size { InstructionCost::GasMem(gas, mem_size) => {
RequiredMem::Mem(mem_size) => { let (mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, mem.size(), &mem_size));
let (mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, mem.size(), &mem_size)); let gas = overflowing!(gas.overflowing_add(mem_gas));
let gas = overflowing!(gas.overflowing_add(mem_gas)); Ok((gas, new_mem_size))
Ok((gas, new_mem_size))
},
RequiredMem::OutOfMemory => Err(evm::Error::OutOfGas)
}, },
InstructionCost::GasMemCopy(gas, mem_size, copy) => match mem_size { InstructionCost::GasMemCopy(gas, mem_size, copy) => {
RequiredMem::Mem(mem_size) => { let (mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, mem.size(), &mem_size));
let (mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, mem.size(), &mem_size)); let copy = overflowing!(add_u256_usize(&copy, 31));
let copy = overflowing!(add_u256_usize(&copy, 31)); let copy_gas = U256::from(schedule.copy_gas) * (copy / U256::from(32));
let copy_gas = U256::from(schedule.copy_gas) * (copy / U256::from(32)); let gas = overflowing!(gas.overflowing_add(copy_gas));
let gas = overflowing!(gas.overflowing_add(copy_gas)); let gas = overflowing!(gas.overflowing_add(mem_gas));
let gas = overflowing!(gas.overflowing_add(mem_gas)); Ok((gas, new_mem_size))
Ok((gas, new_mem_size))
},
RequiredMem::OutOfMemory => Err(evm::Error::OutOfGas)
} }
} }
} }
@ -510,35 +499,16 @@ impl Interpreter {
}, req_mem_size_rounded.low_u64() as usize)) }, req_mem_size_rounded.low_u64() as usize))
} }
fn mem_max(&self, m_a: RequiredMem, m_b: RequiredMem) -> RequiredMem { fn mem_needed_const(&self, mem: &U256, add: usize) -> Result<U256, evm::Error> {
match (m_a, m_b) { Ok(overflowing!(mem.overflowing_add(U256::from(add))))
(RequiredMem::Mem(a), RequiredMem::Mem(b)) => {
RequiredMem::Mem(cmp::max(a, b))
},
(RequiredMem::OutOfMemory, _) | (_, RequiredMem::OutOfMemory) => {
RequiredMem::OutOfMemory
}
}
} }
fn mem_needed_const(&self, mem: &U256, add: usize) -> RequiredMem { fn mem_needed(&self, offset: &U256, size: &U256) -> Result<U256, ::evm::Error> {
match mem.overflowing_add(U256::from(add)) {
(_, true) => RequiredMem::OutOfMemory,
(mem, false) => RequiredMem::Mem(mem)
}
}
fn mem_needed(&self, offset: &U256, size: &U256) -> RequiredMem {
if self.is_zero(size) { if self.is_zero(size) {
return RequiredMem::Mem(U256::zero()); return Ok(U256::zero());
} }
match offset.clone().overflowing_add(size.clone()) { Ok(overflowing!(offset.overflowing_add(size.clone())))
(_result, true) => RequiredMem::OutOfMemory,
(result, false) => {
RequiredMem::Mem(result)
}
}
} }
fn exec_instruction(&self, fn exec_instruction(&self,