frontend/worldcoin_mpc/
components.rs

1use shared_types::Field;
2
3use crate::{
4    layouter::builder::{CircuitBuilder, NodeRef},
5    worldcoin_mpc::parameters::GR4_MODULUS,
6};
7
8/// Components used by worldcoin mpc
9pub struct WorldcoinMpcComponents;
10
11impl WorldcoinMpcComponents {
12    /// Calculates masked iris code from iris code and mask, making the result
13    /// available as self.sector.
14    ///
15    /// Spec: --  iris_code in {0, 1}
16    ///       --  mask in {0, 1}
17    ///       --  masked_iris_code in {-1, 0, 1}, where 0 means that the bit was
18    ///           masked and {-1, 1} correspond to {0, 1} iris_code responses
19    ///
20    /// It is assumed that `iris_code` and `mask` have the same length.
21    ///
22    /// the expression is `mask - 2 * (iris_code * mask)`, a.k.a
23    /// (-2) * iris_code - mask
24    ///
25    /// see notion page: Worldcoin specification: iris code versions and Hamming distance
26    pub fn masked_iris_code<F: Field>(
27        builder_ref: &mut CircuitBuilder<F>,
28        iris_code: &NodeRef<F>,
29        mask: &NodeRef<F>,
30    ) -> NodeRef<F> {
31        builder_ref.add_sector(-(iris_code * F::from(2)) - mask + F::from(GR4_MODULUS))
32    }
33
34    /// Calculates `iris_code + evaluation_point_times_slopes`, making the result available as self.sector.
35    /// It is assumed that `iris_code` and `evaluation_point_times_slopes` have the same length.
36    pub fn sum<F: Field>(
37        builder_ref: &mut CircuitBuilder<F>,
38        encoded_masked_iris_code: &NodeRef<F>,
39        evaluation_point_times_slopes: &NodeRef<F>,
40    ) -> NodeRef<F> {
41        builder_ref.add_sector(encoded_masked_iris_code + evaluation_point_times_slopes)
42    }
43
44    /// Checks `computed_shares` and `shared_moduled` are the same modulo const `GR4_MODULO`.
45    /// Uses an auxilary `quotient` to store their difference divided by `GR4_MODULO`.
46    /// Makes the result available as self.sector. Also makes a zero output layer.
47    /// It is assumed that `computed_shares` and `shared_moduled` have the same length.
48    pub fn congruence<F: Field>(
49        builder_ref: &mut CircuitBuilder<F>,
50        quotient: &NodeRef<F>,
51        computed_shares: &NodeRef<F>,
52        shares_reduced_modulo_gr4_modulus: &NodeRef<F>,
53    ) -> NodeRef<F> {
54        let sector = builder_ref.add_sector(
55            quotient * F::from(GR4_MODULUS) + shares_reduced_modulo_gr4_modulus - computed_shares,
56        );
57
58        builder_ref.set_output(&sector);
59        sector
60    }
61}