From e0c4cab96f5ccc676f28400bf5a03f04991783aa Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Thu, 7 Nov 2024 08:58:56 +0000 Subject: [PATCH 1/2] RISC-V: introduce EnrichedCell, for attaching derived values in storage This additionally adds a `ManagerRoot` onto the Manager, where attached values may require stricter trait requirements than the current manager necessarily has --- src/riscv/lib/src/state_backend.rs | 115 ++++++++++++++++- .../lib/src/state_backend/owned_backend.rs | 114 ++++++++++++++++- src/riscv/lib/src/state_backend/region.rs | 117 +++++++++++++++++- 3 files changed, 338 insertions(+), 8 deletions(-) diff --git a/src/riscv/lib/src/state_backend.rs b/src/riscv/lib/src/state_backend.rs index c8e33ddebfbf..98ac0aacc4ae 100644 --- a/src/riscv/lib/src/state_backend.rs +++ b/src/riscv/lib/src/state_backend.rs @@ -68,13 +68,38 @@ pub use elems::*; pub use layout::*; pub use region::*; +/// An enriched value may be stored in a [`ManagerBase::EnrichedCell`]. +/// +/// This allows a value to have an additional, derived, value attached - that may be expensive +/// to derive lazily. +/// +/// This derived value does not form part of any stored state/commitments. +pub trait EnrichedValue: 'static { + type E: 'static; + type D; +} + /// Manager of the state backend storage -pub trait ManagerBase { +pub trait ManagerBase: Sized { /// Region that has been allocated in the state storage type Region; /// Dynamic region represents a fixed-sized byte vector that has been allocated in the state storage type DynRegion; + + /// An [enriched] value may have a derived value attached. + /// + /// [enriched]: EnrichedValue + type EnrichedCell; + + /// The root manager may either be itself, or occassionally the manager that this manager + /// wraps. + /// + /// For example, the [`Ref`] backend is often use to wrap the [`Owned`] backend to gain access + /// to its regions. In this case, the root manager would be the owned backend. + /// + /// [`Owned`]: owned_backend::Owned + type ManagerRoot: ManagerBase; } /// Manager with allocation capabilities @@ -90,6 +115,12 @@ pub trait ManagerAlloc: 'static + ManagerReadWrite { /// Allocate a dynamic region in the state storage. fn allocate_dyn_region(&mut self) -> Self::DynRegion; + + /// Allocate an enriched cell. + fn allocate_enriched_cell(&mut self, init_value: V::E) -> Self::EnrichedCell + where + V: EnrichedValue, + V::D: for<'a> From<&'a V::E>; } /// Manager with read capabilities @@ -115,10 +146,23 @@ pub trait ManagerRead: ManagerBase { address: usize, values: &mut [E], ); + + /// Read the value, and derived value, contained in the enriched cell. + fn enriched_cell_read(cell: &Self::EnrichedCell) -> (V::E, V::D) + where + V: EnrichedValue, + V::E: Copy, + V::D: for<'a> From<&'a V::E> + Copy; + + /// Obtain a refernce to the value, and derived value, contained in the enriched cell. + fn enriched_cell_ref(cell: &Self::EnrichedCell) -> (&V::E, &V::D) + where + V: EnrichedValue, + V::D: for<'a> From<&'a V::E>; } /// Manager with write capabilities -pub trait ManagerWrite: ManagerBase { +pub trait ManagerWrite: ManagerBase { /// Update an element in the region. fn region_write( region: &mut Self::Region, @@ -142,6 +186,12 @@ pub trait ManagerWrite: ManagerBase { address: usize, values: &[E], ); + + /// Update the value contained in an enriched cell. The derived value will be recalculated. + fn enriched_cell_write(cell: &mut Self::EnrichedCell, value: V::E) + where + V: EnrichedValue, + V::D: for<'a> From<&'a V::E>; } /// Manager with capabilities that require both read and write @@ -167,6 +217,16 @@ pub trait ManagerSerialise: ManagerBase { region: &Self::DynRegion, serializer: S, ) -> Result; + + /// Serialise the contents of the enriched cell. + fn serialise_enriched_cell( + cell: &Self::EnrichedCell, + serializer: S, + ) -> Result + where + V: EnrichedValue, + V::E: serde::Serialize, + S: serde::Serializer; } /// Manager with the ability to deserialise regions @@ -185,6 +245,15 @@ pub trait ManagerDeserialise: ManagerBase { fn deserialise_dyn_region<'de, const LEN: usize, D: serde::Deserializer<'de>>( deserializer: D, ) -> Result, D::Error>; + + /// Deserialise an enriched cell. + fn deserialise_enriched_cell<'de, V, D: serde::Deserializer<'de>>( + deserializer: D, + ) -> Result, D::Error> + where + V: EnrichedValue, + V::E: serde::Deserialize<'de>, + V::D: for<'a> From<&'a V::E>; } /// Manager with the ability to clone regions @@ -196,15 +265,26 @@ pub trait ManagerClone: ManagerBase { /// Clone the dynamic region. fn clone_dyn_region(region: &Self::DynRegion) -> Self::DynRegion; + + /// Clone the enriched cell. + fn clone_enriched_cell(cell: &Self::EnrichedCell) -> Self::EnrichedCell + where + V: EnrichedValue, + V::E: Copy, + V::D: Copy; } /// Manager wrapper around `M` whose regions are immutable references to regions of `M` -pub struct Ref<'backend, M>(std::marker::PhantomData<&'backend M>); +pub struct Ref<'backend, M>(std::marker::PhantomData); impl<'backend, M: ManagerBase> ManagerBase for Ref<'backend, M> { type Region = &'backend M::Region; type DynRegion = &'backend M::DynRegion; + + type EnrichedCell = &'backend M::EnrichedCell; + + type ManagerRoot = M::ManagerRoot; } impl ManagerSerialise for Ref<'_, M> { @@ -221,6 +301,16 @@ impl ManagerSerialise for Ref<'_, M> { ) -> Result { M::serialise_dyn_region(region, serializer) } + + fn serialise_enriched_cell( + cell: &Self::EnrichedCell, + serializer: S, + ) -> Result + where + V::E: serde::Serialize, + { + M::serialise_enriched_cell(cell, serializer) + } } impl ManagerRead for Ref<'_, M> { @@ -250,6 +340,25 @@ impl ManagerRead for Ref<'_, M> { ) { M::dyn_region_read_all(region, address, values) } + + fn enriched_cell_read( + cell: &Self::EnrichedCell, + ) -> (V::E, V::D) + where + V::D: for<'a> From<&'a V::E> + Copy, + V::E: Copy, + { + M::enriched_cell_read(cell) + } + + fn enriched_cell_ref( + cell: &Self::EnrichedCell, + ) -> (&V::E, &V::D) + where + V::D: for<'a> From<&'a V::E>, + { + M::enriched_cell_ref(cell) + } } #[cfg(test)] diff --git a/src/riscv/lib/src/state_backend/owned_backend.rs b/src/riscv/lib/src/state_backend/owned_backend.rs index 2aa2ac32cf1b..ed8512723fc4 100644 --- a/src/riscv/lib/src/state_backend/owned_backend.rs +++ b/src/riscv/lib/src/state_backend/owned_backend.rs @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MIT use super::{ - AllocatedOf, Elem, Layout, ManagerAlloc, ManagerBase, ManagerClone, ManagerDeserialise, - ManagerRead, ManagerReadWrite, ManagerSerialise, ManagerWrite, StaticCopy, + AllocatedOf, Elem, EnrichedValue, Layout, ManagerAlloc, ManagerBase, ManagerClone, + ManagerDeserialise, ManagerRead, ManagerReadWrite, ManagerSerialise, ManagerWrite, StaticCopy, }; use serde::ser::SerializeTuple; use std::{ @@ -28,6 +28,10 @@ impl ManagerBase for Owned { type Region = [E; LEN]; type DynRegion = Box<[u8; LEN]>; + + type EnrichedCell = (V::E, V::D); + + type ManagerRoot = Self; } impl ManagerAlloc for Owned { @@ -47,6 +51,14 @@ impl ManagerAlloc for Owned { Box::from_raw(alloc.cast()) } } + + fn allocate_enriched_cell(&mut self, value: V::E) -> Self::EnrichedCell + where + V::D: for<'a> From<&'a V::E>, + { + let derived = V::D::::from(&value); + (value, derived) + } } impl ManagerRead for Owned { @@ -98,6 +110,18 @@ impl ManagerRead for Owned { elem.from_stored_in_place(); } } + + fn enriched_cell_read(cell: &Self::EnrichedCell) -> (V::E, V::D) + where + V::E: Copy, + V::D: Copy, + { + *cell + } + + fn enriched_cell_ref(cell: &Self::EnrichedCell) -> (&V::E, &V::D) { + (&cell.0, &cell.1) + } } impl ManagerWrite for Owned { @@ -150,6 +174,16 @@ impl ManagerWrite for Owned { } } } + + fn enriched_cell_write(cell: &mut Self::EnrichedCell, value: V::E) + where + V::D: for<'a> From<&'a V::E>, + { + let derived = V::D::from(&value); + + cell.0 = value; + cell.1 = derived; + } } impl ManagerReadWrite for Owned { @@ -191,6 +225,17 @@ impl ManagerSerialise for Owned { ) -> Result { serializer.serialize_bytes(region.as_slice()) } + + fn serialise_enriched_cell( + cell: &Self::EnrichedCell, + serializer: S, + ) -> Result + where + V::E: serde::Serialize, + { + use serde::Serialize; + cell.0.serialize(serializer) + } } impl ManagerDeserialise for Owned { @@ -261,6 +306,19 @@ impl ManagerDeserialise for Owned { vec.try_into() .map_err(|_err| serde::de::Error::custom("Dynamic region of mismatching length")) } + + fn deserialise_enriched_cell<'de, V: EnrichedValue, D: serde::Deserializer<'de>>( + deserializer: D, + ) -> Result, D::Error> + where + V::E: serde::Deserialize<'de>, + V::D: for<'a> From<&'a V::E>, + { + use serde::Deserialize; + let value = V::E::deserialize(deserializer)?; + let derived = V::D::::from(&value); + Ok((value, derived)) + } } impl ManagerClone for Owned { @@ -274,12 +332,23 @@ impl ManagerClone for Owned { fn clone_dyn_region(region: &Self::DynRegion) -> Self::DynRegion { region.clone() } + + fn clone_enriched_cell(cell: &Self::EnrichedCell) -> Self::EnrichedCell + where + V::E: Copy, + V::D: Copy, + { + #[allow(clippy::clone_on_copy)] + cell.clone() + } } #[cfg(test)] pub mod test_helpers { use super::*; - use crate::state_backend::{test_helpers::TestBackendFactory, Cell, Cells, DynCells}; + use crate::state_backend::{ + test_helpers::TestBackendFactory, Cell, Cells, DynCells, EnrichedCell, + }; /// Test backend factory for the owned state manager pub struct OwnedTestBackendFactory; @@ -345,6 +414,45 @@ pub mod test_helpers { }); } + /// Ensure [`EnrichedCell`] can be serialised and deserialised in a consistent way. + #[test] + fn enriched_cell_serialise() { + pub struct Enriching; + pub struct Fun(Box u64>); + + impl EnrichedValue for Enriching { + type E = u64; + type D = Fun; + } + + impl<'a> From<&'a u64> for Fun { + fn from(value: &'a u64) -> Self { + let value = *value; + Self(Box::new(move |x| value.wrapping_add(x))) + } + } + + proptest::proptest!(|(value: u64)| { + let mut cell: EnrichedCell = EnrichedCell::bind((0u64, Fun::from(&0))); + cell.write(value); + + assert_eq!(value, *cell.read_ref().0); + let bytes = bincode::serialize(&cell).unwrap(); + + let cell_after: EnrichedCell = bincode::deserialize(&bytes).unwrap(); + + for i in 0..5 { + assert_eq!(cell.read_ref().0, cell_after.read_ref().0); + + let fun = cell.read_ref().1; + let fun_after = cell_after.read_ref().1; + + assert_eq!(value.wrapping_add(i), (fun.0)(i)); + assert_eq!((fun.0)(i), (fun_after.0)(i)); + } + }); + } + /// Ensure that [`Cell`] serialises in a way that represents the underlying element /// directly instead of wrapping it into an array (as it is an array under the hood). #[test] diff --git a/src/riscv/lib/src/state_backend/region.rs b/src/riscv/lib/src/state_backend/region.rs index c0f07ad397e4..07bfdae5f045 100644 --- a/src/riscv/lib/src/state_backend/region.rs +++ b/src/riscv/lib/src/state_backend/region.rs @@ -5,12 +5,90 @@ use super::{ hash::{self, Hash, HashError, HashWriter, RootHashable}, - Elem, ManagerBase, ManagerClone, ManagerDeserialise, ManagerRead, ManagerReadWrite, - ManagerSerialise, ManagerWrite, Ref, + Elem, EnrichedValue, ManagerBase, ManagerClone, ManagerDeserialise, ManagerRead, + ManagerReadWrite, ManagerSerialise, ManagerWrite, Ref, }; use crate::storage::binary; +use std::borrow::Borrow; use std::num::NonZeroUsize; +/// Link a stored value directly with a derived value - +/// that would either be expensive to compute each time, or cannot +/// itself be stored. +/// +/// Only the value of `E` forms part of the 'state' for the purposes of +/// commitments etc. +pub struct EnrichedCell { + cell: M::EnrichedCell, +} + +impl EnrichedCell { + /// Bind this state to the enriched cell. + pub fn bind(cell: M::EnrichedCell) -> Self { + Self { cell } + } + + /// Obtain a structure with references to the bound enriched cell of this type. + pub fn struct_ref(&self) -> EnrichedCell> { + EnrichedCell { + cell: self.cell.borrow(), + } + } + + /// Write the value back to the enriched cell. + /// + /// Reading the new value will produce the new derived value also. + pub fn write(&mut self, value: V::E) + where + M: ManagerWrite, + V::D: for<'a> From<&'a V::E>, + { + M::enriched_cell_write(&mut self.cell, value) + } + + /// Read the value & derived value from the enriched cell. + pub fn read(&self) -> (V::E, V::D) + where + M: ManagerRead, + V::E: Copy, + V::D: for<'a> From<&'a V::E> + Copy, + { + M::enriched_cell_read(&self.cell) + } + + /// Obtain references to the value & derived value contained + /// within the cell. + pub fn read_ref(&self) -> (&V::E, &V::D) + where + M: ManagerRead, + V::D: for<'a> From<&'a V::E>, + { + M::enriched_cell_ref(&self.cell) + } +} + +impl Clone for EnrichedCell +where + V::E: Copy, + V::D: Copy, +{ + fn clone(&self) -> Self { + Self { + cell: M::clone_enriched_cell(&self.cell), + } + } +} + +impl PartialEq for EnrichedCell +where + V::E: PartialEq, + V::D: for<'a> From<&'a V::E>, +{ + fn eq(&self, other: &Self) -> bool { + M::enriched_cell_ref(&self.cell).0 == M::enriched_cell_ref(&other.cell).0 + } +} + /// Single element of type `E` #[repr(transparent)] pub struct Cell { @@ -274,6 +352,27 @@ impl serde::Serializ } } +impl serde::Serialize for EnrichedCell +where + V::E: serde::Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + M::serialise_enriched_cell(&self.cell, serializer) + } +} + +impl RootHashable for EnrichedCell +where + V::E: serde::Serialize, +{ + fn hash(&self) -> Result { + Hash::blake2b_hash(self) + } +} + impl<'de, E: serde::Deserialize<'de>, const LEN: usize, M: ManagerDeserialise> serde::Deserialize<'de> for Cells { @@ -286,6 +385,20 @@ impl<'de, E: serde::Deserialize<'de>, const LEN: usize, M: ManagerDeserialise> } } +impl<'de, V: EnrichedValue, M: ManagerDeserialise> serde::Deserialize<'de> for EnrichedCell +where + V::E: serde::Deserialize<'de>, + V::D: for<'a> From<&'a V::E>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let cell = M::deserialise_enriched_cell(deserializer)?; + Ok(Self { cell }) + } +} + impl RootHashable for Cells { fn hash(&self) -> Result { Hash::blake2b_hash(self) -- GitLab From dbe89469d2c493dfc0d7250673a56c33ab0ec655 Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Mon, 25 Nov 2024 10:05:09 +0000 Subject: [PATCH 2/2] RISC-V: additional trait for capturing derive in EnrichedCell This allows a more simple specification of the trait bounds, rather than relying on threading `V::D: for<'a> From<&'a V::E>` --- .../lib/src/machine_state/block_cache.rs | 4 +- src/riscv/lib/src/state_backend.rs | 60 +++++++++++++------ .../lib/src/state_backend/owned_backend.rs | 37 +++++++----- src/riscv/lib/src/state_backend/region.rs | 31 ++++++---- 4 files changed, 88 insertions(+), 44 deletions(-) diff --git a/src/riscv/lib/src/machine_state/block_cache.rs b/src/riscv/lib/src/machine_state/block_cache.rs index 093ad9823c2c..782022d30f46 100644 --- a/src/riscv/lib/src/machine_state/block_cache.rs +++ b/src/riscv/lib/src/machine_state/block_cache.rs @@ -80,9 +80,9 @@ use super::{bus::Address, ProgramCounterUpdate}; use crate::cache_utils::FenceCounter; use crate::cache_utils::Sizes; use crate::default::ConstDefault; -use crate::state_backend::{self, ManagerAlloc, ManagerClone}; use crate::state_backend::{ - AllocatedOf, Atom, Cell, ManagerBase, ManagerRead, ManagerReadWrite, ManagerWrite, Ref, + self, AllocatedOf, Atom, Cell, ManagerAlloc, ManagerBase, ManagerClone, ManagerRead, + ManagerReadWrite, ManagerWrite, Ref, }; use crate::traps::{EnvironException, Exception}; use std::marker::PhantomData; diff --git a/src/riscv/lib/src/state_backend.rs b/src/riscv/lib/src/state_backend.rs index 98ac0aacc4ae..8634ea7d183b 100644 --- a/src/riscv/lib/src/state_backend.rs +++ b/src/riscv/lib/src/state_backend.rs @@ -76,11 +76,29 @@ pub use region::*; /// This derived value does not form part of any stored state/commitments. pub trait EnrichedValue: 'static { type E: 'static; - type D; + type D: Sized; +} + +/// Specifies that there exists a path to derive `V::D` from `&V::E`, +/// for a given manager. +pub trait EnrichedValueLinked: EnrichedValue { + /// Construct the derived value from the stored value, maps to + /// the `From` trait by default. + fn derive(v: &Self::E) -> Self::D; +} + +impl EnrichedValueLinked for Value +where + Value: EnrichedValue, + Value::D: for<'a> From<&'a Value::E>, +{ + fn derive(v: &Self::E) -> Self::D { + v.into() + } } /// Manager of the state backend storage -pub trait ManagerBase: Sized { +pub trait ManagerBase { /// Region that has been allocated in the state storage type Region; @@ -119,8 +137,7 @@ pub trait ManagerAlloc: 'static + ManagerReadWrite { /// Allocate an enriched cell. fn allocate_enriched_cell(&mut self, init_value: V::E) -> Self::EnrichedCell where - V: EnrichedValue, - V::D: for<'a> From<&'a V::E>; + V: EnrichedValueLinked; } /// Manager with read capabilities @@ -150,15 +167,20 @@ pub trait ManagerRead: ManagerBase { /// Read the value, and derived value, contained in the enriched cell. fn enriched_cell_read(cell: &Self::EnrichedCell) -> (V::E, V::D) where - V: EnrichedValue, + V: EnrichedValueLinked, V::E: Copy, - V::D: for<'a> From<&'a V::E> + Copy; + V::D: Copy; /// Obtain a refernce to the value, and derived value, contained in the enriched cell. fn enriched_cell_ref(cell: &Self::EnrichedCell) -> (&V::E, &V::D) + where + V: EnrichedValueLinked; + + /// Obtain a refernce to the value, and derived value, contained in the enriched cell. + fn enriched_cell_read_stored(cell: &Self::EnrichedCell) -> V::E where V: EnrichedValue, - V::D: for<'a> From<&'a V::E>; + V::E: Copy; } /// Manager with write capabilities @@ -190,8 +212,7 @@ pub trait ManagerWrite: ManagerBase { /// Update the value contained in an enriched cell. The derived value will be recalculated. fn enriched_cell_write(cell: &mut Self::EnrichedCell, value: V::E) where - V: EnrichedValue, - V::D: for<'a> From<&'a V::E>; + V: EnrichedValueLinked; } /// Manager with capabilities that require both read and write @@ -251,9 +272,8 @@ pub trait ManagerDeserialise: ManagerBase { deserializer: D, ) -> Result, D::Error> where - V: EnrichedValue, - V::E: serde::Deserialize<'de>, - V::D: for<'a> From<&'a V::E>; + V: EnrichedValueLinked, + V::E: serde::Deserialize<'de>; } /// Manager with the ability to clone regions @@ -341,23 +361,29 @@ impl ManagerRead for Ref<'_, M> { M::dyn_region_read_all(region, address, values) } - fn enriched_cell_read( + fn enriched_cell_read>( cell: &Self::EnrichedCell, ) -> (V::E, V::D) where - V::D: for<'a> From<&'a V::E> + Copy, + V::D: Copy, V::E: Copy, { M::enriched_cell_read(cell) } - fn enriched_cell_ref( + fn enriched_cell_ref>( cell: &Self::EnrichedCell, ) -> (&V::E, &V::D) +where { + M::enriched_cell_ref(cell) + } + + fn enriched_cell_read_stored(cell: &Self::EnrichedCell) -> V::E where - V::D: for<'a> From<&'a V::E>, + V: EnrichedValue, + V::E: Copy, { - M::enriched_cell_ref(cell) + M::enriched_cell_read_stored(cell) } } diff --git a/src/riscv/lib/src/state_backend/owned_backend.rs b/src/riscv/lib/src/state_backend/owned_backend.rs index ed8512723fc4..be955101c19c 100644 --- a/src/riscv/lib/src/state_backend/owned_backend.rs +++ b/src/riscv/lib/src/state_backend/owned_backend.rs @@ -3,8 +3,9 @@ // SPDX-License-Identifier: MIT use super::{ - AllocatedOf, Elem, EnrichedValue, Layout, ManagerAlloc, ManagerBase, ManagerClone, - ManagerDeserialise, ManagerRead, ManagerReadWrite, ManagerSerialise, ManagerWrite, StaticCopy, + AllocatedOf, Elem, EnrichedValue, EnrichedValueLinked, Layout, ManagerAlloc, ManagerBase, + ManagerClone, ManagerDeserialise, ManagerRead, ManagerReadWrite, ManagerSerialise, + ManagerWrite, StaticCopy, }; use serde::ser::SerializeTuple; use std::{ @@ -52,11 +53,11 @@ impl ManagerAlloc for Owned { } } - fn allocate_enriched_cell(&mut self, value: V::E) -> Self::EnrichedCell - where - V::D: for<'a> From<&'a V::E>, - { - let derived = V::D::::from(&value); + fn allocate_enriched_cell>( + &mut self, + value: V::E, + ) -> Self::EnrichedCell { + let derived = V::derive(&value); (value, derived) } } @@ -122,6 +123,14 @@ impl ManagerRead for Owned { fn enriched_cell_ref(cell: &Self::EnrichedCell) -> (&V::E, &V::D) { (&cell.0, &cell.1) } + + fn enriched_cell_read_stored(cell: &Self::EnrichedCell) -> V::E + where + V: EnrichedValue, + V::E: Copy, + { + cell.0 + } } impl ManagerWrite for Owned { @@ -175,11 +184,11 @@ impl ManagerWrite for Owned { } } - fn enriched_cell_write(cell: &mut Self::EnrichedCell, value: V::E) + fn enriched_cell_write(cell: &mut Self::EnrichedCell, value: V::E) where - V::D: for<'a> From<&'a V::E>, + V: EnrichedValueLinked, { - let derived = V::D::from(&value); + let derived = V::derive(&value); cell.0 = value; cell.1 = derived; @@ -307,16 +316,16 @@ impl ManagerDeserialise for Owned { .map_err(|_err| serde::de::Error::custom("Dynamic region of mismatching length")) } - fn deserialise_enriched_cell<'de, V: EnrichedValue, D: serde::Deserializer<'de>>( + fn deserialise_enriched_cell<'de, V, D: serde::Deserializer<'de>>( deserializer: D, ) -> Result, D::Error> where + V: EnrichedValueLinked, V::E: serde::Deserialize<'de>, - V::D: for<'a> From<&'a V::E>, { use serde::Deserialize; let value = V::E::deserialize(deserializer)?; - let derived = V::D::::from(&value); + let derived = V::derive(&value); Ok((value, derived)) } } @@ -422,7 +431,7 @@ pub mod test_helpers { impl EnrichedValue for Enriching { type E = u64; - type D = Fun; + type D = Fun; } impl<'a> From<&'a u64> for Fun { diff --git a/src/riscv/lib/src/state_backend/region.rs b/src/riscv/lib/src/state_backend/region.rs index 07bfdae5f045..b7bc015dd29b 100644 --- a/src/riscv/lib/src/state_backend/region.rs +++ b/src/riscv/lib/src/state_backend/region.rs @@ -5,8 +5,8 @@ use super::{ hash::{self, Hash, HashError, HashWriter, RootHashable}, - Elem, EnrichedValue, ManagerBase, ManagerClone, ManagerDeserialise, ManagerRead, - ManagerReadWrite, ManagerSerialise, ManagerWrite, Ref, + Elem, EnrichedValue, EnrichedValueLinked, ManagerBase, ManagerClone, ManagerDeserialise, + ManagerRead, ManagerReadWrite, ManagerSerialise, ManagerWrite, Ref, }; use crate::storage::binary; use std::borrow::Borrow; @@ -16,8 +16,7 @@ use std::num::NonZeroUsize; /// that would either be expensive to compute each time, or cannot /// itself be stored. /// -/// Only the value of `E` forms part of the 'state' for the purposes of -/// commitments etc. +/// Only the value of `V::E` forms part of the 'state' for the purposes of commitments etc. pub struct EnrichedCell { cell: M::EnrichedCell, } @@ -41,7 +40,7 @@ impl EnrichedCell { pub fn write(&mut self, value: V::E) where M: ManagerWrite, - V::D: for<'a> From<&'a V::E>, + V: EnrichedValueLinked, { M::enriched_cell_write(&mut self.cell, value) } @@ -50,8 +49,9 @@ impl EnrichedCell { pub fn read(&self) -> (V::E, V::D) where M: ManagerRead, + V: EnrichedValueLinked, V::E: Copy, - V::D: for<'a> From<&'a V::E> + Copy, + V::D: Copy, { M::enriched_cell_read(&self.cell) } @@ -61,10 +61,19 @@ impl EnrichedCell { pub fn read_ref(&self) -> (&V::E, &V::D) where M: ManagerRead, - V::D: for<'a> From<&'a V::E>, + V: EnrichedValueLinked, { M::enriched_cell_ref(&self.cell) } + + /// Read only the stored value from the enriched cell. + pub fn read_stored(&self) -> V::E + where + M: ManagerRead, + V::E: Copy, + { + M::enriched_cell_read_stored(&self.cell) + } } impl Clone for EnrichedCell @@ -79,10 +88,10 @@ where } } -impl PartialEq for EnrichedCell +impl PartialEq for EnrichedCell where + V: EnrichedValueLinked, V::E: PartialEq, - V::D: for<'a> From<&'a V::E>, { fn eq(&self, other: &Self) -> bool { M::enriched_cell_ref(&self.cell).0 == M::enriched_cell_ref(&other.cell).0 @@ -385,10 +394,10 @@ impl<'de, E: serde::Deserialize<'de>, const LEN: usize, M: ManagerDeserialise> } } -impl<'de, V: EnrichedValue, M: ManagerDeserialise> serde::Deserialize<'de> for EnrichedCell +impl<'de, V, M: ManagerDeserialise> serde::Deserialize<'de> for EnrichedCell where + V: EnrichedValueLinked, V::E: serde::Deserialize<'de>, - V::D: for<'a> From<&'a V::E>, { fn deserialize(deserializer: D) -> Result where -- GitLab