2020-08-22 13:15:39 -07:00
|
|
|
//! This module provides an implementation of a variant of (Turbo)[PLONK][plonk]
|
|
|
|
//! that is designed specifically for the polynomial commitment scheme described
|
|
|
|
//! in the [Halo][halo] paper.
|
|
|
|
//!
|
|
|
|
//! [halo]: https://eprint.iacr.org/2019/1021
|
|
|
|
//! [plonk]: https://eprint.iacr.org/2019/953
|
|
|
|
|
2021-02-11 06:30:26 -08:00
|
|
|
use blake2b_simd::Params as Blake2bParams;
|
2022-11-29 21:05:37 -08:00
|
|
|
use group::ff::{Field, FromUniformBytes, PrimeField};
|
2021-02-11 06:30:26 -08:00
|
|
|
|
2022-11-29 21:05:37 -08:00
|
|
|
use crate::arithmetic::CurveAffine;
|
2021-01-12 07:28:35 -08:00
|
|
|
use crate::poly::{
|
2022-09-15 23:15:52 -07:00
|
|
|
commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff,
|
|
|
|
PinnedEvaluationDomain, Polynomial,
|
2021-01-12 07:28:35 -08:00
|
|
|
};
|
2021-04-30 18:28:50 -07:00
|
|
|
use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript};
|
2020-08-22 13:15:39 -07:00
|
|
|
|
2021-12-09 06:52:23 -08:00
|
|
|
mod assigned;
|
2020-08-22 13:15:39 -07:00
|
|
|
mod circuit;
|
2021-05-18 09:50:09 -07:00
|
|
|
mod error;
|
2020-09-29 07:25:04 -07:00
|
|
|
mod keygen;
|
2020-11-30 22:53:20 -08:00
|
|
|
mod lookup;
|
2020-12-21 21:56:30 -08:00
|
|
|
pub(crate) mod permutation;
|
2020-12-02 07:16:37 -08:00
|
|
|
mod vanishing;
|
|
|
|
|
2020-08-22 13:15:39 -07:00
|
|
|
mod prover;
|
|
|
|
mod verifier;
|
|
|
|
|
2021-12-09 06:52:23 -08:00
|
|
|
pub use assigned::*;
|
2020-08-22 13:15:39 -07:00
|
|
|
pub use circuit::*;
|
2021-05-18 09:50:09 -07:00
|
|
|
pub use error::*;
|
2020-09-29 07:25:04 -07:00
|
|
|
pub use keygen::*;
|
2020-08-22 13:15:39 -07:00
|
|
|
pub use prover::*;
|
|
|
|
pub use verifier::*;
|
|
|
|
|
2022-09-15 23:15:52 -07:00
|
|
|
use crate::helpers::CurveRead;
|
2021-01-12 07:28:35 -08:00
|
|
|
use std::io;
|
|
|
|
|
2020-09-29 07:25:04 -07:00
|
|
|
/// This is a verifying key which allows for the verification of proofs for a
|
|
|
|
/// particular circuit.
|
2022-04-26 04:53:44 -07:00
|
|
|
#[derive(Clone, Debug)]
|
2020-09-29 07:25:04 -07:00
|
|
|
pub struct VerifyingKey<C: CurveAffine> {
|
2020-08-22 13:15:39 -07:00
|
|
|
domain: EvaluationDomain<C::Scalar>,
|
2020-08-22 15:10:27 -07:00
|
|
|
fixed_commitments: Vec<C>,
|
2021-07-02 15:20:36 -07:00
|
|
|
permutation: permutation::VerifyingKey<C>,
|
2020-09-29 07:25:04 -07:00
|
|
|
cs: ConstraintSystem<C::Scalar>,
|
2022-06-22 12:33:36 -07:00
|
|
|
/// Cached maximum degree of `cs` (which doesn't change after construction).
|
|
|
|
cs_degree: usize,
|
2022-06-22 12:25:32 -07:00
|
|
|
/// The representative of this `VerifyingKey` in transcripts.
|
|
|
|
transcript_repr: C::Scalar,
|
2022-09-15 23:15:52 -07:00
|
|
|
selectors: Vec<Vec<bool>>,
|
2020-09-29 07:25:04 -07:00
|
|
|
}
|
|
|
|
|
2022-11-29 21:05:37 -08:00
|
|
|
impl<C: CurveAffine> VerifyingKey<C>
|
|
|
|
where
|
|
|
|
C::Scalar: FromUniformBytes<64>,
|
|
|
|
{
|
2022-09-15 23:15:52 -07:00
|
|
|
/// Writes a verifying key to a buffer.
|
|
|
|
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
2023-05-01 02:41:40 -07:00
|
|
|
// Version byte that will be checked on read.
|
|
|
|
writer.write_all(&[0x01])?;
|
|
|
|
|
|
|
|
writer.write_all(&(u32::try_from(self.fixed_commitments.len()).unwrap()).to_le_bytes())?;
|
2022-09-15 23:15:52 -07:00
|
|
|
for commitment in &self.fixed_commitments {
|
|
|
|
writer.write_all(commitment.to_bytes().as_ref())?;
|
|
|
|
}
|
|
|
|
self.permutation.write(writer)?;
|
|
|
|
|
|
|
|
// write self.selectors
|
2023-05-01 02:41:40 -07:00
|
|
|
writer.write_all(&(u32::try_from(self.selectors.len()).unwrap()).to_le_bytes())?;
|
2022-09-15 23:15:52 -07:00
|
|
|
for selector in &self.selectors {
|
2023-05-01 02:41:40 -07:00
|
|
|
let mut selector_bytes = vec![0u8; (selector.len() + 7) / 8];
|
2022-10-08 15:55:42 -07:00
|
|
|
for (i, selector_idx) in selector.iter().enumerate() {
|
2022-09-15 23:15:52 -07:00
|
|
|
let byte_index = i / 8;
|
|
|
|
let bit_index = i % 8;
|
2022-10-08 15:55:42 -07:00
|
|
|
selector_bytes[byte_index] |= (*selector_idx as u8) << bit_index;
|
2022-09-15 23:15:52 -07:00
|
|
|
}
|
|
|
|
writer.write_all(&selector_bytes)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Reads a verification key from a buffer.
|
|
|
|
pub fn read<R: io::Read, ConcreteCircuit: Circuit<C::Scalar>>(
|
|
|
|
reader: &mut R,
|
|
|
|
params: &Params<C>,
|
|
|
|
) -> io::Result<Self> {
|
|
|
|
let (domain, cs, _) = keygen::create_domain::<C, ConcreteCircuit>(params);
|
2023-05-01 02:41:40 -07:00
|
|
|
|
|
|
|
let mut version_byte = [0u8; 1];
|
|
|
|
reader.read_exact(&mut version_byte)?;
|
|
|
|
if 0x01 != version_byte[0] {
|
|
|
|
return Err(io::Error::new(
|
|
|
|
io::ErrorKind::InvalidData,
|
|
|
|
"unexpected version byte",
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut num_fixed_columns_le_bytes = [0u8; 4];
|
|
|
|
reader.read_exact(&mut num_fixed_columns_le_bytes)?;
|
|
|
|
let num_fixed_columns = u32::from_le_bytes(num_fixed_columns_le_bytes);
|
2022-09-15 23:15:52 -07:00
|
|
|
|
2022-10-08 15:55:42 -07:00
|
|
|
let fixed_commitments: Vec<_> = (0..num_fixed_columns)
|
2022-09-15 23:15:52 -07:00
|
|
|
.map(|_| C::read(reader))
|
2023-05-01 02:41:40 -07:00
|
|
|
.collect::<io::Result<_>>()?;
|
2022-09-15 23:15:52 -07:00
|
|
|
|
|
|
|
let permutation = permutation::VerifyingKey::read(reader, &cs.permutation)?;
|
|
|
|
|
|
|
|
// read selectors
|
2023-05-01 02:41:40 -07:00
|
|
|
let mut num_selectors_le_bytes = [0u8; 4];
|
|
|
|
reader.read_exact(&mut num_selectors_le_bytes)?;
|
|
|
|
let num_selectors = u32::from_le_bytes(num_selectors_le_bytes);
|
|
|
|
if cs.num_selectors != num_selectors.try_into().unwrap() {
|
|
|
|
return Err(io::Error::new(
|
|
|
|
io::ErrorKind::InvalidData,
|
|
|
|
"unexpected number of selectors",
|
|
|
|
));
|
|
|
|
}
|
2022-09-15 23:15:52 -07:00
|
|
|
let selectors: Vec<Vec<bool>> = vec![vec![false; params.n as usize]; cs.num_selectors]
|
|
|
|
.into_iter()
|
|
|
|
.map(|mut selector| {
|
2023-05-01 02:41:40 -07:00
|
|
|
let mut selector_bytes = vec![0u8; (selector.len() + 7) / 8];
|
|
|
|
reader.read_exact(&mut selector_bytes)?;
|
2022-10-08 15:55:42 -07:00
|
|
|
for (i, selector_idx) in selector.iter_mut().enumerate() {
|
2022-09-15 23:15:52 -07:00
|
|
|
let byte_index = i / 8;
|
|
|
|
let bit_index = i % 8;
|
2022-10-08 15:55:42 -07:00
|
|
|
*selector_idx = (selector_bytes[byte_index] >> bit_index) & 1 == 1;
|
2022-09-15 23:15:52 -07:00
|
|
|
}
|
|
|
|
Ok(selector)
|
|
|
|
})
|
2023-05-01 02:41:40 -07:00
|
|
|
.collect::<io::Result<_>>()?;
|
|
|
|
|
2022-09-15 23:15:52 -07:00
|
|
|
let (cs, _) = cs.compress_selectors(selectors.clone());
|
|
|
|
|
|
|
|
Ok(Self::from_parts(
|
|
|
|
domain,
|
|
|
|
fixed_commitments,
|
|
|
|
permutation,
|
|
|
|
cs,
|
|
|
|
selectors,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2022-06-22 12:25:32 -07:00
|
|
|
fn from_parts(
|
|
|
|
domain: EvaluationDomain<C::Scalar>,
|
|
|
|
fixed_commitments: Vec<C>,
|
|
|
|
permutation: permutation::VerifyingKey<C>,
|
|
|
|
cs: ConstraintSystem<C::Scalar>,
|
2022-09-15 23:15:52 -07:00
|
|
|
selectors: Vec<Vec<bool>>,
|
2022-06-22 12:25:32 -07:00
|
|
|
) -> Self {
|
2022-06-22 12:33:36 -07:00
|
|
|
// Compute cached values.
|
|
|
|
let cs_degree = cs.degree();
|
|
|
|
|
2022-06-22 12:25:32 -07:00
|
|
|
let mut vk = Self {
|
|
|
|
domain,
|
|
|
|
fixed_commitments,
|
|
|
|
permutation,
|
|
|
|
cs,
|
2022-06-22 12:33:36 -07:00
|
|
|
cs_degree,
|
2022-06-22 12:25:32 -07:00
|
|
|
// Temporary, this is not pinned.
|
2022-11-29 21:05:37 -08:00
|
|
|
transcript_repr: C::Scalar::ZERO,
|
2022-09-15 23:15:52 -07:00
|
|
|
selectors,
|
2022-06-22 12:25:32 -07:00
|
|
|
};
|
|
|
|
|
2021-02-11 06:30:26 -08:00
|
|
|
let mut hasher = Blake2bParams::new()
|
|
|
|
.hash_length(64)
|
2021-02-17 14:17:23 -08:00
|
|
|
.personal(b"Halo2-Verify-Key")
|
2021-02-11 06:30:26 -08:00
|
|
|
.to_state();
|
|
|
|
|
2022-06-22 12:25:32 -07:00
|
|
|
let s = format!("{:?}", vk.pinned());
|
2021-02-11 06:30:26 -08:00
|
|
|
|
2021-02-17 09:46:20 -08:00
|
|
|
hasher.update(&(s.len() as u64).to_le_bytes());
|
|
|
|
hasher.update(s.as_bytes());
|
2021-02-08 22:01:33 -08:00
|
|
|
|
2021-02-11 06:30:26 -08:00
|
|
|
// Hash in final Blake2bState
|
2022-11-29 21:05:37 -08:00
|
|
|
vk.transcript_repr = C::Scalar::from_uniform_bytes(hasher.finalize().as_array());
|
2022-06-22 12:25:32 -07:00
|
|
|
|
|
|
|
vk
|
|
|
|
}
|
2022-11-29 21:05:37 -08:00
|
|
|
}
|
2022-06-22 12:25:32 -07:00
|
|
|
|
2022-11-29 21:05:37 -08:00
|
|
|
impl<C: CurveAffine> VerifyingKey<C> {
|
2022-06-22 12:25:32 -07:00
|
|
|
/// Hashes a verification key into a transcript.
|
|
|
|
pub fn hash_into<E: EncodedChallenge<C>, T: Transcript<C, E>>(
|
|
|
|
&self,
|
|
|
|
transcript: &mut T,
|
|
|
|
) -> io::Result<()> {
|
|
|
|
transcript.common_scalar(self.transcript_repr)?;
|
2021-02-11 06:30:26 -08:00
|
|
|
|
2021-02-08 22:01:33 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-02-17 14:15:08 -08:00
|
|
|
|
|
|
|
/// Obtains a pinned representation of this verification key that contains
|
|
|
|
/// the minimal information necessary to reconstruct the verification key.
|
|
|
|
pub fn pinned(&self) -> PinnedVerificationKey<'_, C> {
|
|
|
|
PinnedVerificationKey {
|
2021-02-18 06:51:41 -08:00
|
|
|
base_modulus: C::Base::MODULUS,
|
|
|
|
scalar_modulus: C::Scalar::MODULUS,
|
2021-02-17 14:15:08 -08:00
|
|
|
domain: self.domain.pinned(),
|
|
|
|
fixed_commitments: &self.fixed_commitments,
|
2021-07-02 15:20:36 -07:00
|
|
|
permutation: &self.permutation,
|
2021-02-17 14:15:08 -08:00
|
|
|
cs: self.cs.pinned(),
|
|
|
|
}
|
|
|
|
}
|
2021-01-12 07:28:35 -08:00
|
|
|
}
|
|
|
|
|
2021-02-17 14:15:08 -08:00
|
|
|
/// Minimal representation of a verification key that can be used to identify
|
|
|
|
/// its active contents.
|
2021-11-23 14:36:27 -08:00
|
|
|
#[allow(dead_code)]
|
2021-02-18 06:51:41 -08:00
|
|
|
#[derive(Debug)]
|
2021-02-17 14:15:08 -08:00
|
|
|
pub struct PinnedVerificationKey<'a, C: CurveAffine> {
|
2021-02-18 06:51:41 -08:00
|
|
|
base_modulus: &'static str,
|
|
|
|
scalar_modulus: &'static str,
|
2021-02-17 14:15:08 -08:00
|
|
|
domain: PinnedEvaluationDomain<'a, C::Scalar>,
|
2021-02-18 06:51:41 -08:00
|
|
|
cs: PinnedConstraintSystem<'a, C::Scalar>,
|
2021-02-17 14:15:08 -08:00
|
|
|
fixed_commitments: &'a Vec<C>,
|
2021-07-02 15:20:36 -07:00
|
|
|
permutation: &'a permutation::VerifyingKey<C>,
|
2021-02-17 09:46:20 -08:00
|
|
|
}
|
2020-09-29 07:25:04 -07:00
|
|
|
/// This is a proving key which allows for the creation of proofs for a
|
|
|
|
/// particular circuit.
|
2022-04-26 04:53:44 -07:00
|
|
|
#[derive(Clone, Debug)]
|
2020-09-29 07:25:04 -07:00
|
|
|
pub struct ProvingKey<C: CurveAffine> {
|
|
|
|
vk: VerifyingKey<C>,
|
|
|
|
l0: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
|
2021-07-09 08:18:45 -07:00
|
|
|
l_blind: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
|
2021-07-02 15:20:36 -07:00
|
|
|
l_last: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
|
2020-11-30 22:35:56 -08:00
|
|
|
fixed_values: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
|
2020-09-07 09:22:25 -07:00
|
|
|
fixed_polys: Vec<Polynomial<C::Scalar, Coeff>>,
|
|
|
|
fixed_cosets: Vec<Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
2021-07-02 15:20:36 -07:00
|
|
|
permutation: permutation::ProvingKey<C>,
|
2020-08-22 13:15:39 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 07:25:04 -07:00
|
|
|
impl<C: CurveAffine> ProvingKey<C> {
|
2020-09-29 07:28:00 -07:00
|
|
|
/// Get the underlying [`VerifyingKey`].
|
2020-09-29 07:25:04 -07:00
|
|
|
pub fn get_vk(&self) -> &VerifyingKey<C> {
|
|
|
|
&self.vk
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: CurveAffine> VerifyingKey<C> {
|
2020-09-29 07:28:00 -07:00
|
|
|
/// Get the underlying [`EvaluationDomain`].
|
2020-09-29 07:25:04 -07:00
|
|
|
pub fn get_domain(&self) -> &EvaluationDomain<C::Scalar> {
|
|
|
|
&self.domain
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-30 22:44:14 -08:00
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
struct Theta;
|
|
|
|
type ChallengeTheta<F> = ChallengeScalar<F, Theta>;
|
|
|
|
|
2020-11-25 11:26:31 -08:00
|
|
|
#[derive(Clone, Copy, Debug)]
|
2020-12-01 13:14:14 -08:00
|
|
|
struct Beta;
|
|
|
|
type ChallengeBeta<F> = ChallengeScalar<F, Beta>;
|
2020-11-25 11:26:31 -08:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
2020-12-01 13:14:14 -08:00
|
|
|
struct Gamma;
|
|
|
|
type ChallengeGamma<F> = ChallengeScalar<F, Gamma>;
|
2020-11-25 11:26:31 -08:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
2020-12-01 13:14:14 -08:00
|
|
|
struct Y;
|
|
|
|
type ChallengeY<F> = ChallengeScalar<F, Y>;
|
2020-11-25 11:26:31 -08:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
2020-12-01 13:14:14 -08:00
|
|
|
struct X;
|
|
|
|
type ChallengeX<F> = ChallengeScalar<F, X>;
|