Skip to content
This repository has been archived by the owner on Dec 9, 2021. It is now read-only.

Commit

Permalink
CurveEndoGate2 generator
Browse files Browse the repository at this point in the history
  • Loading branch information
dlubarov committed Dec 11, 2020
1 parent 5ff0d41 commit 4802159
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 18 deletions.
74 changes: 67 additions & 7 deletions src/gates2/curve_endo.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
use std::marker::PhantomData;

use crate::{CircuitConfig, ConstraintPolynomial, Curve, Gate2, SimpleGenerator, WitnessGenerator2};
use crate::{CircuitConfig, ConstraintPolynomial, Curve, Field, Gate2, PartialWitness2, SimpleGenerator, Target2, Wire, WitnessGenerator2, HaloCurve};

/// Performs a step of Halo's accumulate-with-endomorphism loop.
pub struct CurveEndoGate2<C: Curve> {
pub struct CurveEndoGate2<C: HaloCurve> {
_phantom: PhantomData<C>,
}

impl<C: Curve> CurveEndoGate2<C> {
impl<C: HaloCurve> CurveEndoGate2<C> {
pub const WIRE_ADDEND_X: usize = 0;
pub const WIRE_ADDEND_Y: usize = 1;
pub const WIRE_SCALAR_BIT_0: usize = 2;
pub const WIRE_SCALAR_BIT_1: usize = 3;
pub const WIRE_GROUP_ACC_X: usize = 4;
pub const WIRE_GROUP_ACC_Y: usize = 5;
pub const WIRE_INVERSE: usize = 6;
pub const WIRE_LAMBDA: usize = 7;
}

impl<C: Curve> Gate2<C::BaseField> for CurveEndoGate2<C> {
impl<C: HaloCurve> Gate2<C::BaseField> for CurveEndoGate2<C> {
fn id(&self) -> String {
"CurveEndoGate".into()
}
Expand All @@ -33,13 +34,72 @@ impl<C: Curve> Gate2<C::BaseField> for CurveEndoGate2<C> {
_local_constants: Vec<C::BaseField>,
_next_constants: Vec<<C as Curve>::BaseField>,
) -> Vec<Box<dyn WitnessGenerator2<C::BaseField>>> {
unimplemented!()
vec![CurveEndoGateGenerator { gate_index, _phantom: PhantomData }]
}
}

struct CurveEndoGateGenerator<C: Curve> {
struct CurveEndoGateGenerator<C: HaloCurve> {
gate_index: usize,
_phantom: PhantomData<C>,
}

impl<C: Curve> SimpleGenerator<C::BaseField> for CurveEndoGateGenerator<C> {}
impl<C: HaloCurve> SimpleGenerator<C::BaseField> for CurveEndoGateGenerator<C> {
fn dependencies(&self) -> Vec<Target2<C::BaseField>> {
vec![
Target2::Wire(Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_ADDEND_X }),
Target2::Wire(Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_ADDEND_Y }),
Target2::Wire(Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_SCALAR_BIT_0 }),
Target2::Wire(Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_SCALAR_BIT_1 }),
Target2::Wire(Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_GROUP_ACC_X }),
Target2::Wire(Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_GROUP_ACC_Y }),
]
}

fn run_once(
&mut self,
witness: &PartialWitness2<C::BaseField>,
) -> PartialWitness2<C::BaseField> {
let addend_x_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_ADDEND_X };
let addend_y_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_ADDEND_Y };
let scalar_bit_0_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_SCALAR_BIT_0 };
let scalar_bit_1_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_SCALAR_BIT_1 };
let group_acc_old_x_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_GROUP_ACC_X };
let group_acc_old_y_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_GROUP_ACC_Y };
let group_acc_new_x_wire = Wire { gate: self.gate_index + 1, input: CurveEndoGate2::<C>::WIRE_GROUP_ACC_X };
let group_acc_new_y_wire = Wire { gate: self.gate_index + 1, input: CurveEndoGate2::<C>::WIRE_GROUP_ACC_Y };
let inverse_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_INVERSE };
let lambda_wire = Wire { gate: self.gate_index, input: CurveEndoGate2::<C>::WIRE_LAMBDA };

let addend_x = witness.get_wire(addend_x_wire);
let addend_y = witness.get_wire(addend_y_wire);
let scalar_bit_0 = witness.get_wire(scalar_bit_0_wire);
let scalar_bit_1 = witness.get_wire(scalar_bit_1_wire);
let group_acc_old_x = witness.get_wire(group_acc_old_x_wire);
let group_acc_old_y = witness.get_wire(group_acc_old_y_wire);

// Compute S_i as defined in Halo.
let mut s_i_x = addend_x;
if scalar_bit_0 == C::BaseField::ONE {
s_i_x = s_i_x * C::ZETA;
}
let mut s_i_y = addend_y;
if scalar_bit_1 == C::BaseField::ZERO {
s_i_y = -s_i_y;
}

// Compute group_acc_new = group_acc_old_x + s_i.
let dx = group_acc_old_x - s_i_x;
let dy = group_acc_old_y - s_i_y;
let inverse = dx.multiplicative_inverse().expect("x_1 = x_2");
let lambda = dy * inverse;
let group_acc_new_x = lambda.square() - group_acc_old_x - s_i_x;
let group_acc_new_y = lambda * (group_acc_old_x - group_acc_new_x) - group_acc_old_y;

let mut result = PartialWitness2::new();
result.set_wire(inverse_wire, inverse);
result.set_wire(lambda_wire, lambda);
result.set_wire(group_acc_new_x_wire, group_acc_new_x);
result.set_wire(group_acc_new_y_wire, group_acc_new_y);
result
}
}
4 changes: 2 additions & 2 deletions src/gates2/deterministic_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ impl<F: Field> SimpleGenerator<F> for OutputGenerator<F> {
// Lookup the values if they exist. If not, we can just insert a zero, knowing
// that it will not be used. (If it was used, it would have been included in our
// dependencies, and this generator would not have run yet.)
let local_value = witness.try_get(Target2::Wire(local_wire)).unwrap_or(F::ZERO);
let next_value = witness.try_get(Target2::Wire(next_wire)).unwrap_or(F::ZERO);
let local_value = witness.try_get_target(Target2::Wire(local_wire)).unwrap_or(F::ZERO);
let next_value = witness.try_get_target(Target2::Wire(next_wire)).unwrap_or(F::ZERO);

local_wire_values.push(local_value);
next_wire_values.push(next_value);
Expand Down
2 changes: 1 addition & 1 deletion src/plonk2/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<F: Field> SimpleGenerator<F> for CopyGenerator<F> {
}

fn run_once(&mut self, witness: &PartialWitness2<F>) -> PartialWitness2<F> {
let value = witness.get(self.src);
let value = witness.get_target(self.src);
PartialWitness2::singleton(self.dst, value)
}
}
16 changes: 8 additions & 8 deletions src/plonk2/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ impl<F: Field> PartialWitness2<F> {

pub fn singleton(target: Target2<F>, value: F) -> Self {
let mut witness = PartialWitness2::new();
witness.set(target, value);
witness.set_target(target, value);
witness
}

pub fn is_empty(&self) -> bool {
self.target_values.is_empty()
}

pub fn get(&self, target: Target2<F>) -> F {
pub fn get_target(&self, target: Target2<F>) -> F {
self.target_values[&target]
}

pub fn get_wire(&self, wire: Wire) -> F {
self.get(Target2::Wire(wire))
pub fn try_get_target(&self, target: Target2<F>) -> Option<F> {
self.target_values.get(&target).cloned()
}

pub fn try_get(&self, target: Target2<F>) -> Option<F> {
self.target_values.get(&target).cloned()
pub fn get_wire(&self, wire: Wire) -> F {
self.get_target(Target2::Wire(wire))
}

pub fn contains(&self, target: Target2<F>) -> bool {
Expand All @@ -44,11 +44,11 @@ impl<F: Field> PartialWitness2<F> {
targets.iter().all(|&t| self.contains(t))
}

pub fn set(&mut self, target: Target2<F>, value: F) {
pub fn set_target(&mut self, target: Target2<F>, value: F) {
self.target_values.insert(target, value);
}

pub fn set_wire(&mut self, wire: Wire, value: F) {
self.set(Target2::Wire(wire), value)
self.set_target(Target2::Wire(wire), value)
}
}

0 comments on commit 4802159

Please sign in to comment.