jf_relation/
constants.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the Jellyfish library.
3
4// You should have received a copy of the MIT License
5// along with the Jellyfish library. If not, see <https://mit-license.org/>.
6
7//! Crate wide constants.
8
9use ark_ff::{FftField, PrimeField};
10use ark_std::{rand::SeedableRng, vec, vec::Vec};
11use rand_chacha::ChaChaRng;
12
13// ==========================
14// Circuit-related constants.
15// ==========================
16
17/// The number of input wires.
18pub const GATE_WIDTH: usize = 4;
19/// The number of multiplication selectors.
20pub const N_MUL_SELECTORS: usize = 2;
21/// The number of TurboPlonk selectors.
22pub const N_TURBO_PLONK_SELECTORS: usize = 13;
23
24/// Compute constants K0, K1, ..., K_{`num_wire_types`-1} so that cosets {Ki *
25/// H} are disjoint, each coset |Ki * H| = `coset_size`.
26/// `coset_size` is optional, when provided, will accelerate constants
27/// searching.
28#[inline]
29#[allow(non_snake_case)]
30pub fn compute_coset_representatives<F: PrimeField>(
31    num_wire_types: usize,
32    coset_size: Option<usize>,
33) -> Vec<F> {
34    // check if two cosets `aH == bH` where `a, b` are cosets representations
35    fn is_equal_coset<F: PrimeField>(pow_a_N: F, pow_b_N: F) -> bool {
36        // check (a^-1 * b)^`N` = 1
37        pow_a_N
38            .inverse()
39            .expect("Unreachable: all elements in a prime field should have inverse")
40            * pow_b_N
41            == F::one()
42    }
43
44    // check if a new k is valid: i.e. doesn't represent the same coset as any
45    // previous values `prev`.
46    fn is_valid_k<F: PrimeField>(pow_k_N: F, pow_prev_N: &[F]) -> bool {
47        !pow_prev_N
48            .iter()
49            .any(|&pow_k_prev_N| is_equal_coset(pow_k_N, pow_k_prev_N))
50    }
51
52    // storing cached `Ki -> Ki^coset_size` values.
53    let mut pow_k_N_vec = vec![];
54    let mut k_vec = vec![];
55    let mut rng = ChaChaRng::from_seed([0u8; 32]); // empty bytes as seed
56
57    // the exponent N for checking membership of domain H
58    let N = match coset_size {
59        Some(size) => size,
60        None => {
61            // let `2^s * t` be the size of the multiplicative group defined by the field
62            // `F`, for some odd integer `t`, `s` is the 2-adicity of `F*`.
63            // `2^s` is a guaranteed to be multiple of |H|.
64            2usize.pow(<F as FftField>::TWO_ADICITY)
65        },
66    };
67    for i in 0..num_wire_types {
68        if i == 0 {
69            // set first K0 = 1, namely the H itself
70            k_vec.push(F::one());
71            pow_k_N_vec.push(F::one());
72        } else {
73            let mut next = F::rand(&mut rng);
74            let mut pow_next_N = next.pow([N as u64]);
75            while !is_valid_k(pow_next_N, &pow_k_N_vec) {
76                next = F::rand(&mut rng);
77                pow_next_N = next.pow([N as u64]);
78            }
79            k_vec.push(next);
80            pow_k_N_vec.push(pow_next_N);
81        }
82    }
83    k_vec
84}