//! 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 crate::arithmetic::{CurveAffine, FieldExt}; use crate::poly::{ commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, PinnedEvaluationDomain, Polynomial, }; use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript}; mod circuit; mod keygen; mod lookup; pub(crate) mod permutation; mod vanishing; mod prover; mod verifier; pub use circuit::*; 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(Debug)] pub struct VerifyingKey { domain: EvaluationDomain, fixed_commitments: Vec, permutation: permutation::VerifyingKey, cs: ConstraintSystem, } impl VerifyingKey { /// Writes a verifying key to a buffer. pub fn write(&self, writer: &mut W) -> io::Result<()> { for commitment in &self.fixed_commitments { writer.write_all(commitment.to_bytes().as_ref())?; } self.permutation.write(writer)?; Ok(()) } /// Reads a verification key from a buffer. pub fn read>( reader: &mut R, params: &Params, ) -> io::Result { let (domain, cs, _) = keygen::create_domain::(params); let fixed_commitments: Vec<_> = (0..cs.num_fixed_columns) .map(|_| C::read(reader)) .collect::>()?; let permutation = permutation::VerifyingKey::read(reader, &cs.permutation)?; Ok(VerifyingKey { domain, fixed_commitments, permutation, cs, }) } /// Hashes a verification key into a transcript. pub fn hash_into, T: Transcript>( &self, transcript: &mut T, ) -> io::Result<()> { let mut hasher = Blake2bParams::new() .hash_length(64) .personal(b"Halo2-Verify-Key") .to_state(); let s = format!("{:?}", self.pinned()); hasher.update(&(s.len() as u64).to_le_bytes()); hasher.update(s.as_bytes()); // Hash in final Blake2bState transcript.common_scalar(C::Scalar::from_bytes_wide(hasher.finalize().as_array()))?; 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. #[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(Debug)] pub struct ProvingKey { vk: VerifyingKey, l0: Polynomial, l_cover: Polynomial, l_last: Polynomial, fixed_values: Vec>, fixed_polys: Vec>, fixed_cosets: Vec>, permutation: permutation::ProvingKey, } /// This is an error that could occur during proving or circuit synthesis. // TODO: these errors need to be cleaned up #[derive(Debug)] pub enum Error { /// This is an error that can occur during synthesis of the circuit, for /// example, when the witness is not present. SynthesisError, /// The structured reference string or the parameters are not compatible /// with the circuit being synthesized. IncompatibleParams, /// The constraint system is not satisfied. ConstraintSystemFailure, /// Out of bounds index passed to a backend BoundsFailure, /// Opening error OpeningError, /// Transcript error TranscriptError, /// Insufficient number of rows available NotEnoughRowsAvailable, } 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;