proof_of_sql/proof_primitive/hyperkzg/
commitment.rs

1use super::{BNScalar, HyperKZGPublicSetup};
2use crate::base::{
3    commitment::{Commitment, CommittableColumn},
4    impl_serde_for_ark_serde_checked,
5    scalar::Scalar,
6    slice_ops,
7};
8use alloc::vec::Vec;
9use ark_bn254::{G1Affine, G1Projective};
10use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
11use core::ops::{AddAssign, Mul, Neg, Sub, SubAssign};
12
13/// This is the commitment type used in the hyperkzg proof system.
14#[derive(Clone, Copy, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Default)]
15pub struct HyperKZGCommitment {
16    /// The underlying commitment.
17    pub commitment: G1Projective,
18}
19impl_serde_for_ark_serde_checked!(HyperKZGCommitment);
20
21impl AddAssign for HyperKZGCommitment {
22    fn add_assign(&mut self, rhs: Self) {
23        self.commitment = self.commitment + rhs.commitment;
24    }
25}
26impl From<&G1Affine> for HyperKZGCommitment {
27    fn from(value: &G1Affine) -> Self {
28        Self {
29            commitment: (*value).into(),
30        }
31    }
32}
33
34impl Mul<&HyperKZGCommitment> for BNScalar {
35    type Output = HyperKZGCommitment;
36    fn mul(self, rhs: &HyperKZGCommitment) -> Self::Output {
37        Self::Output {
38            commitment: rhs.commitment * self.0,
39        }
40    }
41}
42
43impl Mul<HyperKZGCommitment> for BNScalar {
44    type Output = HyperKZGCommitment;
45    #[expect(clippy::op_ref)]
46    fn mul(self, rhs: HyperKZGCommitment) -> Self::Output {
47        self * &rhs
48    }
49}
50impl Neg for HyperKZGCommitment {
51    type Output = Self;
52    fn neg(self) -> Self::Output {
53        (-BNScalar::ONE) * self
54    }
55}
56impl SubAssign for HyperKZGCommitment {
57    fn sub_assign(&mut self, rhs: Self) {
58        *self += -rhs;
59    }
60}
61impl Sub for HyperKZGCommitment {
62    type Output = Self;
63    fn sub(mut self, rhs: Self) -> Self::Output {
64        self -= rhs;
65        self
66    }
67}
68
69#[cfg(any(not(feature = "blitzar"), test))]
70#[tracing::instrument(
71    name = "compute_commitment_generic_impl (cpu)",
72    level = "debug",
73    skip_all
74)]
75fn compute_commitment_generic_impl<T: Into<BNScalar> + Clone>(
76    setup: HyperKZGPublicSetup<'_>,
77    offset: usize,
78    scalars: &[T],
79) -> HyperKZGCommitment {
80    assert!(offset + scalars.len() <= setup.len());
81    let product: G1Projective = scalars
82        .iter()
83        .zip(&setup[offset..offset + scalars.len()])
84        .map(|(t, s)| *s * Into::<BNScalar>::into(t).0)
85        .sum();
86    HyperKZGCommitment {
87        commitment: G1Projective::from(product),
88    }
89}
90
91#[cfg(any(not(feature = "blitzar"), test))]
92#[tracing::instrument(name = "compute_commitments_impl (cpu)", level = "debug", skip_all)]
93fn compute_commitments_impl(
94    committable_columns: &[crate::base::commitment::CommittableColumn],
95    offset: usize,
96    setup: &<HyperKZGCommitment as Commitment>::PublicSetup<'_>,
97) -> Vec<HyperKZGCommitment> {
98    committable_columns
99        .iter()
100        .map(|column| match column {
101            CommittableColumn::Boolean(vals) => {
102                compute_commitment_generic_impl(setup, offset, vals)
103            }
104            CommittableColumn::Uint8(vals) => compute_commitment_generic_impl(setup, offset, vals),
105            CommittableColumn::TinyInt(vals) => {
106                compute_commitment_generic_impl(setup, offset, vals)
107            }
108            CommittableColumn::SmallInt(vals) => {
109                compute_commitment_generic_impl(setup, offset, vals)
110            }
111            CommittableColumn::Int(vals) => compute_commitment_generic_impl(setup, offset, vals),
112            CommittableColumn::BigInt(vals) | CommittableColumn::TimestampTZ(_, _, vals) => {
113                compute_commitment_generic_impl(setup, offset, vals)
114            }
115            CommittableColumn::Int128(vals) => compute_commitment_generic_impl(setup, offset, vals),
116            CommittableColumn::Decimal75(_, _, vals)
117            | CommittableColumn::Scalar(vals)
118            | CommittableColumn::VarChar(vals)
119            | CommittableColumn::VarBinary(vals) => {
120                compute_commitment_generic_impl(setup, offset, vals)
121            }
122        })
123        .collect()
124}
125
126impl Commitment for HyperKZGCommitment {
127    type Scalar = BNScalar;
128    type PublicSetup<'a> = HyperKZGPublicSetup<'a>;
129
130    #[cfg(not(feature = "blitzar"))]
131    #[tracing::instrument(name = "compute_commitments (cpu)", level = "debug", skip_all)]
132    fn compute_commitments(
133        committable_columns: &[crate::base::commitment::CommittableColumn],
134        offset: usize,
135        setup: &Self::PublicSetup<'_>,
136    ) -> Vec<Self> {
137        compute_commitments_impl(committable_columns, offset, setup)
138    }
139
140    #[cfg(feature = "blitzar")]
141    #[tracing::instrument(name = "compute_commitments (gpu)", level = "debug", skip_all)]
142    fn compute_commitments(
143        committable_columns: &[crate::base::commitment::CommittableColumn],
144        offset: usize,
145        setup: &Self::PublicSetup<'_>,
146    ) -> Vec<Self> {
147        if committable_columns.is_empty() {
148            return Vec::new();
149        }
150
151        // Find the maximum length of the columns to get number of generators to use
152        let max_column_len = committable_columns
153            .iter()
154            .map(CommittableColumn::len)
155            .max()
156            .expect("You must have at least one column");
157
158        let mut blitzar_commitments = vec![G1Affine::default(); committable_columns.len()];
159
160        blitzar::compute::compute_bn254_g1_uncompressed_commitments_with_generators(
161            &mut blitzar_commitments,
162            &slice_ops::slice_cast(committable_columns),
163            &setup[offset..offset + max_column_len],
164        );
165
166        slice_ops::slice_cast(&blitzar_commitments)
167    }
168
169    fn to_transcript_bytes(&self) -> Vec<u8> {
170        let mut writer = Vec::with_capacity(self.commitment.compressed_size());
171        self.commitment.serialize_compressed(&mut writer).unwrap();
172        writer
173    }
174}
175
176#[cfg(test)]
177mod tests {
178    use super::*;
179    #[cfg(feature = "hyperkzg_proof")]
180    use crate::base::database::OwnedColumn;
181    #[cfg(feature = "hyperkzg_proof")]
182    use crate::proof_primitive::hyperkzg::nova_commitment_key_to_hyperkzg_public_setup;
183    #[cfg(feature = "hyperkzg_proof")]
184    use crate::proof_primitive::hyperkzg::HyperKZGEngine;
185    use ark_ec::AffineRepr;
186    #[cfg(feature = "hyperkzg_proof")]
187    use nova_snark::provider::hyperkzg::{CommitmentEngine, CommitmentKey};
188    #[cfg(feature = "hyperkzg_proof")]
189    use nova_snark::traits::commitment::CommitmentEngineTrait;
190    #[cfg(feature = "hyperkzg_proof")]
191    use proptest::prelude::*;
192
193    #[test]
194    fn we_can_convert_default_point_to_a_hyperkzg_commitment_from_ark_bn254_g1_affine() {
195        let commitment: HyperKZGCommitment = HyperKZGCommitment::from(&G1Affine::default());
196        assert_eq!(commitment.commitment, G1Affine::default());
197    }
198
199    #[test]
200    fn we_can_convert_generator_to_a_hyperkzg_commitment_from_ark_bn254_g1_affine() {
201        let commitment: HyperKZGCommitment = (&G1Affine::generator()).into();
202        let expected: HyperKZGCommitment = HyperKZGCommitment::from(&G1Affine::generator());
203        assert_eq!(commitment.commitment, expected.commitment);
204    }
205
206    #[cfg(feature = "hyperkzg_proof")]
207    proptest! {
208        #[test]
209        fn blitzar_and_non_blitzar_commitments_are_equal(owned_column: OwnedColumn<BNScalar>) {
210            let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", owned_column.len());
211
212            let public_setup = nova_commitment_key_to_hyperkzg_public_setup(&ck);
213
214            let committable_columns = [CommittableColumn::from(&owned_column)];
215
216            let non_blitzar_commitments = compute_commitments_impl(&committable_columns, 0, &&public_setup[..]);
217            let blitzar_commitments = HyperKZGCommitment::compute_commitments(&committable_columns, 0, &&public_setup[..]);
218
219            prop_assert_eq!(non_blitzar_commitments, blitzar_commitments);
220        }
221    }
222}