diff --git a/crates/interpreter/src/interpreter/serde.rs b/crates/interpreter/src/interpreter/serde.rs index eb4d8524fc..2cc8fd0496 100644 --- a/crates/interpreter/src/interpreter/serde.rs +++ b/crates/interpreter/src/interpreter/serde.rs @@ -1,36 +1,67 @@ +use super::Interpreter; use crate::{ Contract, FunctionStack, Gas, InstructionResult, InterpreterAction, SharedMemory, Stack, }; - -use super::Interpreter; use revm_primitives::Bytes; -use serde::de::{self, MapAccess, Visitor}; -use serde::ser::SerializeStruct; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt; + +#[derive(Serialize)] +struct InterpreterSerde<'a> { + program_counter: usize, + + gas: &'a Gas, + contract: &'a Contract, + instruction_result: InstructionResult, + bytecode: &'a Bytes, + is_eof: bool, + is_eof_init: bool, + shared_memory: &'a SharedMemory, + stack: &'a Stack, + function_stack: &'a FunctionStack, + return_data_buffer: &'a Bytes, + is_static: bool, + next_action: &'a InterpreterAction, +} + +#[derive(Deserialize)] +struct InterpreterDe { + program_counter: usize, + + gas: Gas, + contract: Contract, + instruction_result: InstructionResult, + bytecode: Bytes, + is_eof: bool, + is_eof_init: bool, + shared_memory: SharedMemory, + stack: Stack, + function_stack: FunctionStack, + return_data_buffer: Bytes, + is_static: bool, + next_action: InterpreterAction, +} impl Serialize for Interpreter { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - let mut state = serializer.serialize_struct("Interpreter", 8)?; - // Convert the instruction pointer to a usize for serialization - let program_counter = self.program_counter(); - state.serialize_field("program_counter", &program_counter)?; - state.serialize_field("gas", &self.gas)?; - state.serialize_field("contract", &self.contract)?; - state.serialize_field("instruction_result", &self.instruction_result)?; - state.serialize_field("bytecode", &self.bytecode)?; - state.serialize_field("is_eof", &self.is_eof)?; - state.serialize_field("is_eof_init", &self.is_eof_init)?; - state.serialize_field("shared_memory", &self.shared_memory)?; - state.serialize_field("stack", &self.stack)?; - state.serialize_field("function_stack", &self.function_stack)?; - state.serialize_field("return_data_buffer", &self.return_data_buffer)?; - state.serialize_field("is_static", &self.is_static)?; - state.serialize_field("next_action", &self.next_action)?; - state.end() + InterpreterSerde { + program_counter: self.program_counter(), + gas: &self.gas, + contract: &self.contract, + instruction_result: self.instruction_result, + bytecode: &self.bytecode, + is_eof: self.is_eof, + is_eof_init: self.is_eof_init, + shared_memory: &self.shared_memory, + stack: &self.stack, + function_stack: &self.function_stack, + return_data_buffer: &self.return_data_buffer, + is_static: self.is_static, + next_action: &self.next_action, + } + .serialize(serializer) } } @@ -39,192 +70,45 @@ impl<'de> Deserialize<'de> for Interpreter { where D: Deserializer<'de>, { - struct InterpreterVisitor; - - #[derive(serde::Deserialize)] - #[serde(field_identifier, rename_all = "lowercase")] - enum InterpreterFields { - ProgramCounter, - Gas, - Contract, - InstructionResult, - Bytecode, - IsEof, - IsEofInit, - SharedMemory, - Stack, - FunctionStack, - ReturnDataBuffer, - IsStatic, - NextAction, - } - - #[allow(clippy::too_many_arguments)] - fn rebuild_interp( - program_counter: isize, - gas: Gas, - contract: Contract, - instruction_result: InstructionResult, - bytecode: Bytes, - is_eof: bool, - is_eof_init: bool, - shared_memory: SharedMemory, - stack: Stack, - function_stack: FunctionStack, - return_data_buffer: Bytes, - is_static: bool, - next_action: InterpreterAction, - ) -> Result { - // Reconstruct the instruction pointer from usize - if program_counter < 0 || program_counter >= bytecode.len() as isize { - return Err("program_counter index out of range"); - } - - // SAFETY: range of program_counter checked above - let instruction_pointer = unsafe { bytecode.as_ptr().offset(program_counter) }; - - // Construct and return the Interpreter instance - Ok(Interpreter { - instruction_pointer, - gas, - contract, - instruction_result, - bytecode, - is_eof, - is_eof_init, - shared_memory, - stack, - function_stack, - return_data_buffer, - is_static, - next_action, - }) - } - - impl<'de> Visitor<'de> for InterpreterVisitor { - type Value = Interpreter; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("struct Interpreter") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: de::SeqAccess<'de>, - { - macro_rules! extract_field { - ($i:ident, $idx:expr) => { - let $i = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length($idx, &self))?; - }; - } - extract_field!(instruction_pointer, 0); - extract_field!(gas, 1); - extract_field!(contract, 2); - extract_field!(instruction_result, 3); - extract_field!(bytecode, 4); - extract_field!(is_eof, 5); - extract_field!(is_eof_init, 6); - extract_field!(shared_memory, 7); - extract_field!(stack, 8); - extract_field!(function_stack, 9); - extract_field!(return_data_buffer, 10); - extract_field!(is_static, 11); - extract_field!(next_action, 12); - rebuild_interp( - instruction_pointer, - gas, - contract, - instruction_result, - bytecode, - is_eof, - is_eof_init, - shared_memory, - stack, - function_stack, - return_data_buffer, - is_static, - next_action, - ) - .map_err(de::Error::custom) - } - - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - macro_rules! parse_map { - ( $(($enum:pat, $var_name:ident)),* ) => { - $( - let mut $var_name = None; - )* - while let Some(key) = map.next_key()? { - match key { - $( - $enum => { - $var_name = Some(map.next_value()?); - } - )* - } - } - $( - let $var_name = $var_name.ok_or_else(|| de::Error::missing_field(stringify!($var_name)))?; - )* - }; - } - parse_map!( - (InterpreterFields::ProgramCounter, program_counter), - (InterpreterFields::Gas, gas), - (InterpreterFields::Contract, contract), - (InterpreterFields::InstructionResult, instruction_result), - (InterpreterFields::Bytecode, bytecode), - (InterpreterFields::IsEof, is_eof), - (InterpreterFields::IsEofInit, is_eof_init), - (InterpreterFields::SharedMemory, shared_memory), - (InterpreterFields::Stack, stack), - (InterpreterFields::FunctionStack, function_stack), - (InterpreterFields::ReturnDataBuffer, return_data_buffer), - (InterpreterFields::IsStatic, is_static), - (InterpreterFields::NextAction, next_action) - ); - - rebuild_interp( - program_counter, - gas, - contract, - instruction_result, - bytecode, - is_eof, - is_eof_init, - shared_memory, - stack, - function_stack, - return_data_buffer, - is_static, - next_action, - ) - .map_err(de::Error::custom) - } + let InterpreterDe { + program_counter, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + } = InterpreterDe::deserialize(deserializer)?; + + // Reconstruct the instruction pointer from usize + if program_counter >= bytecode.len() { + return Err(serde::de::Error::custom("program_counter out of bounds")); } - const FIELDS: &[&str] = &[ - "program_counter", - "gas", - "contract", - "instruction_result", - "bytecode", - "is_eof", - "is_eof_init", - "shared_memory", - "stack", - "function_stack", - "return_data_buffer", - "is_static", - "next_action", - ]; - - deserializer.deserialize_struct("Interpreter", FIELDS, InterpreterVisitor) + // SAFETY: range of program_counter checked above + let instruction_pointer = unsafe { bytecode.as_ptr().add(program_counter) }; + + Ok(Interpreter { + instruction_pointer, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + }) } }