Skip to content

Commit

Permalink
Merge pull request privacy-scaling-explorations#126 from input-output…
Browse files Browse the repository at this point in the history
…-hk/dev-feature/pluto-eris-prime-bits

Add `PrimeFieldBits` support for Pluto/Eris
  • Loading branch information
b13decker authored Feb 27, 2024
2 parents 5758763 + 3f1ff84 commit 313797d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
2 changes: 1 addition & 1 deletion halo2_gadgets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ ff = { version = "0.13", features = ["bits"] }
group = "0.13"
halo2_proofs = { version = "0.2", path = "../halo2_proofs" }
lazy_static = "1"
halo2curves = { git = "https://github.com/davidnevadoc/halo2curves", rev = "55b8797e73003cd4c68da491d911522c240df3c4" }
halo2curves = { git = "https://github.com/davidnevadoc/halo2curves", rev = "33b1d2fe0f4576fde180e171eeab24f3d8573f2e", features = ["bits"] }
proptest = { version = "1.0.0", optional = true }
rand = "0.8"
subtle = "2.3"
Expand Down
2 changes: 1 addition & 1 deletion halo2_proofs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ backtrace = { version = "0.3", optional = true }
rayon = "1.5.1"
ff = "0.13"
group = "0.13"
halo2curves = { git = "https://github.com/davidnevadoc/halo2curves", rev = "55b8797e73003cd4c68da491d911522c240df3c4" }
halo2curves = { git = "https://github.com/davidnevadoc/halo2curves", rev = "33b1d2fe0f4576fde180e171eeab24f3d8573f2e", features = ["bits"] }
rand_core = { version = "0.6", default-features = false }
tracing = "0.1"
blake2b_simd = "1"
Expand Down
68 changes: 68 additions & 0 deletions halo2_proofs/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,71 @@ pub(crate) fn polynomial_slice_byte_length<F: PrimeField, B>(slice: &[Polynomial
let field_len = F::default().to_repr().as_ref().len();
4 + slice.len() * (4 + field_len * slice.get(0).map(|poly| poly.len()).unwrap_or(0))
}

#[cfg(test)]
mod pluto_eris_tests {
//! This ensures that the pluto / eris curves defined in the `halo2curves` repo satisfy our
//! serialization requirements.

use bitvec::{array::BitArray, bitarr, prelude::Lsb0, BitArr};
use ff::{Field, PrimeField, PrimeFieldBits};
use halo2curves::{
pluto_eris::{ErisAffine, Fp, Pluto},
CurveAffine,
};

/// There isn't a nice associated type on the `Pluto` struct to indicate the base field, so
/// we hardcode it here.
type PlutoBase = Fp;
/// Base field for Eris is defined at its `CurveAffine` implementation; elsewhere known as `Fq`
type ErisBase = <ErisAffine as CurveAffine>::Base;

/// Returns constant values for pluto and eris moduli.
///
/// These exact bits are produced by the sage script
/// `halo2_gadgets/scripts/full_width_variable_base_scalar_mul.sage`, which uses the
/// [constants defined by daira](https://github.com/daira/pluto-eris) as a point of truth.
fn pluto_eris_moduli() -> (BitArray<[u64; 7]>, BitArray<[u64; 7]>) {
let mut big_endian_pluto = bitarr![u64, Lsb0; 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
big_endian_pluto.reverse();
let mut big_endian_eris = bitarr![u64, Lsb0; 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
big_endian_eris.reverse();

// These are reversed, so the returned values are little endian
(big_endian_pluto, big_endian_eris)
}

#[test]
fn pluto_eris_moduli_serialize_correctly() {
let (expected_pluto, expected_eris) = pluto_eris_moduli();

let actual_pluto = PlutoBase::char_le_bits();
assert_eq!(actual_pluto, expected_pluto);

let actual_eris = ErisBase::char_le_bits();
assert_eq!(actual_eris, expected_eris);
}

#[test]
fn pluto_eris_known_values_serialize_correctly() {
// For 1, the first bit should be 1 and the rest should be 0
let one_pluto = PlutoBase::ONE.to_le_bits();
assert!(one_pluto[0]);
assert!(one_pluto[1..].not_any());

let one_eris = ErisBase::ONE.to_le_bits();
assert!(one_eris[0]);
assert!(one_eris[1..].not_any());

// For -1, the first bit should be opposite the modulus, and the rest should all match
let (expected_pluto, expected_eris) = pluto_eris_moduli();

let neg_one_pluto = (-PlutoBase::ONE).to_le_bits();
assert_ne!(neg_one_pluto[0], expected_pluto[0]);
assert_eq!(neg_one_pluto[1..], expected_pluto[1..]);

let neg_one_eris = (-ErisBase::ONE).to_le_bits();
assert_ne!(neg_one_eris[0], expected_eris[0]);
assert_eq!(neg_one_eris[1..], expected_eris[1..]);
}
}

0 comments on commit 313797d

Please sign in to comment.