//! 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 use blake2b_simd::Params as Blake2bParams; use group::ff::{Field, FromUniformBytes, PrimeField}; use crate::arithmetic::CurveAffine; use crate::poly::{ Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, PinnedEvaluationDomain, Polynomial, }; use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript}; mod assigned; mod circuit; mod error; mod keygen; mod lookup; pub(crate) mod permutation; mod vanishing; mod prover; mod verifier; pub use assigned::*; pub use circuit::*; pub use error::*; pub use keygen::*; pub use prover::*; pub use verifier::*; use std::io; /// This is a verifying key which allows for the verification of proofs for a /// particular circuit. #[derive(Clone, Debug)] pub struct VerifyingKey { domain: EvaluationDomain, fixed_commitments: Vec, permutation: permutation::VerifyingKey, cs: ConstraintSystem, /// Cached maximum degree of `cs` (which doesn't change after construction). cs_degree: usize, /// The representative of this `VerifyingKey` in transcripts. transcript_repr: C::Scalar, } impl VerifyingKey where C::Scalar: FromUniformBytes<64>, { fn from_parts( domain: EvaluationDomain, fixed_commitments: Vec, permutation: permutation::VerifyingKey, cs: ConstraintSystem, ) -> Self { // Compute cached values. let cs_degree = cs.degree(); let mut vk = Self { domain, fixed_commitments, permutation, cs, cs_degree, // Temporary, this is not pinned. transcript_repr: C::Scalar::ZERO, }; let mut hasher = Blake2bParams::new() .hash_length(64) .personal(b"Halo2-Verify-Key") .to_state(); let s = format!("{:?}", vk.pinned()); hasher.update(&(s.len() as u64).to_le_bytes()); hasher.update(s.as_bytes()); // Hash in final Blake2bState vk.transcript_repr = C::Scalar::from_uniform_bytes(hasher.finalize().as_array()); vk } } impl VerifyingKey { /// Hashes a verification key into a transcript. pub fn hash_into, T: Transcript>( &self, transcript: &mut T, ) -> io::Result<()> { transcript.common_scalar(self.transcript_repr)?; Ok(()) } /// 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 { base_modulus: C::Base::MODULUS, scalar_modulus: C::Scalar::MODULUS, domain: self.domain.pinned(), fixed_commitments: &self.fixed_commitments, permutation: &self.permutation, cs: self.cs.pinned(), } } } /// Minimal representation of a verification key that can be used to identify /// its active contents. #[allow(dead_code)] #[derive(Debug)] pub struct PinnedVerificationKey<'a, C: CurveAffine> { base_modulus: &'static str, scalar_modulus: &'static str, domain: PinnedEvaluationDomain<'a, C::Scalar>, cs: PinnedConstraintSystem<'a, C::Scalar>, fixed_commitments: &'a Vec, permutation: &'a permutation::VerifyingKey, } /// This is a proving key which allows for the creation of proofs for a /// particular circuit. #[derive(Clone, Debug)] pub struct ProvingKey { vk: VerifyingKey, l0: Polynomial, l_blind: Polynomial, l_last: Polynomial, fixed_values: Vec>, fixed_polys: Vec>, fixed_cosets: Vec>, permutation: permutation::ProvingKey, } impl ProvingKey { /// Get the underlying [`VerifyingKey`]. pub fn get_vk(&self) -> &VerifyingKey { &self.vk } } impl VerifyingKey { /// Get the underlying [`EvaluationDomain`]. pub fn get_domain(&self) -> &EvaluationDomain { &self.domain } } #[derive(Clone, Copy, Debug)] struct Theta; type ChallengeTheta = ChallengeScalar; #[derive(Clone, Copy, Debug)] struct Beta; type ChallengeBeta = ChallengeScalar; #[derive(Clone, Copy, Debug)] struct Gamma; type ChallengeGamma = ChallengeScalar; #[derive(Clone, Copy, Debug)] struct Y; type ChallengeY = ChallengeScalar; #[derive(Clone, Copy, Debug)] struct X; type ChallengeX = ChallengeScalar;