use ark_ff::{BigInteger, PrimeField};
use ark_r1cs_std::{boolean::Boolean, convert::ToBitsGadget, fields::fp::FpVar};
use ark_relations::gr1cs::SynthesisError;
pub use self::absorbable::{Absorbable, AbsorbableVar};
pub mod absorbable;
pub mod griffin;
pub mod poseidon;
pub mod recording;
pub mod replay;
pub trait Transcript<F: PrimeField>: Clone {
type Config: Clone;
type Gadget: TranscriptGadget<F, Widget = Self>;
fn new(config: Self::Config) -> Self;
fn new_with_pp_hash(config: Self::Config, pp_hash: F) -> Self {
let mut sponge = Self::new(config);
sponge.add_field_elements(&[pp_hash]);
sponge
}
fn add<A: Absorbable + ?Sized>(&mut self, input: &A) -> &mut Self {
let mut elems = Vec::new();
input.absorb_into(&mut elems);
self.add_field_elements(&elems)
}
fn add_field_elements(&mut self, input: &[F]) -> &mut Self;
fn get_bits(&mut self, num_bits: usize) -> Vec<bool> {
let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize;
let num_elements = num_bits.div_ceil(usable_bits);
let src_elements = self.get_field_elements(num_elements);
let mut bits: Vec<bool> = Vec::with_capacity(usable_bits * num_elements);
for elem in &src_elements {
let elem_bits = elem.into_bigint().to_bits_le();
bits.extend_from_slice(&elem_bits[..usable_bits]);
}
bits.truncate(num_bits);
bits
}
fn get_field_element(&mut self) -> F {
self.get_field_elements(1)[0]
}
fn get_field_elements(&mut self, num_elements: usize) -> Vec<F>;
fn separate_domain(&self, domain: &[u8]) -> Self {
let mut new_sponge = self.clone();
let mut input = (domain.len() as u64).to_le_bytes().to_vec();
input.extend_from_slice(domain);
let limbs = input
.chunks((F::MODULUS_BIT_SIZE as usize - 1) / 8)
.map(|chunk| F::from_le_bytes_mod_order(chunk))
.collect::<Vec<_>>();
new_sponge.add_field_elements(&limbs);
new_sponge
}
fn challenge_field_element(&mut self) -> F {
let c = self.get_field_elements(1);
self.add_field_elements(&c);
c[0]
}
fn challenge_bits(&mut self, num_bits: usize) -> Vec<bool> {
let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize;
let num_elements = num_bits.div_ceil(usable_bits);
let src_elements = self.challenge_field_elements(num_elements);
let mut bits: Vec<bool> = Vec::with_capacity(usable_bits * num_elements);
for elem in &src_elements {
let elem_bits = elem.into_bigint().to_bits_le();
bits.extend_from_slice(&elem_bits[..usable_bits]);
}
bits.truncate(num_bits);
bits
}
fn challenge_field_elements(&mut self, n: usize) -> Vec<F> {
let c = self.get_field_elements(n);
self.add_field_elements(&c);
c
}
}
pub trait TranscriptGadget<F: PrimeField>: Clone {
type Config: Clone;
type Widget: Transcript<F, Gadget = Self>;
fn new(config: Self::Config) -> Self;
fn new_with_pp_hash(config: Self::Config, pp_hash: &FpVar<F>) -> Result<Self, SynthesisError> {
let mut sponge = Self::new(config);
sponge.add(&pp_hash)?;
Ok(sponge)
}
fn add<A: AbsorbableVar<F>>(&mut self, input: &A) -> Result<&mut Self, SynthesisError>;
fn get_bits(&mut self, num_bits: usize) -> Result<Vec<Boolean<F>>, SynthesisError> {
let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize;
let num_elements = num_bits.div_ceil(usable_bits);
let src_elements = self.get_field_elements(num_elements)?;
let mut bits: Vec<Boolean<F>> = Vec::with_capacity(usable_bits * num_elements);
for elem in &src_elements {
bits.extend_from_slice(&elem.to_bits_le()?[..usable_bits]);
}
bits.truncate(num_bits);
Ok(bits)
}
fn get_field_element(&mut self) -> Result<FpVar<F>, SynthesisError> {
Ok(self.get_field_elements(1)?.swap_remove(0))
}
fn get_field_elements(&mut self, num_elements: usize) -> Result<Vec<FpVar<F>>, SynthesisError>;
fn separate_domain(&self, domain: &[u8]) -> Result<Self, SynthesisError> {
let mut new_sponge = self.clone();
let mut input = (domain.len() as u64).to_le_bytes().to_vec();
input.extend_from_slice(domain);
let limbs = input
.chunks((F::MODULUS_BIT_SIZE as usize - 1) / 8)
.map(|chunk| FpVar::Constant(F::from_le_bytes_mod_order(chunk)))
.collect::<Vec<_>>();
new_sponge.add(&limbs)?;
Ok(new_sponge)
}
fn challenge_field_element(&mut self) -> Result<FpVar<F>, SynthesisError> {
let mut c = self.get_field_elements(1)?;
self.add(&c[0])?;
Ok(c.swap_remove(0))
}
fn challenge_bits(&mut self, num_bits: usize) -> Result<Vec<Boolean<F>>, SynthesisError> {
let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize;
let num_elements = num_bits.div_ceil(usable_bits);
let src_elements = self.challenge_field_elements(num_elements)?;
let mut bits: Vec<Boolean<F>> = Vec::with_capacity(usable_bits * num_elements);
for elem in &src_elements {
bits.extend_from_slice(&elem.to_bits_le()?[..usable_bits]);
}
bits.truncate(num_bits);
Ok(bits)
}
fn challenge_field_elements(&mut self, n: usize) -> Result<Vec<FpVar<F>>, SynthesisError> {
let c = self.get_field_elements(n)?;
self.add(&c)?;
Ok(c)
}
}