diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index e9b69b88..caf3a7f8 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -117,7 +117,9 @@ impl, C: GenericConfig, const D: usize> common_data: &CommonCircuitData, ) -> anyhow::Result { let mut buffer = Buffer::new(bytes); - let proof = buffer.read_proof_with_public_inputs(common_data)?; + let proof = buffer + .read_proof_with_public_inputs(common_data) + .map_err(anyhow::Error::msg)?; Ok(proof) } } @@ -233,7 +235,9 @@ impl, C: GenericConfig, const D: usize> pub fn to_bytes(&self) -> Vec { let mut buffer = Vec::new(); - let _ = buffer.write_compressed_proof_with_public_inputs(self); + buffer + .write_compressed_proof_with_public_inputs(self) + .expect("Writing to a byte-vector cannot fail."); buffer } @@ -243,7 +247,9 @@ impl, C: GenericConfig, const D: usize> common_data: &CommonCircuitData, ) -> anyhow::Result { let mut buffer = Buffer::new(bytes); - let proof = buffer.read_compressed_proof_with_public_inputs(common_data)?; + let proof = buffer + .read_compressed_proof_with_public_inputs(common_data) + .map_err(anyhow::Error::msg)?; Ok(proof) } } diff --git a/plonky2/src/util/serialization.rs b/plonky2/src/util/serialization.rs index ce56709d..712e936a 100644 --- a/plonky2/src/util/serialization.rs +++ b/plonky2/src/util/serialization.rs @@ -1,8 +1,8 @@ use alloc::vec; use alloc::vec::Vec; use core::convert::Infallible; -#[cfg(feature = "std")] -use std::io::{self, Cursor, Read as _, Write as _}; +use core::fmt::{Debug, Display, Formatter}; +use core::mem::size_of; use hashbrown::HashMap; @@ -23,69 +23,65 @@ use crate::plonk::proof::{ CompressedProof, CompressedProofWithPublicInputs, OpeningSet, Proof, ProofWithPublicInputs, }; -/// Buffer Position -pub trait Position { - /// Returns the position of the buffer. - fn position(&self) -> u64; +/// A no_std compatible variant of `std::io::Error` +#[derive(Debug)] +pub struct IoError; + +impl Display for IoError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + Debug::fmt(self, f) + } } -/// Buffer Size -pub trait Size { - /// Returns the length of `self`. - fn len(&self) -> usize; +/// A no_std compatible variant of `std::io::Result` +pub type IoResult = Result; - /// Returns `true` if `self` has length zero. - #[inline] +/// A `Read` which is able to report how many bytes are remaining. +pub trait Remaining: Read { + /// Returns the number of bytes remaining in the buffer. + fn remaining(&self) -> usize; + + /// Returns whether zero bytes are remaining. fn is_empty(&self) -> bool { - self.len() == 0 + self.remaining() == 0 } } -impl Size for Vec { - #[inline] - fn len(&self) -> usize { - self.len() - } -} - -/// Reading +/// Similar to `std::io::Read`, but works with no_std. pub trait Read { - /// Error Type - type Error; - /// Reads exactly the length of `bytes` from `self` and writes it to `bytes`. - fn read_exact(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error>; + fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()>; /// Reads a `u8` value from `self`. #[inline] - fn read_u8(&mut self) -> Result { - let mut buf = [0; core::mem::size_of::()]; + fn read_u8(&mut self) -> IoResult { + let mut buf = [0; size_of::()]; self.read_exact(&mut buf)?; Ok(buf[0]) } /// Reads a `u32` value from `self`. #[inline] - fn read_u32(&mut self) -> Result { - let mut buf = [0; core::mem::size_of::()]; + fn read_u32(&mut self) -> IoResult { + let mut buf = [0; size_of::()]; self.read_exact(&mut buf)?; Ok(u32::from_le_bytes(buf)) } /// Reads a element from the field `F` with size less than `2^64` from `self.` #[inline] - fn read_field(&mut self) -> Result + fn read_field(&mut self) -> IoResult where F: Field64, { - let mut buf = [0; core::mem::size_of::()]; + let mut buf = [0; size_of::()]; self.read_exact(&mut buf)?; Ok(F::from_canonical_u64(u64::from_le_bytes(buf))) } /// Reads a vector of elements from the field `F` from `self`. #[inline] - fn read_field_vec(&mut self, length: usize) -> Result, Self::Error> + fn read_field_vec(&mut self, length: usize) -> IoResult> where F: Field64, { @@ -96,7 +92,7 @@ pub trait Read { /// Reads an element from the field extension of `F` from `self.` #[inline] - fn read_field_ext(&mut self) -> Result + fn read_field_ext(&mut self) -> IoResult where F: Field64 + Extendable, { @@ -114,7 +110,7 @@ pub trait Read { fn read_field_ext_vec( &mut self, length: usize, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, { @@ -123,7 +119,7 @@ pub trait Read { /// Reads a hash value from `self`. #[inline] - fn read_hash(&mut self) -> Result + fn read_hash(&mut self) -> IoResult where F: RichField, H: Hasher, @@ -135,7 +131,7 @@ pub trait Read { /// Reads a value of type [`MerkleCap`] from `self` with the given `cap_height`. #[inline] - fn read_merkle_cap(&mut self, cap_height: usize) -> Result, Self::Error> + fn read_merkle_cap(&mut self, cap_height: usize) -> IoResult> where F: RichField, H: Hasher, @@ -153,7 +149,7 @@ pub trait Read { fn read_opening_set( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -182,7 +178,7 @@ pub trait Read { /// Reads a value of type [`MerkleProof`] from `self`. #[inline] - fn read_merkle_proof(&mut self) -> Result, Self::Error> + fn read_merkle_proof(&mut self) -> IoResult> where F: RichField, H: Hasher, @@ -200,7 +196,7 @@ pub trait Read { fn read_fri_initial_proof( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -239,7 +235,7 @@ pub trait Read { &mut self, arity: usize, compressed: bool, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -257,7 +253,7 @@ pub trait Read { fn read_fri_query_rounds( &mut self, common_data: &CommonCircuitData, - ) -> Result>, Self::Error> + ) -> IoResult>> where F: RichField + Extendable, C: GenericConfig, @@ -285,7 +281,7 @@ pub trait Read { fn read_fri_proof( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -312,7 +308,7 @@ pub trait Read { fn read_proof( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -337,16 +333,14 @@ pub trait Read { fn read_proof_with_public_inputs( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where - Self: Position + Size, + Self: Remaining, F: RichField + Extendable, C: GenericConfig, { let proof = self.read_proof(common_data)?; - let public_inputs = self.read_field_vec( - (self.len() - self.position() as usize) / core::mem::size_of::(), - )?; + let public_inputs = self.read_field_vec(self.remaining() / size_of::())?; Ok(ProofWithPublicInputs { proof, public_inputs, @@ -358,7 +352,7 @@ pub trait Read { fn read_compressed_fri_query_rounds( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -406,7 +400,7 @@ pub trait Read { fn read_compressed_fri_proof( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -433,7 +427,7 @@ pub trait Read { fn read_compressed_proof( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where F: RichField + Extendable, C: GenericConfig, @@ -458,16 +452,14 @@ pub trait Read { fn read_compressed_proof_with_public_inputs( &mut self, common_data: &CommonCircuitData, - ) -> Result, Self::Error> + ) -> IoResult> where - Self: Position + Size, + Self: Remaining, F: RichField + Extendable, C: GenericConfig, { let proof = self.read_compressed_proof(common_data)?; - let public_inputs = self.read_field_vec( - (self.len() - self.position() as usize) / core::mem::size_of::(), - )?; + let public_inputs = self.read_field_vec((self.remaining() as usize) / size_of::())?; Ok(CompressedProofWithPublicInputs { proof, public_inputs, @@ -481,23 +473,23 @@ pub trait Write { type Error; /// Writes all `bytes` to `self`. - fn write_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error>; + fn write_all(&mut self, bytes: &[u8]) -> IoResult<()>; /// Writes a byte `x` to `self`. #[inline] - fn write_u8(&mut self, x: u8) -> Result<(), Self::Error> { + fn write_u8(&mut self, x: u8) -> IoResult<()> { self.write_all(&[x]) } /// Writes a word `x` to `self.` #[inline] - fn write_u32(&mut self, x: u32) -> Result<(), Self::Error> { + fn write_u32(&mut self, x: u32) -> IoResult<()> { self.write_all(&x.to_le_bytes()) } /// Writes an element `x` from the field `F` to `self`. #[inline] - fn write_field(&mut self, x: F) -> Result<(), Self::Error> + fn write_field(&mut self, x: F) -> IoResult<()> where F: PrimeField64, { @@ -506,7 +498,7 @@ pub trait Write { /// Writes a vector `v` of elements from the field `F` to `self`. #[inline] - fn write_field_vec(&mut self, v: &[F]) -> Result<(), Self::Error> + fn write_field_vec(&mut self, v: &[F]) -> IoResult<()> where F: PrimeField64, { @@ -518,7 +510,7 @@ pub trait Write { /// Writes an element `x` from the field extension of `F` to `self`. #[inline] - fn write_field_ext(&mut self, x: F::Extension) -> Result<(), Self::Error> + fn write_field_ext(&mut self, x: F::Extension) -> IoResult<()> where F: RichField + Extendable, { @@ -530,10 +522,7 @@ pub trait Write { /// Writes a vector `v` of elements from the field extension of `F` to `self`. #[inline] - fn write_field_ext_vec( - &mut self, - v: &[F::Extension], - ) -> Result<(), Self::Error> + fn write_field_ext_vec(&mut self, v: &[F::Extension]) -> IoResult<()> where F: RichField + Extendable, { @@ -545,7 +534,7 @@ pub trait Write { /// Writes a hash `h` to `self`. #[inline] - fn write_hash(&mut self, h: H::Hash) -> Result<(), Self::Error> + fn write_hash(&mut self, h: H::Hash) -> IoResult<()> where F: RichField, H: Hasher, @@ -555,7 +544,7 @@ pub trait Write { /// Writes `cap`, a value of type [`MerkleCap`], to `self`. #[inline] - fn write_merkle_cap(&mut self, cap: &MerkleCap) -> Result<(), Self::Error> + fn write_merkle_cap(&mut self, cap: &MerkleCap) -> IoResult<()> where F: RichField, H: Hasher, @@ -568,10 +557,7 @@ pub trait Write { /// Writes a value `os` of type [`OpeningSet`] to `self.` #[inline] - fn write_opening_set( - &mut self, - os: &OpeningSet, - ) -> Result<(), Self::Error> + fn write_opening_set(&mut self, os: &OpeningSet) -> IoResult<()> where F: RichField + Extendable, { @@ -586,7 +572,7 @@ pub trait Write { /// Writes a value `p` of type [`MerkleProof`] to `self.` #[inline] - fn write_merkle_proof(&mut self, p: &MerkleProof) -> Result<(), Self::Error> + fn write_merkle_proof(&mut self, p: &MerkleProof) -> IoResult<()> where F: RichField, H: Hasher, @@ -608,7 +594,7 @@ pub trait Write { fn write_fri_initial_proof( &mut self, fitp: &FriInitialTreeProof, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -625,7 +611,7 @@ pub trait Write { fn write_fri_query_step( &mut self, fqs: &FriQueryStep, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -639,7 +625,7 @@ pub trait Write { fn write_fri_query_rounds( &mut self, fqrs: &[FriQueryRound], - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -658,7 +644,7 @@ pub trait Write { fn write_fri_proof( &mut self, fp: &FriProof, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -673,10 +659,7 @@ pub trait Write { /// Writes a value `proof` of type [`Proof`] to `self.` #[inline] - fn write_proof( - &mut self, - proof: &Proof, - ) -> Result<(), Self::Error> + fn write_proof(&mut self, proof: &Proof) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -693,7 +676,7 @@ pub trait Write { fn write_proof_with_public_inputs( &mut self, proof_with_pis: &ProofWithPublicInputs, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -711,7 +694,7 @@ pub trait Write { fn write_compressed_fri_query_rounds( &mut self, cfqrs: &CompressedFriQueryRounds, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -739,7 +722,7 @@ pub trait Write { fn write_compressed_fri_proof( &mut self, fp: &CompressedFriProof, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -757,7 +740,7 @@ pub trait Write { fn write_compressed_proof( &mut self, proof: &CompressedProof, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -774,7 +757,7 @@ pub trait Write { fn write_compressed_proof_with_public_inputs( &mut self, proof_with_pis: &CompressedProofWithPublicInputs, - ) -> Result<(), Self::Error> + ) -> IoResult<()> where F: RichField + Extendable, C: GenericConfig, @@ -792,7 +775,7 @@ impl Write for Vec { type Error = Infallible; #[inline] - fn write_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { + fn write_all(&mut self, bytes: &[u8]) -> IoResult<()> { self.extend_from_slice(bytes); Ok(()) } @@ -801,55 +784,42 @@ impl Write for Vec { /// Buffer #[cfg(feature = "std")] #[derive(Debug)] -pub struct Buffer(Cursor>); +pub struct Buffer { + bytes: Vec, + pos: usize, +} #[cfg(feature = "std")] impl Buffer { /// Builds a new [`Buffer`] over `buffer`. #[inline] - pub fn new(buffer: Vec) -> Self { - Self(Cursor::new(buffer)) + pub fn new(bytes: Vec) -> Self { + Self { bytes, pos: 0 } } /// Returns the inner buffer. #[inline] pub fn bytes(self) -> Vec { - self.0.into_inner() + self.bytes } } -#[cfg(feature = "std")] -impl Size for Buffer { - #[inline] - fn len(&self) -> usize { - self.0.get_ref().len() +impl Remaining for Buffer { + fn remaining(&self) -> usize { + self.bytes.len() - self.pos } } -#[cfg(feature = "std")] -impl Position for Buffer { - #[inline] - fn position(&self) -> u64 { - self.0.position() - } -} - -#[cfg(feature = "std")] impl Read for Buffer { - type Error = io::Error; - #[inline] - fn read_exact(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.0.read_exact(bytes) - } -} - -#[cfg(feature = "std")] -impl Write for Buffer { - type Error = io::Error; - - #[inline] - fn write_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { - self.0.write_all(bytes) + fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()> { + let n = bytes.len(); + if self.remaining() < n { + Err(IoError) + } else { + bytes.copy_from_slice(&self.bytes[self.pos..][..n]); + self.pos += n; + Ok(()) + } } }