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:
Jack Grigg 2021-02-22 18:58:50 +00:00
parent 082d66d6e7
commit 55fb581f17
5 changed files with 34 additions and 41 deletions

View File

@ -84,9 +84,12 @@ pub trait Curve:
/// # Example
///
/// ```
/// use halo2::arithmetic::{Curve, CurveAffine};
/// fn pedersen_commitment<C: CurveAffine>(x: C::Scalar, r: C::Scalar) -> C {
/// let hasher = C::Curve::hash_to_curve("z.cash:example_pedersen_commitment");
/// use halo2::arithmetic::Curve;
/// fn pedersen_commitment<C: Curve>(
/// 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 h = hasher(b"h");
/// (g * x + &(h * r)).to_affine()

View File

@ -11,7 +11,7 @@ use super::{Fp, Fq};
use crate::arithmetic::{Curve, CurveAffine, FieldExt, Group};
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) => {
/// Represents a point in the projective coordinate space.
#[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())
}
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 {
$name::curve_constant_a()
@ -759,29 +759,26 @@ macro_rules! impl_projective_curve_specific {
}
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> {
use super::hashtocurve;
Box::new(move |message| {
let mut us = [Field::zero(); 2];
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],
$name::THETA,
$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],
$name::THETA,
$name::Z,
);
let r = q0 + &q1;
debug_assert!(bool::from(r.is_on_curve()));
hashtocurve::iso_map::<$base, $name_affine, $iso_affine>(
&r,
&$name::ISOGENY_CONSTANTS,
)
hashtocurve::iso_map::<$base, $name, $iso>(&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
fn hash_to_curve<'a>(_domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
unimplemented!()
@ -835,7 +832,7 @@ new_curve_impl!(
(pub),
Ep,
EpAffine,
IsoEpAffine,
IsoEp,
Fp,
Fq,
b"halo2_____pallas",
@ -848,7 +845,7 @@ new_curve_impl!(
(pub),
Eq,
EqAffine,
IsoEqAffine,
IsoEq,
Fq,
Fp,
b"halo2______vesta",
@ -861,7 +858,7 @@ new_curve_impl!(
(pub(crate)),
IsoEp,
IsoEpAffine,
EpAffine,
Ep,
Fp,
Fq,
b"halo2_iso_pallas",
@ -879,7 +876,7 @@ new_curve_impl!(
(pub(crate)),
IsoEq,
IsoEqAffine,
EqAffine,
Eq,
Fq,
Fp,
b"halo2__iso_vesta",

View File

@ -3,7 +3,7 @@
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`.
pub fn hash_to_field<F: FieldExt>(
@ -72,10 +72,10 @@ pub fn hash_to_field<F: FieldExt>(
}
/// Implements a degree 3 isogeny map.
pub fn iso_map<F: FieldExt, C: CurveAffine<Base = F>, I: CurveAffine<Base = F>>(
p: &I::Curve,
pub fn iso_map<F: FieldExt, C: Curve<Base = F>, I: Curve<Base = F>>(
p: &I,
iso: &[C::Base; 13],
) -> C::Curve {
) -> C {
// The input and output are in Jacobian coordinates, using the method
// 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 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,
theta: F,
z: F,
) -> I::Curve {
) -> I {
// 1. tv1 = inv0(Z^2 * u^4 + Z * u^2)
// 2. x1 = (-B / A) * (1 + tv1)
// 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)),
);
I::Curve::new_jacobian(num_x * div, y * div3, div).unwrap()
I::new_jacobian(num_x * div, y * div3, div).unwrap()
}

View File

@ -42,8 +42,7 @@ fn test_iso_map() {
]),
)
.unwrap();
let p =
super::hashtocurve::iso_map::<_, Affine, super::IsoEpAffine>(&r, &Ep::ISOGENY_CONSTANTS);
let p = super::hashtocurve::iso_map::<_, Point, super::IsoEp>(&r, &Ep::ISOGENY_CONSTANTS);
let (x, y, z) = p.jacobian_coordinates();
assert!(
format!("{:?}", x) == "0x318cc15f281662b3f26d0175cab97b924870c837879cac647e877be51a85e898"
@ -58,8 +57,7 @@ fn test_iso_map() {
// check that iso_map([2] r) = [2] iso_map(r)
let r2 = r.double();
assert!(bool::from(r2.is_on_curve()));
let p2 =
super::hashtocurve::iso_map::<_, Affine, super::IsoEpAffine>(&r2, &Ep::ISOGENY_CONSTANTS);
let p2 = super::hashtocurve::iso_map::<_, Point, super::IsoEp>(&r2, &Ep::ISOGENY_CONSTANTS);
assert!(bool::from(p2.is_on_curve()));
assert!(p2 == p.double());
}
@ -92,8 +90,7 @@ fn test_iso_map_identity() {
let r = (r * -Fq::one()) + r;
assert!(bool::from(r.is_on_curve()));
assert!(bool::from(r.is_identity()));
let p =
super::hashtocurve::iso_map::<_, Affine, super::IsoEpAffine>(&r, &Ep::ISOGENY_CONSTANTS);
let p = super::hashtocurve::iso_map::<_, Point, super::IsoEp>(&r, &Ep::ISOGENY_CONSTANTS);
assert!(bool::from(p.is_on_curve()));
assert!(bool::from(p.is_identity()));
}
@ -101,12 +98,11 @@ fn test_iso_map_identity() {
#[test]
fn test_map_to_curve_simple_swu() {
use crate::arithmetic::Curve;
use crate::pasta::curves::{IsoEp, IsoEpAffine};
use crate::pasta::curves::IsoEp;
use crate::pasta::hashtocurve::map_to_curve_simple_swu;
// The zero input is a special case.
let p: IsoEp =
map_to_curve_simple_swu::<Fp, EpAffine, IsoEpAffine>(&Fp::zero(), Ep::THETA, Ep::Z);
let p: IsoEp = map_to_curve_simple_swu::<Fp, Ep, IsoEp>(&Fp::zero(), Ep::THETA, Ep::Z);
let (x, y, z) = p.jacobian_coordinates();
println!("{:?}", p);
assert!(
@ -119,8 +115,7 @@ fn test_map_to_curve_simple_swu() {
format!("{:?}", z) == "0x054b3ba10416dc104157b1318534a19d5d115472da7d746f8a5f250cd8cdef36"
);
let p: IsoEp =
map_to_curve_simple_swu::<Fp, EpAffine, IsoEpAffine>(&Fp::one(), Ep::THETA, Ep::Z);
let p: IsoEp = map_to_curve_simple_swu::<Fp, Ep, IsoEp>(&Fp::one(), Ep::THETA, Ep::Z);
let (x, y, z) = p.jacobian_coordinates();
println!("{:?}", p);
assert!(

View File

@ -17,12 +17,11 @@ pub type Affine = EqAffine;
#[test]
fn test_map_to_curve_simple_swu() {
use crate::arithmetic::Curve;
use crate::pasta::curves::{IsoEq, IsoEqAffine};
use crate::pasta::curves::IsoEq;
use crate::pasta::hashtocurve::map_to_curve_simple_swu;
// The zero input is a special case.
let p: IsoEq =
map_to_curve_simple_swu::<Fq, EqAffine, IsoEqAffine>(&Fq::zero(), Eq::THETA, Eq::Z);
let p: IsoEq = map_to_curve_simple_swu::<Fq, Eq, IsoEq>(&Fq::zero(), Eq::THETA, Eq::Z);
let (x, y, z) = p.jacobian_coordinates();
println!("{:?}", p);
assert!(
@ -35,8 +34,7 @@ fn test_map_to_curve_simple_swu() {
format!("{:?}", z) == "0x0b851e9e579403a76df1100f556e1f226e5656bdf38f3bf8601d8a3a9a15890b"
);
let p: IsoEq =
map_to_curve_simple_swu::<Fq, EqAffine, IsoEqAffine>(&Fq::one(), Eq::THETA, Eq::Z);
let p: IsoEq = map_to_curve_simple_swu::<Fq, Eq, IsoEq>(&Fq::one(), Eq::THETA, Eq::Z);
let (x, y, z) = p.jacobian_coordinates();
println!("{:?}", p);
assert!(