use alloc::vec::Vec;
use p3_challenger::{CanSample, CanSampleBits, CanSampleUniformBits};
use p3_field::{BasedVectorSpace, Field};
use crate::{
TranscriptData,
channel::{Channel, TranscriptChallenger},
};
#[derive(Clone, Debug)]
pub struct ProverTranscript<F, C, Ch> {
challenger: Ch,
fields: Vec<F>,
commitments: Vec<C>,
}
impl<F, C, Ch> ProverTranscript<F, C, Ch> {
pub fn new(challenger: Ch) -> Self {
Self {
challenger,
fields: Vec::new(),
commitments: Vec::new(),
}
}
pub fn finalize(self) -> (Ch::Digest, TranscriptData<F, C>)
where
F: Field,
C: Clone,
Ch: TranscriptChallenger<F, C>,
{
let digest = self.challenger.finalize();
(digest, TranscriptData::new(self.fields, self.commitments))
}
pub fn size_in_bytes(&self) -> usize {
size_of_val(self.fields.as_slice()) + size_of_val(self.commitments.as_slice())
}
}
pub trait ProverChannel: Channel {
fn send_field_slice(&mut self, values: &[Self::F]);
fn send_commitment_slice(&mut self, values: &[Self::Commitment]);
fn send_field_element(&mut self, value: Self::F) {
self.send_field_slice(core::slice::from_ref(&value));
}
fn send_algebra_element<A>(&mut self, value: A)
where
A: BasedVectorSpace<Self::F>,
{
self.send_field_slice(value.as_basis_coefficients_slice());
}
fn send_algebra_slice<A>(&mut self, values: &[A])
where
A: BasedVectorSpace<Self::F>,
{
for value in values {
self.send_field_slice(value.as_basis_coefficients_slice());
}
}
fn send_commitment(&mut self, value: Self::Commitment) {
self.send_commitment_slice(core::slice::from_ref(&value));
}
fn hint_field_slice(&mut self, values: &[Self::F]);
fn hint_commitment_slice(&mut self, values: &[Self::Commitment]);
fn hint_field_element(&mut self, value: Self::F) {
self.hint_field_slice(core::slice::from_ref(&value));
}
fn hint_commitment(&mut self, value: Self::Commitment) {
self.hint_commitment_slice(core::slice::from_ref(&value));
}
fn grind(&mut self, bits: usize) -> Self::F;
}
impl<F, C, Ch> Channel for ProverTranscript<F, C, Ch>
where
F: Field,
C: Clone,
Ch: TranscriptChallenger<F, C>,
{
type F = F;
type Commitment = C;
type Challenger = Ch;
fn sample(&mut self) -> F {
self.challenger.sample()
}
fn sample_bits(&mut self, bits: usize) -> usize {
self.challenger.sample_bits(bits)
}
}
impl<F, C, Ch> ProverChannel for ProverTranscript<F, C, Ch>
where
F: Field,
C: Clone,
Ch: TranscriptChallenger<F, C>,
{
fn send_field_slice(&mut self, values: &[Self::F]) {
self.fields.extend_from_slice(values);
self.challenger.observe_slice(values);
}
fn send_commitment_slice(&mut self, values: &[Self::Commitment]) {
self.commitments.extend_from_slice(values);
self.challenger.observe_slice(values);
}
fn hint_field_slice(&mut self, values: &[Self::F]) {
self.fields.extend_from_slice(values);
}
fn hint_commitment_slice(&mut self, values: &[Self::Commitment]) {
self.commitments.extend_from_slice(values);
}
fn grind(&mut self, bits: usize) -> Self::F {
let witness = self.challenger.grind(bits);
self.fields.push(witness);
witness
}
}
impl<F, C, Ch, T> CanSample<T> for ProverTranscript<F, C, Ch>
where
Ch: CanSample<T>,
{
#[inline]
fn sample(&mut self) -> T {
self.challenger.sample()
}
}
impl<F, C, Ch> CanSampleBits<usize> for ProverTranscript<F, C, Ch>
where
Ch: CanSampleBits<usize>,
{
#[inline]
fn sample_bits(&mut self, bits: usize) -> usize {
self.challenger.sample_bits(bits)
}
}
impl<F, C, Ch> CanSampleUniformBits<F> for ProverTranscript<F, C, Ch>
where
Ch: CanSampleUniformBits<F>,
{
#[inline]
fn sample_uniform_bits<const RESAMPLE: bool>(
&mut self,
bits: usize,
) -> Result<usize, p3_challenger::ResamplingError> {
self.challenger.sample_uniform_bits::<RESAMPLE>(bits)
}
}