Skip to content

Commit

Permalink
implement serde for interpreter (#1909)
Browse files Browse the repository at this point in the history
* implement serde for interpreter

* add bytecode check

* remove bytecode check

* remove defaults generic params

* add sanity check + cargo fmt

* modify panic message
  • Loading branch information
FredCoen authored Dec 14, 2024
1 parent 45581c4 commit 22435a4
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 0 deletions.
37 changes: 37 additions & 0 deletions crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use std::rc::Rc;
use subroutine_stack::SubRoutineImpl;

#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
pub struct Interpreter<WIRE: InterpreterTypes> {
pub bytecode: WIRE::Bytecode,
pub stack: WIRE::Stack,
Expand Down Expand Up @@ -284,4 +285,40 @@ mod tests {
// >();
// let _ = interp.run(EMPTY_SHARED_MEMORY, table, host);
// }

use super::*;
use bytecode::Bytecode;
use primitives::{Address, Bytes, U256};
use specification::hardfork::SpecId;
use std::{cell::RefCell, rc::Rc};

#[test]
#[cfg(feature = "serde")]
fn test_interpreter_serde() {
let bytecode = Bytecode::new_raw(Bytes::from(&[0x60, 0x00, 0x60, 0x00, 0x01][..]));
let interpreter = Interpreter::<EthInterpreter>::new(
Rc::new(RefCell::new(SharedMemory::new())),
bytecode,
InputsImpl {
target_address: Address::ZERO,
caller_address: Address::ZERO,
input: Bytes::default(),
call_value: U256::ZERO,
},
false,
false,
SpecId::LATEST,
u64::MAX,
);

let serialized = bincode::serialize(&interpreter).unwrap();

let deserialized: Interpreter<EthInterpreter> = bincode::deserialize(&serialized).unwrap();

assert_eq!(
interpreter.bytecode.pc(),
deserialized.bytecode.pc(),
"Program counter should be preserved"
);
}
}
3 changes: 3 additions & 0 deletions crates/interpreter/src/interpreter/ext_bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use primitives::Bytes;

use super::{EofCodeInfo, EofContainer, EofData, Immediates, Jumps, LegacyBytecode};

#[cfg(feature = "serde")]
mod serde;

#[derive(Debug)]
pub struct ExtBytecode {
base: Bytecode,
Expand Down
42 changes: 42 additions & 0 deletions crates/interpreter/src/interpreter/ext_bytecode/serde.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use super::ExtBytecode;
use crate::interpreter::Jumps;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[derive(Serialize, Deserialize)]
struct ExtBytecodeSerde {
base: bytecode::Bytecode,
program_counter: usize,
}

impl Serialize for ExtBytecode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
ExtBytecodeSerde {
base: self.base.clone(),
program_counter: self.pc(),
}
.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for ExtBytecode {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let ExtBytecodeSerde {
base,
program_counter,
} = ExtBytecodeSerde::deserialize(deserializer)?;

let mut bytecode = Self::new(base);

if program_counter >= bytecode.base.bytecode().len() {
panic!("serde pc: {program_counter} is greater than or equal to bytecode len");
}
bytecode.absolute_jump(program_counter);
Ok(bytecode)
}
}
3 changes: 3 additions & 0 deletions crates/interpreter/src/interpreter/input.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::interpreter_types::InputsTrait;
use primitives::{Address, Bytes, U256};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct InputsImpl {
pub target_address: Address,
pub caller_address: Address,
Expand Down
3 changes: 3 additions & 0 deletions crates/interpreter/src/interpreter/loop_control.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::interpreter_types::LoopControl as LoopControlTrait;
use crate::{Gas, InstructionResult, InterpreterAction};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LoopControl {
/// The execution control flag. If this is not set to `Continue`, the interpreter will stop
/// execution.
Expand Down
3 changes: 3 additions & 0 deletions crates/interpreter/src/interpreter/return_data.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::interpreter::ReturnData;
use primitives::Bytes;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Default)]
pub struct ReturnDataImpl(Bytes);

Expand Down
3 changes: 3 additions & 0 deletions crates/interpreter/src/interpreter/runtime_flags.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use specification::hardfork::SpecId;

use super::RuntimeFlag;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RuntimeFlags {
pub is_static: bool,
pub is_eof_init: bool,
Expand Down

0 comments on commit 22435a4

Please sign in to comment.