arnaucube
arnaucube/hyperplonkPublic Self-hosted repository
hyperplonk/poly-iop/src/transcript.rs
poly-iop/src/transcript.rsRaw
  1use std::marker::PhantomData;
  2
  3use ark_ff::PrimeField;
  4use merlin::Transcript;
  5
  6use crate::{
  7    errors::PolyIOPErrors,
  8    structs::{DomainInfo, IOPProverMessage},
  9    to_bytes,
 10};
 11
 12pub struct IOPTranscript<F: PrimeField> {
 13    transcript: Transcript,
 14    is_empty: bool,
 15    #[doc(hidden)]
 16    phantom: PhantomData<F>,
 17}
 18
 19impl<F: PrimeField> IOPTranscript<F> {
 20    /// create a new IOP transcript
 21    pub(crate) fn new(label: &'static [u8]) -> Self {
 22        Self {
 23            transcript: Transcript::new(label),
 24            is_empty: true,
 25            phantom: PhantomData::default(),
 26        }
 27    }
 28
 29    // append the message to the transcript
 30    pub fn append_message(
 31        &mut self,
 32        label: &'static [u8],
 33        msg: &[u8],
 34    ) -> Result<(), PolyIOPErrors> {
 35        self.transcript.append_message(label, msg);
 36        self.is_empty = false;
 37        Ok(())
 38    }
 39
 40    pub(crate) fn append_domain_info(
 41        &mut self,
 42        domain_info: &DomainInfo<F>,
 43    ) -> Result<(), PolyIOPErrors> {
 44        let message = format!(
 45            "max_mul {} num_var {}",
 46            domain_info.max_degree, domain_info.num_variables
 47        );
 48        self.append_message(b"aux info", message.as_bytes())?;
 49
 50        Ok(())
 51    }
 52
 53    // append the message to the transcript
 54    pub(crate) fn append_field_element(
 55        &mut self,
 56        label: &'static [u8],
 57        field_elem: &F,
 58    ) -> Result<(), PolyIOPErrors> {
 59        self.append_message(label, &to_bytes!(field_elem)?)
 60    }
 61
 62    pub(crate) fn append_prover_message(
 63        &mut self,
 64        prover_message: &IOPProverMessage<F>,
 65    ) -> Result<(), PolyIOPErrors> {
 66        for e in prover_message.evaluations.iter() {
 67            self.append_field_element(b"prover_message", e)?;
 68        }
 69        Ok(())
 70    }
 71
 72    // generate the challenge for the current transcript
 73    // and append it to the transcript
 74    pub(crate) fn get_and_append_challenge(
 75        &mut self,
 76        label: &'static [u8],
 77    ) -> Result<F, PolyIOPErrors> {
 78        if self.is_empty {
 79            return Err(PolyIOPErrors::InvalidTranscript(
 80                "transcript is empty".to_string(),
 81            ));
 82        }
 83
 84        let mut buf = [0u8; 64];
 85        self.transcript.challenge_bytes(label, &mut buf);
 86        let challenge = F::from_le_bytes_mod_order(&buf);
 87        self.transcript
 88            .append_message(label, &to_bytes!(&challenge)?);
 89        Ok(challenge)
 90    }
 91
 92    // generate a list of challenges for the current transcript
 93    // and append it to the transcript
 94    pub(crate) fn get_and_append_challenge_vectors(
 95        &mut self,
 96        label: &'static [u8],
 97        len: usize,
 98    ) -> Result<Vec<F>, PolyIOPErrors> {
 99        //  we need to reject when transcript is empty
100        let mut res = vec![];
101        for _ in 0..len {
102            res.push(self.get_and_append_challenge(label)?)
103        }
104        Ok(res)
105    }
106}