grapevine-sonobe/src/utils/inputs.rs
src/utils/inputs.rsRaw
1use ark_ff::{PrimeField, BigInteger};
2use ark_pallas::Fr;
3use ark_std::rand::rngs::OsRng;
4use std::error::Error;
5use num_bigint::{BigInt, Sign::Plus, RandBigInt};
6
7use super::{MAX_SECRET_LENGTH, MAX_USERNAME_LENGTH, SECRET_FIELD_LENGTH};
8
9/** Get the starting ivc inputs (z0) for the grapevine circuit */
10pub fn get_z0<F: PrimeField>() -> [F; 4] {
11 (0..4).map(|_| F::zero()).collect::<Vec<F>>().try_into().unwrap()
12}
13
14/** Generates a random field element for given field as bigint */
15pub fn random_f_bigint<F: PrimeField>() -> BigInt {
16 let lower_bound = BigInt::from(0);
17 let upper_bound = BigInt::from_bytes_be(Plus, &F::MODULUS.to_bytes_be());
18 OsRng.gen_bigint_range(&lower_bound, &upper_bound)
19}
20
21/**
22 * Converts a given word to array of 6 field elements
23 * @dev split into 31-byte strings to fit in finite field and pad with 0's where necessary
24 *
25 * @param phrase - the string entered by user to compute hash for (will be length checked)
26 * @return - array of 6 Fr elements
27 */
28pub fn serialize_phrase(
29 phrase: &String,
30) -> Result<[BigInt; SECRET_FIELD_LENGTH], Box<dyn Error>> {
31 // check length
32 if phrase.len() > MAX_SECRET_LENGTH {
33 return Err("Phrase must be <= 180 characters".into());
34 }
35 // convert each 31-byte chunk to field element
36 let mut chunks: [BigInt; SECRET_FIELD_LENGTH] = Default::default();
37 for i in 0..SECRET_FIELD_LENGTH {
38 // get the range
39 let start = i * 31;
40 let end = (i + 1) * 31;
41 let mut chunk: [u8; 32] = [0; 32];
42 // select slice from range and pad if needed
43 if start >= phrase.len() {
44 } else if end > phrase.len() {
45 chunk[1..(phrase.len() - start + 1)].copy_from_slice(&phrase.as_bytes()[start..]);
46 } else {
47 chunk[1..32].copy_from_slice(&phrase.as_bytes()[start..end]);
48 }
49 // wrap in field element
50 chunks[i] = BigInt::from_bytes_be(Plus, &chunk);
51 }
52 Ok(chunks)
53}
54
55/**
56* Converts a given username to a field element
57*
58* @param username - the username to convert to utf8 and into field element
59* @return - the username serialied into the field element
60*/
61pub fn serialize_username(username: &String) -> Result<BigInt, Box<dyn Error>> {
62 // check length
63 if username.len() > MAX_USERNAME_LENGTH {
64 return Err("Username must be <= 30 characters".into());
65 }
66 // convert to big endian bytes
67 let mut bytes: [u8; 32] = [0; 32];
68 bytes[1..(username.len() + 1)].copy_from_slice(&username.as_bytes()[..]);
69 // convert to bigint
70 Ok(BigInt::from_bytes_be(Plus, &bytes))
71}