Skip to main content

sonobe_primitives/transcripts/recording/
mod.rs

1//! Implementation of transcripts that can automatically record generated
2//! challenges, eliminating the need to pass challenges throughout protocols.
3
4use ark_ff::PrimeField;
5use ark_r1cs_std::fields::fp::FpVar;
6use ark_relations::gr1cs::SynthesisError;
7
8use super::{AbsorbableVar, Transcript, TranscriptGadget};
9
10/// [`RecordingTranscript`] wraps a regular transcript to record all challenges
11/// it produces.
12#[derive(Clone)]
13pub struct RecordingTranscript<F: PrimeField, T: Transcript<F>> {
14    inner: T,
15    pub(super) cached_challenges: Vec<F>,
16}
17
18impl<F: PrimeField, T: Transcript<F>> Transcript<F> for RecordingTranscript<F, T> {
19    type Config = T;
20    type Gadget = RecordingTranscriptVar<F, T::Gadget>;
21
22    fn new(inner: Self::Config) -> Self {
23        Self {
24            inner,
25            cached_challenges: vec![],
26        }
27    }
28
29    fn add_field_elements(&mut self, input: &[F]) -> &mut Self {
30        self.inner.add_field_elements(input);
31        self
32    }
33
34    fn get_field_elements(&mut self, num_elements: usize) -> Vec<F> {
35        let v = self.inner.get_field_elements(num_elements);
36        self.cached_challenges.extend_from_slice(&v);
37        v
38    }
39}
40
41/// [`RecordingTranscriptVar`] is the in-circuit variable of [`RecordingTranscript`].
42#[derive(Clone)]
43pub struct RecordingTranscriptVar<F: PrimeField, T: TranscriptGadget<F>> {
44    inner: T,
45    pub(super) cached_challenges: Vec<FpVar<F>>,
46}
47
48impl<F: PrimeField, T: TranscriptGadget<F>> TranscriptGadget<F> for RecordingTranscriptVar<F, T> {
49    type Config = T;
50    type Widget = RecordingTranscript<F, T::Widget>;
51
52    fn new(inner: Self::Config) -> Self {
53        Self {
54            inner,
55            cached_challenges: vec![],
56        }
57    }
58
59    fn add<A: AbsorbableVar<F>>(&mut self, input: &A) -> Result<&mut Self, SynthesisError> {
60        self.inner.add(input)?;
61        Ok(self)
62    }
63
64    fn get_field_elements(&mut self, num_elements: usize) -> Result<Vec<FpVar<F>>, SynthesisError> {
65        let v = self.inner.get_field_elements(num_elements)?;
66        self.cached_challenges.extend_from_slice(&v);
67        Ok(v)
68    }
69}