Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(crypto): add xyzz coordinates #2008

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions crates/crypto/examples/consts_pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ fn generate_consts(bits: u32) -> Result<String, std::fmt::Error> {
write!(buf, "use crate::algebra::curve::AffinePoint;\n\n")?;
write!(buf, "pub const CURVE_CONSTS_BITS: usize = {bits};\n\n")?;

push_points(&mut buf, "P1", &PEDERSEN_P1, 248, bits)?;
push_points(&mut buf, "P1", PEDERSEN_P1, 248, bits)?;
buf.push_str("\n\n\n");
push_points(&mut buf, "P2", &PEDERSEN_P2, 4, bits)?;
push_points(&mut buf, "P2", PEDERSEN_P2, 4, bits)?;
buf.push_str("\n\n\n");
push_points(&mut buf, "P3", &PEDERSEN_P3, 248, bits)?;
push_points(&mut buf, "P3", PEDERSEN_P3, 248, bits)?;
buf.push_str("\n\n\n");
push_points(&mut buf, "P4", &PEDERSEN_P4, 4, bits)?;
push_points(&mut buf, "P4", PEDERSEN_P4, 4, bits)?;

Ok(buf)
}
Expand All @@ -48,12 +48,10 @@ fn generate_consts(bits: u32) -> Result<String, std::fmt::Error> {
fn push_points(
buf: &mut String,
name: &str,
base: &ProjectivePoint,
base: AffinePoint,
max_bits: u32,
bits: u32,
) -> std::fmt::Result {
let base = AffinePoint::from(base);

let full_chunks = max_bits / bits;
let leftover_bits = max_bits % bits;
let table_size_full = (1 << bits) - 1;
Expand Down
14 changes: 14 additions & 0 deletions crates/crypto/src/algebra/curve/affine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ impl From<&ProjectivePoint> for AffinePoint {
}
}

impl From<&XYZZPoint> for AffinePoint {
fn from(p: &XYZZPoint) -> Self {
let a = p.zzz.inverse().unwrap();
let b = (p.zz * a).square();
let x = p.x * b;
let y = p.y * a;
AffinePoint {
x,
y,
infinity: false,
}
}
}

impl AffinePoint {
/// Create a point from (x,y) as raw u64's in Montgomery representation
pub const fn from_raw(x: [u64; 4], y: [u64; 4]) -> Self {
Expand Down
3 changes: 3 additions & 0 deletions crates/crypto/src/algebra/curve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ mod gen_mul;
mod params;
mod projective;

mod xyzz;

pub use affine::AffinePoint;
pub use params::{CURVE_A, CURVE_B, CURVE_G, CURVE_ORDER};
pub use projective::ProjectivePoint;
pub use xyzz::XYZZPoint;

#[cfg(test)]
mod tests;
43 changes: 22 additions & 21 deletions crates/crypto/src/algebra/curve/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,22 @@ use bitvec::slice::BitSlice;
use crate::algebra::curve::*;
use crate::algebra::field::*;

/// A projective point on an elliptic curve over [MontFelt].
/// A projective point on an elliptic curve over [MontFelt] satisfying:
/// x = X / Z
/// y = Y / Z
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ProjectivePoint {
pub x: MontFelt,
pub y: MontFelt,
pub z: MontFelt,
pub infinity: bool,
}

impl From<&AffinePoint> for ProjectivePoint {
fn from(p: &AffinePoint) -> Self {
let x = p.x;
let y = p.y;
let z = MontFelt::ONE;
ProjectivePoint {
x,
y,
z,
infinity: false,
}
ProjectivePoint { x, y, z }
}
}

Expand All @@ -36,7 +32,6 @@ impl ProjectivePoint {
x,
y,
z: MontFelt::ONE,
infinity: false,
}
}

Expand All @@ -48,7 +43,6 @@ impl ProjectivePoint {
x,
y,
z: MontFelt::ONE,
infinity: false,
}
}

Expand All @@ -63,8 +57,7 @@ impl ProjectivePoint {
Self {
x: MontFelt::ZERO,
y: MontFelt::ZERO,
z: MontFelt::ONE,
infinity: true,
z: MontFelt::ZERO,
}
}

Expand All @@ -73,9 +66,14 @@ impl ProjectivePoint {
self.y = -self.y;
}

/// Check if the point is the point of infinity
pub fn is_infinity(&self) -> bool {
self.z.is_zero()
}

/// Double a point
pub fn double(&mut self) {
if self.infinity {
if self.is_infinity() {
return;
}

Expand All @@ -99,14 +97,13 @@ impl ProjectivePoint {

/// Add a point to this point
pub fn add(&mut self, other: &ProjectivePoint) {
if other.infinity {
if other.is_infinity() {
return;
}
if self.infinity {
if self.is_infinity() {
self.x = other.x;
self.y = other.y;
self.z = other.z;
self.infinity = other.infinity;
return;
}
let u0 = self.x * other.z;
Expand All @@ -115,7 +112,7 @@ impl ProjectivePoint {
let t1 = other.y * self.z;
if u0 == u1 {
if t0 != t1 {
self.infinity = true;
self.z = MontFelt::ZERO;
} else {
self.double();
}
Expand Down Expand Up @@ -144,11 +141,15 @@ impl ProjectivePoint {
if other.infinity {
return;
}
if self.infinity {
if self.is_infinity() {
self.x = other.x;
self.y = other.y;
self.z = MontFelt::ONE;
self.infinity = other.infinity;
self.z = if other.infinity {
MontFelt::ZERO
} else {
MontFelt::ONE
};

return;
}
let u0 = self.x;
Expand All @@ -157,7 +158,7 @@ impl ProjectivePoint {
let t1 = other.y * self.z;
if u0 == u1 {
if t0 != t1 {
self.infinity = true;
self.z = MontFelt::ZERO;
return;
} else {
self.double();
Expand Down
69 changes: 69 additions & 0 deletions crates/crypto/src/algebra/curve/xyzz.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::algebra::curve::*;
use crate::algebra::field::*;

/// A XYZZ point on an elliptic curve over [MontFelt] satisfying:
/// x = X / ZZ
/// y = Y / ZZ
/// ZZ^3 = ZZZ^2
///
/// This point representation is used for fast table-based scalar multiplication
/// and only include add_affine and add_affine_unchecked operations.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct XYZZPoint {
pub x: MontFelt,
pub y: MontFelt,
pub zz: MontFelt,
pub zzz: MontFelt,
}

impl From<&AffinePoint> for XYZZPoint {
fn from(p: &AffinePoint) -> Self {
let x = p.x;
let y = p.y;
let zz = MontFelt::ONE;
let zzz = MontFelt::ONE;
XYZZPoint { x, y, zz, zzz }
}
}

impl XYZZPoint {
/// Check if the point is the point of infinity
pub fn is_infinity(&self) -> bool {
self.zz.is_zero()
}

/// Add an affine point to this point
pub fn add_affine(&mut self, other: &AffinePoint) {
if other.infinity {
return;
}
if self.is_infinity() {
self.x = other.x;
self.y = other.y;
let z = if other.infinity {
MontFelt::ZERO
} else {
MontFelt::ONE
};
self.zz = z;
self.zzz = z;

return;
}
self.add_affine_unchecked(other);
}

/// Add an affine point to this point, neither must be the point of infinity
pub fn add_affine_unchecked(&mut self, other: &AffinePoint) {
// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
let p = other.x * self.zz - self.x;
let r = other.y * self.zzz - self.y;
let pp = p.square();
let ppp = p * pp;
let q = self.x * pp;
self.x = r.square() - ppp - q.double();
self.y = r * (q - self.x) - self.y * ppp;
self.zz *= pp;
self.zzz *= ppp;
}
}
12 changes: 6 additions & 6 deletions crates/crypto/src/hash/pedersen/gens.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
//! Generators for the Pedersen hash function.
//!
//! See <https://docs.starkware.co/starkex/crypto/pedersen-hash-function.html>
use crate::algebra::curve::ProjectivePoint;
use crate::algebra::curve::AffinePoint;

/// Montgomery representation of the Stark curve constant P0.
pub const PEDERSEN_P0: ProjectivePoint = ProjectivePoint::from_hex(
pub const PEDERSEN_P0: AffinePoint = AffinePoint::from_hex(
"49EE3EBA8C1600700EE1B87EB599F16716B0B1022947733551FDE4050CA6804",
"3CA0CFE4B3BC6DDF346D49D06EA0ED34E621062C0E056C1D0405D266E10268A",
);

/// Montgomery representation of the Stark curve constant P1.
pub const PEDERSEN_P1: ProjectivePoint = ProjectivePoint::from_hex(
pub const PEDERSEN_P1: AffinePoint = AffinePoint::from_hex(
"234287DCBAFFE7F969C748655FCA9E58FA8120B6D56EB0C1080D17957EBE47B",
"3B056F100F96FB21E889527D41F4E39940135DD7A6C94CC6ED0268EE89E5615",
);

/// Montgomery representation of the Stark curve constant P2.
pub const PEDERSEN_P2: ProjectivePoint = ProjectivePoint::from_hex(
pub const PEDERSEN_P2: AffinePoint = AffinePoint::from_hex(
"4FA56F376C83DB33F9DAB2656558F3399099EC1DE5E3018B7A6932DBA8AA378",
"3FA0984C931C9E38113E0C0E47E4401562761F92A7A23B45168F4E80FF5B54D",
);

/// Montgomery representation of the Stark curve constant P3.
pub const PEDERSEN_P3: ProjectivePoint = ProjectivePoint::from_hex(
pub const PEDERSEN_P3: AffinePoint = AffinePoint::from_hex(
"4BA4CC166BE8DEC764910F75B45F74B40C690C74709E90F3AA372F0BD2D6997",
"40301CF5C1751F4B971E46C4EDE85FCAC5C59A5CE5AE7C48151F27B24B219C",
);

/// Montgomery representation of the Stark curve constant P4.
pub const PEDERSEN_P4: ProjectivePoint = ProjectivePoint::from_hex(
pub const PEDERSEN_P4: AffinePoint = AffinePoint::from_hex(
"54302DCB0E6CC1C6E44CCA8F61A63BB2CA65048D53FB325D36FF12C49A58202",
"1B77B3E37D13504B348046268D8AE25CE98AD783C25561A879DCC77E99C2426",
);
8 changes: 5 additions & 3 deletions crates/crypto/src/hash/pedersen/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ pub fn pedersen_hash(a: Felt, b: Felt) -> Felt {

// Preprocessed material is lookup-tables for each chunk of bits
let table_size = (1 << CURVE_CONSTS_BITS) - 1;
let add_points = |acc: &mut ProjectivePoint, bits: &BitSlice<u8, _>, prep: &[AffinePoint]| {
let add_points = |acc: &mut XYZZPoint, bits: &BitSlice<u8, _>, prep: &[AffinePoint]| {
bits.chunks(CURVE_CONSTS_BITS)
.enumerate()
.for_each(|(i, v)| {
let offset: usize = v.load_le();
if offset > 0 {
// Table lookup at 'offset-1' in table for chunk 'i'
acc.add_affine(&prep[i * table_size + offset - 1]);
// We can add unchecked, since acc and prep. point cannot be infinity.
acc.add_affine_unchecked(&prep[i * table_size + offset - 1]);
}
});
};

// Compute hash
let mut acc = PEDERSEN_P0;
let mut acc = XYZZPoint::from(&PEDERSEN_P0);

add_points(&mut acc, &a_bits[..248], &CURVE_CONSTS_P1); // Add a_low * P1
add_points(&mut acc, &a_bits[248..252], &CURVE_CONSTS_P2); // Add a_high * P2
add_points(&mut acc, &b_bits[..248], &CURVE_CONSTS_P3); // Add b_low * P3
Expand Down