mod implementors;
use std::io::{self, Cursor, Read, Write};
pub use implementors::Blake2b256;
const BLAKE2B_PREFIX_CHALLENGE: u8 = 0;
const BLAKE2B_PREFIX_COMMON: u8 = 1;
pub trait TranscriptHash: Clone {
type Input;
type Output;
fn init() -> Self;
fn absorb(&mut self, input: &Self::Input);
fn squeeze(&mut self) -> Self::Output;
}
pub trait Hashable<H: TranscriptHash>: Sized {
fn to_input(&self) -> H::Input;
fn to_bytes(&self) -> Vec<u8>;
fn read(buffer: &mut impl Read) -> io::Result<Self>;
}
pub trait Sampleable<H: TranscriptHash> {
fn sample(hash_output: H::Output) -> Self;
}
pub trait Transcript: Clone {
type Hash: TranscriptHash;
fn init() -> Self;
fn init_from_bytes(bytes: &[u8]) -> Self;
fn squeeze_challenge<T: Sampleable<Self::Hash>>(&mut self) -> T;
fn common<T: Hashable<Self::Hash>>(&mut self, input: &T) -> io::Result<()>;
fn read<T: Hashable<Self::Hash>>(&mut self) -> io::Result<T>;
fn write<T: Hashable<Self::Hash>>(&mut self, input: &T) -> io::Result<()>;
fn finalize(self) -> Vec<u8>;
fn assert_empty(&mut self) -> io::Result<()>;
}
#[derive(Clone, Debug)]
pub struct CircuitTranscript<H: TranscriptHash> {
state: H,
buffer: Cursor<Vec<u8>>,
}
impl<H: TranscriptHash> CircuitTranscript<H> {
pub fn buffer(&mut self) -> &mut Cursor<Vec<u8>> {
&mut self.buffer
}
}
impl<H: TranscriptHash> Transcript for CircuitTranscript<H> {
type Hash = H;
fn init() -> Self {
Self {
state: H::init(),
buffer: Cursor::new(vec![]),
}
}
fn init_from_bytes(bytes: &[u8]) -> Self {
Self {
state: H::init(),
buffer: Cursor::new(bytes.to_vec()),
}
}
fn squeeze_challenge<T: Sampleable<H>>(&mut self) -> T {
T::sample(self.state.squeeze())
}
fn common<T: Hashable<H>>(&mut self, input: &T) -> io::Result<()> {
self.state.absorb(&input.to_input());
Ok(())
}
fn read<T: Hashable<H>>(&mut self) -> io::Result<T> {
let val = T::read(&mut self.buffer)?;
self.common(&val)?;
Ok(val)
}
fn write<T: Hashable<H>>(&mut self, input: &T) -> io::Result<()> {
self.common(input)?;
let bytes = input.to_bytes();
self.buffer.write_all(&bytes)
}
fn finalize(self) -> Vec<u8> {
self.buffer.into_inner()
}
fn assert_empty(&mut self) -> io::Result<()> {
if self.buffer.get_ref().len() == self.buffer.position() as usize {
return Ok(());
}
Err(io::Error::new(
io::ErrorKind::NotFound,
"Transcript has unexpected trailing bytes.",
))
}
}
pub(crate) fn read_n<C, T>(transcript: &mut T, n: usize) -> io::Result<Vec<C>>
where
T: Transcript,
C: Hashable<T::Hash>,
{
(0..n).map(|_| transcript.read()).collect()
}