jf_utils/
conversion.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
7use ark_ec::CurveConfig;
8use ark_ff::{BigInteger, Field, PrimeField};
9use ark_std::{
10    borrow::Borrow,
11    cmp::min,
12    iter::{once, repeat},
13    mem,
14    vec::Vec,
15};
16use sha2::{Digest, Sha512};
17
18/// Convert a scalar field element to a base field element.
19/// Mod reduction is not performed since the conversion occurs
20/// for fields on a same curve.
21pub fn fr_to_fq<F, P>(scalar: &P::ScalarField) -> F
22where
23    F: PrimeField,
24    P: CurveConfig<BaseField = F>,
25{
26    // sanity checks:
27    // ensure | jubjub scalar field | <= | BLS Scalar field |
28    // jubjub scalar field:
29    // 6554484396890773809930967563523245729705921265872317281365359162392183254199
30    // BLS12-381 scalar field:
31    // 52435875175126190479447740508185965837690552500527637822603658699938581184513
32    // jubjub377 scalar field:
33    // 2111115437357092606062206234695386632838870926408408195193685246394721360383
34    // BLS12-377 scalar field:
35    // 8444461749428370424248824938781546531375899335154063827935233455917409239041
36    F::from_le_bytes_mod_order(&scalar.into_bigint().to_bytes_le())
37}
38
39/// Convert a base field element to a scalar field element.
40/// Perform a mod reduction if the base field element is greater than
41/// the modulus of the scalar field.
42pub fn fq_to_fr<F, P>(base: &F) -> P::ScalarField
43where
44    F: PrimeField,
45    P: CurveConfig<BaseField = F>,
46{
47    P::ScalarField::from_le_bytes_mod_order(&base.into_bigint().to_bytes_le())
48}
49
50/// Convert a field element in F(rom) to a field element in T(o),
51/// with |T| < |F|; truncating the element via masking the top
52/// F::MODULUS_BIT_SIZE - T::MODULUS_BIT_SIZE with 0s
53pub fn fq_to_fr_with_mask<F, T>(base: &F) -> T
54where
55    F: PrimeField,
56    T: PrimeField,
57{
58    assert!(T::MODULUS_BIT_SIZE < F::MODULUS_BIT_SIZE);
59    let length = (T::MODULUS_BIT_SIZE >> 3) as usize;
60    // ensure that no mod reduction happened
61    T::from_le_bytes_mod_order(&base.into_bigint().to_bytes_le()[0..length])
62}
63
64// convert a field element in F(rom)
65// to a field element in T(o).
66// return an error if a mod reduction occurs.
67#[inline]
68pub fn field_switching<F, T>(base: &F) -> T
69where
70    F: PrimeField,
71    T: PrimeField,
72{
73    let bytes = base.into_bigint().to_bytes_le();
74    let t = T::from_le_bytes_mod_order(&bytes);
75
76    // check t == base
77    // i.e., t did not overflow the target field
78    let bytes_rec = t.into_bigint().to_bytes_le();
79    let length = min(bytes.len(), bytes_rec.len());
80    assert_eq!(bytes_rec[0..length], bytes[0..length],);
81    t
82}
83
84/// Hash a sequence of bytes to into a field
85/// element, whose order is less than 256 bits.
86pub fn hash_to_field<B, F>(bytes: B) -> F
87where
88    B: AsRef<[u8]>,
89    F: PrimeField,
90{
91    // we extract a random `rand_byte_len` bytes from the hash
92    // the compute res = OS2IP(output) mod p
93    // which is less than 2^-128 from uniform
94    let rand_byte_len = (F::MODULUS_BIT_SIZE + 7) as usize / 8 + 128 / 8;
95    let mut hasher = Sha512::default();
96    hasher.update(bytes.as_ref());
97    let output = &hasher.finalize()[0..rand_byte_len];
98
99    F::from_le_bytes_mod_order(output)
100}
101
102/// Deterministic, infallible, invertible conversion from arbitrary bytes to
103/// field elements.
104///
105/// # How it works
106///
107/// - The first [`Field`] element in the result encodes `bytes` length as a
108///   `u64`.
109/// - Partition `bytes` into chunks of length P, where P is the field
110///   characteristic byte length minus 1.
111/// - Convert each chunk into [`Field::BasePrimeField`] via
112///   [`PrimeField::from_le_bytes_mod_order`]. Reduction modulo the field
113///   characteristic is guaranteed not to occur because chunk byte length is
114///   sufficiently small.
115/// - Collect [`Field::BasePrimeField`] elements into [`Field`] elements and
116///   append to result.
117/// - If `bytes` is empty then result is empty.
118///
119/// # Panics
120///
121/// Panics only under conditions that should be checkable at compile time:
122///
123/// - The [`Field::BasePrimeField`] modulus bit length is too small to hold a
124///   `u64`.
125/// - The byte length of a single [`Field::BasePrimeField`] element fails to fit
126///   inside a `usize`.
127/// - The extension degree of the [`Field`] fails to fit inside a `usize`.
128/// - The byte length of a [`Field`] element fails to fit inside a `usize`.
129///
130/// If any of the above conditions holds then this function *always* panics.
131pub fn bytes_to_field_elements<B, F>(bytes: B) -> Vec<F>
132where
133    B: Borrow<[u8]>,
134    F: Field,
135{
136    let bytes = bytes.borrow();
137    let (primefield_bytes_len, extension_degree, field_bytes_len) = compile_time_checks::<F>();
138    if bytes.is_empty() {
139        return Vec::new();
140    }
141
142    // Result length is always less than `bytes` length for sufficiently large
143    // `bytes`. Thus, the following should never panic.
144    let result_len = (field_bytes_len
145        .checked_add(bytes.len())
146        .expect("result len should fit into usize")
147        - 1)
148        / field_bytes_len
149        + 1;
150
151    let result = once(F::from(bytes.len() as u64)) // the first field element encodes the bytes length as u64
152        .chain(bytes.chunks(field_bytes_len).map(|field_elem_bytes| {
153            F::from_base_prime_field_elems(
154                &field_elem_bytes.chunks(primefield_bytes_len)
155                .map(F::BasePrimeField::from_le_bytes_mod_order)
156                // not enough prime field elems? fill remaining elems with zero
157                .chain(repeat(F::BasePrimeField::ZERO).take(
158                    extension_degree - (field_elem_bytes.len()-1) / primefield_bytes_len - 1)
159                )
160                .collect::<Vec<_>>(),
161            )
162            .expect("failed to construct field element")
163        }))
164        .collect::<Vec<_>>();
165
166    // sanity check
167    assert_eq!(
168        result.len(),
169        result_len,
170        "invalid result len, expect {}, found {}",
171        result_len,
172        result.len()
173    );
174    result
175}
176
177/// Deterministic, infallible inverse of [`bytes_to_field_elements`].
178///
179/// This function is not invertible because [`bytes_to_field_elements`] is not
180/// onto.
181///
182/// ## Panics
183///
184/// Panics under the conditions listed at [`bytes_to_field_elements`], or if the
185/// length of the return `Vec<u8>` overflows `usize`.
186pub fn bytes_from_field_elements<T, F>(elems: T) -> Vec<u8>
187where
188    T: Borrow<[F]>,
189    F: Field,
190{
191    let elems = elems.borrow();
192    let (primefield_bytes_len, _, field_bytes_len) = compile_time_checks::<F>();
193    if elems.is_empty() {
194        return Vec::new();
195    }
196
197    let (first_elem, elems) = elems.split_first().expect("elems should be non-empty");
198
199    // the first element encodes the number of bytes to return
200    let result_len = usize::try_from(u64::from_le_bytes(
201        first_elem
202            .to_base_prime_field_elements()
203            .next()
204            .expect("first base prime field elem should be non-empty")
205            .into_bigint()
206            .to_bytes_le()[..mem::size_of::<u64>()]
207            .try_into()
208            .expect("conversion from [u8] to u64 should succeed"),
209    ))
210    .expect("result len conversion from u64 to usize should succeed");
211
212    let result_capacity = field_bytes_len
213        .checked_mul(elems.len())
214        .expect("result capacity should fit into usize");
215
216    // If `elems` was produced by `bytes_to_field_elements`
217    // then the original bytes MUST end before the final field element
218    // so we expect `result_len <= result_capacity`.
219    // But if `elems` is arbitrary then `result_len` could be large,
220    // so we enforce `result_len <= result_capacity`.
221    // Do not enforce a lower bound on `result_len` because the caller might
222    // pad `elems`, for example with extra zeros from polynomial interpolation.
223    let result_len = min(result_len, result_capacity);
224
225    // for each base prime field element:
226    // - convert to bytes
227    // - drop the trailing byte
228    // - append bytes to result
229    let mut result = Vec::with_capacity(result_capacity);
230    for elem in elems {
231        for primefield_elem in elem.to_base_prime_field_elements() {
232            let primefield_bytes = primefield_elem.into_bigint().to_bytes_le();
233            let (_, primefield_bytes) = primefield_bytes
234                .split_last() // ignore the final byte of primefield_elem
235                .expect("prime field elem bytes should be non-empty");
236            assert_eq!(
237                primefield_bytes.len(),
238                primefield_bytes_len,
239                "invalid prime field elem bytes len, expect {}, found {}",
240                primefield_bytes_len,
241                primefield_bytes.len()
242            );
243            result.extend_from_slice(primefield_bytes);
244        }
245    }
246
247    // sanity check
248    assert_eq!(
249        result.len(),
250        result_capacity,
251        "invalid result len, expect {}, found {}",
252        result_capacity,
253        result.len()
254    );
255
256    result.truncate(result_len);
257    result
258}
259
260/// Compute various `usize` quantities as a function of the generic [`Field`]
261/// parameter.
262///
263/// It should be possible to do all this at compile time but I don't know how.
264/// Want to panic on overflow, so use checked arithmetic and type conversion.
265///
266/// # Returns
267///
268/// Returns the following tuple:
269/// 1. The byte length P of the [`BasePrimeField`] modulus minus 1.
270/// 2. The extension degree of the [`Field`].
271/// 3. The total byte length of a single [`Field`] element under the constraint
272/// that   each [`BasePrimeField`] element fits into only P bytes.
273///
274/// # Panics
275///
276/// Panics under the conditions listed at [`bytes_to_field_elements`].
277fn compile_time_checks<F: Field>() -> (usize, usize, usize) {
278    assert!(
279        F::BasePrimeField::MODULUS_BIT_SIZE > 64,
280        "base prime field modulus bit len {} too small to hold a u64",
281        F::BasePrimeField::MODULUS_BIT_SIZE
282    );
283
284    let primefield_bytes_len = usize::try_from((F::BasePrimeField::MODULUS_BIT_SIZE - 1) / 8)
285        .expect("prime field modulus byte len should fit into usize");
286    let extension_degree =
287        usize::try_from(F::extension_degree()).expect("extension degree should fit into usize");
288    let field_bytes_len = primefield_bytes_len
289        .checked_mul(extension_degree)
290        .expect("field element byte len should fit into usize");
291    (primefield_bytes_len, extension_degree, field_bytes_len)
292}
293
294#[cfg(test)]
295mod tests {
296    use crate::test_rng;
297
298    use super::*;
299    use ark_bls12_377::Fq12 as Fq12_377;
300    use ark_bls12_381::Fq12 as Fq12_381;
301    use ark_bn254::Fq12 as Fq12_254;
302    use ark_ed_on_bls12_377::{EdwardsConfig as Param377, Fr as Fr377};
303    use ark_ed_on_bls12_381::{EdwardsConfig as Param381, Fr as Fr381};
304    use ark_ed_on_bn254::{EdwardsConfig as Param254, Fr as Fr254};
305    use ark_std::{rand::RngCore, UniformRand};
306
307    #[test]
308    fn test_bn254_scalar_conversion() {
309        let mut rng = test_rng();
310        for _ in 0..6 {
311            let jj = Fr254::rand(&mut rng);
312            let jj_bls = fr_to_fq::<_, Param254>(&jj);
313            assert!(jj.into_bigint() == jj_bls.into_bigint());
314        }
315    }
316
317    #[test]
318    fn test_jubjub_bls_scalar_conversion_377() {
319        let mut rng = test_rng();
320        for _ in 0..6 {
321            let jj = Fr377::rand(&mut rng);
322            let jj_bls = fr_to_fq::<_, Param377>(&jj);
323            assert!(jj.into_bigint() == jj_bls.into_bigint());
324        }
325    }
326
327    #[test]
328    fn test_jubjub_bls_scalar_conversion_381() {
329        let mut rng = test_rng();
330        for _ in 0..6 {
331            let jj = Fr381::rand(&mut rng);
332            let jj_bls = fr_to_fq::<_, Param381>(&jj);
333            assert!(jj.into_bigint() == jj_bls.into_bigint());
334        }
335    }
336
337    fn bytes_field_elems<F: Field>() {
338        let lengths = [0, 1, 2, 16, 31, 32, 33, 48, 65, 100, 200];
339        let trailing_zeros_lengths = [0, 1, 2, 5, 50];
340
341        let max_len = *lengths.iter().max().unwrap();
342        let max_trailing_zeros_len = *trailing_zeros_lengths.iter().max().unwrap();
343        let mut bytes = Vec::with_capacity(max_len + max_trailing_zeros_len);
344        let mut elems: Vec<F> = Vec::with_capacity(max_len);
345        let mut rng = test_rng();
346
347        for len in lengths {
348            for trailing_zeros_len in trailing_zeros_lengths {
349                // fill bytes with random bytes and trailing zeros
350                bytes.resize(len + trailing_zeros_len, 0);
351                rng.fill_bytes(&mut bytes[..len]);
352                bytes[len..].fill(0);
353
354                // round trip
355                let encoded_bytes: Vec<F> = bytes_to_field_elements(bytes.as_ref());
356                let result = bytes_from_field_elements(encoded_bytes);
357                assert_eq!(result, bytes);
358            }
359
360            // test infallibility of bytes_from_field_elements
361            // with random field elements
362            elems.resize(len, F::zero());
363            elems.iter_mut().for_each(|e| *e = F::rand(&mut rng));
364            bytes_from_field_elements(elems.as_ref());
365        }
366    }
367
368    #[test]
369    fn test_bytes_field_elems() {
370        bytes_field_elems::<Fr381>();
371        bytes_field_elems::<Fr377>();
372        bytes_field_elems::<Fr254>();
373        bytes_field_elems::<Fq12_381>();
374        bytes_field_elems::<Fq12_377>();
375        bytes_field_elems::<Fq12_254>();
376    }
377}