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_uncompressed(&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}