Skip to content

Commit

Permalink
feat: added to/from_bytes for ProvingKey and VerifyingKey
Browse files Browse the repository at this point in the history
* add `pack`/`unpack` helper functions between `&[bool]` and `u8`.

Extracted from privacy-scaling-explorations@2c7f288

Co-authored-by: Carlos Pérez <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
  • Loading branch information
daira and CPerezz committed May 1, 2023
1 parent bae3053 commit 58e797d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 12 deletions.
19 changes: 19 additions & 0 deletions halo2_proofs/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
49 changes: 37 additions & 12 deletions halo2_proofs/src/plonk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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)
})
Expand All @@ -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>,
Expand Down
4 changes: 4 additions & 0 deletions halo2_proofs/src/plonk/permutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 58e797d

Please sign in to comment.