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