Skip to main content

sonobe_primitives/transcripts/replay/
mod.rs

1//! Implementation of transcripts that always produces designated challenge
2//! values.
3
4use ark_ff::PrimeField;
5use ark_r1cs_std::fields::fp::FpVar;
6use ark_relations::gr1cs::SynthesisError;
7
8use super::{AbsorbableVar, Transcript, TranscriptGadget};
9use crate::transcripts::recording::{RecordingTranscript, RecordingTranscriptVar};
10
11/// [`ReplayTranscript`] is a convenience struct that generates specific values
12/// as challenges without running the actual hash function.
13///
14/// WARNING: This struct itself is insecure. The caller is responsible for
15/// checking the validity of the designated challenge values.
16#[derive(Clone)]
17pub struct ReplayTranscript<F> {
18    cached_challenges: Vec<F>,
19}
20
21impl<F: PrimeField, T: Transcript<F>> From<RecordingTranscript<F, T>> for ReplayTranscript<F> {
22    fn from(value: RecordingTranscript<F, T>) -> Self {
23        Self::new(value.cached_challenges)
24    }
25}
26
27impl<F: PrimeField> Transcript<F> for ReplayTranscript<F> {
28    type Config = Vec<F>;
29    type Gadget = ReplayTranscriptVar<F>;
30
31    fn new(mut cached_challenges: Self::Config) -> Self {
32        cached_challenges.reverse();
33        Self { cached_challenges }
34    }
35
36    fn add_field_elements(&mut self, _: &[F]) -> &mut Self {
37        self
38    }
39
40    fn get_field_elements(&mut self, num_elements: usize) -> Vec<F> {
41        let mut result = vec![];
42        for _ in 0..num_elements {
43            result.push(self.cached_challenges.pop().unwrap())
44        }
45        result
46    }
47}
48
49/// [`ReplayTranscriptVar`] is the in-circuit variable of [`ReplayTranscript`].
50#[derive(Clone)]
51pub struct ReplayTranscriptVar<F: PrimeField> {
52    cached_challenges: Vec<FpVar<F>>,
53}
54
55impl<F: PrimeField, T: TranscriptGadget<F>> From<RecordingTranscriptVar<F, T>>
56    for ReplayTranscriptVar<F>
57{
58    fn from(value: RecordingTranscriptVar<F, T>) -> Self {
59        Self::new(value.cached_challenges)
60    }
61}
62
63impl<F: PrimeField> TranscriptGadget<F> for ReplayTranscriptVar<F> {
64    type Config = Vec<FpVar<F>>;
65    type Widget = ReplayTranscript<F>;
66
67    fn new(mut cached_challenges: Vec<FpVar<F>>) -> Self {
68        cached_challenges.reverse();
69        Self { cached_challenges }
70    }
71
72    fn add<A: AbsorbableVar<F> + ?Sized>(&mut self, _: &A) -> Result<&mut Self, SynthesisError> {
73        Ok(self)
74    }
75
76    fn get_field_elements(&mut self, num_elements: usize) -> Result<Vec<FpVar<F>>, SynthesisError> {
77        let mut result = vec![];
78        for _ in 0..num_elements {
79            result.push(self.cached_challenges.pop().unwrap())
80        }
81        Ok(result)
82    }
83}