remainder/input_layer/
fiat_shamir_challenge.rs

1//! A part of the input layer that is random and secured through F-S
2
3use std::marker::PhantomData;
4
5use serde::{Deserialize, Serialize};
6use shared_types::Field;
7
8use crate::{
9    layer::LayerId,
10    mle::{dense::DenseMle, evals::MultilinearExtension},
11};
12
13/// Represents a verifier challenge, where we generate random constants in the
14/// form of coefficients of an MLE that can be used e.g. for packing constants, or in logup, or
15/// permutation checks and so on.
16#[derive(Debug, Clone)]
17pub struct FiatShamirChallenge<F: Field> {
18    /// The data.
19    pub mle: MultilinearExtension<F>,
20    /// The layer ID.
21    pub(crate) layer_id: LayerId,
22}
23
24/// Verifier's description of a [FiatShamirChallenge].
25#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash)]
26#[serde(bound = "F: Field")]
27pub struct FiatShamirChallengeDescription<F: Field> {
28    /// The layer ID.
29    layer_id: LayerId,
30
31    /// The number of variables needed to index the data of this verifier challenge.
32    pub num_bits: usize,
33
34    _marker: PhantomData<F>,
35}
36
37impl<F: Field> FiatShamirChallengeDescription<F> {
38    /// Constructor for the [FiatShamirChallengeDescription] using the
39    /// number of bits that are in the MLE of the layer.
40    pub fn new(layer_id: LayerId, num_bits: usize) -> Self {
41        Self {
42            layer_id,
43            num_bits,
44            _marker: PhantomData,
45        }
46    }
47}
48
49impl<F: Field> FiatShamirChallenge<F> {
50    /// Create a new [FiatShamirChallenge] from the given MLE allocating the next available FS layer
51    /// ID.
52    pub fn new(mle: MultilinearExtension<F>) -> Self {
53        let layer_id = LayerId::next_fiat_shamir_challenge_layer_id();
54        Self { mle, layer_id }
55    }
56
57    /// Return the MLE stored in self as a DenseMle with the correct layer ID.
58    pub fn get_mle(&self) -> DenseMle<F> {
59        DenseMle::new_from_raw(self.mle.to_vec(), self.layer_id)
60    }
61
62    /// Return the layer id.
63    pub fn layer_id(&self) -> LayerId {
64        self.layer_id
65    }
66}
67
68impl<F: Field> FiatShamirChallengeDescription<F> {
69    /// Return the layer id.
70    pub fn layer_id(&self) -> LayerId {
71        self.layer_id
72    }
73
74    /// Create a [FiatShamirChallenge] from this
75    /// [FiatShamirChallengeDescription] and the given values.
76    /// Panics if the length of `values` is not equal to the number of
77    /// evaluations in the MLE.
78    pub fn instantiate(&self, values: Vec<F>) -> FiatShamirChallenge<F> {
79        assert_eq!(values.len(), 1 << self.num_bits);
80        FiatShamirChallenge {
81            mle: MultilinearExtension::new(values),
82            layer_id: self.layer_id,
83        }
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use crate::claims::RawClaim;
90    use crate::utils::mle::verify_claim;
91
92    use super::*;
93    use shared_types::{
94        transcript::{
95            test_transcript::TestSponge, ProverTranscript, TranscriptReader, TranscriptWriter,
96            VerifierTranscript,
97        },
98        Fr,
99    };
100
101    #[test]
102    fn test_circuit_fiat_shamir_challenge() {
103        // Setup phase.
104        let layer_id = LayerId::Input(0);
105
106        // MLE on 2 variables.
107        let num_vars = 2;
108        let num_evals = 1 << num_vars;
109
110        // Transcript writer with test sponge that always returns `1`.
111        let mut transcript_writer: TranscriptWriter<Fr, TestSponge<Fr>> =
112            TranscriptWriter::new("Test Transcript Writer");
113
114        let claim_point = vec![Fr::from(2), Fr::from(2)];
115        let claim_result = Fr::from(1);
116        let claim: RawClaim<Fr> = RawClaim::new(claim_point, claim_result);
117
118        let mle_vec = transcript_writer.get_challenges("random challenges for FS", num_evals);
119        let mle = MultilinearExtension::new(mle_vec);
120
121        let fs_desc = FiatShamirChallengeDescription::<Fr>::new(layer_id, mle.num_vars());
122        // Nothing really to test for FiatShamirChallenge
123        let _fiat_shamir_challenge = FiatShamirChallenge::new(mle);
124
125        // Verifier phase.
126        // 1. Retrieve proof/transcript.
127        let transcript = transcript_writer.get_transcript();
128        let mut transcript_reader: TranscriptReader<Fr, TestSponge<Fr>> =
129            TranscriptReader::new(transcript);
130
131        // 2. Get commitment from transcript.
132        let values = transcript_reader
133            .get_challenges("random challenges for FS", 1 << fs_desc.num_bits)
134            .unwrap();
135        let fiat_shamir_challenge = fs_desc.instantiate(values);
136
137        // 3. ... [skip] verify other layers.
138
139        // 4. Verify this layer's commitment.
140        verify_claim(&fiat_shamir_challenge.mle.to_vec(), &claim);
141    }
142}