use crate::rand::Rand;
use crate::rand::Rng;
use crate::tests::init_cs;
use franklin_crypto::bellman::pairing::bn256::{Bn256, Fr};
use franklin_crypto::boojum::algebraic_props::round_function::AbsorptionModeTrait;
use franklin_crypto::boojum::cs::implementations::pow::PoWRunner;
use franklin_crypto::boojum::field::goldilocks::GoldilocksField;
use franklin_crypto::boojum::field::SmallField;
use franklin_crypto::boojum::field::U64Representable;
use franklin_crypto::boojum::worker::Worker;
use franklin_crypto::plonk::circuit::{allocated_num::Num, linear_combination::LinearCombination};
use crate::circuit::poseidon2::{circuit_poseidon2_hash, circuit_poseidon2_round_function};
use crate::poseidon::{poseidon_hash, poseidon_round_function};
use crate::poseidon2::{poseidon2_hash, poseidon2_round_function};
use super::Poseidon2Sponge;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct TestingAbsorption;
impl AbsorptionModeTrait<Fr> for TestingAbsorption {
#[inline(always)]
fn absorb(dst: &mut Fr, src: &Fr) {
*dst = *src;
}
#[inline(always)]
fn pad(_dst: &mut Fr) {}
}
#[test]
fn test_different_absorbtions() {
let num_elements = 1000;
let mut rng = crate::rand::thread_rng();
let buffer: Vec<_> = (0..num_elements).map(|_| Fr::rand(&mut rng)).collect();
let mut hash = Poseidon2Sponge::<Bn256, GoldilocksField, TestingAbsorption, 2, 3>::new();
for element in buffer.iter() {
hash.absorb_single(element);
}
let commitment1 = hash.finalize();
let mut hash = Poseidon2Sponge::<Bn256, GoldilocksField, TestingAbsorption, 2, 3>::new();
hash.absorb(&buffer);
let commitment2 = hash.finalize();
assert_eq!(commitment1, commitment2);
dbg!(commitment1);
}
#[ignore]
#[test]
fn test_vs_poseidon() {
const NUM_ELEMENTS: usize = 10000;
let mut rng = crate::rand::thread_rng();
let buffer = [0; NUM_ELEMENTS].map(|_| Fr::rand(&mut rng));
let start = std::time::Instant::now();
poseidon_hash::<Bn256, NUM_ELEMENTS>(&buffer);
dbg!(start.elapsed());
let start = std::time::Instant::now();
poseidon2_hash::<Bn256, NUM_ELEMENTS>(&buffer);
dbg!(start.elapsed());
let mut buffer = buffer.to_vec();
let params = crate::PoseidonParams::<Bn256, 2, 3>::default();
let start = std::time::Instant::now();
for chunk in buffer.chunks_exact_mut(3) {
poseidon_round_function::<Bn256, _, 2, 3>(¶ms, chunk.try_into().unwrap());
}
dbg!(start.elapsed());
let params = crate::poseidon2::Poseidon2Params::<Bn256, 2, 3>::default();
let start = std::time::Instant::now();
for chunk in buffer.chunks_exact_mut(3) {
poseidon2_round_function::<Bn256, 2, 3>(chunk.try_into().unwrap(), ¶ms);
}
dbg!(start.elapsed());
}
#[test]
fn test_of_sponge_state() {
let num_elements = 5;
let mut rng = crate::rand::thread_rng();
let buffer1: Vec<_> = (0..num_elements).map(|_| Fr::rand(&mut rng)).collect();
let mut rng = crate::rand::thread_rng();
let buffer2: Vec<_> = (0..num_elements).map(|_| GoldilocksField::from_u64_unchecked(rng.gen_range(0..GoldilocksField::CHAR))).collect();
dbg!(&buffer1, &buffer2);
let mut hash = Poseidon2Sponge::<Bn256, GoldilocksField, TestingAbsorption, 2, 3>::new();
dbg!(&hash);
hash.absorb_single(&buffer1[0]);
dbg!(&hash);
hash.absorb_single_small_field(&buffer2[0]);
dbg!(&hash);
hash.absorb_single_small_field(&buffer2[1]);
dbg!(&hash);
hash.absorb_single(&buffer1[1]);
dbg!(&hash);
hash.absorb_single(&buffer1[2]);
dbg!(&hash);
hash.absorb_single_small_field(&buffer2[2]);
dbg!(&hash);
dbg!(&hash.finalize());
dbg!(&hash);
}
#[test]
fn test_circuit_round_function() {
let params = crate::poseidon2::Poseidon2Params::<Bn256, 2, 3>::default();
let cs = &mut init_cs::<Bn256>();
let mut rng = crate::rand::thread_rng();
let mut state = [0; 3].map(|_| Fr::rand(&mut rng));
let mut circuit_state = state.map(|x| Num::alloc(cs, Some(x)).unwrap().into());
poseidon2_round_function::<Bn256, 2, 3>(&mut state, ¶ms);
circuit_poseidon2_round_function(cs, ¶ms, &mut circuit_state).unwrap();
assert_eq!(state, circuit_state.map(|x| x.get_value().unwrap()));
}
#[test]
fn test_circuit_hash() {
let cs = &mut init_cs::<Bn256>();
const NUM_ELEMENTS: usize = 10;
let mut rng = crate::rand::thread_rng();
let buffer = [0; NUM_ELEMENTS].map(|_| Fr::rand(&mut rng));
let num_buffer = buffer.map(|x| Num::alloc(cs, Some(x)).unwrap());
let hash1 = poseidon2_hash::<Bn256, NUM_ELEMENTS>(&buffer);
let hash2 = circuit_poseidon2_hash(cs, &num_buffer, None).unwrap();
assert_eq!(hash1, hash2.map(|x| x.get_value().unwrap()));
}
#[test]
fn test_pow_runner() {
let worker = Worker::new();
let mut rng = crate::rand::thread_rng();
let buffer: Vec<_> = (0..4).map(|_| GoldilocksField::from_u64_unchecked(rng.gen_range(0..GoldilocksField::CHAR))).collect();
let challenge = Poseidon2Sponge::<Bn256, GoldilocksField, TestingAbsorption, 2, 3>::run_from_field_elements(buffer, 10, &worker);
dbg!(challenge);
}