diff --git a/nimue/src/errors.rs b/nimue/src/errors.rs index 0a5bacd..95ad642 100644 --- a/nimue/src/errors.rs +++ b/nimue/src/errors.rs @@ -17,7 +17,7 @@ /// An error to signal that the verification equation has failed. Destined for end users. /// /// A [`core::Result::Result`] wrapper called [`ProofResult`] (having error fixed to [`ProofError`]) is also provided. -use std::{borrow::Borrow, error::Error, fmt::Display}; +use std::{borrow::Borrow, error::Error, fmt::Display, string::FromUtf8Error}; /// Signals an invalid IO pattern. /// @@ -82,3 +82,9 @@ impl From for IOPatternError { IOPatternError(value.to_string()) } } + +impl From for IOPatternError { + fn from(value: FromUtf8Error) -> Self { + Self(value.to_string()) + } +} diff --git a/nimue/src/hash/keccak.rs b/nimue/src/hash/keccak.rs index 4d8949a..748c649 100644 --- a/nimue/src/hash/keccak.rs +++ b/nimue/src/hash/keccak.rs @@ -16,7 +16,7 @@ fn transmute_state(st: &mut AlignedKeccakState) -> &mut [u64; 25] { /// This is a wrapper around 200-byte buffer that's always 8-byte aligned /// to make pointers to it safely convertible to pointers to [u64; 25] /// (since u64 words must be 8-byte aligned) -#[derive(Clone, Zeroize, ZeroizeOnDrop)] +#[derive(Clone, Zeroize, ZeroizeOnDrop, PartialEq, Eq)] #[repr(align(8))] pub struct AlignedKeccakState([u8; 200]); diff --git a/nimue/src/hash/sponge.rs b/nimue/src/hash/sponge.rs index 985af62..04d9a67 100644 --- a/nimue/src/hash/sponge.rs +++ b/nimue/src/hash/sponge.rs @@ -37,7 +37,7 @@ pub trait Sponge: Zeroize + Default + Clone + AsRef<[Self::U]> + AsMut<[Self::U] } /// A cryptographic sponge. -#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)] +#[derive(Clone, Default, Zeroize, ZeroizeOnDrop, PartialEq, Eq)] pub struct DuplexSponge { sponge: C, absorb_pos: usize, diff --git a/nimue/src/iopattern.rs b/nimue/src/iopattern.rs index 939e8d0..fa89106 100644 --- a/nimue/src/iopattern.rs +++ b/nimue/src/iopattern.rs @@ -34,7 +34,7 @@ const SEP_BYTE: &str = "\0"; /// The struct [`IOPattern`] guarantees the creation of a valid IO Pattern string, whose lengths are coherent with the types described in the protocol. No information about the types themselves is stored in an IO Pattern. /// This means that [`Merlin`][`crate::Merlin`] or [`Arthur`][`crate::Arthur`] instances can generate successfully a protocol transcript respecting the length constraint but not the types. See [issue #6](https://github.com/arkworks-rs/nimue/issues/6) for a discussion on the topic. -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] pub struct IOPattern where U: Unit, @@ -139,6 +139,17 @@ impl, U: Unit> IOPattern { self.io.as_bytes() } + /// Return the IO Pattern as owned bytes. + pub fn to_bytes(&self) -> Vec { + self.io.clone().into_bytes() + } + + /// Construct an IO Pattern from serialized bytes (usually output from `Self::to_bytes()`) + pub fn from_bytes(bytes: Vec) -> Result { + let io = String::from_utf8(bytes)?; + Ok(Self::from_string(io)) + } + /// Parse the givern IO Pattern into a sequence of [`Op`]'s. pub(crate) fn finalize(&self) -> VecDeque { // Guaranteed to succeed as instances are all valid iopatterns diff --git a/nimue/src/tests.rs b/nimue/src/tests.rs index 4295dba..78295fc 100644 --- a/nimue/src/tests.rs +++ b/nimue/src/tests.rs @@ -16,6 +16,8 @@ fn test_iopattern() { // test that the byte separator is always added let iop = IOPattern::::new("example.com"); assert!(iop.as_bytes().starts_with(b"example.com")); + + assert_eq!(IOPattern::from_bytes(iop.to_bytes()).unwrap(), iop); } /// Test Merlin's rng is not doing completely stupid things.