jf_utils/
lib.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//! Jellyfish utilities library.
7
8#![cfg_attr(not(feature = "std"), no_std)]
9// Temporarily allow warning for nightly compilation with [`displaydoc`].
10#![allow(warnings)]
11#[cfg(test)]
12extern crate std;
13
14#[cfg(any(not(feature = "std"), target_has_atomic = "ptr"))]
15#[doc(hidden)]
16extern crate alloc;
17
18mod conversion;
19mod macros;
20mod multi_pairing;
21pub mod par_utils;
22pub mod reed_solomon_code;
23mod serialize;
24
25use ark_ec::twisted_edwards::TECurveConfig as Config;
26use ark_ff::{Field, PrimeField};
27use ark_std::{
28    ops::Mul,
29    rand::{self, rngs::StdRng},
30    string::{String, ToString},
31    vec::Vec,
32};
33
34pub use conversion::*;
35#[allow(unused_imports)]
36pub use macros::*;
37pub use multi_pairing::*;
38pub use serialize::*;
39
40#[inline]
41pub fn field_byte_len<F: PrimeField>() -> usize {
42    ((F::MODULUS_BIT_SIZE + 7) / 8) as usize
43}
44
45#[inline]
46pub fn field_bit_len<F: PrimeField>() -> usize {
47    F::MODULUS_BIT_SIZE as usize
48}
49
50#[inline]
51pub fn challenge_bit_len<F: PrimeField>() -> usize {
52    // Our challenge is of size 248 bits
53    // This is enough for a soundness error of 2^-128
54    (field_byte_len::<F>() - 1) << 3
55}
56
57#[inline]
58pub fn compute_len_to_next_multiple(len: usize, multiple: usize) -> usize {
59    if len % multiple == 0 {
60        len
61    } else {
62        len + multiple - len % multiple
63    }
64}
65
66// Pad message with 0 until `msg` is multiple of `multiple`
67#[inline]
68pub fn pad_with_zeros<F: Field>(vec: &mut Vec<F>, multiple: usize) {
69    let len = vec.len();
70    let new_len = compute_len_to_next_multiple(len, multiple);
71    vec.resize(new_len, F::zero())
72}
73
74/// Compute the hadamard product of two vectors (of equal length).
75#[inline]
76pub fn hadamard_product<T, B>(a: impl AsRef<[T]>, b: impl AsRef<[B]>) -> Result<Vec<B>, String>
77where
78    B: for<'a> Mul<&'a T, Output = B> + Copy,
79{
80    let (a, b) = (a.as_ref(), b.as_ref());
81    if a.len() != b.len() {
82        return Err(
83            "Cannot compute hadmard product of two vectors of different length".to_string(),
84        );
85    }
86
87    let res: Vec<B> = a.iter().zip(b.iter()).map(|(ai, &bi)| bi * ai).collect();
88    Ok(res)
89}
90
91pub fn test_rng() -> StdRng {
92    use rand::SeedableRng;
93    // arbitrary seed
94    let seed = [
95        1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96        0, 0, 0, 0,
97    ];
98    StdRng::from_seed(seed)
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use ark_ec::CurveGroup;
105
106    fn test_hadamard_template<Fr: PrimeField, G1: CurveGroup<ScalarField = Fr>>() {
107        let mut rng = test_rng();
108        for _ in 0..10 {
109            let a: Vec<Fr> = (0..20).map(|_| Fr::rand(&mut rng)).collect();
110            let b: Vec<Fr> = (0..20).map(|_| Fr::rand(&mut rng)).collect();
111
112            let product = hadamard_product(&a, &b).unwrap();
113            assert!(product.iter().enumerate().all(|(i, &c)| c == a[i] * b[i]));
114
115            let c: Vec<Fr> = (0..21).map(|_| Fr::rand(&mut rng)).collect();
116            assert!(hadamard_product(&a, &c).is_err());
117
118            let d: Vec<G1> = (0..20).map(|_| G1::rand(&mut rng)).collect();
119            let product = hadamard_product(&a, &d).unwrap();
120            assert!(product.iter().enumerate().all(|(i, &c)| c == d[i] * a[i]));
121        }
122    }
123
124    #[test]
125    fn test_hadamard() {
126        test_hadamard_template::<ark_bls12_381::Fr, ark_bls12_381::G1Projective>();
127        test_hadamard_template::<ark_bls12_377::Fr, ark_bls12_377::G1Projective>();
128        test_hadamard_template::<ark_bn254::Fr, ark_bn254::G1Projective>();
129    }
130}