Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: optionally unblinded advice columns #220

31 changes: 31 additions & 0 deletions halo2_proofs/src/plonk/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,9 @@ pub struct ConstraintSystem<F: Field> {
pub(crate) num_selectors: usize,
pub(crate) num_challenges: usize,

/// Contains the index of each advice column that is left unblinded.
pub(crate) unblinded_advice_columns: Vec<usize>,

/// Contains the phase for each advice column. Should have same length as num_advice_columns.
pub(crate) advice_column_phase: Vec<sealed::Phase>,
/// Contains the phase for each challenge. Should have same length as num_challenges.
Expand Down Expand Up @@ -1662,6 +1665,7 @@ impl<F: Field> Default for ConstraintSystem<F> {
num_instance_columns: 0,
num_selectors: 0,
num_challenges: 0,
unblinded_advice_columns: Vec::new(),
advice_column_phase: Vec::new(),
challenge_phase: Vec::new(),
selector_map: vec![],
Expand Down Expand Up @@ -2139,11 +2143,38 @@ impl<F: Field> ConstraintSystem<F> {
tmp
}

/// Allocate a new unblinded advice column at `FirstPhase`
pub fn unblinded_advice_column(&mut self) -> Column<Advice> {
self.unblinded_advice_column_in(FirstPhase)
}

/// Allocate a new advice column at `FirstPhase`
pub fn advice_column(&mut self) -> Column<Advice> {
self.advice_column_in(FirstPhase)
}

/// Allocate a new unblinded advice column in given phase. The allows for the generation of deterministic commitments to advice columns
alexander-camuto marked this conversation as resolved.
Show resolved Hide resolved
/// which can be used to split large circuits into smaller ones, whose proofs can then be "joined" together by their common witness commitments.
pub fn unblinded_advice_column_in<P: Phase>(&mut self, phase: P) -> Column<Advice> {
let phase = phase.to_sealed();
if let Some(previous_phase) = phase.prev() {
self.assert_phase_exists(
previous_phase,
format!("Column<Advice> in later phase {:?}", phase).as_str(),
);
}

let tmp = Column {
index: self.num_advice_columns,
column_type: Advice { phase },
};
self.unblinded_advice_columns.push(tmp.index);
self.num_advice_columns += 1;
self.num_advice_queries.push(0);
self.advice_column_phase.push(phase);
tmp
CPerezz marked this conversation as resolved.
Show resolved Hide resolved
}

/// Allocate a new advice column in given phase
pub fn advice_column_in<P: Phase>(&mut self, phase: P) -> Column<Advice> {
let phase = phase.to_sealed();
Expand Down
27 changes: 21 additions & 6 deletions halo2_proofs/src/plonk/prover.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use ff::{Field, FromUniformBytes, WithSmallOrderMulGroup};
use group::Curve;
use rand_core::RngCore;
use std::collections::BTreeSet;
use std::collections::{BTreeSet, HashSet};
use std::ops::RangeTo;
use std::{collections::HashMap, iter};

Expand Down Expand Up @@ -147,6 +147,7 @@ where
k: u32,
current_phase: sealed::Phase,
advice: Vec<Polynomial<Assigned<F>, LagrangeCoeff>>,
unblinded_advice: HashSet<usize>,
alexander-camuto marked this conversation as resolved.
Show resolved Hide resolved
challenges: &'a HashMap<usize, F>,
instances: &'a [&'a [F]],
usable_rows: RangeTo<usize>,
Expand Down Expand Up @@ -319,6 +320,7 @@ where
k: params.k(),
current_phase,
advice: vec![domain.empty_lagrange_assigned(); meta.num_advice_columns],
unblinded_advice: HashSet::from_iter(meta.unblinded_advice_columns.clone()),
instances,
challenges: &challenges,
// The prover will not be allowed to assign values to advice
Expand Down Expand Up @@ -353,16 +355,29 @@ where
);

// Add blinding factors to advice columns
for advice_values in &mut advice_values {
for cell in &mut advice_values[unusable_rows_start..] {
*cell = Scheme::Scalar::random(&mut rng);
for (column_index, advice_values) in column_indices.iter().zip(&mut advice_values) {
if witness.unblinded_advice.contains(column_index) {
for cell in &mut advice_values[unusable_rows_start..] {
*cell = Scheme::Scalar::random(&mut rng);
}
} else {
#[cfg(feature = "sanity-checks")]
alexander-camuto marked this conversation as resolved.
Show resolved Hide resolved
for cell in &advice_values[unusable_rows_start..] {
assert_eq!(*cell, Scheme::Scalar::ZERO);
}
}
}

// Compute commitments to advice column polynomials
let blinds: Vec<_> = advice_values
let blinds: Vec<_> = column_indices
.iter()
.map(|_| Blind(Scheme::Scalar::random(&mut rng)))
.map(|i| {
if witness.unblinded_advice.contains(i) {
Blind::default()
} else {
Blind(Scheme::Scalar::random(&mut rng))
}
})
.collect();
let advice_commitments_projective: Vec<_> = advice_values
.iter()
Expand Down
Loading