arnaucube
arnaucube/fri-commitmentPublic Self-hosted repository
fri-commitment/src/transcript.rs
src/transcript.rsRaw
 1use ark_ff::PrimeField;
 2use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
 3use ark_serialize::CanonicalSerialize;
 4use merlin::Transcript as FSTranscript; // FS stands for Fiat-Shamir
 5use std::marker::PhantomData;
 6
 7// This Transcript approach is a modified version from https://github.com/caulk-crypto/caulk ,
 8// using Merlin transcript (https://merlin.cool/).
 9pub struct Transcript<F: PrimeField> {
10    phantom: PhantomData<F>,
11    transcript: FSTranscript,
12}
13
14impl<F: PrimeField> Transcript<F> {
15    pub fn new() -> Self {
16        Self {
17            phantom: PhantomData::default(),
18            transcript: FSTranscript::new(b"FRI transcript"),
19        }
20    }
21    pub fn add<T: CanonicalSerialize>(&mut self, label: &'static [u8], r: &T) {
22        let mut buf = vec![];
23        r.serialize(&mut buf).unwrap();
24        self.transcript.append_message(label, buf.as_ref());
25    }
26    pub fn get_challenge(&mut self, label: &'static [u8]) -> F {
27        let mut bytes = [0u8; 64];
28        self.transcript.challenge_bytes(label, &mut bytes);
29        let challenge = F::from_le_bytes_mod_order(bytes.as_ref());
30        self.add(b"new challenge", &challenge);
31        challenge
32    }
33    pub fn get_challenge_in_eval_domain(
34        &mut self,
35        eval_domain: GeneralEvaluationDomain<F>,
36        label: &'static [u8],
37    ) -> (usize, F) {
38        let mut bytes = [0u8; 8];
39        self.transcript.challenge_bytes(label, &mut bytes);
40        let c: usize = usize::from_le_bytes(bytes);
41        let size = eval_domain.size();
42        let pos = c % size;
43        let challenge = eval_domain.element(pos);
44        self.add(b"new challenge", &challenge);
45        (pos, challenge)
46    }
47}