Disable ZK in large_config (#180)

* Disable ZK in large_config

Speeds up the tests from ~6m to ~1m (debug mode). `large_config` is crate-private so I don't think we need to worry about real users forgetting ZK, and I don't think ZK seems important in these tests, though we should probably have ZK enabled for a couple tests.

A couple tests need ZK or they fail; I added a TODO to look later.

This led to a few other changes:
- Fixed a bug where `trim` could truncate the final poly to a non-power-of-two length. This was improbable when ZK is on due to randomization.
- Gave a few methods access to the whole `CircuitConfig` vs `FriConfig` -- sort of necessary for the above fix, and I don't think there's much downside.
- Remove `cap_height` from `FriConfig` -- didn't really need it any more after giving more methods access to `CircuitConfig`, and having a single copy of the param feels cleaner/safer to me.

* PR feedback
This commit is contained in:
Daniel Lubarov 2021-08-14 10:01:10 -07:00 committed by GitHub
parent f3bfd66657
commit e4cbee2b57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 50 additions and 34 deletions

View File

@ -32,7 +32,6 @@ fn bench_prove<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
proof_of_work_bits: 20, proof_of_work_bits: 20,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], reduction_arity_bits: vec![2, 2, 2, 2, 2, 2],
num_query_rounds: 35, num_query_rounds: 35,
cap_height: 1,
}, },
}; };

View File

@ -205,7 +205,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
lde_final_poly, lde_final_poly,
lde_final_values, lde_final_values,
challenger, challenger,
&config.fri_config, &config,
timing, timing,
); );
@ -281,8 +281,8 @@ mod tests {
proof_of_work_bits: 2, proof_of_work_bits: 2,
reduction_arity_bits: vec![2, 3, 1, 2], reduction_arity_bits: vec![2, 3, 1, 2],
num_query_rounds: 3, num_query_rounds: 3,
cap_height: 1,
}; };
// We only care about `fri_config, num_constants`, and `num_routed_wires` here. // We only care about `fri_config, num_constants`, and `num_routed_wires` here.
let common_data = CommonCircuitData { let common_data = CommonCircuitData {
config: CircuitConfig { config: CircuitConfig {
@ -300,12 +300,12 @@ mod tests {
circuit_digest: HashOut::from_partial(vec![]), circuit_digest: HashOut::from_partial(vec![]),
}; };
let lpcs = (0..4) let commitments = (0..4)
.map(|i| { .map(|i| {
PolynomialBatchCommitment::<F>::from_values( PolynomialBatchCommitment::<F>::from_values(
gen_random_test_case(ks[i], degree_bits), gen_random_test_case(ks[i], degree_bits),
common_data.config.rate_bits, common_data.config.rate_bits,
PlonkPolynomials::polynomials(i).blinding, common_data.config.zero_knowledge && PlonkPolynomials::polynomials(i).blinding,
common_data.config.cap_height, common_data.config.cap_height,
&mut TimingTree::default(), &mut TimingTree::default(),
) )
@ -314,7 +314,12 @@ mod tests {
let zeta = gen_random_point::<F, D>(degree_bits); let zeta = gen_random_point::<F, D>(degree_bits);
let (proof, os) = PolynomialBatchCommitment::open_plonk::<D>( let (proof, os) = PolynomialBatchCommitment::open_plonk::<D>(
&[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]], &[
&commitments[0],
&commitments[1],
&commitments[2],
&commitments[3],
],
zeta, zeta,
&mut Challenger::new(), &mut Challenger::new(),
&common_data, &common_data,
@ -322,10 +327,10 @@ mod tests {
); );
let merkle_caps = &[ let merkle_caps = &[
lpcs[0].merkle_tree.cap.clone(), commitments[0].merkle_tree.cap.clone(),
lpcs[1].merkle_tree.cap.clone(), commitments[1].merkle_tree.cap.clone(),
lpcs[2].merkle_tree.cap.clone(), commitments[2].merkle_tree.cap.clone(),
lpcs[3].merkle_tree.cap.clone(), commitments[3].merkle_tree.cap.clone(),
]; ];
verify_fri_proof( verify_fri_proof(

View File

@ -16,6 +16,4 @@ pub struct FriConfig {
/// Number of query rounds to perform. /// Number of query rounds to perform.
pub num_query_rounds: usize, pub num_query_rounds: usize,
pub cap_height: usize,
} }

View File

@ -8,6 +8,7 @@ use crate::hash::hash_types::HashOut;
use crate::hash::hashing::hash_n_to_1; use crate::hash::hashing::hash_n_to_1;
use crate::hash::merkle_tree::MerkleTree; use crate::hash::merkle_tree::MerkleTree;
use crate::iop::challenger::Challenger; use crate::iop::challenger::Challenger;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::plonk_common::reduce_with_powers; use crate::plonk::plonk_common::reduce_with_powers;
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
use crate::timed; use crate::timed;
@ -22,7 +23,7 @@ pub fn fri_proof<F: Field + Extendable<D>, const D: usize>(
// Evaluation of the polynomial on the large domain. // Evaluation of the polynomial on the large domain.
lde_polynomial_values: PolynomialValues<F::Extension>, lde_polynomial_values: PolynomialValues<F::Extension>,
challenger: &mut Challenger<F>, challenger: &mut Challenger<F>,
config: &FriConfig, config: &CircuitConfig,
timing: &mut TimingTree, timing: &mut TimingTree,
) -> FriProof<F, D> { ) -> FriProof<F, D> {
let n = lde_polynomial_values.values.len(); let n = lde_polynomial_values.values.len();
@ -45,12 +46,17 @@ pub fn fri_proof<F: Field + Extendable<D>, const D: usize>(
let pow_witness = timed!( let pow_witness = timed!(
timing, timing,
"find for proof-of-work witness", "find for proof-of-work witness",
fri_proof_of_work(current_hash, config) fri_proof_of_work(current_hash, &config.fri_config)
); );
// Query phase // Query phase
let query_round_proofs = let query_round_proofs = fri_prover_query_rounds(
fri_prover_query_rounds(initial_merkle_trees, &trees, challenger, n, config); initial_merkle_trees,
&trees,
challenger,
n,
&config.fri_config,
);
FriProof { FriProof {
commit_phase_merkle_caps: trees.iter().map(|t| t.cap.clone()).collect(), commit_phase_merkle_caps: trees.iter().map(|t| t.cap.clone()).collect(),
@ -64,14 +70,14 @@ fn fri_committed_trees<F: Field + Extendable<D>, const D: usize>(
mut coeffs: PolynomialCoeffs<F::Extension>, mut coeffs: PolynomialCoeffs<F::Extension>,
mut values: PolynomialValues<F::Extension>, mut values: PolynomialValues<F::Extension>,
challenger: &mut Challenger<F>, challenger: &mut Challenger<F>,
config: &FriConfig, config: &CircuitConfig,
) -> (Vec<MerkleTree<F>>, PolynomialCoeffs<F::Extension>) { ) -> (Vec<MerkleTree<F>>, PolynomialCoeffs<F::Extension>) {
let mut trees = Vec::new(); let mut trees = Vec::new();
let mut shift = F::MULTIPLICATIVE_GROUP_GENERATOR; let mut shift = F::MULTIPLICATIVE_GROUP_GENERATOR;
let num_reductions = config.reduction_arity_bits.len(); let num_reductions = config.fri_config.reduction_arity_bits.len();
for i in 0..num_reductions { for i in 0..num_reductions {
let arity = 1 << config.reduction_arity_bits[i]; let arity = 1 << config.fri_config.reduction_arity_bits[i];
reverse_index_bits_in_place(&mut values.values); reverse_index_bits_in_place(&mut values.values);
let chunked_values = values let chunked_values = values
@ -97,7 +103,9 @@ fn fri_committed_trees<F: Field + Extendable<D>, const D: usize>(
values = coeffs.coset_fft(shift.into()) values = coeffs.coset_fft(shift.into())
} }
coeffs.trim(); /// The coefficients being removed here should always be zero.
coeffs.coeffs.truncate(coeffs.len() >> config.rate_bits);
challenger.observe_extension_elements(&coeffs.coeffs); challenger.observe_extension_elements(&coeffs.coeffs);
(trees, coeffs) (trees, coeffs)
} }

View File

@ -291,15 +291,13 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
round_proof: &FriQueryRoundTarget<D>, round_proof: &FriQueryRoundTarget<D>,
common_data: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) { ) {
let config = &common_data.config.fri_config; let config = &common_data.config;
let n_log = log2_strict(n); let n_log = log2_strict(n);
// TODO: Do we need to range check `x_index` to a target smaller than `p`? // TODO: Do we need to range check `x_index` to a target smaller than `p`?
let x_index = challenger.get_challenge(self); let x_index = challenger.get_challenge(self);
let mut x_index_bits = self.low_bits(x_index, n_log, 64); let mut x_index_bits = self.low_bits(x_index, n_log, 64);
let cap_index = self.le_sum( let cap_index = self
x_index_bits[x_index_bits.len() - common_data.config.fri_config.cap_height..] .le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].into_iter());
.into_iter(),
);
with_context!( with_context!(
self, self,
"check FRI initial proof", "check FRI initial proof",
@ -349,7 +347,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
) )
); );
for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() { for (i, &arity_bits) in config.fri_config.reduction_arity_bits.iter().enumerate() {
let evals = &round_proof.steps[i].evals; let evals = &round_proof.steps[i].evals;
// Split x_index into the index of the coset x is in, and the index of x within that coset. // Split x_index into the index of the coset x is in, and the index of x within that coset.

View File

@ -712,7 +712,7 @@ mod tests {
type FF = QuarticCrandallField; type FF = QuarticCrandallField;
const D: usize = 4; const D: usize = 4;
let config = CircuitConfig::large_config(); let config = CircuitConfig::large_zk_config();
let pw = PartialWitness::new(config.num_wires); let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config); let mut builder = CircuitBuilder::<F, D>::new(config);

View File

@ -113,7 +113,7 @@ mod tests {
fn test_interpolate2() -> Result<()> { fn test_interpolate2() -> Result<()> {
type F = CrandallField; type F = CrandallField;
type FF = QuarticCrandallField; type FF = QuarticCrandallField;
let config = CircuitConfig::large_config(); let config = CircuitConfig::large_zk_config();
let pw = PartialWitness::new(config.num_wires); let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config); let mut builder = CircuitBuilder::<F, 4>::new(config);

View File

@ -48,7 +48,6 @@ impl Default for CircuitConfig {
proof_of_work_bits: 1, proof_of_work_bits: 1,
reduction_arity_bits: vec![1, 1, 1, 1], reduction_arity_bits: vec![1, 1, 1, 1],
num_query_rounds: 1, num_query_rounds: 1,
cap_height: 1,
}, },
} }
} }
@ -66,14 +65,25 @@ impl CircuitConfig {
security_bits: 128, security_bits: 128,
rate_bits: 3, rate_bits: 3,
num_challenges: 3, num_challenges: 3,
zero_knowledge: true, zero_knowledge: false,
cap_height: 1, cap_height: 1,
fri_config: FriConfig {
proof_of_work_bits: 1,
reduction_arity_bits: vec![1],
num_query_rounds: 1,
},
}
}
pub(crate) fn large_zk_config() -> Self {
CircuitConfig {
zero_knowledge: true,
fri_config: FriConfig { fri_config: FriConfig {
proof_of_work_bits: 1, proof_of_work_bits: 1,
reduction_arity_bits: vec![1, 1, 1, 1], reduction_arity_bits: vec![1, 1, 1, 1],
num_query_rounds: 1, num_query_rounds: 1,
cap_height: 1,
}, },
..Self::large_config()
} }
} }
} }

View File

@ -375,7 +375,6 @@ mod tests {
proof_of_work_bits: 1, proof_of_work_bits: 1,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], reduction_arity_bits: vec![2, 2, 2, 2, 2, 2],
num_query_rounds: 40, num_query_rounds: 40,
cap_height: 1,
}, },
}; };
let (proof_with_pis, vd, cd) = { let (proof_with_pis, vd, cd) = {
@ -431,7 +430,6 @@ mod tests {
proof_of_work_bits: 1, proof_of_work_bits: 1,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], reduction_arity_bits: vec![2, 2, 2, 2, 2, 2],
num_query_rounds: 40, num_query_rounds: 40,
cap_height: 3,
}, },
}; };
let (proof_with_pis, vd, cd) = { let (proof_with_pis, vd, cd) = {

View File

@ -26,7 +26,7 @@ pub(crate) fn log2_ceil(n: usize) -> usize {
/// Computes `log_2(n)`, panicking if `n` is not a power of two. /// Computes `log_2(n)`, panicking if `n` is not a power of two.
pub(crate) fn log2_strict(n: usize) -> usize { pub(crate) fn log2_strict(n: usize) -> usize {
assert!(n.is_power_of_two(), "Not a power of two"); assert!(n.is_power_of_two(), "Not a power of two: {}", n);
log2_ceil(n) log2_ceil(n)
} }