mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
Define hash-to-curve over Curve, not CurveAffine
This removes an unnecessary layer of indirection from the type system, and ensures that these APIs depend on the halo2-specific trait with the extensions we require.
This commit is contained in:
parent
082d66d6e7
commit
55fb581f17
5 changed files with 34 additions and 41 deletions
|
|
@ -84,9 +84,12 @@ pub trait Curve:
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use halo2::arithmetic::{Curve, CurveAffine};
|
/// use halo2::arithmetic::Curve;
|
||||||
/// fn pedersen_commitment<C: CurveAffine>(x: C::Scalar, r: C::Scalar) -> C {
|
/// fn pedersen_commitment<C: Curve>(
|
||||||
/// let hasher = C::Curve::hash_to_curve("z.cash:example_pedersen_commitment");
|
/// x: <C as Curve>::Scalar,
|
||||||
|
/// r: <C as Curve>::Scalar,
|
||||||
|
/// ) -> C::Affine {
|
||||||
|
/// let hasher = C::hash_to_curve("z.cash:example_pedersen_commitment");
|
||||||
/// let g = hasher(b"g");
|
/// let g = hasher(b"g");
|
||||||
/// let h = hasher(b"h");
|
/// let h = hasher(b"h");
|
||||||
/// (g * x + &(h * r)).to_affine()
|
/// (g * x + &(h * r)).to_affine()
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use super::{Fp, Fq};
|
||||||
use crate::arithmetic::{Curve, CurveAffine, FieldExt, Group};
|
use crate::arithmetic::{Curve, CurveAffine, FieldExt, Group};
|
||||||
|
|
||||||
macro_rules! new_curve_impl {
|
macro_rules! new_curve_impl {
|
||||||
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso_affine:ident, $base:ident, $scalar:ident, $blake2b_personalization:literal,
|
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident, $blake2b_personalization:literal,
|
||||||
$curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => {
|
$curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => {
|
||||||
/// Represents a point in the projective coordinate space.
|
/// Represents a point in the projective coordinate space.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
|
@ -85,7 +85,7 @@ macro_rules! new_curve_impl {
|
||||||
$name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.ct_is_zero())
|
$name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.ct_is_zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_projective_curve_ext!($name, $name_affine, $iso_affine, $base, $curve_type);
|
impl_projective_curve_ext!($name, $name_affine, $iso, $base, $curve_type);
|
||||||
|
|
||||||
fn a() -> Self::Base {
|
fn a() -> Self::Base {
|
||||||
$name::curve_constant_a()
|
$name::curve_constant_a()
|
||||||
|
|
@ -759,29 +759,26 @@ macro_rules! impl_projective_curve_specific {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_projective_curve_ext {
|
macro_rules! impl_projective_curve_ext {
|
||||||
($name:ident, $name_affine:ident, $iso_affine:ident, $base:ident, special_a0_b5) => {
|
($name:ident, $name_affine:ident, $iso:ident, $base:ident, special_a0_b5) => {
|
||||||
fn hash_to_curve<'a>(domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
|
fn hash_to_curve<'a>(domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
|
||||||
use super::hashtocurve;
|
use super::hashtocurve;
|
||||||
|
|
||||||
Box::new(move |message| {
|
Box::new(move |message| {
|
||||||
let mut us = [Field::zero(); 2];
|
let mut us = [Field::zero(); 2];
|
||||||
hashtocurve::hash_to_field($name_affine::CURVE_ID, domain_prefix, message, &mut us);
|
hashtocurve::hash_to_field($name_affine::CURVE_ID, domain_prefix, message, &mut us);
|
||||||
let q0 = hashtocurve::map_to_curve_simple_swu::<$base, $name_affine, $iso_affine>(
|
let q0 = hashtocurve::map_to_curve_simple_swu::<$base, $name, $iso>(
|
||||||
&us[0],
|
&us[0],
|
||||||
$name::THETA,
|
$name::THETA,
|
||||||
$name::Z,
|
$name::Z,
|
||||||
);
|
);
|
||||||
let q1 = hashtocurve::map_to_curve_simple_swu::<$base, $name_affine, $iso_affine>(
|
let q1 = hashtocurve::map_to_curve_simple_swu::<$base, $name, $iso>(
|
||||||
&us[1],
|
&us[1],
|
||||||
$name::THETA,
|
$name::THETA,
|
||||||
$name::Z,
|
$name::Z,
|
||||||
);
|
);
|
||||||
let r = q0 + &q1;
|
let r = q0 + &q1;
|
||||||
debug_assert!(bool::from(r.is_on_curve()));
|
debug_assert!(bool::from(r.is_on_curve()));
|
||||||
hashtocurve::iso_map::<$base, $name_affine, $iso_affine>(
|
hashtocurve::iso_map::<$base, $name, $iso>(&r, &$name::ISOGENY_CONSTANTS)
|
||||||
&r,
|
|
||||||
&$name::ISOGENY_CONSTANTS,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -795,7 +792,7 @@ macro_rules! impl_projective_curve_ext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($name:ident, $name_affine:ident, $iso_affine:ident, $base:ident, general) => {
|
($name:ident, $name_affine:ident, $iso:ident, $base:ident, general) => {
|
||||||
/// Unimplemented: hashing to this curve is not supported
|
/// Unimplemented: hashing to this curve is not supported
|
||||||
fn hash_to_curve<'a>(_domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
|
fn hash_to_curve<'a>(_domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|
@ -835,7 +832,7 @@ new_curve_impl!(
|
||||||
(pub),
|
(pub),
|
||||||
Ep,
|
Ep,
|
||||||
EpAffine,
|
EpAffine,
|
||||||
IsoEpAffine,
|
IsoEp,
|
||||||
Fp,
|
Fp,
|
||||||
Fq,
|
Fq,
|
||||||
b"halo2_____pallas",
|
b"halo2_____pallas",
|
||||||
|
|
@ -848,7 +845,7 @@ new_curve_impl!(
|
||||||
(pub),
|
(pub),
|
||||||
Eq,
|
Eq,
|
||||||
EqAffine,
|
EqAffine,
|
||||||
IsoEqAffine,
|
IsoEq,
|
||||||
Fq,
|
Fq,
|
||||||
Fp,
|
Fp,
|
||||||
b"halo2______vesta",
|
b"halo2______vesta",
|
||||||
|
|
@ -861,7 +858,7 @@ new_curve_impl!(
|
||||||
(pub(crate)),
|
(pub(crate)),
|
||||||
IsoEp,
|
IsoEp,
|
||||||
IsoEpAffine,
|
IsoEpAffine,
|
||||||
EpAffine,
|
Ep,
|
||||||
Fp,
|
Fp,
|
||||||
Fq,
|
Fq,
|
||||||
b"halo2_iso_pallas",
|
b"halo2_iso_pallas",
|
||||||
|
|
@ -879,7 +876,7 @@ new_curve_impl!(
|
||||||
(pub(crate)),
|
(pub(crate)),
|
||||||
IsoEq,
|
IsoEq,
|
||||||
IsoEqAffine,
|
IsoEqAffine,
|
||||||
EqAffine,
|
Eq,
|
||||||
Fq,
|
Fq,
|
||||||
Fp,
|
Fp,
|
||||||
b"halo2__iso_vesta",
|
b"halo2__iso_vesta",
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use subtle::ConstantTimeEq;
|
use subtle::ConstantTimeEq;
|
||||||
|
|
||||||
use crate::arithmetic::{Curve, CurveAffine, FieldExt};
|
use crate::arithmetic::{Curve, FieldExt};
|
||||||
|
|
||||||
/// Hashes over a message and writes the output to all of `buf`.
|
/// Hashes over a message and writes the output to all of `buf`.
|
||||||
pub fn hash_to_field<F: FieldExt>(
|
pub fn hash_to_field<F: FieldExt>(
|
||||||
|
|
@ -72,10 +72,10 @@ pub fn hash_to_field<F: FieldExt>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements a degree 3 isogeny map.
|
/// Implements a degree 3 isogeny map.
|
||||||
pub fn iso_map<F: FieldExt, C: CurveAffine<Base = F>, I: CurveAffine<Base = F>>(
|
pub fn iso_map<F: FieldExt, C: Curve<Base = F>, I: Curve<Base = F>>(
|
||||||
p: &I::Curve,
|
p: &I,
|
||||||
iso: &[C::Base; 13],
|
iso: &[C::Base; 13],
|
||||||
) -> C::Curve {
|
) -> C {
|
||||||
// The input and output are in Jacobian coordinates, using the method
|
// The input and output are in Jacobian coordinates, using the method
|
||||||
// in "Avoiding inversions" [WB2019, section 4.3].
|
// in "Avoiding inversions" [WB2019, section 4.3].
|
||||||
|
|
||||||
|
|
@ -96,14 +96,14 @@ pub fn iso_map<F: FieldExt, C: CurveAffine<Base = F>, I: CurveAffine<Base = F>>(
|
||||||
let xo = num_x * div_y * zo;
|
let xo = num_x * div_y * zo;
|
||||||
let yo = num_y * div_x * zo.square();
|
let yo = num_y * div_x * zo.square();
|
||||||
|
|
||||||
C::Curve::new_jacobian(xo, yo, zo).unwrap()
|
C::new_jacobian(xo, yo, zo).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_to_curve_simple_swu<F: FieldExt, C: CurveAffine<Base = F>, I: CurveAffine<Base = F>>(
|
pub fn map_to_curve_simple_swu<F: FieldExt, C: Curve<Base = F>, I: Curve<Base = F>>(
|
||||||
u: &F,
|
u: &F,
|
||||||
theta: F,
|
theta: F,
|
||||||
z: F,
|
z: F,
|
||||||
) -> I::Curve {
|
) -> I {
|
||||||
// 1. tv1 = inv0(Z^2 * u^4 + Z * u^2)
|
// 1. tv1 = inv0(Z^2 * u^4 + Z * u^2)
|
||||||
// 2. x1 = (-B / A) * (1 + tv1)
|
// 2. x1 = (-B / A) * (1 + tv1)
|
||||||
// 3. If tv1 == 0, set x1 = B / (Z * A)
|
// 3. If tv1 == 0, set x1 = B / (Z * A)
|
||||||
|
|
@ -171,5 +171,5 @@ pub fn map_to_curve_simple_swu<F: FieldExt, C: CurveAffine<Base = F>, I: CurveAf
|
||||||
(u.get_lower_32() % 2).ct_eq(&(y.get_lower_32() % 2)),
|
(u.get_lower_32() % 2).ct_eq(&(y.get_lower_32() % 2)),
|
||||||
);
|
);
|
||||||
|
|
||||||
I::Curve::new_jacobian(num_x * div, y * div3, div).unwrap()
|
I::new_jacobian(num_x * div, y * div3, div).unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,7 @@ fn test_iso_map() {
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let p =
|
let p = super::hashtocurve::iso_map::<_, Point, super::IsoEp>(&r, &Ep::ISOGENY_CONSTANTS);
|
||||||
super::hashtocurve::iso_map::<_, Affine, super::IsoEpAffine>(&r, &Ep::ISOGENY_CONSTANTS);
|
|
||||||
let (x, y, z) = p.jacobian_coordinates();
|
let (x, y, z) = p.jacobian_coordinates();
|
||||||
assert!(
|
assert!(
|
||||||
format!("{:?}", x) == "0x318cc15f281662b3f26d0175cab97b924870c837879cac647e877be51a85e898"
|
format!("{:?}", x) == "0x318cc15f281662b3f26d0175cab97b924870c837879cac647e877be51a85e898"
|
||||||
|
|
@ -58,8 +57,7 @@ fn test_iso_map() {
|
||||||
// check that iso_map([2] r) = [2] iso_map(r)
|
// check that iso_map([2] r) = [2] iso_map(r)
|
||||||
let r2 = r.double();
|
let r2 = r.double();
|
||||||
assert!(bool::from(r2.is_on_curve()));
|
assert!(bool::from(r2.is_on_curve()));
|
||||||
let p2 =
|
let p2 = super::hashtocurve::iso_map::<_, Point, super::IsoEp>(&r2, &Ep::ISOGENY_CONSTANTS);
|
||||||
super::hashtocurve::iso_map::<_, Affine, super::IsoEpAffine>(&r2, &Ep::ISOGENY_CONSTANTS);
|
|
||||||
assert!(bool::from(p2.is_on_curve()));
|
assert!(bool::from(p2.is_on_curve()));
|
||||||
assert!(p2 == p.double());
|
assert!(p2 == p.double());
|
||||||
}
|
}
|
||||||
|
|
@ -92,8 +90,7 @@ fn test_iso_map_identity() {
|
||||||
let r = (r * -Fq::one()) + r;
|
let r = (r * -Fq::one()) + r;
|
||||||
assert!(bool::from(r.is_on_curve()));
|
assert!(bool::from(r.is_on_curve()));
|
||||||
assert!(bool::from(r.is_identity()));
|
assert!(bool::from(r.is_identity()));
|
||||||
let p =
|
let p = super::hashtocurve::iso_map::<_, Point, super::IsoEp>(&r, &Ep::ISOGENY_CONSTANTS);
|
||||||
super::hashtocurve::iso_map::<_, Affine, super::IsoEpAffine>(&r, &Ep::ISOGENY_CONSTANTS);
|
|
||||||
assert!(bool::from(p.is_on_curve()));
|
assert!(bool::from(p.is_on_curve()));
|
||||||
assert!(bool::from(p.is_identity()));
|
assert!(bool::from(p.is_identity()));
|
||||||
}
|
}
|
||||||
|
|
@ -101,12 +98,11 @@ fn test_iso_map_identity() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_map_to_curve_simple_swu() {
|
fn test_map_to_curve_simple_swu() {
|
||||||
use crate::arithmetic::Curve;
|
use crate::arithmetic::Curve;
|
||||||
use crate::pasta::curves::{IsoEp, IsoEpAffine};
|
use crate::pasta::curves::IsoEp;
|
||||||
use crate::pasta::hashtocurve::map_to_curve_simple_swu;
|
use crate::pasta::hashtocurve::map_to_curve_simple_swu;
|
||||||
|
|
||||||
// The zero input is a special case.
|
// The zero input is a special case.
|
||||||
let p: IsoEp =
|
let p: IsoEp = map_to_curve_simple_swu::<Fp, Ep, IsoEp>(&Fp::zero(), Ep::THETA, Ep::Z);
|
||||||
map_to_curve_simple_swu::<Fp, EpAffine, IsoEpAffine>(&Fp::zero(), Ep::THETA, Ep::Z);
|
|
||||||
let (x, y, z) = p.jacobian_coordinates();
|
let (x, y, z) = p.jacobian_coordinates();
|
||||||
println!("{:?}", p);
|
println!("{:?}", p);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
@ -119,8 +115,7 @@ fn test_map_to_curve_simple_swu() {
|
||||||
format!("{:?}", z) == "0x054b3ba10416dc104157b1318534a19d5d115472da7d746f8a5f250cd8cdef36"
|
format!("{:?}", z) == "0x054b3ba10416dc104157b1318534a19d5d115472da7d746f8a5f250cd8cdef36"
|
||||||
);
|
);
|
||||||
|
|
||||||
let p: IsoEp =
|
let p: IsoEp = map_to_curve_simple_swu::<Fp, Ep, IsoEp>(&Fp::one(), Ep::THETA, Ep::Z);
|
||||||
map_to_curve_simple_swu::<Fp, EpAffine, IsoEpAffine>(&Fp::one(), Ep::THETA, Ep::Z);
|
|
||||||
let (x, y, z) = p.jacobian_coordinates();
|
let (x, y, z) = p.jacobian_coordinates();
|
||||||
println!("{:?}", p);
|
println!("{:?}", p);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@ pub type Affine = EqAffine;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_map_to_curve_simple_swu() {
|
fn test_map_to_curve_simple_swu() {
|
||||||
use crate::arithmetic::Curve;
|
use crate::arithmetic::Curve;
|
||||||
use crate::pasta::curves::{IsoEq, IsoEqAffine};
|
use crate::pasta::curves::IsoEq;
|
||||||
use crate::pasta::hashtocurve::map_to_curve_simple_swu;
|
use crate::pasta::hashtocurve::map_to_curve_simple_swu;
|
||||||
|
|
||||||
// The zero input is a special case.
|
// The zero input is a special case.
|
||||||
let p: IsoEq =
|
let p: IsoEq = map_to_curve_simple_swu::<Fq, Eq, IsoEq>(&Fq::zero(), Eq::THETA, Eq::Z);
|
||||||
map_to_curve_simple_swu::<Fq, EqAffine, IsoEqAffine>(&Fq::zero(), Eq::THETA, Eq::Z);
|
|
||||||
let (x, y, z) = p.jacobian_coordinates();
|
let (x, y, z) = p.jacobian_coordinates();
|
||||||
println!("{:?}", p);
|
println!("{:?}", p);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
@ -35,8 +34,7 @@ fn test_map_to_curve_simple_swu() {
|
||||||
format!("{:?}", z) == "0x0b851e9e579403a76df1100f556e1f226e5656bdf38f3bf8601d8a3a9a15890b"
|
format!("{:?}", z) == "0x0b851e9e579403a76df1100f556e1f226e5656bdf38f3bf8601d8a3a9a15890b"
|
||||||
);
|
);
|
||||||
|
|
||||||
let p: IsoEq =
|
let p: IsoEq = map_to_curve_simple_swu::<Fq, Eq, IsoEq>(&Fq::one(), Eq::THETA, Eq::Z);
|
||||||
map_to_curve_simple_swu::<Fq, EqAffine, IsoEqAffine>(&Fq::one(), Eq::THETA, Eq::Z);
|
|
||||||
let (x, y, z) = p.jacobian_coordinates();
|
let (x, y, z) = p.jacobian_coordinates();
|
||||||
println!("{:?}", p);
|
println!("{:?}", p);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue