mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-07 14:54:10 +00:00
Pedersen hashes with full optimization
This commit is contained in:
parent
4fa73efc1e
commit
88bdff6ce9
@ -1,6 +1,9 @@
|
|||||||
use pairing::{Engine, Field};
|
use pairing::{Engine, Field};
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::num::AllocatedNum;
|
use super::num::{
|
||||||
|
AllocatedNum,
|
||||||
|
Num
|
||||||
|
};
|
||||||
use super::boolean::Boolean;
|
use super::boolean::Boolean;
|
||||||
use bellman::{
|
use bellman::{
|
||||||
ConstraintSystem
|
ConstraintSystem
|
||||||
@ -123,7 +126,7 @@ pub fn lookup3_xy_with_conditional_negation<E: Engine, CS>(
|
|||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
bits: &[Boolean],
|
bits: &[Boolean],
|
||||||
coords: &[(E::Fr, E::Fr)]
|
coords: &[(E::Fr, E::Fr)]
|
||||||
) -> Result<(AllocatedNum<E>, AllocatedNum<E>), SynthesisError>
|
) -> Result<(Num<E>, Num<E>), SynthesisError>
|
||||||
where CS: ConstraintSystem<E>
|
where CS: ConstraintSystem<E>
|
||||||
{
|
{
|
||||||
assert_eq!(bits.len(), 3);
|
assert_eq!(bits.len(), 3);
|
||||||
@ -145,17 +148,9 @@ pub fn lookup3_xy_with_conditional_negation<E: Engine, CS>(
|
|||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allocate the x-coordinate resulting from the lookup
|
|
||||||
let res_x = AllocatedNum::alloc(
|
|
||||||
cs.namespace(|| "x"),
|
|
||||||
|| {
|
|
||||||
Ok(coords[*i.get()?].0)
|
|
||||||
}
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Allocate the y-coordinate resulting from the lookup
|
// Allocate the y-coordinate resulting from the lookup
|
||||||
// and conditional negation
|
// and conditional negation
|
||||||
let res_y = AllocatedNum::alloc(
|
let y = AllocatedNum::alloc(
|
||||||
cs.namespace(|| "y"),
|
cs.namespace(|| "y"),
|
||||||
|| {
|
|| {
|
||||||
let mut tmp = coords[*i.get()?].1;
|
let mut tmp = coords[*i.get()?].1;
|
||||||
@ -176,15 +171,11 @@ pub fn lookup3_xy_with_conditional_negation<E: Engine, CS>(
|
|||||||
|
|
||||||
let precomp = Boolean::and(cs.namespace(|| "precomp"), &bits[0], &bits[1])?;
|
let precomp = Boolean::and(cs.namespace(|| "precomp"), &bits[0], &bits[1])?;
|
||||||
|
|
||||||
cs.enforce(
|
let x = Num::zero()
|
||||||
|| "x-coordinate lookup",
|
.add_bool_with_coeff(one, &Boolean::constant(true), x_coeffs[0b00])
|
||||||
|lc| lc + (x_coeffs[0b00], one)
|
.add_bool_with_coeff(one, &bits[0], x_coeffs[0b01])
|
||||||
+ &bits[0].lc::<E>(one, x_coeffs[0b01])
|
.add_bool_with_coeff(one, &bits[1], x_coeffs[0b10])
|
||||||
+ &bits[1].lc::<E>(one, x_coeffs[0b10])
|
.add_bool_with_coeff(one, &precomp, x_coeffs[0b11]);
|
||||||
+ &precomp.lc::<E>(one, x_coeffs[0b11]),
|
|
||||||
|lc| lc + one,
|
|
||||||
|lc| lc + res_x.get_variable()
|
|
||||||
);
|
|
||||||
|
|
||||||
let y_lc = precomp.lc::<E>(one, y_coeffs[0b11]) +
|
let y_lc = precomp.lc::<E>(one, y_coeffs[0b11]) +
|
||||||
&bits[1].lc::<E>(one, y_coeffs[0b10]) +
|
&bits[1].lc::<E>(one, y_coeffs[0b10]) +
|
||||||
@ -195,10 +186,10 @@ pub fn lookup3_xy_with_conditional_negation<E: Engine, CS>(
|
|||||||
|| "y-coordinate lookup",
|
|| "y-coordinate lookup",
|
||||||
|lc| lc + &y_lc + &y_lc,
|
|lc| lc + &y_lc + &y_lc,
|
||||||
|lc| lc + &bits[2].lc::<E>(one, E::Fr::one()),
|
|lc| lc + &bits[2].lc::<E>(one, E::Fr::one()),
|
||||||
|lc| lc + &y_lc - res_y.get_variable()
|
|lc| lc + &y_lc - y.get_variable()
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok((res_x, res_y))
|
Ok((x, y.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -12,7 +12,10 @@ use super::{
|
|||||||
Assignment
|
Assignment
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::num::AllocatedNum;
|
use super::num::{
|
||||||
|
AllocatedNum,
|
||||||
|
Num
|
||||||
|
};
|
||||||
|
|
||||||
use ::jubjub::{
|
use ::jubjub::{
|
||||||
JubjubEngine,
|
JubjubEngine,
|
||||||
@ -470,8 +473,8 @@ impl<E: JubjubEngine> EdwardsPoint<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MontgomeryPoint<E: Engine> {
|
pub struct MontgomeryPoint<E: Engine> {
|
||||||
x: AllocatedNum<E>,
|
x: Num<E>,
|
||||||
y: AllocatedNum<E>
|
y: Num<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: JubjubEngine> MontgomeryPoint<E> {
|
impl<E: JubjubEngine> MontgomeryPoint<E> {
|
||||||
@ -504,9 +507,9 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
|
|
||||||
cs.enforce(
|
cs.enforce(
|
||||||
|| "u computation",
|
|| "u computation",
|
||||||
|lc| lc + self.y.get_variable(),
|
|lc| lc + &self.y.lc(E::Fr::one()),
|
||||||
|lc| lc + u.get_variable(),
|
|lc| lc + u.get_variable(),
|
||||||
|lc| lc + (*params.scale(), self.x.get_variable())
|
|lc| lc + &self.x.lc(*params.scale())
|
||||||
);
|
);
|
||||||
|
|
||||||
// Compute v = (x - 1) / (x + 1)
|
// Compute v = (x - 1) / (x + 1)
|
||||||
@ -531,10 +534,10 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
let one = CS::one();
|
let one = CS::one();
|
||||||
cs.enforce(
|
cs.enforce(
|
||||||
|| "v computation",
|
|| "v computation",
|
||||||
|lc| lc + self.x.get_variable()
|
|lc| lc + &self.x.lc(E::Fr::one())
|
||||||
+ one,
|
+ one,
|
||||||
|lc| lc + v.get_variable(),
|
|lc| lc + v.get_variable(),
|
||||||
|lc| lc + self.x.get_variable()
|
|lc| lc + &self.x.lc(E::Fr::one())
|
||||||
- one,
|
- one,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -549,8 +552,8 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
/// on the curve. Useful for constants and
|
/// on the curve. Useful for constants and
|
||||||
/// window table lookups.
|
/// window table lookups.
|
||||||
pub fn interpret_unchecked(
|
pub fn interpret_unchecked(
|
||||||
x: AllocatedNum<E>,
|
x: Num<E>,
|
||||||
y: AllocatedNum<E>
|
y: Num<E>
|
||||||
) -> Self
|
) -> Self
|
||||||
{
|
{
|
||||||
MontgomeryPoint {
|
MontgomeryPoint {
|
||||||
@ -590,13 +593,13 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
|
|
||||||
cs.enforce(
|
cs.enforce(
|
||||||
|| "evaluate lambda",
|
|| "evaluate lambda",
|
||||||
|lc| lc + other.x.get_variable()
|
|lc| lc + &other.x.lc(E::Fr::one())
|
||||||
- self.x.get_variable(),
|
- &self.x.lc(E::Fr::one()),
|
||||||
|
|
||||||
|lc| lc + lambda.get_variable(),
|
|lc| lc + lambda.get_variable(),
|
||||||
|
|
||||||
|lc| lc + other.y.get_variable()
|
|lc| lc + &other.y.lc(E::Fr::one())
|
||||||
- self.y.get_variable()
|
- &self.y.lc(E::Fr::one())
|
||||||
);
|
);
|
||||||
|
|
||||||
// Compute x'' = lambda^2 - A - x - x'
|
// Compute x'' = lambda^2 - A - x - x'
|
||||||
@ -617,8 +620,8 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
|lc| lc + lambda.get_variable(),
|
|lc| lc + lambda.get_variable(),
|
||||||
|lc| lc + lambda.get_variable(),
|
|lc| lc + lambda.get_variable(),
|
||||||
|lc| lc + (*params.montgomery_a(), one)
|
|lc| lc + (*params.montgomery_a(), one)
|
||||||
+ self.x.get_variable()
|
+ &self.x.lc(E::Fr::one())
|
||||||
+ other.x.get_variable()
|
+ &other.x.lc(E::Fr::one())
|
||||||
+ xprime.get_variable()
|
+ xprime.get_variable()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -636,18 +639,18 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
// y' + y = lambda(x - x')
|
// y' + y = lambda(x - x')
|
||||||
cs.enforce(
|
cs.enforce(
|
||||||
|| "evaluate yprime",
|
|| "evaluate yprime",
|
||||||
|lc| lc + self.x.get_variable()
|
|lc| lc + &self.x.lc(E::Fr::one())
|
||||||
- xprime.get_variable(),
|
- xprime.get_variable(),
|
||||||
|
|
||||||
|lc| lc + lambda.get_variable(),
|
|lc| lc + lambda.get_variable(),
|
||||||
|
|
||||||
|lc| lc + yprime.get_variable()
|
|lc| lc + yprime.get_variable()
|
||||||
+ self.y.get_variable()
|
+ &self.y.lc(E::Fr::one())
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(MontgomeryPoint {
|
Ok(MontgomeryPoint {
|
||||||
x: xprime,
|
x: xprime.into(),
|
||||||
y: yprime
|
y: yprime.into()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -697,7 +700,7 @@ mod test {
|
|||||||
Ok(y)
|
Ok(y)
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
let p = MontgomeryPoint::interpret_unchecked(numx, numy);
|
let p = MontgomeryPoint::interpret_unchecked(numx.into(), numy.into());
|
||||||
|
|
||||||
let q = p.into_edwards(&mut cs, params).unwrap();
|
let q = p.into_edwards(&mut cs, params).unwrap();
|
||||||
|
|
||||||
@ -1068,13 +1071,13 @@ mod test {
|
|||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
let p1 = MontgomeryPoint {
|
let p1 = MontgomeryPoint {
|
||||||
x: num_x0,
|
x: num_x0.into(),
|
||||||
y: num_y0
|
y: num_y0.into()
|
||||||
};
|
};
|
||||||
|
|
||||||
let p2 = MontgomeryPoint {
|
let p2 = MontgomeryPoint {
|
||||||
x: num_x1,
|
x: num_x1.into(),
|
||||||
y: num_y1
|
y: num_y1.into()
|
||||||
};
|
};
|
||||||
|
|
||||||
let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap();
|
let p3 = p1.add(cs.namespace(|| "addition"), &p2, params).unwrap();
|
||||||
|
@ -321,6 +321,61 @@ impl<E: Engine> AllocatedNum<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Num<E: Engine> {
|
||||||
|
value: Option<E::Fr>,
|
||||||
|
lc: LinearCombination<E>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> From<AllocatedNum<E>> for Num<E> {
|
||||||
|
fn from(num: AllocatedNum<E>) -> Num<E> {
|
||||||
|
Num {
|
||||||
|
value: num.value,
|
||||||
|
lc: LinearCombination::<E>::zero() + num.variable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> Num<E> {
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
Num {
|
||||||
|
value: Some(E::Fr::zero()),
|
||||||
|
lc: LinearCombination::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> Option<E::Fr> {
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lc(&self, coeff: E::Fr) -> LinearCombination<E> {
|
||||||
|
LinearCombination::zero() + (coeff, &self.lc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_bool_with_coeff(
|
||||||
|
self,
|
||||||
|
one: Variable,
|
||||||
|
bit: &Boolean,
|
||||||
|
coeff: E::Fr
|
||||||
|
) -> Self
|
||||||
|
{
|
||||||
|
let newval = match (self.value, bit.get_value()) {
|
||||||
|
(Some(mut curval), Some(mut bval)) => {
|
||||||
|
if bval {
|
||||||
|
curval.add_assign(&coeff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(curval)
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
Num {
|
||||||
|
value: newval,
|
||||||
|
lc: self.lc + &bit.lc(one, coeff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use rand::{SeedableRng, Rand, Rng, XorShiftRng};
|
use rand::{SeedableRng, Rand, Rng, XorShiftRng};
|
||||||
|
@ -155,7 +155,7 @@ mod test {
|
|||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
assert!(cs.is_satisfied());
|
||||||
assert_eq!(cs.num_constraints(), 1549);
|
assert_eq!(cs.num_constraints(), 1377);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user