proof_of_sql/base/commitment/
commitment_evaluation_proof.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use super::Commitment;
use crate::base::{proof::Transcript, scalar::Scalar};
#[cfg(feature = "blitzar")]
use crate::base::{scalar::MontScalar, slice_ops};
#[cfg(feature = "blitzar")]
use blitzar::proof::{InnerProductProof, ProofError};
#[cfg(feature = "blitzar")]
use curve25519_dalek::RistrettoPoint;
use serde::{Deserialize, Serialize};

/// A trait for using commitment schemes generically. Specifically, this trait is for the evaluation proof of a commitment scheme.
pub trait CommitmentEvaluationProof {
    /// The associated scalar that the commitment is for.
    type Scalar: Scalar + Serialize + for<'a> Deserialize<'a>;
    /// The associated commitment type.
    type Commitment: for<'a> Commitment<Scalar = Self::Scalar, PublicSetup<'a> = Self::ProverPublicSetup<'a>>
        + Serialize
        + for<'a> Deserialize<'a>;
    /// The error type for the proof.
    type Error;
    /// The public setup parameters required by the prover.
    /// This is simply precomputed data that is required by the prover to create a proof.
    type ProverPublicSetup<'a>: Copy;
    /// The public setup parameters required by the verifier.
    /// This is simply precomputed data that is required by the verifier to verify a proof.
    type VerifierPublicSetup<'a>: Copy;
    /// Create a new proof.
    ///
    /// Note: `b_point` must have length `nu`, where `2^nu` is at least the length of `a`.
    /// `b_point` are the values for the variables that are being evaluated.
    /// The resulting evaluation is the the inner product of `a` and `b`, where `b` is the expanded vector form of `b_point`.
    fn new(
        transcript: &mut impl Transcript,
        a: &[Self::Scalar],
        b_point: &[Self::Scalar],
        generators_offset: u64,
        setup: &Self::ProverPublicSetup<'_>,
    ) -> Self;
    /// Verify a proof.
    ///
    /// Note: `b_point` must have length `nu`, where `2^nu` is at least the length of `a`.
    /// `b_point` are the values for the variables that are being evaluated.
    /// The resulting evaluation is the the inner product of `a` and `b`, where `b` is the expanded vector form of `b_point`.
    #[allow(clippy::too_many_arguments)]
    fn verify_proof(
        &self,
        transcript: &mut impl Transcript,
        a_commit: &Self::Commitment,
        product: &Self::Scalar,
        b_point: &[Self::Scalar],
        generators_offset: u64,
        table_length: usize,
        setup: &Self::VerifierPublicSetup<'_>,
    ) -> Result<(), Self::Error> {
        self.verify_batched_proof(
            transcript,
            core::slice::from_ref(a_commit),
            &[Self::Scalar::ONE],
            product,
            b_point,
            generators_offset,
            table_length,
            setup,
        )
    }
    /// Verify a batch proof. This can be more efficient than verifying individual proofs for some schemes.
    #[allow(clippy::too_many_arguments)]
    fn verify_batched_proof(
        &self,
        transcript: &mut impl Transcript,
        commit_batch: &[Self::Commitment],
        batching_factors: &[Self::Scalar],
        product: &Self::Scalar,
        b_point: &[Self::Scalar],
        generators_offset: u64,
        table_length: usize,
        setup: &Self::VerifierPublicSetup<'_>,
    ) -> Result<(), Self::Error>;
}

#[cfg(feature = "blitzar")]
impl CommitmentEvaluationProof for InnerProductProof {
    type Scalar = MontScalar<ark_curve25519::FrConfig>;
    type Commitment = RistrettoPoint;
    type Error = ProofError;
    type ProverPublicSetup<'a> = ();
    type VerifierPublicSetup<'a> = ();
    fn new(
        transcript: &mut impl Transcript,
        a: &[Self::Scalar],
        b_point: &[Self::Scalar],
        generators_offset: u64,
        _setup: &Self::ProverPublicSetup<'_>,
    ) -> Self {
        assert!(!a.is_empty());
        let b = &mut vec![MontScalar::default(); a.len()];
        if b_point.is_empty() {
            assert_eq!(b.len(), 1);
            b[0] = Self::Scalar::ONE;
        } else {
            crate::base::polynomial::compute_evaluation_vector(b, b_point);
        }
        // The InnerProductProof from blitzar only works with the merlin Transcript.
        // So, we wrap the call to it.
        transcript.wrap_transcript(|transcript| {
            Self::create(
                transcript,
                &slice_ops::slice_cast(a),
                &slice_ops::slice_cast(b),
                generators_offset,
            )
        })
    }

    fn verify_batched_proof(
        &self,
        transcript: &mut impl Transcript,
        commit_batch: &[Self::Commitment],
        batching_factors: &[Self::Scalar],
        product: &Self::Scalar,
        b_point: &[Self::Scalar],
        generators_offset: u64,
        table_length: usize,
        _setup: &Self::VerifierPublicSetup<'_>,
    ) -> Result<(), Self::Error> {
        assert!(table_length > 0);
        let b = &mut vec![MontScalar::default(); table_length];
        if b_point.is_empty() {
            assert_eq!(b.len(), 1);
            b[0] = Self::Scalar::ONE;
        } else {
            crate::base::polynomial::compute_evaluation_vector(b, b_point);
        }
        // The InnerProductProof from blitzar only works with the merlin Transcript.
        // So, we wrap the call to it.
        transcript.wrap_transcript(|transcript| {
            self.verify(
                transcript,
                &commit_batch
                    .iter()
                    .zip(batching_factors.iter())
                    .map(|(c, m)| *m * c)
                    .fold(RistrettoPoint::default(), |mut a, c| {
                        a += c;
                        a
                    }),
                &product.into(),
                &slice_ops::slice_cast(b),
                generators_offset,
            )
        })
    }
}