feat: added `to/from_bytes` for `ProvingKey` and `VerifyingKey`

* add `pack`/`unpack` helper functions between `&[bool]` and `u8`.

Extracted from 2c7f288932

Co-authored-by: Carlos Pérez <37264926+CPerezz@users.noreply.github.com>
Signed-off-by: Daira Emma Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Emma Hopwood 2023-05-01 16:23:49 +01:00
parent bae30538b5
commit 58e797da93
3 changed files with 60 additions and 12 deletions

View File

@ -14,3 +14,22 @@ pub(crate) trait CurveRead: CurveAffine {
}
impl<C: CurveAffine> CurveRead for C {}
/// Converts a slice of `bool` into a `u8`.
///
/// Panics if the slice has length greater than 8.
pub fn pack(bits: &[bool]) -> u8 {
let mut value = 0u8;
assert!(bits.len() <= 8);
for (bit_index, bit) in bits.iter().enumerate() {
value |= (*bit as u8) << bit_index;
}
value
}
/// Writes the first `bits.len()` bits of a `u8` into `bits`.
pub fn unpack(byte: u8, bits: &mut [bool]) {
for (bit_index, bit) in bits.iter_mut().enumerate() {
*bit = (byte >> bit_index) & 1 == 1;
}
}

View File

@ -9,6 +9,7 @@ use blake2b_simd::Params as Blake2bParams;
use group::ff::{Field, FromUniformBytes, PrimeField};
use crate::arithmetic::CurveAffine;
use crate::helpers::{pack, unpack, CurveRead};
use crate::poly::{
commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff,
PinnedEvaluationDomain, Polynomial,
@ -33,7 +34,6 @@ pub use keygen::*;
pub use prover::*;
pub use verifier::*;
use crate::helpers::CurveRead;
use std::io;
/// This is a verifying key which allows for the verification of proofs for a
@ -69,19 +69,16 @@ where
// write self.selectors
writer.write_all(&(u32::try_from(self.selectors.len()).unwrap()).to_le_bytes())?;
for selector in &self.selectors {
let mut selector_bytes = vec![0u8; (selector.len() + 7) / 8];
for (i, selector_idx) in selector.iter().enumerate() {
let byte_index = i / 8;
let bit_index = i % 8;
selector_bytes[byte_index] |= (*selector_idx as u8) << bit_index;
// since `selector` is filled with `bool`, we pack them 8 at a time into bytes and then write
for bits in selector.chunks(8) {
writer.write_all(&[pack(bits)])?;
}
writer.write_all(&selector_bytes)?;
}
Ok(())
}
/// Reads a verification key from a buffer.
/// Reads a verifying key from a buffer.
pub fn read<R: io::Read, ConcreteCircuit: Circuit<C::Scalar>>(
reader: &mut R,
params: &Params<C>,
@ -122,10 +119,8 @@ where
.map(|mut selector| {
let mut selector_bytes = vec![0u8; (selector.len() + 7) / 8];
reader.read_exact(&mut selector_bytes)?;
for (i, selector_idx) in selector.iter_mut().enumerate() {
let byte_index = i / 8;
let bit_index = i % 8;
*selector_idx = (selector_bytes[byte_index] >> bit_index) & 1 == 1;
for (bits, byte) in selector.chunks_mut(8).zip(selector_bytes) {
unpack(byte, bits);
}
Ok(selector)
})
@ -142,6 +137,36 @@ where
))
}
/// Writes a verifying key to a vector of bytes.
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::<u8>::with_capacity(self.bytes_length());
self.write(&mut bytes)
.expect("Writing to vector should not fail");
bytes
}
/// Reads a verifying key from a slice of bytes.
pub fn from_bytes<ConcreteCircuit: Circuit<C::Scalar>>(
mut bytes: &[u8],
params: &Params<C>,
) -> io::Result<Self> {
Self::read::<_, ConcreteCircuit>(&mut bytes, params)
}
/// Gets the total number of bytes in the serialization of `self`.
fn bytes_length(&self) -> usize {
1 + 4
+ self.fixed_commitments.len() * C::default().to_bytes().as_ref().len()
+ self.permutation.bytes_length()
+ 4
+ self.selectors.len()
* self
.selectors
.get(0)
.map(|selector| (selector.len() + 7) / 8)
.unwrap_or(0)
}
fn from_parts(
domain: EvaluationDomain<C::Scalar>,
fixed_commitments: Vec<C>,

View File

@ -103,6 +103,10 @@ impl<C: CurveAffine> VerifyingKey<C> {
.collect::<io::Result<_>>()?;
Ok(VerifyingKey { commitments })
}
pub(crate) fn bytes_length(&self) -> usize {
4 + self.commitments.len() * C::default().to_bytes().as_ref().len()
}
}
/// The proving key for a single permutation argument.