diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 4ba6e9dc..53844ac5 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -426,7 +426,7 @@ impl<'a> Interpreter<'a> { 0xf6 => self.run_get_context(), // "GET_CONTEXT", 0xf7 => self.run_set_context(), // "SET_CONTEXT", 0xf8 => self.run_mload_32bytes(), // "MLOAD_32BYTES", - 0xf9 => todo!(), // "EXIT_KERNEL", + 0xf9 => self.run_exit_kernel(), // "EXIT_KERNEL", 0xfa => todo!(), // "STATICCALL", 0xfb => self.run_mload_general(), // "MLOAD_GENERAL", 0xfc => self.run_mstore_general(), // "MSTORE_GENERAL", @@ -1126,6 +1126,25 @@ impl<'a> Interpreter<'a> { } } + fn run_exit_kernel(&mut self) { + let _dummy = self.pop(); // not sure why we need this extra pop on the interpreter + let kexit_info = self.pop(); + + let kexit_info_u64 = kexit_info.0[0]; + let program_counter = kexit_info_u64 as u32 as usize; + let is_kernel_mode_val = (kexit_info_u64 >> 32) as u32; + assert!(is_kernel_mode_val == 0 || is_kernel_mode_val == 1); + let is_kernel_mode = is_kernel_mode_val != 0; + let gas_used_val = kexit_info.0[3]; + if TryInto::::try_into(gas_used_val).is_err() { + panic!("Gas overflow"); + } + + self.generation_state.registers.program_counter = program_counter; + self.generation_state.registers.is_kernel = is_kernel_mode; + self.generation_state.registers.gas_used = gas_used_val; + } + pub(crate) fn stack_len(&self) -> usize { self.generation_state.registers.stack_len } diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index f4c18fe6..77355789 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -7,6 +7,7 @@ use keccak_hash::keccak; use rand::{thread_rng, Rng}; use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::constants::context_metadata::ContextMetadata::GasLimit; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; @@ -142,7 +143,11 @@ fn test_extcodecopy() -> Result<()> { // Prepare the interpreter by inserting the account in the state trie. prepare_interpreter(&mut interpreter, address, &account)?; - let extcodecopy = KERNEL.global_labels["extcodecopy"]; + interpreter.generation_state.memory.contexts[interpreter.context].segments + [Segment::ContextMetadata as usize] + .set(GasLimit as usize, U256::from(1000000000000u64) << 192); + + let extcodecopy = KERNEL.global_labels["sys_extcodecopy"]; // Put random data in main memory and the `KernelAccountCode` segment for realism. let mut rng = thread_rng(); @@ -169,6 +174,7 @@ fn test_extcodecopy() -> Result<()> { interpreter.push(offset.into()); interpreter.push(dest_offset.into()); interpreter.push(U256::from_big_endian(address.as_bytes())); + interpreter.push(0.into()); // kexit_info interpreter.generation_state.inputs.contract_code = HashMap::from([(keccak(&code), code.clone())]); interpreter.run()?;