mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-12 10:05:47 +00:00
Add Montgomery point interpretation.
This commit is contained in:
parent
eb8803f9eb
commit
7d6a57661b
@ -28,6 +28,34 @@ pub struct MontgomeryPoint<E: Engine, Var> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E: JubjubEngine, Var: Copy> MontgomeryPoint<E, Var> {
|
impl<E: JubjubEngine, Var: Copy> MontgomeryPoint<E, Var> {
|
||||||
|
pub fn interpret<CS>(
|
||||||
|
mut cs: CS,
|
||||||
|
x: &AllocatedNum<E, Var>,
|
||||||
|
y: &AllocatedNum<E, Var>,
|
||||||
|
params: &E::Params
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where CS: ConstraintSystem<E, Variable=Var>
|
||||||
|
{
|
||||||
|
// y^2 = x^3 + A.x^2 + x
|
||||||
|
|
||||||
|
let x2 = x.square(cs.namespace(|| "x^2"))?;
|
||||||
|
let x3 = x2.mul(cs.namespace(|| "x^3"), x)?;
|
||||||
|
|
||||||
|
cs.enforce(
|
||||||
|
|| "on curve check",
|
||||||
|
LinearCombination::zero() + y.get_variable(),
|
||||||
|
LinearCombination::zero() + y.get_variable(),
|
||||||
|
LinearCombination::zero() + x3.get_variable()
|
||||||
|
+ (*params.montgomery_a(), x2.get_variable())
|
||||||
|
+ x.get_variable()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(MontgomeryPoint {
|
||||||
|
x: x.clone(),
|
||||||
|
y: y.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs an affine point doubling, not defined for
|
/// Performs an affine point doubling, not defined for
|
||||||
/// the point of order two (0, 0).
|
/// the point of order two (0, 0).
|
||||||
pub fn double<CS>(
|
pub fn double<CS>(
|
||||||
@ -146,6 +174,54 @@ mod test {
|
|||||||
};
|
};
|
||||||
use super::{MontgomeryPoint, AllocatedNum};
|
use super::{MontgomeryPoint, AllocatedNum};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_interpret() {
|
||||||
|
let params = &JubjubBls12::new();
|
||||||
|
let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
for _ in 0..100 {
|
||||||
|
let p = montgomery::Point::<Bls12, _>::rand(rng, ¶ms);
|
||||||
|
let (mut x, mut y) = p.into_xy().unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut cs = TestConstraintSystem::<Bls12>::new();
|
||||||
|
let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || {
|
||||||
|
Ok(x)
|
||||||
|
}).unwrap();
|
||||||
|
let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || {
|
||||||
|
Ok(y)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let p = MontgomeryPoint::interpret(&mut cs, &numx, &numy, ¶ms).unwrap();
|
||||||
|
|
||||||
|
assert!(cs.is_satisfied());
|
||||||
|
assert_eq!(p.x.get_value().unwrap(), x);
|
||||||
|
assert_eq!(p.y.get_value().unwrap(), y);
|
||||||
|
|
||||||
|
y.negate();
|
||||||
|
cs.set("y/num", y);
|
||||||
|
assert!(cs.is_satisfied());
|
||||||
|
x.negate();
|
||||||
|
cs.set("x/num", x);
|
||||||
|
assert!(!cs.is_satisfied());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut cs = TestConstraintSystem::<Bls12>::new();
|
||||||
|
let numx = AllocatedNum::alloc(cs.namespace(|| "x"), || {
|
||||||
|
Ok(x)
|
||||||
|
}).unwrap();
|
||||||
|
let numy = AllocatedNum::alloc(cs.namespace(|| "y"), || {
|
||||||
|
Ok(y)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
MontgomeryPoint::interpret(&mut cs, &numx, &numy, ¶ms).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(cs.which_is_unsatisfied().unwrap(), "on curve check");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_doubling_order_2() {
|
fn test_doubling_order_2() {
|
||||||
let params = &JubjubBls12::new();
|
let params = &JubjubBls12::new();
|
||||||
|
@ -25,6 +25,15 @@ pub struct AllocatedNum<E: Engine, Var> {
|
|||||||
variable: Var
|
variable: Var
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Var: Copy, E: Engine> Clone for AllocatedNum<E, Var> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
AllocatedNum {
|
||||||
|
value: self.value,
|
||||||
|
variable: self.variable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Engine, Var: Copy> AllocatedNum<E, Var> {
|
impl<E: Engine, Var: Copy> AllocatedNum<E, Var> {
|
||||||
pub fn alloc<CS, F>(
|
pub fn alloc<CS, F>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
@ -190,6 +199,38 @@ impl<E: Engine, Var: Copy> AllocatedNum<E, Var> {
|
|||||||
Ok(num)
|
Ok(num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mul<CS>(
|
||||||
|
&self,
|
||||||
|
mut cs: CS,
|
||||||
|
other: &Self
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where CS: ConstraintSystem<E, Variable=Var>
|
||||||
|
{
|
||||||
|
let mut value = None;
|
||||||
|
|
||||||
|
let var = cs.alloc(|| "product num", || {
|
||||||
|
let mut tmp = *self.value.get()?;
|
||||||
|
tmp.mul_assign(other.value.get()?);
|
||||||
|
|
||||||
|
value = Some(tmp);
|
||||||
|
|
||||||
|
Ok(tmp)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Constrain: a * b = ab
|
||||||
|
cs.enforce(
|
||||||
|
|| "multiplication constraint",
|
||||||
|
LinearCombination::zero() + self.variable,
|
||||||
|
LinearCombination::zero() + other.variable,
|
||||||
|
LinearCombination::zero() + var
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(AllocatedNum {
|
||||||
|
value: value,
|
||||||
|
variable: var
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn square<CS>(
|
pub fn square<CS>(
|
||||||
&self,
|
&self,
|
||||||
mut cs: CS
|
mut cs: CS
|
||||||
@ -294,6 +335,21 @@ mod test {
|
|||||||
assert!(!cs.is_satisfied());
|
assert!(!cs.is_satisfied());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_num_multiplication() {
|
||||||
|
let mut cs = TestConstraintSystem::<Bls12>::new();
|
||||||
|
|
||||||
|
let n = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::from_str("12").unwrap())).unwrap();
|
||||||
|
let n2 = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::from_str("10").unwrap())).unwrap();
|
||||||
|
let n3 = n.mul(&mut cs, &n2).unwrap();
|
||||||
|
|
||||||
|
assert!(cs.is_satisfied());
|
||||||
|
assert!(cs.get("product num") == Fr::from_str("120").unwrap());
|
||||||
|
assert!(n3.value.unwrap() == Fr::from_str("120").unwrap());
|
||||||
|
cs.set("product num", Fr::from_str("121").unwrap());
|
||||||
|
assert!(!cs.is_satisfied());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_num_nonzero() {
|
fn test_num_nonzero() {
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user