Division gadget for extension field

This commit is contained in:
wborgeaud 2021-06-07 17:55:27 +02:00
parent a8da9b945e
commit 8cf2758b6c
4 changed files with 110 additions and 25 deletions

View File

@ -8,6 +8,7 @@ use crate::circuit_data::{
VerifierCircuitData, VerifierOnlyCircuitData,
};
use crate::field::cosets::get_unique_coset_shifts;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field::Field;
use crate::gates::constant::ConstantGate;
@ -130,6 +131,12 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.assert_equal(src, dst);
}
pub fn route_extension(&mut self, src: ExtensionTarget<D>, dst: ExtensionTarget<D>) {
for i in 0..D {
self.route(src.0[i], dst.0[i]);
}
}
/// Adds a generator which will copy `src` to `dst`.
pub fn generate_copy(&mut self, src: Target, dst: Target) {
self.add_generator(CopyGenerator { src, dst });
@ -154,6 +161,12 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.assert_equal(x, zero);
}
pub fn assert_equal_extension(&mut self, x: ExtensionTarget<D>, y: ExtensionTarget<D>) {
for i in 0..D {
self.assert_equal(x.0[i], y.0[i]);
}
}
pub fn add_generators(&mut self, generators: Vec<Box<dyn WitnessGenerator<F>>>) {
self.generators.extend(generators);
}

View File

@ -3,10 +3,12 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field::Field;
use crate::gates::arithmetic::ArithmeticGate;
use crate::gates::mul_extension::MulExtensionGate;
use crate::generator::SimpleGenerator;
use crate::target::Target;
use crate::wire::Wire;
use crate::witness::PartialWitness;
use std::convert::TryInto;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Computes `-x`.
@ -234,32 +236,32 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
y: ExtensionTarget<D>,
) -> ExtensionTarget<D> {
// Add an `ArithmeticGate` to compute `q * y`.
let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ZERO]);
let gate = self.add_gate(MulExtensionGate::new(), vec![F::ONE]);
let wire_multiplicand_0 = Wire {
gate,
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
};
let wire_multiplicand_1 = Wire {
gate,
input: ArithmeticGate::WIRE_MULTIPLICAND_1,
};
let wire_addend = Wire {
gate,
input: ArithmeticGate::WIRE_ADDEND,
};
let wire_output = Wire {
gate,
input: ArithmeticGate::WIRE_OUTPUT,
};
let multiplicand_0 = MulExtensionGate::<D>::wires_multiplicand_0()
.map(|i| Target::Wire(Wire { gate, input: i }))
.collect::<Vec<_>>();
let multiplicand_0 = ExtensionTarget(multiplicand_0.try_into().unwrap());
let multiplicand_1 = MulExtensionGate::<D>::wires_multiplicand_1()
.map(|i| Target::Wire(Wire { gate, input: i }))
.collect::<Vec<_>>();
let multiplicand_1 = ExtensionTarget(multiplicand_1.try_into().unwrap());
let output = MulExtensionGate::<D>::wires_output()
.map(|i| Target::Wire(Wire { gate, input: i }))
.collect::<Vec<_>>();
let output = ExtensionTarget(output.try_into().unwrap());
let q = Target::Wire(wire_multiplicand_0);
todo!()
// self.add_generator(QuotientGeneratorExtension {
// numerator: x,
// denominator: ExtensionTarget(),
// quotient: ExtensionTarget(),
// })
self.add_generator(QuotientGeneratorExtension {
numerator: x,
denominator: y,
quotient: multiplicand_0,
});
self.route_extension(y, multiplicand_1);
self.assert_equal_extension(output, x);
multiplicand_0
}
}
@ -335,3 +337,53 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
}
#[cfg(test)]
mod tests {
use crate::circuit_builder::CircuitBuilder;
use crate::circuit_data::CircuitConfig;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::field::Field;
use crate::fri::FriConfig;
use crate::prover::PLONK_BLINDING;
use crate::witness::PartialWitness;
#[test]
fn test_div_extension() {
type F = CrandallField;
type FF = QuarticCrandallField;
const D: usize = 4;
let config = CircuitConfig {
num_wires: 134,
num_routed_wires: 12,
security_bits: 128,
rate_bits: 0,
num_challenges: 3,
fri_config: FriConfig {
proof_of_work_bits: 1,
rate_bits: 0,
reduction_arity_bits: vec![1],
num_query_rounds: 1,
blinding: PLONK_BLINDING.to_vec(),
},
};
let mut builder = CircuitBuilder::<F, D>::new(config);
let x = FF::rand();
let y = FF::rand();
let x = FF::TWO;
let y = FF::ONE;
let z = x / y;
let xt = builder.constant_extension(x);
let yt = builder.constant_extension(y);
let zt = builder.constant_extension(z);
let comp_zt = builder.div_unsafe_extension(xt, yt);
builder.assert_equal_extension(zt, comp_zt);
let data = builder.build();
let proof = data.prove(PartialWitness::new());
}
}

View File

@ -4,8 +4,8 @@ pub mod constant;
pub(crate) mod gate;
pub mod gmimc;
mod interpolation;
pub mod mul_extension;
pub(crate) mod noop;
#[cfg(test)]
mod gate_testing;
mod mul_extension;

View File

@ -81,6 +81,26 @@ impl<F: Field> PartialWitness<F> {
}
}
pub fn set_extension_target<const D: usize>(
&mut self,
et: ExtensionTarget<D>,
value: F::Extension,
) where
F: Extendable<D>,
{
let limbs = value.to_basefield_array();
for i in 0..D {
let opt_old_value = self.target_values.insert(et.0[i], limbs[i]);
if let Some(old_value) = opt_old_value {
assert_eq!(
old_value, limbs[i],
"Target was set twice with different values: {:?}",
et.0[i]
);
}
}
}
pub fn set_wire(&mut self, wire: Wire, value: F) {
self.set_target(Target::Wire(wire), value)
}