Skip to content

Commit

Permalink
mod/guest: plucking helper functions into a separate utils.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
ndrwnaguib committed Jan 13, 2025
1 parent e886abf commit 8864755
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 183 deletions.
1 change: 1 addition & 0 deletions methods/guest/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod utils;
187 changes: 4 additions & 183 deletions methods/guest/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,137 +1,17 @@
use num_bigint::{BigInt, RandBigInt};
use num_traits::{One, Zero};
use rand::seq::SliceRandom;
use rand::{rngs::StdRng, Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use risc0_zkvm::guest::env;
use serde::Serialize;
use sha2::{Digest, Sha256};
use std::collections::HashMap;
use zk_auctions_core::gm::{encrypt_bit_gm_coin, get_next_random, StrainRandomGenerator};

use zk_auctions_core::gm::{
decrypt_bit_and, decrypt_bit_gm, decrypt_gm, dot_mod, embed_and, embed_bit_and,
encrypt_bit_and, encrypt_bit_gm, encrypt_bit_gm_coin, encrypt_gm, encrypt_gm_coin,
generate_keys, get_next_random, StrainRandomGenerator,
use guest::utils::{
bigint_to_seed, compute_permutation, divm, get_rand_jn1, hash_flat, permute, set_rand_seed,
StrainProof,
};

use zk_auctions_core::number::Jacobi;

#[derive(Debug, Serialize)]
enum StrainProof {
MEPermutations((HashMap<usize, usize>, HashMap<usize, HashMap<usize, BigInt>>)),
AMPermutations((HashMap<usize, usize>, Vec<Vec<BigInt>>)),
HashInput(
HashMap<
usize,
(HashMap<usize, HashMap<usize, BigInt>>, HashMap<usize, HashMap<usize, BigInt>>),
>,
),
}

fn divm(a: &BigInt, b: &BigInt, n: &BigInt) -> BigInt {
let b_inv = b.modinv(n).unwrap();
(a * b_inv) % n
}

fn standard_deviation(data: &[f64], mean: f64) -> f64 {
(data.iter().map(|value| (value - mean).powi(2)).sum::<f64>() / data.len() as f64).sqrt()
}

fn rand32(n: &BigInt) -> Vec<BigInt> {
let mut result = Vec::new();
for _ in 0..32 {
result.push(get_next_random(n));
}
result
}

fn generate_rand_matrix(n: &BigInt, rows: usize, cols: usize) -> Vec<Vec<BigInt>> {
let mut matrix = Vec::new();
for _ in 0..rows {
let mut row = Vec::new();
for _ in 0..cols {
row.push(get_next_random(n));
}
matrix.push(row);
}
matrix
}

fn get_rand_jn1(n: &BigInt, rng: Option<ChaCha20Rng>) -> BigInt {
let mut rng = rng.unwrap_or(/* default value */ ChaCha20Rng::from_entropy());
loop {
let r = rng.gen_bigint_range(&BigInt::zero(), &n);

if r.jacobi(&n) == 1 {
return r;
}
}
}

fn set_rand_seed(num_list: &[BigInt]) -> ChaCha20Rng {
let mut hasher = Sha256::new();

for x in num_list {
hasher.update(x.to_bytes_be().1);
}

let hash_result = hasher.finalize();
let mut seed = [0u8; 32];
seed.copy_from_slice(&hash_result[..32]); // SHA256 output is 32 bytes
ChaCha20Rng::from_seed(seed)
// Non-thread-safe seeding
}

fn hash_flat_recursive(hasher: &mut Sha256, obj: &dyn Hashable) {
obj.hash_flat(hasher);
}

pub trait Hashable {
fn hash_flat(&self, hasher: &mut Sha256);
}

impl Hashable for BigInt {
fn hash_flat(&self, hasher: &mut Sha256) {
hasher.update(self.to_string().as_bytes());
}
}

impl Hashable for usize {
fn hash_flat(&self, hasher: &mut Sha256) {
hasher.update(self.to_string().as_bytes());
}
}

impl<T: Hashable> Hashable for Vec<T> {
fn hash_flat(&self, hasher: &mut Sha256) {
for item in self {
hash_flat_recursive(hasher, item);
}
}
}

impl<K: Hashable, V: Hashable> Hashable for HashMap<K, V> {
fn hash_flat(&self, hasher: &mut Sha256) {
for (key, value) in self {
hash_flat_recursive(hasher, key);
hash_flat_recursive(hasher, value);
}
}
}

impl<T1: Hashable, T2: Hashable> Hashable for (T1, T2) {
fn hash_flat(&self, hasher: &mut Sha256) {
hash_flat_recursive(hasher, &self.0);
hash_flat_recursive(hasher, &self.1);
}
}

fn hash_flat<T: Hashable>(input: &T) -> u64 {
let mut hasher = Sha256::new();
input.hash_flat(&mut hasher);
u64::from_le_bytes(hasher.finalize().to_vec()[..8].try_into().unwrap())
}

fn compute_proof_enc(c1: Vec<BigInt>, n1: &BigInt, r1: &[BigInt]) -> Vec<Vec<Vec<BigInt>>> {
let mut rng = rand::thread_rng();

Expand Down Expand Up @@ -392,65 +272,6 @@ fn compute_proof_shuffle(res: &[Vec<BigInt>], n2: &BigInt) -> HashMap<usize, Str
proof
}

fn compute_permutation(
res: &[Vec<BigInt>],
n: &BigInt,
) -> (HashMap<usize, usize>, HashMap<usize, HashMap<usize, BigInt>>, Vec<Vec<BigInt>>) {
let seed = get_next_random(n);
let permutation_desc = permute(res.len(), &seed);

let mut output_permutation = HashMap::new();
let mut reencrypt_factors = Vec::new();

for (i, res_i) in res.iter().enumerate() {
let mut rs = Vec::new();
let mut and_encryptions = HashMap::new();

for (j, res_ij) in res_i.iter().enumerate() {
let r = get_next_random(n);
rs.push(r.clone());
let rsquare = r.modpow(&BigInt::from(2), n);
let reencryption = (rsquare * res_ij) % n;
and_encryptions.insert(j, reencryption);
}

output_permutation.insert(permutation_desc[&i], and_encryptions);
reencrypt_factors.push(rs);
}

(permutation_desc, output_permutation, reencrypt_factors)
}

fn bigint_to_seed(bigint: &BigInt) -> [u8; 32] {
// Convert BigInt to bytes
let bytes = bigint.to_signed_bytes_le();

// Hash the bytes to 32 bytes using SHA-256
let hash = Sha256::digest(&bytes);

// Convert hash output to a 32-byte array
let mut seed = [0u8; 32];
seed.copy_from_slice(&hash);
seed
}

fn permute(length: usize, seed_bigint: &BigInt) -> HashMap<usize, usize> {
let seed = bigint_to_seed(&seed_bigint);
let mut rng = ChaCha20Rng::from_seed(seed);
let mut permutation: HashMap<usize, usize> = (0..length).map(|i| (i, i)).collect();

for i in 0..(length - 1) {
let index = rng.gen_range(i..length);
let value_i = permutation[&i];
let value_index = permutation[&index];

permutation.insert(i, value_index);
permutation.insert(index, value_i);
}

permutation
}

fn main() {
let (c1, n1, r1): (Vec<BigInt>, BigInt, Vec<BigInt>) = env::read();
let (cipher_i, cipher_j, cipher_ij, number1, pub_key_i, pub_key_j, r12, sound_param): (
Expand Down
162 changes: 162 additions & 0 deletions methods/guest/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
use num_bigint::{BigInt, RandBigInt};
use num_traits::{One, Zero};
use rand::seq::SliceRandom;
use rand::{rngs::StdRng, Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use serde::Serialize;
use sha2::{Digest, Sha256};
use std::collections::HashMap;
use zk_auctions_core::number::Jacobi;

use zk_auctions_core::gm::get_next_random;

#[derive(Debug, Serialize)]
pub enum StrainProof {
MEPermutations((HashMap<usize, usize>, HashMap<usize, HashMap<usize, BigInt>>)),
AMPermutations((HashMap<usize, usize>, Vec<Vec<BigInt>>)),
HashInput(
HashMap<
usize,
(HashMap<usize, HashMap<usize, BigInt>>, HashMap<usize, HashMap<usize, BigInt>>),
>,
),
}

pub fn divm(a: &BigInt, b: &BigInt, n: &BigInt) -> BigInt {
let b_inv = b.modinv(n).unwrap();
(a * b_inv) % n
}

pub fn get_rand_jn1(n: &BigInt, rng: Option<ChaCha20Rng>) -> BigInt {
let mut rng = rng.unwrap_or(/* default value */ ChaCha20Rng::from_entropy());
loop {
let r = rng.gen_bigint_range(&BigInt::zero(), &n);

if r.jacobi(&n) == 1 {
return r;
}
}
}

pub fn set_rand_seed(num_list: &[BigInt]) -> ChaCha20Rng {
let mut hasher = Sha256::new();

for x in num_list {
hasher.update(x.to_bytes_be().1);
}

let hash_result = hasher.finalize();
let mut seed = [0u8; 32];
seed.copy_from_slice(&hash_result[..32]); // SHA256 output is 32 bytes
ChaCha20Rng::from_seed(seed)
// Non-thread-safe seeding
}

fn hash_flat_recursive(hasher: &mut Sha256, obj: &dyn Hashable) {
obj.hash_flat(hasher);
}

pub trait Hashable {
fn hash_flat(&self, hasher: &mut Sha256);
}

impl Hashable for BigInt {
fn hash_flat(&self, hasher: &mut Sha256) {
hasher.update(self.to_string().as_bytes());
}
}

impl Hashable for usize {
fn hash_flat(&self, hasher: &mut Sha256) {
hasher.update(self.to_string().as_bytes());
}
}

impl<T: Hashable> Hashable for Vec<T> {
fn hash_flat(&self, hasher: &mut Sha256) {
for item in self {
hash_flat_recursive(hasher, item);
}
}
}

impl<K: Hashable, V: Hashable> Hashable for HashMap<K, V> {
fn hash_flat(&self, hasher: &mut Sha256) {
for (key, value) in self {
hash_flat_recursive(hasher, key);
hash_flat_recursive(hasher, value);
}
}
}

impl<T1: Hashable, T2: Hashable> Hashable for (T1, T2) {
fn hash_flat(&self, hasher: &mut Sha256) {
hash_flat_recursive(hasher, &self.0);
hash_flat_recursive(hasher, &self.1);
}
}

pub fn hash_flat<T: Hashable>(input: &T) -> u64 {
let mut hasher = Sha256::new();
input.hash_flat(&mut hasher);
u64::from_le_bytes(hasher.finalize().to_vec()[..8].try_into().unwrap())
}

pub fn bigint_to_seed(bigint: &BigInt) -> [u8; 32] {
// Convert BigInt to bytes
let bytes = bigint.to_signed_bytes_le();

// Hash the bytes to 32 bytes using SHA-256
let hash = Sha256::digest(&bytes);

// Convert hash output to a 32-byte array
let mut seed = [0u8; 32];
seed.copy_from_slice(&hash);
seed
}

pub fn compute_permutation(
res: &[Vec<BigInt>],
n: &BigInt,
) -> (HashMap<usize, usize>, HashMap<usize, HashMap<usize, BigInt>>, Vec<Vec<BigInt>>) {
let seed = get_next_random(n);
let permutation_desc = permute(res.len(), &seed);

let mut output_permutation = HashMap::new();
let mut reencrypt_factors = Vec::new();

for (i, res_i) in res.iter().enumerate() {
let mut rs = Vec::new();
let mut and_encryptions = HashMap::new();

for (j, res_ij) in res_i.iter().enumerate() {
let r = get_next_random(n);
rs.push(r.clone());
let rsquare = r.modpow(&BigInt::from(2), n);
let reencryption = (rsquare * res_ij) % n;
and_encryptions.insert(j, reencryption);
}

output_permutation.insert(permutation_desc[&i], and_encryptions);
reencrypt_factors.push(rs);
}

(permutation_desc, output_permutation, reencrypt_factors)
}

pub fn permute(length: usize, seed_bigint: &BigInt) -> HashMap<usize, usize> {
let seed = bigint_to_seed(&seed_bigint);
let mut rng = ChaCha20Rng::from_seed(seed);
let mut permutation: HashMap<usize, usize> = (0..length).map(|i| (i, i)).collect();

for i in 0..(length - 1) {
let index = rng.gen_range(i..length);
let value_i = permutation[&i];
let value_index = permutation[&index];

permutation.insert(i, value_index);
permutation.insert(index, value_i);
}

permutation
}

0 comments on commit 8864755

Please sign in to comment.