Skip to main content

lib_q_stark_commit/adapters/
extension_mmcs.rs

1use alloc::vec::Vec;
2use core::marker::PhantomData;
3use core::ops::Deref;
4
5use lib_q_stark_field::{
6    ExtensionField,
7    Field,
8};
9use lib_q_stark_matrix::extension::FlatMatrixView;
10use lib_q_stark_matrix::{
11    Dimensions,
12    Matrix,
13};
14
15use crate::{
16    BatchOpening,
17    BatchOpeningRef,
18    Mmcs,
19};
20
21/// A wrapper to lift an MMCS from a base field `F` to an extension field `EF`.
22///
23/// `ExtensionMmcs` allows committing to and opening matrices over an extension field by internally
24/// using an MMCS defined on the base field. It works by flattening each extension field element
25/// into its base field coordinates for commitment, and then reconstructing them on opening.
26#[derive(Clone, Debug)]
27pub struct ExtensionMmcs<F, EF, InnerMmcs> {
28    /// The inner MMCS instance used to handle commitments at the base field level.
29    pub(crate) inner: InnerMmcs,
30
31    pub(crate) _phantom: PhantomData<(F, EF)>,
32}
33
34impl<F, EF, InnerMmcs> ExtensionMmcs<F, EF, InnerMmcs> {
35    pub const fn new(inner: InnerMmcs) -> Self {
36        Self {
37            inner,
38            _phantom: PhantomData,
39        }
40    }
41}
42
43impl<F, EF, InnerMmcs> Mmcs<EF> for ExtensionMmcs<F, EF, InnerMmcs>
44where
45    F: Field,
46    EF: ExtensionField<F>,
47    InnerMmcs: Mmcs<F>,
48{
49    type ProverData<M> = InnerMmcs::ProverData<FlatMatrixView<F, EF, M>>;
50    type Commitment = InnerMmcs::Commitment;
51    type Proof = InnerMmcs::Proof;
52    type Error = InnerMmcs::Error;
53
54    fn commit<M: Matrix<EF>>(&self, inputs: Vec<M>) -> (Self::Commitment, Self::ProverData<M>) {
55        self.inner
56            .commit(inputs.into_iter().map(FlatMatrixView::new).collect())
57    }
58
59    fn open_batch<M: Matrix<EF>>(
60        &self,
61        index: usize,
62        prover_data: &Self::ProverData<M>,
63    ) -> BatchOpening<EF, Self> {
64        let (inner_opened_values, inner_proof) = self.inner.open_batch(index, prover_data).unpack();
65        let opened_ext_values = inner_opened_values
66            .into_iter()
67            .map(EF::reconstitute_from_base)
68            .collect();
69        BatchOpening::new(opened_ext_values, inner_proof)
70    }
71
72    fn get_matrices<'a, M: Matrix<EF>>(&self, prover_data: &'a Self::ProverData<M>) -> Vec<&'a M> {
73        self.inner
74            .get_matrices(prover_data)
75            .into_iter()
76            .map(|mat| mat.deref())
77            .collect()
78    }
79
80    fn verify_batch(
81        &self,
82        commit: &Self::Commitment,
83        dimensions: &[Dimensions],
84        index: usize,
85        batch_opening: BatchOpeningRef<'_, EF, Self>,
86    ) -> Result<(), Self::Error> {
87        let opened_base_values: Vec<Vec<F>> = batch_opening
88            .opened_values
89            .iter()
90            .cloned()
91            .map(EF::flatten_to_base)
92            .collect();
93        let base_dimensions = dimensions
94            .iter()
95            .map(|dim| Dimensions {
96                width: dim.width * EF::DIMENSION,
97                height: dim.height,
98            })
99            .collect::<Vec<_>>();
100        self.inner.verify_batch(
101            commit,
102            &base_dimensions,
103            index,
104            BatchOpeningRef::new(&opened_base_values, batch_opening.opening_proof),
105        )
106    }
107}