mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
Progress
This commit is contained in:
parent
f5dfe95b2e
commit
6f2275bc6d
@ -157,16 +157,20 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let evals = [0, 1, 4]
|
||||
.iter()
|
||||
.flat_map(|&i| proof.unsalted_evals(i, config))
|
||||
.map(|&e| F::Extension::from_basefield(e));
|
||||
.map(|&e| self.convert_to_ext(e));
|
||||
let openings = os
|
||||
.constants
|
||||
.iter()
|
||||
.chain(&os.plonk_sigmas)
|
||||
.chain(&os.quotient_polys);
|
||||
let numerator = izip!(evals, openings, &mut alpha_powers)
|
||||
.map(|(e, &o, a)| a * (e - o))
|
||||
.sum::<F::Extension>();
|
||||
let denominator = subgroup_x - zeta;
|
||||
let mut numerator = self.zero_extension();
|
||||
for (e, &o) in izip!(evals, openings) {
|
||||
let a = alpha_powers.next(self);
|
||||
let diff = self.sub_extension(e, o);
|
||||
numerator = self.mul_add_extension(a, diff, numerator);
|
||||
}
|
||||
let denominator = self.sub_extension(subgroup_x, zeta);
|
||||
// let quotient = self.div_unsafe()
|
||||
sum += numerator / denominator;
|
||||
|
||||
let ev: F::Extension = proof
|
||||
|
||||
@ -225,29 +225,40 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
q
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the powers of a certain base element `b`: `b^0, b^1, b^2, ...`.
|
||||
#[derive(Clone)]
|
||||
pub struct PowersTarget<const D: usize> {
|
||||
base: ExtensionTarget<D>,
|
||||
current: ExtensionTarget<D>,
|
||||
}
|
||||
/// Computes `q = x / y` by witnessing `q` and requiring that `q * y = x`. This can be unsafe in
|
||||
/// some cases, as it allows `0 / 0 = <anything>`.
|
||||
pub fn div_unsafe_extension(
|
||||
&mut self,
|
||||
x: ExtensionTarget<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]);
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> PowersTarget<D> {
|
||||
fn next(&mut self, builder: &mut CircuitBuilder<F, D>) -> Option<ExtensionTarget<D>> {
|
||||
let result = self.current;
|
||||
self.current = builder.mul_extension(self.base, self.current);
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
pub fn powers(&mut self, base: ExtensionTarget<D>) -> PowersTarget<D> {
|
||||
PowersTarget {
|
||||
base,
|
||||
current: self.one_extension(),
|
||||
}
|
||||
let q = Target::Wire(wire_multiplicand_0);
|
||||
self.add_generator(QuotientGeneratorExtension {
|
||||
numerator: x,
|
||||
denominator: ExtensionTarget(),
|
||||
quotient: ExtensionTarget(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,3 +279,53 @@ impl<F: Field> SimpleGenerator<F> for QuotientGenerator {
|
||||
PartialWitness::singleton_target(self.quotient, num / den)
|
||||
}
|
||||
}
|
||||
|
||||
struct QuotientGeneratorExtension<const D: usize> {
|
||||
numerator: ExtensionTarget<D>,
|
||||
denominator: ExtensionTarget<D>,
|
||||
quotient: ExtensionTarget<D>,
|
||||
}
|
||||
|
||||
impl<F: Field, const D: usize> SimpleGenerator<F> for QuotientGeneratorExtension<D> {
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
let mut deps = self.numerator.to_target_array().to_vec();
|
||||
deps.extend(&self.denominator.to_target_array());
|
||||
deps
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
|
||||
let num = witness.get_extension_target(self.numerator);
|
||||
let dem = witness.get_extension_target(self.denominator);
|
||||
let quotient = num / dem;
|
||||
let mut pw = PartialWitness::new();
|
||||
pw.set_ext_wires(self.quotient.to_target_array(), quotient);
|
||||
pw
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the powers of a certain base element `b`: `b^0, b^1, b^2, ...`.
|
||||
#[derive(Clone)]
|
||||
pub struct PowersTarget<const D: usize> {
|
||||
base: ExtensionTarget<D>,
|
||||
current: ExtensionTarget<D>,
|
||||
}
|
||||
|
||||
impl<const D: usize> PowersTarget<D> {
|
||||
pub fn next<F: Extendable<D>>(
|
||||
&mut self,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let result = self.current;
|
||||
self.current = builder.mul_extension(self.base, self.current);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
pub fn powers(&mut self, base: ExtensionTarget<D>) -> PowersTarget<D> {
|
||||
PowersTarget {
|
||||
base,
|
||||
current: self.one_extension(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,3 +8,4 @@ pub(crate) mod noop;
|
||||
|
||||
#[cfg(test)]
|
||||
mod gate_testing;
|
||||
mod mul_extension;
|
||||
|
||||
160
src/gates/mul_extension.rs
Normal file
160
src/gates/mul_extension.rs
Normal file
@ -0,0 +1,160 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::wire::Wire;
|
||||
use crate::witness::PartialWitness;
|
||||
use std::ops::Range;
|
||||
|
||||
/// A gate which can multiply to field extension elements.
|
||||
/// TODO: Add an addend if `NUM_ROUTED_WIRES` is large enough.
|
||||
#[derive(Debug)]
|
||||
pub struct MulExtensionGate<const D: usize>;
|
||||
|
||||
impl<const D: usize> MulExtensionGate<D> {
|
||||
pub fn new<F: Extendable<D>>() -> GateRef<F, D> {
|
||||
GateRef::new(MulExtensionGate)
|
||||
}
|
||||
|
||||
pub fn wires_multiplicand_0() -> Range<usize> {
|
||||
0..D
|
||||
}
|
||||
pub fn wires_multiplicand_1() -> Range<usize> {
|
||||
D..2 * D
|
||||
}
|
||||
pub fn wires_output() -> Range<usize> {
|
||||
2 * D..3 * D
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGate<D> {
|
||||
fn id(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
let multiplicand_0 = vars.local_wires[Self::WIRE_MULTIPLICAND_0];
|
||||
let multiplicand_1 = vars.local_wires[Self::WIRE_MULTIPLICAND_1];
|
||||
let addend = vars.local_wires[Self::WIRE_ADDEND];
|
||||
let output = vars.local_wires[Self::WIRE_OUTPUT];
|
||||
let computed_output = const_0 * multiplicand_0 * multiplicand_1 + const_1 * addend;
|
||||
vec![computed_output - output]
|
||||
}
|
||||
|
||||
fn eval_unfiltered_recursively(
|
||||
&self,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
vars: EvaluationTargets<D>,
|
||||
) -> Vec<ExtensionTarget<D>> {
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
let multiplicand_0 = vars.local_wires[Self::WIRE_MULTIPLICAND_0];
|
||||
let multiplicand_1 = vars.local_wires[Self::WIRE_MULTIPLICAND_1];
|
||||
let addend = vars.local_wires[Self::WIRE_ADDEND];
|
||||
let output = vars.local_wires[Self::WIRE_OUTPUT];
|
||||
|
||||
let product_term = builder.mul_many_extension(&[const_0, multiplicand_0, multiplicand_1]);
|
||||
let addend_term = builder.mul_extension(const_1, addend);
|
||||
let computed_output = builder.add_many_extension(&[product_term, addend_term]);
|
||||
vec![builder.sub_extension(computed_output, output)]
|
||||
}
|
||||
|
||||
fn generators(
|
||||
&self,
|
||||
gate_index: usize,
|
||||
local_constants: &[F],
|
||||
) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
let gen = ArithmeticGenerator {
|
||||
gate_index,
|
||||
const_0: local_constants[0],
|
||||
const_1: local_constants[1],
|
||||
};
|
||||
vec![Box::new(gen)]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn num_constants(&self) -> usize {
|
||||
2
|
||||
}
|
||||
|
||||
fn degree(&self) -> usize {
|
||||
3
|
||||
}
|
||||
|
||||
fn num_constraints(&self) -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
struct ArithmeticGenerator<F: Field> {
|
||||
gate_index: usize,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
}
|
||||
|
||||
impl<F: Field> SimpleGenerator<F> for ArithmeticGenerator<F> {
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||
}),
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_1,
|
||||
}),
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_ADDEND,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
|
||||
let multiplicand_0_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||
};
|
||||
let multiplicand_1_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_1,
|
||||
};
|
||||
let addend_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_ADDEND,
|
||||
};
|
||||
let output_target = Wire {
|
||||
gate: self.gate_index,
|
||||
input: ArithmeticGate::WIRE_OUTPUT,
|
||||
};
|
||||
|
||||
let multiplicand_0 = witness.get_wire(multiplicand_0_target);
|
||||
let multiplicand_1 = witness.get_wire(multiplicand_1_target);
|
||||
let addend = witness.get_wire(addend_target);
|
||||
|
||||
let output = self.const_0 * multiplicand_0 * multiplicand_1 + self.const_1 * addend;
|
||||
|
||||
PartialWitness::singleton_wire(output_target, output)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
use crate::gates::arithmetic::ArithmeticGate;
|
||||
use crate::gates::gate_testing::test_low_degree;
|
||||
|
||||
#[test]
|
||||
fn low_degree() {
|
||||
test_low_degree(ArithmeticGate::new::<CrandallField, 4>())
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field::Field;
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PartialWitness<F: Field> {
|
||||
@ -39,6 +41,15 @@ impl<F: Field> PartialWitness<F> {
|
||||
targets.iter().map(|&t| self.get_target(t)).collect()
|
||||
}
|
||||
|
||||
pub fn get_extension_target<const D: usize>(&self, et: ExtensionTarget<D>) -> F::Extension
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
F::Extension::from_basefield_array(
|
||||
self.get_targets(&et.to_target_array()).try_into().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn try_get_target(&self, target: Target) -> Option<F> {
|
||||
self.target_values.get(&target).cloned()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user