diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 81ce287b..1839aaf2 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -1,4 +1,5 @@ -use ethereum_types::{U256, U512}; +use ethereum_types::{BigEndianHash, U256, U512}; +use keccak_hash::keccak; /// Halt interpreter execution whenever a jump to this offset is done. const HALT_OFFSET: usize = 0xdeadbeef; @@ -25,6 +26,11 @@ impl EvmMemory { U256::from_big_endian(&self.memory[offset..offset + 32]) } + fn mload8(&mut self, offset: usize) -> u8 { + self.expand(offset + 1); + self.memory[offset] + } + fn mstore(&mut self, offset: usize, value: U256) { self.expand(offset + 32); let value_be = { @@ -119,7 +125,7 @@ impl<'a> Interpreter<'a> { 0x1b => todo!(), // "SHL", 0x1c => todo!(), // "SHR", 0x1d => todo!(), // "SAR", - 0x20 => todo!(), // "KECCAK256", + 0x20 => self.run_sha3(), // "SHA3", 0x30 => todo!(), // "ADDRESS", 0x31 => todo!(), // "BALANCE", 0x32 => todo!(), // "ORIGIN", @@ -286,6 +292,16 @@ impl<'a> Interpreter<'a> { self.push(!x); } + fn run_sha3(&mut self) { + let offset = self.pop().as_usize(); + let size = self.pop().as_usize(); + let bytes = (offset..offset + size) + .map(|i| self.memory.mload8(i)) + .collect::>(); + let hash = keccak(bytes); + self.push(hash.into_uint()); + } + fn run_pop(&mut self) { self.pop(); }