halo2/src/plonk.rs

190 lines
5.7 KiB
Rust
Raw Normal View History

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;
use crate::arithmetic::{CurveAffine, FieldExt};
use crate::poly::{
commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff,
PinnedEvaluationDomain, Polynomial,
};
use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript};
2020-08-22 13:15:39 -07:00
mod circuit;
mod keygen;
2020-11-30 22:53:20 -08:00
mod lookup;
2020-12-21 21:56:30 -08:00
pub(crate) mod permutation;
mod vanishing;
2020-08-22 13:15:39 -07:00
mod prover;
mod verifier;
pub use circuit::*;
pub use keygen::*;
2020-08-22 13:15:39 -07:00
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.
2020-08-22 13:15:39 -07:00
#[derive(Debug)]
pub struct VerifyingKey<C: CurveAffine> {
2020-08-22 13:15:39 -07:00
domain: EvaluationDomain<C::Scalar>,
fixed_commitments: Vec<C>,
permutation: permutation::VerifyingKey<C>,
cs: ConstraintSystem<C::Scalar>,
}
impl<C: CurveAffine> VerifyingKey<C> {
/// Writes a verifying key to a buffer.
pub fn write<W: io::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<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);
let fixed_commitments: Vec<_> = (0..cs.num_fixed_columns)
.map(|_| C::read(reader))
.collect::<Result<_, _>>()?;
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<E: EncodedChallenge<C>, T: Transcript<C, E>>(
2021-04-12 23:47:25 -07:00
&self,
transcript: &mut T,
) -> io::Result<()> {
2021-02-11 06:30:26 -08:00
let mut hasher = Blake2bParams::new()
.hash_length(64)
.personal(b"Halo2-Verify-Key")
2021-02-11 06:30:26 -08:00
.to_state();
let s = format!("{:?}", self.pinned());
2021-02-11 06:30:26 -08:00
hasher.update(&(s.len() as u64).to_le_bytes());
hasher.update(s.as_bytes());
2021-02-11 06:30:26 -08:00
// Hash in final Blake2bState
2021-02-17 12:55:38 -08:00
transcript.common_scalar(C::Scalar::from_bytes_wide(hasher.finalize().as_array()))?;
2021-02-11 06:30:26 -08:00
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<C>,
permutation: &'a permutation::VerifyingKey<C>,
}
/// This is a proving key which allows for the creation of proofs for a
/// particular circuit.
#[derive(Debug)]
pub struct ProvingKey<C: CurveAffine> {
vk: VerifyingKey<C>,
l0: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
l_cover: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
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>>,
permutation: permutation::ProvingKey<C>,
2020-08-22 13:15:39 -07:00
}
/// 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,
2021-07-09 08:14:52 -07:00
/// Insufficient number of rows available
NotEnoughRowsAvailable,
2020-08-22 13:15:39 -07:00
}
impl<C: CurveAffine> ProvingKey<C> {
2020-09-29 07:28:00 -07:00
/// Get the underlying [`VerifyingKey`].
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`].
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>;
#[derive(Clone, Copy, Debug)]
struct Beta;
type ChallengeBeta<F> = ChallengeScalar<F, Beta>;
#[derive(Clone, Copy, Debug)]
struct Gamma;
type ChallengeGamma<F> = ChallengeScalar<F, Gamma>;
#[derive(Clone, Copy, Debug)]
struct Y;
type ChallengeY<F> = ChallengeScalar<F, Y>;
#[derive(Clone, Copy, Debug)]
struct X;
type ChallengeX<F> = ChallengeScalar<F, X>;