frontend/hyrax_worldcoin/
orb.rs

1use std::path::Path;
2
3use crate::zk_iriscode_ss::io::read_bytes_from_file;
4use hyrax::gkr::input_layer::HyraxProverInputCommitment;
5use itertools::Itertools;
6use remainder::mle::evals::MultilinearExtension;
7use remainder::utils::mle::pad_with;
8use shared_types::curves::PrimeOrderCurve;
9use shared_types::ff_field;
10use shared_types::HasByteRepresentation;
11use zeroize::Zeroize;
12
13// log of the number of columns for the Hyrax pre-commitment to the image.
14pub const IMAGE_COMMIT_LOG_NUM_COLS: usize = 9;
15// public string used to derive the generators (arbitrary constant)
16pub const PUBLIC_STRING: &str = "Modulus <3 Worldcoin: ZKML Self-Custody Edition";
17
18/// Helper function to read a Vec of bytes as a serialized Hyrax commitment, in a manner compatible
19/// with the Orb's serialization functions.
20pub fn deserialize_commitment_from_bytes<C: PrimeOrderCurve>(bytes: &[u8]) -> Vec<C> {
21    let commitment: Vec<C> = bytes
22        .chunks(C::COMPRESSED_CURVE_POINT_BYTEWIDTH)
23        .map(|chunk| C::from_bytes_compressed(chunk))
24        .collect_vec();
25    commitment
26}
27
28/// Helper function to read a Vec of bytes as serialized blinding factors in a manner compatiable
29/// with the Orb's serialization functions.
30pub fn deserialize_blinding_factors_from_bytes<C: PrimeOrderCurve>(bytes: &[u8]) -> Vec<C::Scalar> {
31    let blinding_factors: Vec<C::Scalar> = bytes
32        .chunks(C::SCALAR_ELEM_BYTEWIDTH)
33        .map(C::Scalar::from_bytes_le)
34        .collect_vec();
35    blinding_factors
36}
37
38/// An image, its serialized commitment, and its serialized blinding factors (serialized as per the
39/// Orb's serialization functions).
40/// (This is useful since the `Vec<u8>` representation of the attributes are convenient for receiving
41/// data from the phone app.)
42#[derive(Debug, Clone, Zeroize)]
43pub struct SerializedImageCommitment {
44    /// The image, unpadded.
45    pub image: Vec<u8>,
46    /// The commitment to the image, serialized using the curve's compressed representation.
47    pub commitment_bytes: Vec<u8>,
48    /// The blinding factors for the image, serialized in little-endian byte order.
49    pub blinding_factors_bytes: Vec<u8>,
50}
51
52impl<C: PrimeOrderCurve> From<SerializedImageCommitment> for HyraxProverInputCommitment<C> {
53    /// Deserializes a [SerializedImageCommitment] into a [HyraxProverInputCommitment].
54    fn from(serialization: SerializedImageCommitment) -> Self {
55        let image_as_field_elements = serialization
56            .image
57            .iter()
58            .map(|elem| C::Scalar::from(*elem as u64))
59            .collect_vec();
60        let commitment = deserialize_commitment_from_bytes(&serialization.commitment_bytes);
61        let blinding_factors_matrix =
62            deserialize_blinding_factors_from_bytes::<C>(&serialization.blinding_factors_bytes);
63        HyraxProverInputCommitment {
64            mle: MultilinearExtension::new(pad_with(C::Scalar::ZERO, &image_as_field_elements)),
65            commitment,
66            blinding_factors_matrix,
67        }
68    }
69}
70
71/// Returns a [SerializedImageCommitment] containing image, serialized commitment, and serialized
72/// blinding factors for the given version, mask, and eye (uses dummy data).
73pub fn load_image_commitment(
74    base_path: &Path,
75    version: u8,
76    mask: bool,
77    left_eye: bool,
78) -> SerializedImageCommitment {
79    let sizing_suffix = if version == 2 { "_resized" } else { "" };
80    let image_or_mask = if mask { "mask" } else { "image" };
81    let eye = if left_eye { "left" } else { "right" };
82    let image_fn = base_path.join(format!(
83        "{eye}_normalized_{image_or_mask}{sizing_suffix}.bin"
84    ));
85    let image = read_bytes_from_file(image_fn.as_os_str().to_str().unwrap());
86    let commitment_fn = base_path.join(format!(
87        "{eye}_normalized_{image_or_mask}_commitment{sizing_suffix}.bin"
88    ));
89    let commitment_bytes = read_bytes_from_file(commitment_fn.as_os_str().to_str().unwrap());
90    let blinding_factors_fn = base_path.join(format!(
91        "{eye}_normalized_{image_or_mask}_blinding_factors{sizing_suffix}.bin"
92    ));
93    let blinding_factors_bytes =
94        read_bytes_from_file(blinding_factors_fn.as_os_str().to_str().unwrap());
95    SerializedImageCommitment {
96        image,
97        commitment_bytes,
98        blinding_factors_bytes,
99    }
100}