Merge branch 'main' into optimize_arithmetic_ops

This commit is contained in:
wborgeaud 2021-08-10 09:11:08 +02:00
commit 4433fd8048
22 changed files with 163 additions and 113 deletions

View File

@ -12,12 +12,12 @@ edition = "2018"
default-run = "bench_recursion"
[dependencies]
env_logger = "0.8.3"
env_logger = "0.9.0"
log = "0.4.14"
itertools = "0.10.0"
num = "0.3"
rand = "0.7.3"
rand_chacha = "0.2.2"
num = "0.4"
rand = "0.8.4"
rand_chacha = "0.3.1"
rayon = "1.5.1"
unroll = "0.1.5"
anyhow = "1.0.40"

View File

@ -34,6 +34,7 @@ fn bench_prove<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
},
};
let inputs = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config);
let zero = builder.zero();
@ -49,7 +50,6 @@ fn bench_prove<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
builder.add_extension(zero_ext, zero_ext);
let circuit = builder.build();
let inputs = PartialWitness::new();
let proof_with_pis = circuit.prove(inputs)?;
let proof_bytes = serde_cbor::to_vec(&proof_with_pis).unwrap();
info!("Proof length: {} bytes", proof_bytes.len());

View File

@ -343,7 +343,7 @@ impl Field for CrandallField {
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self::from_canonical_u64(rng.gen_range(0, FIELD_ORDER))
Self::from_canonical_u64(rng.gen_range(0..FIELD_ORDER))
}
}

View File

@ -13,7 +13,7 @@ enum FftStrategy {
const FFT_STRATEGY: FftStrategy = FftStrategy::Classic;
type FftRootTable<F> = Vec<Vec<F>>;
pub(crate) type FftRootTable<F> = Vec<Vec<F>>;
fn fft_classic_root_table<F: Field>(n: usize) -> FftRootTable<F> {
let lg_n = log2_strict(n);

View File

@ -23,7 +23,6 @@ pub const SALT_SIZE: usize = 2;
pub struct PolynomialBatchCommitment<F: Field> {
pub polynomials: Vec<PolynomialCoeffs<F>>,
pub merkle_tree: MerkleTree<F>,
pub degree: usize,
pub degree_log: usize,
pub rate_bits: usize,
pub blinding: bool,
@ -31,25 +30,23 @@ pub struct PolynomialBatchCommitment<F: Field> {
impl<F: Field> PolynomialBatchCommitment<F> {
/// Creates a list polynomial commitment for the polynomials interpolating the values in `values`.
pub(crate) fn new(
pub(crate) fn from_values(
values: Vec<PolynomialValues<F>>,
rate_bits: usize,
blinding: bool,
timing: &mut TimingTree,
) -> Self {
let degree = values[0].len();
let polynomials = values.par_iter().map(|v| v.ifft()).collect::<Vec<_>>();
let lde_values = timed!(
let coeffs = timed!(
timing,
"compute LDE",
Self::lde_values(&polynomials, rate_bits, blinding)
"IFFT",
values.par_iter().map(|v| v.ifft()).collect::<Vec<_>>()
);
Self::new_from_data(polynomials, lde_values, degree, rate_bits, blinding, timing)
Self::from_coeffs(coeffs, rate_bits, blinding, timing)
}
/// Creates a list polynomial commitment for the polynomials `polynomials`.
pub(crate) fn new_from_polys(
pub(crate) fn from_coeffs(
polynomials: Vec<PolynomialCoeffs<F>>,
rate_bits: usize,
blinding: bool,
@ -58,21 +55,10 @@ impl<F: Field> PolynomialBatchCommitment<F> {
let degree = polynomials[0].len();
let lde_values = timed!(
timing,
"compute LDE",
"FFT + blinding",
Self::lde_values(&polynomials, rate_bits, blinding)
);
Self::new_from_data(polynomials, lde_values, degree, rate_bits, blinding, timing)
}
fn new_from_data(
polynomials: Vec<PolynomialCoeffs<F>>,
lde_values: Vec<Vec<F>>,
degree: usize,
rate_bits: usize,
blinding: bool,
timing: &mut TimingTree,
) -> Self {
let mut leaves = timed!(timing, "transpose LDEs", transpose(&lde_values));
reverse_index_bits_in_place(&mut leaves);
let merkle_tree = timed!(timing, "build Merkle tree", MerkleTree::new(leaves, false));
@ -80,7 +66,6 @@ impl<F: Field> PolynomialBatchCommitment<F> {
Self {
polynomials,
merkle_tree,
degree,
degree_log: log2_strict(degree),
rate_bits,
blinding,
@ -93,20 +78,23 @@ impl<F: Field> PolynomialBatchCommitment<F> {
blinding: bool,
) -> Vec<Vec<F>> {
let degree = polynomials[0].len();
// If blinding, salt with two random elements to each leaf vector.
let salt_size = if blinding { SALT_SIZE } else { 0 };
polynomials
.par_iter()
.map(|p| {
assert_eq!(p.len(), degree, "Polynomial degree invalid.");
p.lde(rate_bits).coset_fft(F::coset_shift()).values
})
.chain(if blinding {
// If blinding, salt with two random elements to each leaf vector.
(0..SALT_SIZE)
.map(|_| F::rand_vec(degree << rate_bits))
.collect()
} else {
Vec::new()
assert_eq!(p.len(), degree, "Polynomial degrees inconsistent");
p.lde(rate_bits)
.coset_fft_with_options(F::coset_shift(), Some(rate_bits), None)
.values
})
.chain(
(0..salt_size)
.into_par_iter()
.map(|_| F::rand_vec(degree << rate_bits)),
)
.collect()
}
@ -306,7 +294,7 @@ mod tests {
let lpcs = (0..4)
.map(|i| {
PolynomialBatchCommitment::<F>::new(
PolynomialBatchCommitment::<F>::from_values(
gen_random_test_case(ks[i], degree_bits),
common_data.config.rate_bits,
PlonkPolynomials::polynomials(i).blinding,

View File

@ -712,8 +712,8 @@ mod tests {
let config = CircuitConfig::large_config();
let mut pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config);
let mut pw = PartialWitness::new();
let vs = FF::rand_vec(3);
let ts = builder.add_virtual_extension_targets(3);
@ -749,6 +749,7 @@ mod tests {
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config);
let x = FF::rand();
@ -763,7 +764,7 @@ mod tests {
builder.assert_equal_extension(zt, comp_zt_unsafe);
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}

View File

@ -64,6 +64,7 @@ mod tests {
type FF = QuarticCrandallField;
let len = 1 << len_log;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let v = (0..len - 1)
.map(|_| builder.constant_extension(FF::rand()))
@ -83,7 +84,7 @@ mod tests {
}
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}

View File

@ -74,6 +74,7 @@ mod tests {
type F = CrandallField;
type FF = QuarticCrandallField;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let len = 4;
@ -103,7 +104,7 @@ mod tests {
builder.assert_equal_extension(eval, true_eval_target);
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}
@ -113,6 +114,7 @@ mod tests {
type F = CrandallField;
type FF = QuarticCrandallField;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let len = 2;
@ -137,7 +139,7 @@ mod tests {
builder.assert_equal_extension(eval, true_eval_target);
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}

View File

@ -50,6 +50,7 @@ mod tests {
type FF = QuarticCrandallField;
let len = 1 << len_log;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let vec = FF::rand_vec(len);
let v: Vec<_> = vec.iter().map(|x| builder.constant_extension(*x)).collect();
@ -61,7 +62,7 @@ mod tests {
}
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}

View File

@ -48,8 +48,8 @@ mod tests {
type F = CrandallField;
type FF = QuarticCrandallField;
let config = CircuitConfig::large_config();
let mut pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let mut pw = PartialWitness::new();
let (x, y) = (FF::rand(), FF::rand());
let xt = builder.add_virtual_extension_target();

View File

@ -99,6 +99,7 @@ mod tests {
fn test_split_base() -> Result<()> {
type F = CrandallField;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let x = F::from_canonical_usize(0b110100000); // 416 = 1532 in base 6.
let xt = builder.constant(x);
@ -115,7 +116,7 @@ mod tests {
builder.assert_leading_zeros(xt, 64 - 9);
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}
@ -124,9 +125,10 @@ mod tests {
fn test_base_sum() -> Result<()> {
type F = CrandallField;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let n = thread_rng().gen_range(0, 1 << 10);
let n = thread_rng().gen_range(0..(1 << 10));
let x = builder.constant(F::from_canonical_usize(n));
let zero = builder.zero();
@ -147,7 +149,7 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}

View File

@ -124,8 +124,8 @@ pub(crate) fn test_eval_fns<F: Extendable<D>, G: Gate<F, D>, const D: usize>(
let constants = F::Extension::rand_vec(gate.num_constants());
let config = CircuitConfig::large_config();
let mut pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config);
let mut pw = PartialWitness::new();
let wires_t = builder.add_virtual_extension_targets(wires.len());
let constants_t = builder.add_virtual_extension_targets(constants.len());

View File

@ -64,9 +64,9 @@ impl<F: Extendable<D>, const D: usize> Tree<GateRef<F, D>> {
gates.sort_unstable_by_key(|g| (-(g.0.degree() as isize), -(g.0.num_constants() as isize)));
for max_degree_bits in 1..10 {
// The constraint polynomials are padded to the next power in `compute_vanishig_polys`.
// So we can restrict our search space by setting `max_degree` to a power of 2.
let max_degree = 1 << max_degree_bits;
// The quotient polynomials are padded to the next power of 2 in `compute_quotient_polys`.
// So we can restrict our search space by setting `max_degree` to 1 + a power of 2.
let max_degree = (1 << max_degree_bits) + 1;
for max_constants in 1..100 {
if let Some(mut best_tree) = Self::find_tree(&gates, max_degree, max_constants) {
let mut best_num_constants = best_tree.num_constants();

View File

@ -357,7 +357,7 @@ mod tests {
let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::<Vec<_>>();
let mut witness = PartialWitness::new();
let mut witness = PartialWitness::new(gate.num_wires());
witness.set_wire(
Wire {
gate: 0,

View File

@ -154,14 +154,14 @@ mod tests {
fn test_recursive_merkle_proof() -> Result<()> {
type F = CrandallField;
let config = CircuitConfig::large_config();
let mut pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let mut pw = PartialWitness::new();
let log_n = 8;
let n = 1 << log_n;
let leaves = random_data::<F>(n, 7);
let tree = MerkleTree::new(leaves, false);
let i: usize = thread_rng().gen_range(0, n);
let i: usize = thread_rng().gen_range(0..n);
let proof = tree.prove(i);
let proof_t = MerkleProofTarget {

View File

@ -399,6 +399,7 @@ mod tests {
num_routed_wires: 27,
..CircuitConfig::default()
};
let mut witness = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config.clone());
let mut recursive_challenger = RecursiveChallenger::new(&mut builder);
let mut recursive_outputs_per_round: Vec<Vec<Target>> = Vec::new();
@ -409,7 +410,6 @@ mod tests {
);
}
let circuit = builder.build();
let mut witness = PartialWitness::new();
generate_partial_witness(
&mut witness,
&circuit.prover_only.generators,

View File

@ -26,22 +26,23 @@ impl<F: Field> Witness<F> {
#[derive(Clone, Debug)]
pub struct PartialWitness<F: Field> {
pub(crate) target_values: HashMap<Target, F>,
pub(crate) wire_values: Vec<Vec<Option<F>>>,
pub(crate) virtual_target_values: Vec<Option<F>>,
}
impl<F: Field> PartialWitness<F> {
pub fn new() -> Self {
pub fn new(num_wires: usize) -> Self {
PartialWitness {
target_values: HashMap::new(),
wire_values: vec![vec![None; num_wires]],
virtual_target_values: vec![],
}
}
pub fn is_empty(&self) -> bool {
self.target_values.is_empty()
}
pub fn get_target(&self, target: Target) -> F {
self.target_values[&target]
match target {
Target::Wire(Wire { gate, input }) => self.wire_values[gate][input].unwrap(),
Target::VirtualTarget { index } => self.virtual_target_values[index].unwrap(),
}
}
pub fn get_targets(&self, targets: &[Target]) -> Vec<F> {
@ -76,7 +77,10 @@ impl<F: Field> PartialWitness<F> {
}
pub fn try_get_target(&self, target: Target) -> Option<F> {
self.target_values.get(&target).cloned()
match target {
Target::Wire(Wire { gate, input }) => self.wire_values[gate][input],
Target::VirtualTarget { index } => self.virtual_target_values[index],
}
}
pub fn get_wire(&self, wire: Wire) -> F {
@ -88,7 +92,15 @@ impl<F: Field> PartialWitness<F> {
}
pub fn contains(&self, target: Target) -> bool {
self.target_values.contains_key(&target)
match target {
Target::Wire(Wire { gate, input }) => {
self.wire_values.len() > gate && self.wire_values[gate][input].is_some()
}
Target::VirtualTarget { index } => {
self.virtual_target_values.len() > index
&& self.virtual_target_values[index].is_some()
}
}
}
pub fn contains_all(&self, targets: &[Target]) -> bool {
@ -96,13 +108,36 @@ impl<F: Field> PartialWitness<F> {
}
pub fn set_target(&mut self, target: Target, value: F) {
let opt_old_value = self.target_values.insert(target, value);
if let Some(old_value) = opt_old_value {
assert_eq!(
old_value, value,
"Target was set twice with different values: {:?}",
target
);
match target {
Target::Wire(Wire { gate, input }) => {
if gate >= self.wire_values.len() {
self.wire_values
.resize(gate + 1, vec![None; self.wire_values[0].len()]);
}
if let Some(old_value) = self.wire_values[gate][input] {
assert_eq!(
old_value, value,
"Target was set twice with different values: {:?}",
target
);
} else {
self.wire_values[gate][input] = Some(value);
}
}
Target::VirtualTarget { index } => {
if index >= self.virtual_target_values.len() {
self.virtual_target_values.resize(index + 1, None);
}
if let Some(old_value) = self.virtual_target_values[index] {
assert_eq!(
old_value, value,
"Target was set twice with different values: {:?}",
target
);
} else {
self.virtual_target_values[index] = Some(value);
}
}
}
}
@ -162,16 +197,19 @@ impl<F: Field> PartialWitness<F> {
}
pub fn extend<I: Iterator<Item = (Target, F)>>(&mut self, pairs: I) {
self.target_values.extend(pairs);
for (t, v) in pairs {
self.set_target(t, v);
}
}
pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness<F> {
let mut wire_values = vec![vec![F::ZERO; degree]; num_wires];
self.target_values.into_iter().for_each(|(t, v)| {
if let Target::Wire(Wire { gate, input }) = t {
wire_values[input][gate] = v;
assert!(self.wire_values.len() <= degree);
for i in 0..self.wire_values.len() {
for j in 0..num_wires {
wire_values[j][i] = self.wire_values[i][j].unwrap_or(F::ZERO);
}
});
}
Witness { wire_values }
}
@ -212,9 +250,3 @@ impl<F: Field> PartialWitness<F> {
Ok(())
}
}
impl<F: Field> Default for PartialWitness<F> {
fn default() -> Self {
Self::new()
}
}

View File

@ -506,7 +506,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Builds a "full circuit", with both prover and verifier data.
pub fn build(mut self) -> CircuitData<F, D> {
let mut timing = TimingTree::new("preprocess", Level::Trace);
let quotient_degree_factor = 7; // TODO: add this as a parameter.
let start = Instant::now();
// Hash the public inputs, and route them to a `PublicInputGate` which will enforce that
@ -541,10 +540,13 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let gates = self.gates.iter().cloned().collect();
let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates);
assert!(
max_filtered_constraint_degree <= quotient_degree_factor + 1,
"Constraints are too high degree."
);
// `quotient_degree_factor` has to be between `max_filtered_constraint_degree-1` and `1<<rate_bits`.
// We find the value that minimizes `num_partial_product + quotient_degree_factor`.
let quotient_degree_factor = (max_filtered_constraint_degree - 1
..=1 << self.config.rate_bits)
.min_by_key(|&q| num_partial_products(self.config.num_routed_wires, q).0 + q)
.unwrap();
info!("Quotient degree factor set to: {}.", quotient_degree_factor);
let prefixed_gates = PrefixedGate::from_tree(gate_tree);
let subgroup = F::two_adic_subgroup(degree_bits);
@ -555,7 +557,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let sigma_vecs = self.sigma_vecs(&k_is, &subgroup);
let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat();
let constants_sigmas_commitment = PolynomialBatchCommitment::new(
let constants_sigmas_commitment = PolynomialBatchCommitment::from_values(
constants_sigmas_vecs,
self.config.rate_bits,
self.config.zero_knowledge & PlonkPolynomials::CONSTANTS_SIGMAS.blinding,

View File

@ -81,7 +81,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let wires_commitment = timed!(
timing,
"compute wires commitment",
PolynomialBatchCommitment::new(
PolynomialBatchCommitment::from_values(
wires_values,
config.rate_bits,
config.zero_knowledge & PlonkPolynomials::WIRES.blinding,
@ -125,7 +125,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let zs_partial_products_commitment = timed!(
timing,
"commit to Z's",
PolynomialBatchCommitment::new(
PolynomialBatchCommitment::from_values(
zs_partial_products,
config.rate_bits,
config.zero_knowledge & PlonkPolynomials::ZS_PARTIAL_PRODUCTS.blinding,
@ -173,7 +173,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let quotient_polys_commitment = timed!(
timing,
"commit to quotient polys",
PolynomialBatchCommitment::new_from_polys(
PolynomialBatchCommitment::from_coeffs(
all_quotient_poly_chunks,
config.rate_bits,
config.zero_knowledge & PlonkPolynomials::QUOTIENT.blinding,
@ -332,7 +332,7 @@ fn compute_quotient_polys<'a, F: Extendable<D>, const D: usize>(
alphas: &[F],
) -> Vec<PolynomialCoeffs<F>> {
let num_challenges = common_data.config.num_challenges;
let max_degree_bits = log2_ceil(common_data.quotient_degree_factor + 1);
let max_degree_bits = log2_ceil(common_data.quotient_degree_factor);
assert!(
max_degree_bits <= common_data.config.rate_bits,
"Having constraints of degree higher than the rate is not supported yet. \

View File

@ -383,7 +383,7 @@ mod tests {
}
let data = builder.build();
(
data.prove(PartialWitness::new())?,
data.prove(PartialWitness::new(config.num_wires))?,
data.verifier_only,
data.common,
)
@ -391,7 +391,7 @@ mod tests {
verify(proof_with_pis.clone(), &vd, &cd)?;
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let mut pw = PartialWitness::new();
let mut pw = PartialWitness::new(config.num_wires);
let pt = proof_to_proof_target(&proof_with_pis, &mut builder);
set_proof_target(&proof_with_pis, &pt, &mut pw);
@ -438,7 +438,7 @@ mod tests {
}
let data = builder.build();
(
data.prove(PartialWitness::new())?,
data.prove(PartialWitness::new(config.num_wires))?,
data.verifier_only,
data.common,
)
@ -446,7 +446,7 @@ mod tests {
verify(proof_with_pis.clone(), &vd, &cd)?;
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let mut pw = PartialWitness::new();
let mut pw = PartialWitness::new(config.num_wires);
let pt = proof_to_proof_target(&proof_with_pis, &mut builder);
set_proof_target(&proof_with_pis, &pt, &mut pw);
@ -464,7 +464,7 @@ mod tests {
verify(proof_with_pis.clone(), &vd, &cd)?;
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let mut pw = PartialWitness::new();
let mut pw = PartialWitness::new(config.num_wires);
let pt = proof_to_proof_target(&proof_with_pis, &mut builder);
set_proof_target(&proof_with_pis, &pt, &mut pw);

View File

@ -6,6 +6,7 @@ use anyhow::{ensure, Result};
use serde::{Deserialize, Serialize};
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::fft::FftRootTable;
use crate::field::fft::{fft, fft_with_options, ifft};
use crate::field::field_types::Field;
use crate::util::log2_strict;
@ -198,15 +199,33 @@ impl<F: Field> PolynomialCoeffs<F> {
fft(self)
}
pub fn fft_with_options(
&self,
zero_factor: Option<usize>,
root_table: Option<FftRootTable<F>>,
) -> PolynomialValues<F> {
fft_with_options(self, zero_factor, root_table)
}
/// Returns the evaluation of the polynomial on the coset `shift*H`.
pub fn coset_fft(&self, shift: F) -> PolynomialValues<F> {
self.coset_fft_with_options(shift, None, None)
}
/// Returns the evaluation of the polynomial on the coset `shift*H`.
pub fn coset_fft_with_options(
&self,
shift: F,
zero_factor: Option<usize>,
root_table: Option<FftRootTable<F>>,
) -> PolynomialValues<F> {
let modified_poly: Self = shift
.powers()
.zip(&self.coeffs)
.map(|(r, &c)| r * c)
.collect::<Vec<_>>()
.into();
modified_poly.fft()
modified_poly.fft_with_options(zero_factor, root_table)
}
pub fn to_extension<const D: usize>(&self) -> PolynomialCoeffs<F::Extension>
@ -434,7 +453,7 @@ mod tests {
fn test_polynomial_multiplication() {
type F = CrandallField;
let mut rng = thread_rng();
let (a_deg, b_deg) = (rng.gen_range(1, 10_000), rng.gen_range(1, 10_000));
let (a_deg, b_deg) = (rng.gen_range(1..10_000), rng.gen_range(1..10_000));
let a = PolynomialCoeffs::new(F::rand_vec(a_deg));
let b = PolynomialCoeffs::new(F::rand_vec(b_deg));
let m1 = &a * &b;
@ -450,8 +469,8 @@ mod tests {
fn test_inv_mod_xn() {
type F = CrandallField;
let mut rng = thread_rng();
let a_deg = rng.gen_range(1, 1_000);
let n = rng.gen_range(1, 1_000);
let a_deg = rng.gen_range(1..1_000);
let n = rng.gen_range(1..1_000);
let a = PolynomialCoeffs::new(F::rand_vec(a_deg));
let b = a.inv_mod_xn(n);
let mut m = &a * &b;
@ -472,7 +491,7 @@ mod tests {
fn test_polynomial_long_division() {
type F = CrandallField;
let mut rng = thread_rng();
let (a_deg, b_deg) = (rng.gen_range(1, 10_000), rng.gen_range(1, 10_000));
let (a_deg, b_deg) = (rng.gen_range(1..10_000), rng.gen_range(1..10_000));
let a = PolynomialCoeffs::new(F::rand_vec(a_deg));
let b = PolynomialCoeffs::new(F::rand_vec(b_deg));
let (q, r) = a.div_rem_long_division(&b);
@ -486,7 +505,7 @@ mod tests {
fn test_polynomial_division() {
type F = CrandallField;
let mut rng = thread_rng();
let (a_deg, b_deg) = (rng.gen_range(1, 10_000), rng.gen_range(1, 10_000));
let (a_deg, b_deg) = (rng.gen_range(1..10_000), rng.gen_range(1..10_000));
let a = PolynomialCoeffs::new(F::rand_vec(a_deg));
let b = PolynomialCoeffs::new(F::rand_vec(b_deg));
let (q, r) = a.div_rem(&b);
@ -500,7 +519,7 @@ mod tests {
fn test_polynomial_division_by_constant() {
type F = CrandallField;
let mut rng = thread_rng();
let a_deg = rng.gen_range(1, 10_000);
let a_deg = rng.gen_range(1..10_000);
let a = PolynomialCoeffs::new(F::rand_vec(a_deg));
let b = PolynomialCoeffs::from(vec![F::rand()]);
let (q, r) = a.div_rem(&b);
@ -514,8 +533,8 @@ mod tests {
fn test_division_by_z_h() {
type F = CrandallField;
let mut rng = thread_rng();
let a_deg = rng.gen_range(1, 10_000);
let n = rng.gen_range(1, a_deg);
let a_deg = rng.gen_range(1..10_000);
let n = rng.gen_range(1..a_deg);
let mut a = PolynomialCoeffs::new(F::rand_vec(a_deg));
a.trim();
let z_h = {
@ -554,7 +573,7 @@ mod tests {
PolynomialCoeffs::new(xn_min_one_vec)
};
let a = g.exp(rng.gen_range(0, n as u64));
let a = g.exp(rng.gen_range(0..(n as u64)));
let denom = PolynomialCoeffs::new(vec![-a, F::ONE]);
let now = Instant::now();
xn_minus_one.div_rem(&denom);

View File

@ -249,6 +249,7 @@ mod tests {
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config);
let alpha = FF::rand();
@ -264,7 +265,7 @@ mod tests {
builder.assert_equal_extension(manual_reduce, circuit_reduce);
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}
@ -276,6 +277,7 @@ mod tests {
let config = CircuitConfig::large_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, D>::new(config);
let alpha = FF::rand();
@ -294,7 +296,7 @@ mod tests {
builder.assert_equal_extension(manual_reduce, circuit_reduce);
let data = builder.build();
let proof = data.prove(PartialWitness::new())?;
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}