mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-07 23:02:59 +00:00
Define get_for_y for twisted Edwards points.
This commit is contained in:
parent
bfda59f80b
commit
55598e4d4f
@ -81,6 +81,53 @@ impl<E: JubjubEngine, Subgroup> PartialEq for Point<E, Subgroup> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E: JubjubEngine> Point<E, Unknown> {
|
impl<E: JubjubEngine> Point<E, Unknown> {
|
||||||
|
pub fn get_for_y(y: E::Fr, sign: bool, params: &E::Params) -> Option<Self>
|
||||||
|
{
|
||||||
|
// Given a y on the curve, x^2 = (y^2 - 1) / (dy^2 + 1)
|
||||||
|
// This is defined for all valid y-coordinates,
|
||||||
|
// as dy^2 + 1 = 0 has no solution in Fr.
|
||||||
|
|
||||||
|
// tmp1 = y^2
|
||||||
|
let mut tmp1 = y;
|
||||||
|
tmp1.square();
|
||||||
|
|
||||||
|
// tmp2 = (y^2 * d) + 1
|
||||||
|
let mut tmp2 = tmp1;
|
||||||
|
tmp2.mul_assign(params.edwards_d());
|
||||||
|
tmp2.add_assign(&E::Fr::one());
|
||||||
|
|
||||||
|
// tmp1 = y^2 - 1
|
||||||
|
tmp1.sub_assign(&E::Fr::one());
|
||||||
|
|
||||||
|
match tmp2.inverse() {
|
||||||
|
Some(tmp2) => {
|
||||||
|
// tmp1 = (y^2 - 1) / (dy^2 + 1)
|
||||||
|
tmp1.mul_assign(&tmp2);
|
||||||
|
|
||||||
|
match tmp1.sqrt() {
|
||||||
|
Some(mut x) => {
|
||||||
|
if x.into_repr().is_odd() != sign {
|
||||||
|
x.negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut t = x;
|
||||||
|
t.mul_assign(&y);
|
||||||
|
|
||||||
|
Some(Point {
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
t: t,
|
||||||
|
z: E::Fr::one(),
|
||||||
|
_marker: PhantomData
|
||||||
|
})
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This guarantees the point is in the prime order subgroup
|
/// This guarantees the point is in the prime order subgroup
|
||||||
pub fn mul_by_cofactor(&self, params: &E::Params) -> Point<E, PrimeOrder>
|
pub fn mul_by_cofactor(&self, params: &E::Params) -> Point<E, PrimeOrder>
|
||||||
{
|
{
|
||||||
@ -94,44 +141,10 @@ impl<E: JubjubEngine> Point<E, Unknown> {
|
|||||||
pub fn rand<R: Rng>(rng: &mut R, params: &E::Params) -> Self
|
pub fn rand<R: Rng>(rng: &mut R, params: &E::Params) -> Self
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
// given an x on the curve, y^2 = (1 + x^2) / (1 - dx^2)
|
let y: E::Fr = rng.gen();
|
||||||
let x: E::Fr = rng.gen();
|
|
||||||
let mut x2 = x;
|
|
||||||
x2.square();
|
|
||||||
|
|
||||||
let mut num = E::Fr::one();
|
if let Some(p) = Self::get_for_y(y, rng.gen(), params) {
|
||||||
num.add_assign(&x2);
|
return p;
|
||||||
|
|
||||||
x2.mul_assign(params.edwards_d());
|
|
||||||
|
|
||||||
let mut den = E::Fr::one();
|
|
||||||
den.sub_assign(&x2);
|
|
||||||
|
|
||||||
match den.inverse() {
|
|
||||||
Some(invden) => {
|
|
||||||
num.mul_assign(&invden);
|
|
||||||
|
|
||||||
match num.sqrt() {
|
|
||||||
Some(mut y) => {
|
|
||||||
if y.into_repr().is_odd() != rng.gen() {
|
|
||||||
y.negate();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut t = x;
|
|
||||||
t.mul_assign(&y);
|
|
||||||
|
|
||||||
return Point {
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
t: t,
|
|
||||||
z: E::Fr::one(),
|
|
||||||
_marker: PhantomData
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ pub fn test_suite<E: JubjubEngine>(params: &E::Params) {
|
|||||||
test_back_and_forth::<E>(params);
|
test_back_and_forth::<E>(params);
|
||||||
test_jubjub_params::<E>(params);
|
test_jubjub_params::<E>(params);
|
||||||
test_rand::<E>(params);
|
test_rand::<E>(params);
|
||||||
|
test_get_for::<E>(params);
|
||||||
test_identities::<E>(params);
|
test_identities::<E>(params);
|
||||||
test_addition_associativity::<E>(params);
|
test_addition_associativity::<E>(params);
|
||||||
test_order::<E>(params);
|
test_order::<E>(params);
|
||||||
@ -225,6 +226,25 @@ fn test_identities<E: JubjubEngine>(params: &E::Params) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_get_for<E: JubjubEngine>(params: &E::Params) {
|
||||||
|
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
for _ in 0..1000 {
|
||||||
|
let y = E::Fr::rand(rng);
|
||||||
|
let sign = bool::rand(rng);
|
||||||
|
|
||||||
|
if let Some(mut p) = edwards::Point::<E, _>::get_for_y(y, sign, params) {
|
||||||
|
assert!(p.into_xy().0.into_repr().is_odd() == sign);
|
||||||
|
p = p.negate();
|
||||||
|
assert!(
|
||||||
|
edwards::Point::<E, _>::get_for_y(y, !sign, params).unwrap()
|
||||||
|
==
|
||||||
|
p
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_rand<E: JubjubEngine>(params: &E::Params) {
|
fn test_rand<E: JubjubEngine>(params: &E::Params) {
|
||||||
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
@ -288,6 +308,25 @@ fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
|
|||||||
assert!(a.legendre() == LegendreSymbol::QuadraticResidue);
|
assert!(a.legendre() == LegendreSymbol::QuadraticResidue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Other convenient sanity checks regarding d
|
||||||
|
|
||||||
|
// tmp = d
|
||||||
|
let mut tmp = *params.edwards_d();
|
||||||
|
|
||||||
|
// 1 / d is nonsquare
|
||||||
|
assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue);
|
||||||
|
|
||||||
|
// tmp = -d
|
||||||
|
tmp.negate();
|
||||||
|
|
||||||
|
// -d is nonsquare
|
||||||
|
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
|
||||||
|
|
||||||
|
// 1 / -d is nonsquare
|
||||||
|
assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Check that A^2 - 4 is nonsquare:
|
// Check that A^2 - 4 is nonsquare:
|
||||||
let mut tmp = params.montgomery_a().clone();
|
let mut tmp = params.montgomery_a().clone();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user