From 8df0723cbb5fd5d255563dd952fecff3c3ed9440 Mon Sep 17 00:00:00 2001 From: Jan Ferdinand Sauer Date: Sun, 17 Dec 2023 09:43:30 +0100 Subject: [PATCH] feat: (de)serialize `VMState` --- Cargo.toml | 1 + triton-vm/Cargo.toml | 1 + triton-vm/src/op_stack.rs | 5 ++--- triton-vm/src/table/ram_table.rs | 3 ++- triton-vm/src/vm.rs | 13 ++++++++++++- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f938fc9ae..9c8f38fab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ rand_core = "0.6.4" rayon = "1.8" serde = { version = "1", features = ["derive"] } serde_derive = "1" +serde_json = "1.0" strum = { version = "0.25", features = ["derive"] } syn = "2.0" test-strategy = "0.3.1" diff --git a/triton-vm/Cargo.toml b/triton-vm/Cargo.toml index 341919b25..1ca291bf0 100644 --- a/triton-vm/Cargo.toml +++ b/triton-vm/Cargo.toml @@ -46,6 +46,7 @@ cargo-husky.workspace = true pretty_assertions.workspace = true proptest.workspace = true proptest-arbitrary-interop.workspace = true +serde_json.workspace = true test-strategy.workspace = true [[bench]] diff --git a/triton-vm/src/op_stack.rs b/triton-vm/src/op_stack.rs index f5369af38..4a706c4f3 100644 --- a/triton-vm/src/op_stack.rs +++ b/triton-vm/src/op_stack.rs @@ -8,8 +8,7 @@ use arbitrary::Arbitrary; use get_size::GetSize; use itertools::Itertools; use num_traits::Zero; -use serde_derive::Deserialize; -use serde_derive::Serialize; +use serde_derive::*; use strum::EnumCount; use strum::EnumIter; use strum::IntoEnumIterator; @@ -41,7 +40,7 @@ pub const NUM_OP_STACK_REGISTERS: usize = OpStackElement::COUNT; /// and the op-stack underflow memory. The op-stack registers are the first /// [`OpStackElement::COUNT`] elements of the op-stack, and the op-stack underflow memory is the /// remaining elements. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Arbitrary)] // If the op stack is empty, things have gone horribly wrong. Suppressing this lint is preferred // to implementing a basically useless `is_empty()` method. #[allow(clippy::len_without_is_empty)] diff --git a/triton-vm/src/table/ram_table.rs b/triton-vm/src/table/ram_table.rs index a5c7ddfa1..f3f1c3e2e 100644 --- a/triton-vm/src/table/ram_table.rs +++ b/triton-vm/src/table/ram_table.rs @@ -11,6 +11,7 @@ use ndarray::ArrayViewMut2; use ndarray::Axis; use num_traits::One; use num_traits::Zero; +use serde_derive::*; use strum::EnumCount; use twenty_first::shared_math::b_field_element::BFieldElement; use twenty_first::shared_math::b_field_element::BFIELD_ONE; @@ -38,7 +39,7 @@ pub const INSTRUCTION_TYPE_WRITE: BFieldElement = BFIELD_ZERO; pub const INSTRUCTION_TYPE_READ: BFieldElement = BFIELD_ONE; pub const PADDING_INDICATOR: BFieldElement = BFieldElement::new(2); -#[derive(Debug, Clone, PartialEq, Eq, Hash, Arbitrary)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Arbitrary)] pub struct RamTableCall { pub clk: u32, pub ram_pointer: BFieldElement, diff --git a/triton-vm/src/vm.rs b/triton-vm/src/vm.rs index 97f1c1cee..ff4020760 100644 --- a/triton-vm/src/vm.rs +++ b/triton-vm/src/vm.rs @@ -4,9 +4,11 @@ use std::fmt::Display; use std::fmt::Formatter; use std::fmt::Result as FmtResult; +use arbitrary::Arbitrary; use ndarray::Array1; use num_traits::One; use num_traits::Zero; +use serde_derive::*; use twenty_first::shared_math::b_field_element::BFieldElement; use twenty_first::shared_math::b_field_element::BFIELD_ZERO; use twenty_first::shared_math::digest::Digest; @@ -37,7 +39,7 @@ type Result = std::result::Result; /// The number of helper variable registers pub const NUM_HELPER_VARIABLE_REGISTERS: usize = 6; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Arbitrary)] pub struct VMState { /// The **program memory** stores the instructions (and their arguments) of the program /// currently being executed by Triton VM. It is read-only. @@ -2362,4 +2364,13 @@ pub(crate) mod tests { let program = triton_program! { read_io 1 halt }; instruction_does_not_change_vm_state_when_crashing_vm(program, 0); } + + #[proptest] + fn serialize_deserialize_vm_state_to_and_from_json_is_identity( + #[strategy(arb())] vm_state: VMState, + ) { + let serialized = serde_json::to_string(&vm_state).unwrap(); + let deserialized = serde_json::from_str(&serialized).unwrap(); + prop_assert_eq!(vm_state, deserialized); + } }