Skip to content

Commit

Permalink
Merge commit '79ecad4e3b4a9f221c7cfeb6ec01bee43d7c01ff' into axiom/fe…
Browse files Browse the repository at this point in the history
…at/serde-raw

* Do not derive `PartialEq` for projective curve because the projective
  coordinates are ambiguous. We don't need to hash it anyways.
  • Loading branch information
jonathanpwang committed Dec 21, 2022
1 parent 67023a0 commit 9c7b343
Show file tree
Hide file tree
Showing 17 changed files with 667 additions and 282 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "halo2curves"
version = "0.2.1"
version = "0.3.1"
authors = [
"Sean Bowe <ewillbefull@gmail.com>",
"Jack Grigg <jack@z.cash>",
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ This implementation is mostly ported from [matterlabs/pairing](https://github.co

## Bench

None Assembly
No assembly
```
$ cargo test --profile bench test_field -- --nocapture
```

Assembly
Assembly (returns rust nightly)
```
$ cargo test --profile bench test_field --features asm -- --nocapture
```
21 changes: 10 additions & 11 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ use subtle::{Choice, ConditionallySelectable, CtOption};

pub trait CurveAffineExt: pasta_curves::arithmetic::CurveAffine {
fn batch_add<const COMPLETE: bool, const LOAD_POINTS: bool>(
_points: &mut [Self],
_output_indices: &[u32],
_num_points: usize,
_offset: usize,
_bases: &[Self],
_base_positions: &[u32],
) {
unimplemented!()
}

/// Unlike the `Coordinates` trait, this just returns the raw affine coordinantes without checking `is_on_curve`
points: &mut [Self],
output_indices: &[u32],
num_points: usize,
offset: usize,
bases: &[Self],
base_positions: &[u32],
);

/// Unlike the `Coordinates` trait, this just returns the raw affine coordinates without checking `is_on_curve`
fn into_coordinates(self) -> (Self::Base, Self::Base) {
// fallback implementation
let coordinates = self.coordinates().unwrap();
(*coordinates.x(), *coordinates.y())
}
Expand Down
568 changes: 318 additions & 250 deletions src/bn256/assembly.rs

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions src/bn256/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ new_curve_impl!(
G1,
G1Affine,
G1Compressed,
Fq::size(),
Fq,
Fr,
(G1_GENERATOR_X,G1_GENERATOR_Y),
Expand All @@ -38,6 +39,7 @@ new_curve_impl!(
G2,
G2Affine,
G2Compressed,
Fq2::size(),
Fq2,
Fr,
(G2_GENERATOR_X, G2_GENERATOR_Y),
Expand Down Expand Up @@ -292,6 +294,12 @@ mod tests {

assert_eq!(res_affine, exp_affine);
}

#[test]
fn test_serialization() {
crate::tests::curve::random_serialization_test::<G1>();
crate::tests::curve::random_serialization_test::<G2>();
}
}

impl group::UncompressedEncoding for G1Affine {
Expand Down
5 changes: 5 additions & 0 deletions src/bn256/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,9 @@ mod test {
fn test_field() {
crate::tests::field::random_field_tests::<Fq>("fq".to_string());
}

#[test]
fn test_serialization() {
crate::tests::field::random_serialization_test::<Fq>("fq".to_string());
}
}
40 changes: 40 additions & 0 deletions src/bn256/fq2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,41 @@ impl ff::PrimeField for Fq2 {
}
}

impl crate::serde::SerdeObject for Fq2 {
fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
assert_eq!(bytes.len(), 64);
let [c0, c1] = [0, 32].map(|i| Fq::from_raw_bytes_unchecked(&bytes[i..i + 32]));
Self { c0, c1 }
}
fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != 64 {
return None;
}
let [c0, c1] = [0, 32].map(|i| Fq::from_raw_bytes(&bytes[i..i + 32]));
c0.zip(c1).map(|(c0, c1)| Self { c0, c1 })
}
fn to_raw_bytes(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(64);
for limb in self.c0.0.iter().chain(self.c1.0.iter()) {
res.extend_from_slice(&limb.to_le_bytes());
}
res
}
fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
let [c0, c1] = [(); 2].map(|_| Fq::read_raw_unchecked(reader));
Self { c0, c1 }
}
fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let c0 = Fq::read_raw(reader)?;
let c1 = Fq::read_raw(reader)?;
Ok(Self { c0, c1 })
}
fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.c0.write_raw(writer)?;
self.c1.write_raw(writer)
}
}

pub const FROBENIUS_COEFF_FQ2_C1: [Fq; 2] = [
// Fq(-1)**(((q^0) - 1) / 2)
// it's 1 in Montgommery form
Expand Down Expand Up @@ -799,3 +834,8 @@ fn test_frobenius() {
fn test_field() {
crate::tests::field::random_field_tests::<Fq2>("fq2".to_string());
}

#[test]
fn test_serialization() {
crate::tests::field::random_serialization_test::<Fq2>("fq2".to_string());
}
5 changes: 5 additions & 0 deletions src/bn256/fr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,4 +363,9 @@ mod test {
])
);
}

#[test]
fn test_serialization() {
crate::tests::field::random_serialization_test::<Fr>("fr".to_string());
}
}
105 changes: 96 additions & 9 deletions src/derive/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,15 @@ macro_rules! new_curve_impl {
$name:ident,
$name_affine:ident,
$name_compressed:ident,
$compressed_size:expr,
$base:ident,
$scalar:ident,
$generator:expr,
$constant_b:expr,
$curve_id:literal,
) => {

#[derive(Copy, Clone, Debug, PartialEq, Hash, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
$($privacy)* struct $name {
pub x: $base,
pub y: $base,
Expand All @@ -167,8 +168,7 @@ macro_rules! new_curve_impl {
}

#[derive(Copy, Clone, Hash)]
$($privacy)* struct $name_compressed([u8; $base::size()]);

$($privacy)* struct $name_compressed([u8; $compressed_size]);

impl $name {
pub fn generator() -> Self {
Expand Down Expand Up @@ -232,7 +232,7 @@ macro_rules! new_curve_impl {

impl Default for $name_compressed {
fn default() -> Self {
$name_compressed([0; $base::size()])
$name_compressed([0; $compressed_size])
}
}

Expand Down Expand Up @@ -302,6 +302,12 @@ macro_rules! new_curve_impl {
}
}

impl PartialEq for $name {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).into()
}
}

impl cmp::Eq for $name {}

impl CurveExt for $name {
Expand Down Expand Up @@ -473,6 +479,46 @@ macro_rules! new_curve_impl {
}
}

impl $crate::serde::SerdeObject for $name {
fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
assert_eq!(bytes.len(), 3 * $base::size());
let [x, y, z] = [0, 1, 2]
.map(|i| $base::from_raw_bytes_unchecked(&bytes[i * $base::size()..(i + 1) * $base::size()]));
Self { x, y, z }
}
fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != 3 * $base::size() {
return None;
}
let [x, y, z] =
[0, 1, 2].map(|i| $base::from_raw_bytes(&bytes[i * $base::size()..(i + 1) * $base::size()]));
x.zip(y).zip(z).and_then(|((x, y), z)| {
let res = Self { x, y, z };
// Check that the point is on the curve.
bool::from(res.is_on_curve()).then(|| res)
})
}
fn to_raw_bytes(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(3 * $base::size());
Self::write_raw(self, &mut res).unwrap();
res
}
fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
let [x, y, z] = [(); 3].map(|_| $base::read_raw_unchecked(reader));
Self { x, y, z }
}
fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let x = $base::read_raw(reader)?;
let y = $base::read_raw(reader)?;
let z = $base::read_raw(reader)?;
Ok(Self { x, y, z })
}
fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.x.write_raw(writer)?;
self.y.write_raw(writer)?;
self.z.write_raw(writer)
}
}

impl group::prime::PrimeGroup for $name {}

Expand Down Expand Up @@ -557,10 +603,12 @@ macro_rules! new_curve_impl {
fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
let bytes = &bytes.0;
let mut tmp = *bytes;
let ysign = Choice::from(tmp[$base::size() - 1] >> 7);
tmp[$base::size() - 1] &= 0b0111_1111;
let ysign = Choice::from(tmp[$compressed_size - 1] >> 7);
tmp[$compressed_size - 1] &= 0b0111_1111;
let mut xbytes = [0u8; $base::size()];
xbytes.copy_from_slice(&tmp[ ..$base::size()]);

$base::from_bytes(&tmp).and_then(|x| {
$base::from_bytes(&xbytes).and_then(|x| {
CtOption::new(Self::identity(), x.is_zero() & (!ysign)).or_else(|| {
let x3 = x.square() * x;
(x3 + $name::curve_constant_b()).sqrt().and_then(|y| {
Expand Down Expand Up @@ -590,13 +638,52 @@ macro_rules! new_curve_impl {
} else {
let (x, y) = (self.x, self.y);
let sign = (y.to_bytes()[0] & 1) << 7;
let mut xbytes = x.to_bytes();
xbytes[$base::size() - 1] |= sign;
let mut xbytes = [0u8; $compressed_size];
xbytes[..$base::size()].copy_from_slice(&x.to_bytes());
xbytes[$compressed_size - 1] |= sign;
$name_compressed(xbytes)
}
}
}

impl crate::serde::SerdeObject for $name_affine {
fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
assert_eq!(bytes.len(), 2 * $base::size());
let [x, y] =
[0, $base::size()].map(|i| $base::from_raw_bytes_unchecked(&bytes[i..i + $base::size()]));
Self { x, y }
}
fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != 2 * $base::size() {
return None;
}
let [x, y] = [0, $base::size()].map(|i| $base::from_raw_bytes(&bytes[i..i + $base::size()]));
x.zip(y).and_then(|(x, y)| {
let res = Self { x, y };
// Check that the point is on the curve.
bool::from(res.is_on_curve()).then(|| res)
})
}
fn to_raw_bytes(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(2 * $base::size());
Self::write_raw(self, &mut res).unwrap();
res
}
fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
let [x, y] = [(); 2].map(|_| $base::read_raw_unchecked(reader));
Self { x, y }
}
fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let x = $base::read_raw(reader)?;
let y = $base::read_raw(reader)?;
Ok(Self { x, y })
}
fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.x.write_raw(writer)?;
self.y.write_raw(writer)
}
}

impl group::prime::PrimeCurveAffine for $name_affine {
type Curve = $name;
type Scalar = $scalar;
Expand Down
Loading

0 comments on commit 9c7b343

Please sign in to comment.