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 933a4bc
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 40 deletions.
44 changes: 22 additions & 22 deletions src/gates2/curve_add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,60 +119,60 @@ impl<C: Curve> SimpleGenerator<C::BaseField> for CurveAddGateGenerator<C> {
// - p3 = p1 + p2;
// - p4 = if scalar_bit { p3 } else { p1 }

let x1_target = Wire {
let x1_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_GROUP_ACC_X,
};
let y1_target = Wire {
let y1_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_GROUP_ACC_Y,
};
let x4_target = Wire {
let x4_wire = Wire {
gate: self.gate_index + 1,
input: CurveAddGate2::<C>::WIRE_GROUP_ACC_X,
};
let y4_target = Wire {
let y4_wire = Wire {
gate: self.gate_index + 1,
input: CurveAddGate2::<C>::WIRE_GROUP_ACC_Y,
};
let scalar_acc_old_target = Wire {
let scalar_acc_old_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_SCALAR_ACC_OLD,
};
let scalar_acc_new_target = Wire {
let scalar_acc_new_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_SCALAR_ACC_NEW,
};
let x2_target = Wire {
let x2_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_ADDEND_X,
};
let y2_target = Wire {
let y2_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_ADDEND_Y,
};
let scalar_bit_target = Wire {
let scalar_bit_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_SCALAR_BIT,
};
let inverse_target = Wire {
let inverse_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_INVERSE,
};
let lambda_target = Wire {
let lambda_wire = Wire {
gate: self.gate_index,
input: CurveAddGate2::<C>::WIRE_LAMBDA,
};

let x1 = witness.get_wire(x1_target);
let y1 = witness.get_wire(y1_target);
let x1 = witness.get_wire(x1_wire);
let y1 = witness.get_wire(y1_wire);

let scalar_acc_old = witness.get_wire(scalar_acc_old_target);
let scalar_acc_old = witness.get_wire(scalar_acc_old_wire);

let x2 = witness.get_wire(x2_target);
let y2 = witness.get_wire(y2_target);
let x2 = witness.get_wire(x2_wire);
let y2 = witness.get_wire(y2_wire);

let scalar_bit = witness.get_wire(scalar_bit_target);
let scalar_bit = witness.get_wire(scalar_bit_wire);
debug_assert!(scalar_bit.is_zero() || scalar_bit.is_one());

let scalar_acc_new = scalar_acc_old.double() + scalar_bit;
Expand All @@ -191,11 +191,11 @@ impl<C: Curve> SimpleGenerator<C::BaseField> for CurveAddGateGenerator<C> {
};

let mut result = PartialWitness2::new();
result.set_wire(x4_target, x4);
result.set_wire(y4_target, y4);
result.set_wire(scalar_acc_new_target, scalar_acc_new);
result.set_wire(inverse_target, inverse);
result.set_wire(lambda_target, lambda);
result.set_wire(x4_wire, x4);
result.set_wire(y4_wire, y4);
result.set_wire(scalar_acc_new_wire, scalar_acc_new);
result.set_wire(inverse_wire, inverse);
result.set_wire(lambda_wire, lambda);
result
}
}
76 changes: 69 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,74 @@ 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!()
let gen = CurveEndoGateGenerator::<C> { gate_index, _phantom: PhantomData };
vec![Box::new(gen)]
}
}

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 };

// Load input values.
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 933a4bc

Please sign in to comment.