Skip to main content

miden_stark_transcript/
prover.rs

1//! Prover-side transcript channel.
2
3use alloc::vec::Vec;
4
5use p3_challenger::{CanSample, CanSampleBits, CanSampleUniformBits};
6use p3_field::{BasedVectorSpace, Field};
7
8use crate::{
9    TranscriptData,
10    channel::{Channel, TranscriptChallenger},
11};
12
13/// Prover channel that records transcript data and observes into the challenger.
14#[derive(Clone, Debug)]
15pub struct ProverTranscript<F, C, Ch> {
16    challenger: Ch,
17    fields: Vec<F>,
18    commitments: Vec<C>,
19}
20
21impl<F, C, Ch> ProverTranscript<F, C, Ch> {
22    /// Creates a new prover transcript backed by the provided challenger.
23    pub fn new(challenger: Ch) -> Self {
24        Self {
25            challenger,
26            fields: Vec::new(),
27            commitments: Vec::new(),
28        }
29    }
30
31    /// Finalize the transcript, producing a binding digest and returning the proof data.
32    ///
33    /// Delegates to [`CanFinalizeDigest::finalize`](p3_challenger::CanFinalizeDigest::finalize) on
34    /// the inner challenger, which unconditionally applies a final state transition before
35    /// extracting the digest. The digest commits to the entire transcript interaction.
36    pub fn finalize(self) -> (Ch::Digest, TranscriptData<F, C>)
37    where
38        F: Field,
39        C: Clone,
40        Ch: TranscriptChallenger<F, C>,
41    {
42        let digest = self.challenger.finalize();
43        (digest, TranscriptData::new(self.fields, self.commitments))
44    }
45
46    /// Returns the total byte size of the recorded transcript data.
47    pub fn size_in_bytes(&self) -> usize {
48        size_of_val(self.fields.as_slice()) + size_of_val(self.commitments.as_slice())
49    }
50}
51
52/// Prover-side channel interface for transcript operations.
53pub trait ProverChannel: Channel {
54    fn send_field_slice(&mut self, values: &[Self::F]);
55
56    fn send_commitment_slice(&mut self, values: &[Self::Commitment]);
57
58    fn send_field_element(&mut self, value: Self::F) {
59        self.send_field_slice(core::slice::from_ref(&value));
60    }
61
62    fn send_algebra_element<A>(&mut self, value: A)
63    where
64        A: BasedVectorSpace<Self::F>,
65    {
66        self.send_field_slice(value.as_basis_coefficients_slice());
67    }
68
69    fn send_algebra_slice<A>(&mut self, values: &[A])
70    where
71        A: BasedVectorSpace<Self::F>,
72    {
73        for value in values {
74            self.send_field_slice(value.as_basis_coefficients_slice());
75        }
76    }
77
78    fn send_commitment(&mut self, value: Self::Commitment) {
79        self.send_commitment_slice(core::slice::from_ref(&value));
80    }
81
82    fn hint_field_slice(&mut self, values: &[Self::F]);
83
84    fn hint_commitment_slice(&mut self, values: &[Self::Commitment]);
85
86    fn hint_field_element(&mut self, value: Self::F) {
87        self.hint_field_slice(core::slice::from_ref(&value));
88    }
89
90    fn hint_commitment(&mut self, value: Self::Commitment) {
91        self.hint_commitment_slice(core::slice::from_ref(&value));
92    }
93
94    fn grind(&mut self, bits: usize) -> Self::F;
95}
96
97impl<F, C, Ch> Channel for ProverTranscript<F, C, Ch>
98where
99    F: Field,
100    C: Clone,
101    Ch: TranscriptChallenger<F, C>,
102{
103    type F = F;
104    type Commitment = C;
105    type Challenger = Ch;
106
107    fn sample(&mut self) -> F {
108        self.challenger.sample()
109    }
110
111    fn sample_bits(&mut self, bits: usize) -> usize {
112        self.challenger.sample_bits(bits)
113    }
114}
115
116impl<F, C, Ch> ProverChannel for ProverTranscript<F, C, Ch>
117where
118    F: Field,
119    C: Clone,
120    Ch: TranscriptChallenger<F, C>,
121{
122    fn send_field_slice(&mut self, values: &[Self::F]) {
123        self.fields.extend_from_slice(values);
124        self.challenger.observe_slice(values);
125    }
126
127    fn send_commitment_slice(&mut self, values: &[Self::Commitment]) {
128        self.commitments.extend_from_slice(values);
129        self.challenger.observe_slice(values);
130    }
131
132    fn hint_field_slice(&mut self, values: &[Self::F]) {
133        self.fields.extend_from_slice(values);
134    }
135
136    fn hint_commitment_slice(&mut self, values: &[Self::Commitment]) {
137        self.commitments.extend_from_slice(values);
138    }
139
140    fn grind(&mut self, bits: usize) -> Self::F {
141        let witness = self.challenger.grind(bits);
142        self.fields.push(witness);
143        witness
144    }
145}
146
147impl<F, C, Ch, T> CanSample<T> for ProverTranscript<F, C, Ch>
148where
149    Ch: CanSample<T>,
150{
151    #[inline]
152    fn sample(&mut self) -> T {
153        self.challenger.sample()
154    }
155}
156
157impl<F, C, Ch> CanSampleBits<usize> for ProverTranscript<F, C, Ch>
158where
159    Ch: CanSampleBits<usize>,
160{
161    #[inline]
162    fn sample_bits(&mut self, bits: usize) -> usize {
163        self.challenger.sample_bits(bits)
164    }
165}
166
167impl<F, C, Ch> CanSampleUniformBits<F> for ProverTranscript<F, C, Ch>
168where
169    Ch: CanSampleUniformBits<F>,
170{
171    #[inline]
172    fn sample_uniform_bits<const RESAMPLE: bool>(
173        &mut self,
174        bits: usize,
175    ) -> Result<usize, p3_challenger::ResamplingError> {
176        self.challenger.sample_uniform_bits::<RESAMPLE>(bits)
177    }
178}