proof_of_sql/base/commitment/
commitment_evaluation_proof.rs

1use super::Commitment;
2use crate::base::{proof::Transcript, scalar::Scalar};
3#[cfg(feature = "blitzar")]
4use crate::base::{scalar::MontScalar, slice_ops};
5#[cfg(feature = "blitzar")]
6use blitzar::proof::{InnerProductProof, ProofError};
7#[cfg(feature = "blitzar")]
8use curve25519_dalek::RistrettoPoint;
9use serde::{Deserialize, Serialize};
10
11/// A trait for using commitment schemes generically. Specifically, this trait is for the evaluation proof of a commitment scheme.
12pub trait CommitmentEvaluationProof {
13    /// The associated scalar that the commitment is for.
14    type Scalar: Scalar + Serialize + for<'a> Deserialize<'a>;
15    /// The associated commitment type.
16    type Commitment: for<'a> Commitment<Scalar = Self::Scalar, PublicSetup<'a> = Self::ProverPublicSetup<'a>>
17        + Serialize
18        + for<'a> Deserialize<'a>;
19    /// The error type for the proof.
20    type Error;
21    /// The public setup parameters required by the prover.
22    /// This is simply precomputed data that is required by the prover to create a proof.
23    type ProverPublicSetup<'a>: Copy;
24    /// The public setup parameters required by the verifier.
25    /// This is simply precomputed data that is required by the verifier to verify a proof.
26    type VerifierPublicSetup<'a>: Copy;
27    /// Create a new proof.
28    ///
29    /// Note: `b_point` must have length `nu`, where `2^nu` is at least the length of `a`.
30    /// `b_point` are the values for the variables that are being evaluated.
31    /// The resulting evaluation is the inner product of `a` and `b`, where `b` is the expanded vector form of `b_point`.
32    fn new(
33        transcript: &mut impl Transcript,
34        a: &[Self::Scalar],
35        b_point: &[Self::Scalar],
36        generators_offset: u64,
37        setup: &Self::ProverPublicSetup<'_>,
38    ) -> Self;
39    /// Verify a proof.
40    ///
41    /// Note: `b_point` must have length `nu`, where `2^nu` is at least the length of `a`.
42    /// `b_point` are the values for the variables that are being evaluated.
43    /// The resulting evaluation is the inner product of `a` and `b`, where `b` is the expanded vector form of `b_point`.
44    #[allow(clippy::too_many_arguments)]
45    fn verify_proof(
46        &self,
47        transcript: &mut impl Transcript,
48        a_commit: &Self::Commitment,
49        product: &Self::Scalar,
50        b_point: &[Self::Scalar],
51        generators_offset: u64,
52        table_length: usize,
53        setup: &Self::VerifierPublicSetup<'_>,
54    ) -> Result<(), Self::Error> {
55        self.verify_batched_proof(
56            transcript,
57            core::slice::from_ref(a_commit),
58            &[Self::Scalar::ONE],
59            core::slice::from_ref(product),
60            b_point,
61            generators_offset,
62            table_length,
63            setup,
64        )
65    }
66    /// Verify a batch proof. This can be more efficient than verifying individual proofs for some schemes.
67    #[allow(clippy::too_many_arguments)]
68    fn verify_batched_proof(
69        &self,
70        transcript: &mut impl Transcript,
71        commit_batch: &[Self::Commitment],
72        batching_factors: &[Self::Scalar],
73        evaluations: &[Self::Scalar],
74        b_point: &[Self::Scalar],
75        generators_offset: u64,
76        table_length: usize,
77        setup: &Self::VerifierPublicSetup<'_>,
78    ) -> Result<(), Self::Error>;
79}
80
81#[cfg(feature = "blitzar")]
82impl CommitmentEvaluationProof for InnerProductProof {
83    type Scalar = MontScalar<ark_curve25519::FrConfig>;
84    type Commitment = RistrettoPoint;
85    type Error = ProofError;
86    type ProverPublicSetup<'a> = ();
87    type VerifierPublicSetup<'a> = ();
88    fn new(
89        transcript: &mut impl Transcript,
90        a: &[Self::Scalar],
91        b_point: &[Self::Scalar],
92        generators_offset: u64,
93        _setup: &Self::ProverPublicSetup<'_>,
94    ) -> Self {
95        assert!(!a.is_empty());
96        let b = &mut vec![MontScalar::default(); a.len()];
97        if b_point.is_empty() {
98            assert_eq!(b.len(), 1);
99            b[0] = Self::Scalar::ONE;
100        } else {
101            crate::base::polynomial::compute_evaluation_vector(b, b_point);
102        }
103        // The InnerProductProof from blitzar only works with the merlin Transcript.
104        // So, we wrap the call to it.
105        transcript.wrap_transcript(|transcript| {
106            Self::create(
107                transcript,
108                &slice_ops::slice_cast(a),
109                &slice_ops::slice_cast(b),
110                generators_offset,
111            )
112        })
113    }
114
115    fn verify_batched_proof(
116        &self,
117        transcript: &mut impl Transcript,
118        commit_batch: &[Self::Commitment],
119        batching_factors: &[Self::Scalar],
120        evaluations: &[Self::Scalar],
121        b_point: &[Self::Scalar],
122        generators_offset: u64,
123        table_length: usize,
124        _setup: &Self::VerifierPublicSetup<'_>,
125    ) -> Result<(), Self::Error> {
126        assert!(table_length > 0);
127        let b = &mut vec![MontScalar::default(); table_length];
128        if b_point.is_empty() {
129            assert_eq!(b.len(), 1);
130            b[0] = Self::Scalar::ONE;
131        } else {
132            crate::base::polynomial::compute_evaluation_vector(b, b_point);
133        }
134        let product: Self::Scalar = evaluations
135            .iter()
136            .zip(batching_factors)
137            .map(|(&e, &f)| e * f)
138            .sum();
139        // The InnerProductProof from blitzar only works with the merlin Transcript.
140        // So, we wrap the call to it.
141        transcript.wrap_transcript(|transcript| {
142            self.verify(
143                transcript,
144                &commit_batch
145                    .iter()
146                    .zip(batching_factors.iter())
147                    .map(|(c, m)| *m * c)
148                    .fold(RistrettoPoint::default(), |mut a, c| {
149                        a += c;
150                        a
151                    }),
152                &product.into(),
153                &slice_ops::slice_cast(b),
154                generators_offset,
155            )
156        })
157    }
158}