Optional zk (#101)

* Make ZK optional

* Remove rate from FriConfig

Seems redundant, and we've had some tests break due to the two fields not matching.

* zero_knowledge: false in bench
This commit is contained in:
Daniel Lubarov 2021-07-18 23:24:33 -07:00 committed by GitHub
parent 0a5d46bfa9
commit d11bcd1928
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 64 additions and 49 deletions

View File

@ -26,9 +26,9 @@ fn bench_prove<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
security_bits: 128,
rate_bits: 3,
num_challenges: 3,
zero_knowledge: false,
fri_config: FriConfig {
proof_of_work_bits: 20,
rate_bits: 3,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2],
num_query_rounds: 35,
},

View File

@ -333,7 +333,9 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let final_poly_coeffs: usize = degree_estimate / arities.iter().product::<usize>();
let fri_openings = fri_queries * (1 + D * total_fri_folding_points + D * final_poly_coeffs);
// We add D for openings at zeta.
let regular_poly_openings = D + fri_openings;
// We add 2 * D for openings at zeta and g * zeta.
let z_openings = 2 * D + fri_openings;
(regular_poly_openings, z_openings)
@ -364,6 +366,16 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
fn blind_and_pad(&mut self) {
if self.config.zero_knowledge {
self.blind();
}
while !self.gate_instances.len().is_power_of_two() {
self.add_gate_no_constants(NoopGate::get());
}
}
fn blind(&mut self) {
let (regular_poly_openings, z_openings) = self.blinding_counts();
info!(
"Adding {} blinding terms for witness polynomials, and {}*2 for Z polynomials",
@ -410,10 +422,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
);
}
}
while !self.gate_instances.len().is_power_of_two() {
self.add_gate_no_constants(NoopGate::get());
}
}
fn constant_polys(
@ -508,8 +516,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat();
let constants_sigmas_commitment = ListPolynomialCommitment::new(
constants_sigmas_vecs,
self.config.fri_config.rate_bits,
PlonkPolynomials::CONSTANTS_SIGMAS.blinding,
self.config.rate_bits,
self.config.zero_knowledge & PlonkPolynomials::CONSTANTS_SIGMAS.blinding,
);
let constants_sigmas_root = constants_sigmas_commitment.merkle_tree.root;

View File

@ -24,6 +24,7 @@ pub struct CircuitConfig {
/// The number of challenge points to generate, for IOPs that have soundness errors of (roughly)
/// `degree / |F|`.
pub num_challenges: usize,
pub zero_knowledge: bool,
// TODO: Find a better place for this.
pub fri_config: FriConfig,
@ -37,9 +38,9 @@ impl Default for CircuitConfig {
security_bits: 128,
rate_bits: 3,
num_challenges: 3,
zero_knowledge: true,
fri_config: FriConfig {
proof_of_work_bits: 1,
rate_bits: 3,
reduction_arity_bits: vec![1, 1, 1, 1],
num_query_rounds: 1,
},
@ -59,9 +60,9 @@ impl CircuitConfig {
security_bits: 128,
rate_bits: 3,
num_challenges: 3,
zero_knowledge: true,
fri_config: FriConfig {
proof_of_work_bits: 1,
rate_bits: 3,
reduction_arity_bits: vec![1, 1, 1, 1],
num_query_rounds: 1,
},

View File

@ -10,8 +10,6 @@ const EPSILON: f64 = 0.01;
pub struct FriConfig {
pub proof_of_work_bits: u32,
pub rate_bits: usize,
/// The arity of each FRI reduction step, expressed (i.e. the log2 of the actual arity).
/// For example, `[3, 2, 1]` would describe a FRI reduction tree with 8-to-1 reduction, then
/// a 4-to-1 reduction, then a 2-to-1 reduction. After these reductions, the reduced polynomial

View File

@ -1,4 +1,5 @@
use crate::circuit_builder::CircuitBuilder;
use crate::circuit_data::CircuitConfig;
use crate::circuit_data::CommonCircuitData;
use crate::field::extension_field::target::{flatten_target, ExtensionTarget};
use crate::field::extension_field::Extendable;
@ -75,8 +76,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
challenger: &mut RecursiveChallenger,
common_data: &CommonCircuitData<F, D>,
) {
let config = &common_data.config.fri_config;
let total_arities = config.reduction_arity_bits.iter().sum::<usize>();
let config = &common_data.config;
let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>();
debug_assert_eq!(
purported_degree_log,
log2_strict(proof.final_poly.len()) + total_arities - config.rate_bits,
@ -98,16 +99,16 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
challenger.observe_extension_elements(&proof.final_poly.0);
self.set_context("Check PoW");
self.fri_verify_proof_of_work(proof, challenger, config);
self.fri_verify_proof_of_work(proof, challenger, &config.fri_config);
// Check that parameters are coherent.
debug_assert_eq!(
config.num_query_rounds,
config.fri_config.num_query_rounds,
proof.query_round_proofs.len(),
"Number of query rounds does not match config."
);
debug_assert!(
!config.reduction_arity_bits.is_empty(),
!config.fri_config.reduction_arity_bits.is_empty(),
"Number of reductions should be non-zero."
);
@ -154,7 +155,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
common_data: &CommonCircuitData<F, D>,
) -> ExtensionTarget<D> {
assert!(D > 1, "Not implemented for D=1.");
let config = &self.config.fri_config.clone();
let config = self.config.clone();
let degree_log = proof.evals_proofs[0].1.siblings.len() - config.rate_bits;
let subgroup_x = self.convert_to_ext(subgroup_x);
let mut alpha = ReducingFactorTarget::new(alpha);
@ -171,9 +172,9 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
PlonkPolynomials::QUOTIENT,
]
.iter()
.flat_map(|&p| proof.unsalted_evals(p))
.flat_map(|&p| proof.unsalted_evals(p, config.zero_knowledge))
.chain(
&proof.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS)
&proof.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge)
[common_data.partial_products_range()],
)
.map(|&e| self.convert_to_ext(e))
@ -197,7 +198,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// Polynomials opened at `x` and `g x`, i.e., the Zs polynomials.
let zs_evals = proof
.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS)
.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge)
.iter()
.take(common_data.zs_range().end)
.map(|&e| self.convert_to_ext(e))
@ -222,7 +223,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// Polynomials opened at `x` and `x.frobenius()`, i.e., the wires polynomials.
let wire_evals = proof
.unsalted_evals(PlonkPolynomials::WIRES)
.unsalted_evals(PlonkPolynomials::WIRES, config.zero_knowledge)
.iter()
.map(|&e| self.convert_to_ext(e))
.collect::<Vec<_>>();

View File

@ -78,8 +78,8 @@ pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>(
challenger: &mut Challenger<F>,
common_data: &CommonCircuitData<F, D>,
) -> Result<()> {
let config = &common_data.config.fri_config;
let total_arities = config.reduction_arity_bits.iter().sum::<usize>();
let config = &common_data.config;
let total_arities = config.fri_config.reduction_arity_bits.iter().sum::<usize>();
ensure!(
purported_degree_log
== log2_strict(proof.final_poly.len()) + total_arities - config.rate_bits,
@ -101,15 +101,15 @@ pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>(
challenger.observe_extension_elements(&proof.final_poly.coeffs);
// Check PoW.
fri_verify_proof_of_work(proof, challenger, config)?;
fri_verify_proof_of_work(proof, challenger, &config.fri_config)?;
// Check that parameters are coherent.
ensure!(
config.num_query_rounds == proof.query_round_proofs.len(),
config.fri_config.num_query_rounds == proof.query_round_proofs.len(),
"Number of query rounds does not match config."
);
ensure!(
!config.reduction_arity_bits.is_empty(),
!config.fri_config.reduction_arity_bits.is_empty(),
"Number of reductions should be non-zero."
);
@ -151,7 +151,7 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
subgroup_x: F,
common_data: &CommonCircuitData<F, D>,
) -> F::Extension {
let config = &common_data.config.fri_config;
let config = &common_data.config;
assert!(D > 1, "Not implemented for D=1.");
let degree_log = proof.evals_proofs[0].1.siblings.len() - config.rate_bits;
let subgroup_x = F::Extension::from_basefield(subgroup_x);
@ -169,9 +169,9 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
PlonkPolynomials::QUOTIENT,
]
.iter()
.flat_map(|&p| proof.unsalted_evals(p))
.flat_map(|&p| proof.unsalted_evals(p, config.zero_knowledge))
.chain(
&proof.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS)
&proof.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge)
[common_data.partial_products_range()],
)
.map(|&e| F::Extension::from_basefield(e));
@ -193,7 +193,7 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
// Polynomials opened at `x` and `g x`, i.e., the Zs polynomials.
let zs_evals = proof
.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS)
.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge)
.iter()
.map(|&e| F::Extension::from_basefield(e))
.take(common_data.zs_range().end);
@ -213,7 +213,7 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
// Polynomials opened at `x` and `x.frobenius()`, i.e., the wires polynomials.
let wire_evals = proof
.unsalted_evals(PlonkPolynomials::WIRES)
.unsalted_evals(PlonkPolynomials::WIRES, config.zero_knowledge)
.iter()
.map(|&e| F::Extension::from_basefield(e));
let wire_composition_eval = alpha.clone().reduce(wire_evals);

View File

@ -15,8 +15,8 @@ pub struct PolynomialsIndexBlinding {
pub(crate) blinding: bool,
}
impl PolynomialsIndexBlinding {
pub fn salt_size(&self) -> usize {
if self.blinding {
pub fn salt_size(&self, zero_knowledge: bool) -> usize {
if zero_knowledge & self.blinding {
SALT_SIZE
} else {
0

View File

@ -18,6 +18,7 @@ use crate::timed;
use crate::util::scaling::ReducingFactor;
use crate::util::{log2_ceil, log2_strict, reverse_bits, reverse_index_bits_in_place, transpose};
/// Two (~64 bit) field elements gives ~128 bit security.
pub const SALT_SIZE: usize = 2;
pub struct ListPolynomialCommitment<F: Field> {
@ -121,7 +122,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
where
F: Extendable<D>,
{
let config = &common_data.config.fri_config;
let config = &common_data.config;
assert!(D > 1, "Not implemented for D=1.");
let degree_log = commitments[0].degree_log;
let g = F::Extension::primitive_root_of_unity(degree_log);
@ -208,7 +209,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
&lde_final_poly,
&lde_final_values,
challenger,
&config,
&config.fri_config,
);
(
@ -351,7 +352,6 @@ mod tests {
let degree_log = 11;
let fri_config = FriConfig {
proof_of_work_bits: 2,
rate_bits: 2,
reduction_arity_bits: vec![2, 3, 1, 2],
num_query_rounds: 3,
};
@ -376,7 +376,7 @@ mod tests {
.map(|i| {
ListPolynomialCommitment::<F>::new(
gen_random_test_case(ks[i], degree_log),
common_data.config.fri_config.rate_bits,
common_data.config.rate_bits,
PlonkPolynomials::polynomials(i).blinding,
)
})

View File

@ -110,9 +110,13 @@ pub struct FriInitialTreeProof<F: Field> {
}
impl<F: Field> FriInitialTreeProof<F> {
pub(crate) fn unsalted_evals(&self, polynomials: PolynomialsIndexBlinding) -> &[F] {
pub(crate) fn unsalted_evals(
&self,
polynomials: PolynomialsIndexBlinding,
zero_knowledge: bool,
) -> &[F] {
let evals = &self.evals_proofs[polynomials.index].0;
&evals[..evals.len() - polynomials.salt_size()]
&evals[..evals.len() - polynomials.salt_size(zero_knowledge)]
}
}
@ -122,9 +126,13 @@ pub struct FriInitialTreeProofTarget {
}
impl FriInitialTreeProofTarget {
pub(crate) fn unsalted_evals(&self, polynomials: PolynomialsIndexBlinding) -> &[Target] {
pub(crate) fn unsalted_evals(
&self,
polynomials: PolynomialsIndexBlinding,
zero_knowledge: bool,
) -> &[Target] {
let evals = &self.evals_proofs[polynomials.index].0;
&evals[..evals.len() - polynomials.salt_size()]
&evals[..evals.len() - polynomials.salt_size(zero_knowledge)]
}
}

View File

@ -24,7 +24,6 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
inputs: PartialWitness<F>,
) -> Result<Proof<F, D>> {
let fri_config = &common_data.config.fri_config;
let config = &common_data.config;
let num_wires = config.num_wires;
let num_challenges = config.num_challenges;
@ -70,8 +69,8 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let wires_commitment = timed!(
ListPolynomialCommitment::new(
wires_values,
fri_config.rate_bits,
PlonkPolynomials::WIRES.blinding
config.rate_bits,
config.zero_knowledge & PlonkPolynomials::WIRES.blinding
),
"to compute wires commitment"
);
@ -106,8 +105,8 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let zs_partial_products_commitment = timed!(
ListPolynomialCommitment::new(
zs_partial_products,
fri_config.rate_bits,
PlonkPolynomials::ZS_PARTIAL_PRODUCTS.blinding
config.rate_bits,
config.zero_knowledge & PlonkPolynomials::ZS_PARTIAL_PRODUCTS.blinding
),
"to commit to Z's"
);
@ -149,8 +148,8 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let quotient_polys_commitment = timed!(
ListPolynomialCommitment::new_from_polys(
all_quotient_poly_chunks,
fri_config.rate_bits,
PlonkPolynomials::QUOTIENT.blinding
config.rate_bits,
config.zero_knowledge & PlonkPolynomials::QUOTIENT.blinding
),
"to commit to quotient polys"
);

View File

@ -326,9 +326,9 @@ mod tests {
security_bits: 128,
rate_bits: 3,
num_challenges: 3,
zero_knowledge: false,
fri_config: FriConfig {
proof_of_work_bits: 1,
rate_bits: 3,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2, 2],
num_query_rounds: 40,
},