plonky2/src/circuit_data.rs

193 lines
6.0 KiB
Rust
Raw Normal View History

use anyhow::Result;
2021-05-18 15:22:06 +02:00
use crate::field::extension_field::Extendable;
2021-02-09 21:25:21 -08:00
use crate::field::field::Field;
2021-05-07 11:30:03 +02:00
use crate::fri::FriConfig;
2021-03-30 10:02:00 -07:00
use crate::gates::gate::GateRef;
2021-03-21 11:17:00 -07:00
use crate::generator::WitnessGenerator;
2021-04-24 11:20:07 -07:00
use crate::merkle_tree::MerkleTree;
2021-05-18 16:06:47 +02:00
use crate::polynomial::commitment::ListPolynomialCommitment;
use crate::proof::{Hash, HashTarget, Proof};
2021-03-21 11:17:00 -07:00
use crate::prover::prove;
use crate::verifier::verify;
use crate::witness::PartialWitness;
2021-02-09 21:25:21 -08:00
2021-05-07 11:30:03 +02:00
#[derive(Clone)]
2021-02-09 21:25:21 -08:00
pub struct CircuitConfig {
pub num_wires: usize,
pub num_routed_wires: usize,
pub security_bits: usize,
2021-03-25 15:20:14 -07:00
pub rate_bits: usize,
2021-05-14 08:07:00 -07:00
/// The number of challenge points to generate, for IOPs that have soundness errors of (roughly)
/// `degree / |F|`.
pub num_challenges: usize,
2021-05-07 11:30:03 +02:00
// TODO: Find a better place for this.
pub fri_config: FriConfig,
}
impl Default for CircuitConfig {
fn default() -> Self {
CircuitConfig {
2021-04-02 15:29:21 -07:00
num_wires: 4,
num_routed_wires: 4,
security_bits: 128,
rate_bits: 3,
2021-05-14 08:07:00 -07:00
num_challenges: 3,
2021-05-07 11:30:03 +02:00
fri_config: FriConfig {
proof_of_work_bits: 1,
rate_bits: 1,
reduction_arity_bits: vec![1],
num_query_rounds: 1,
blinding: vec![true],
2021-05-07 11:30:03 +02:00
},
}
}
2021-02-09 21:25:21 -08:00
}
impl CircuitConfig {
2021-03-21 11:57:33 -07:00
pub fn num_advice_wires(&self) -> usize {
2021-02-09 21:25:21 -08:00
self.num_wires - self.num_routed_wires
}
}
/// Circuit data required by the prover or the verifier.
pub struct CircuitData<F: Field> {
2021-03-25 15:20:14 -07:00
pub(crate) prover_only: ProverOnlyCircuitData<F>,
pub(crate) verifier_only: VerifierOnlyCircuitData<F>,
2021-03-25 15:20:14 -07:00
pub(crate) common: CommonCircuitData<F>,
2021-02-09 21:25:21 -08:00
}
2021-05-18 15:44:50 +02:00
impl<F: Field> CircuitData<F> {
pub fn prove<const D: usize>(&self, inputs: PartialWitness<F>) -> Proof<F, D>
where
F: Extendable<D>,
{
2021-03-21 11:17:00 -07:00
prove(&self.prover_only, &self.common, inputs)
2021-02-09 21:25:21 -08:00
}
pub fn verify<const D: usize>(&self, proof: Proof<F, D>) -> Result<()>
where
F: Extendable<D>,
{
verify(proof, &self.verifier_only, &self.common)
2021-02-09 21:25:21 -08:00
}
}
2021-04-02 20:58:19 -07:00
/// Circuit data required by the prover. This may be thought of as a proving key, although it
/// includes code for witness generation.
///
/// The goal here is to make proof generation as fast as we can, rather than making this prover
/// structure as succinct as we can. Thus we include various precomputed data which isn't strictly
/// required, like LDEs of preprocessed polynomials. If more succinctness was desired, we could
/// construct a more minimal prover structure and convert back and forth.
2021-02-09 21:25:21 -08:00
pub struct ProverCircuitData<F: Field> {
2021-03-25 15:20:14 -07:00
pub(crate) prover_only: ProverOnlyCircuitData<F>,
pub(crate) common: CommonCircuitData<F>,
2021-02-09 21:25:21 -08:00
}
2021-05-18 15:44:50 +02:00
impl<F: Field> ProverCircuitData<F> {
pub fn prove<const D: usize>(&self, inputs: PartialWitness<F>) -> Proof<F, D>
where
F: Extendable<D>,
{
2021-03-21 11:17:00 -07:00
prove(&self.prover_only, &self.common, inputs)
2021-02-09 21:25:21 -08:00
}
}
/// Circuit data required by the prover.
pub struct VerifierCircuitData<F: Field> {
pub(crate) verifier_only: VerifierOnlyCircuitData<F>,
2021-03-25 15:20:14 -07:00
pub(crate) common: CommonCircuitData<F>,
2021-02-09 21:25:21 -08:00
}
impl<F: Field> VerifierCircuitData<F> {
pub fn verify<const D: usize>(&self, proof: Proof<F, D>) -> Result<()>
where
F: Extendable<D>,
{
verify(proof, &self.verifier_only, &self.common)
2021-02-09 21:25:21 -08:00
}
}
/// Circuit data required by the prover, but not the verifier.
pub(crate) struct ProverOnlyCircuitData<F: Field> {
2021-03-21 11:17:00 -07:00
pub generators: Vec<Box<dyn WitnessGenerator<F>>>,
2021-05-07 11:30:03 +02:00
/// Commitments to the constants polynomial.
pub constants_commitment: ListPolynomialCommitment<F>,
/// Commitments to the sigma polynomial.
pub sigmas_commitment: ListPolynomialCommitment<F>,
2021-02-09 21:25:21 -08:00
}
/// Circuit data required by the verifier, but not the prover.
pub(crate) struct VerifierOnlyCircuitData<F: Field> {
/// A commitment to each constant polynomial.
pub(crate) constants_root: Hash<F>,
/// A commitment to each permutation polynomial.
pub(crate) sigmas_root: Hash<F>,
}
2021-02-09 21:25:21 -08:00
/// Circuit data required by both the prover and the verifier.
pub(crate) struct CommonCircuitData<F: Field> {
2021-03-25 15:20:14 -07:00
pub(crate) config: CircuitConfig,
2021-02-09 21:25:21 -08:00
pub(crate) degree_bits: usize,
2021-02-09 21:25:21 -08:00
2021-03-21 11:57:33 -07:00
/// The types of gates used in this circuit.
2021-03-25 15:20:14 -07:00
pub(crate) gates: Vec<GateRef<F>>,
2021-03-21 11:57:33 -07:00
2021-04-02 19:15:39 -07:00
/// The largest number of constraints imposed by any gate.
pub(crate) num_gate_constraints: usize,
/// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument.
2021-03-30 23:12:47 -07:00
pub(crate) k_is: Vec<F>,
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to
/// seed Fiat-Shamir.
pub(crate) circuit_digest: Hash<F>,
2021-02-09 21:25:21 -08:00
}
2021-03-21 11:57:33 -07:00
impl<F: Field> CommonCircuitData<F> {
pub fn degree(&self) -> usize {
1 << self.degree_bits
}
pub fn lde_size(&self) -> usize {
1 << (self.degree_bits + self.config.rate_bits)
}
pub fn lde_generator(&self) -> F {
F::primitive_root_of_unity(self.degree_bits + self.config.rate_bits)
}
pub fn constraint_degree(&self) -> usize {
2021-04-21 22:31:45 +02:00
self.gates
.iter()
.map(|g| g.0.degree())
2021-03-21 11:57:33 -07:00
.max()
.expect("No gates?")
}
pub fn quotient_degree(&self) -> usize {
self.constraint_degree() - 1
}
pub fn total_constraints(&self) -> usize {
// 2 constraints for each Z check.
2021-05-14 08:07:00 -07:00
self.config.num_challenges * 2 + self.num_gate_constraints
}
2021-03-21 11:57:33 -07:00
}
2021-04-02 20:58:19 -07:00
/// The `Target` version of `VerifierCircuitData`, for use inside recursive circuits. Note that this
/// is intentionally missing certain fields, such as `CircuitConfig`, because we support only a
/// limited form of dynamic inner circuits. We can't practically make things like the wire count
/// dynamic, at least not without setting a maximum wire count and paying for the worst case.
2021-04-03 15:30:33 -07:00
pub struct VerifierCircuitTarget {
2021-04-02 20:58:19 -07:00
/// A commitment to each constant polynomial.
pub(crate) constants_root: HashTarget,
/// A commitment to each permutation polynomial.
pub(crate) sigmas_root: HashTarget,
}