proof-of-sql 0.129.0

High performance zero knowledge (ZK) prover for SQL.
Documentation
use super::HyperKZGEngine;

/// Nova hyperkzg commitment corresponding to `HyperKZGCommitment`.
pub type NovaCommitment = nova_snark::provider::hyperkzg::Commitment<HyperKZGEngine>;

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        base::{
            commitment::{Commitment, CommittableColumn},
            math::decimal::Precision,
            posql_time::{PoSQLTimeUnit, PoSQLTimeZone},
            scalar::Scalar,
        },
        proof_primitive::hyperkzg::{
            convert_g1_affine_from_ark_to_halo2, nova_commitment_key_to_hyperkzg_public_setup,
            BNScalar, HyperKZGCommitment,
        },
    };
    use ark_bn254::G1Affine;
    use ff::Field;
    use itertools::Itertools;
    use nova_snark::{
        provider::{
            bn256_grumpkin::bn256::Scalar as NovaScalar,
            hyperkzg::{CommitmentEngine, CommitmentKey},
        },
        traits::commitment::CommitmentEngineTrait,
    };

    fn ark_to_nova_commitment(commitment: HyperKZGCommitment) -> NovaCommitment {
        NovaCommitment::new(
            convert_g1_affine_from_ark_to_halo2(&G1Affine::from(commitment.commitment)).into(),
        )
    }

    fn compute_commitment_with_hyperkzg_repo<T: Into<BNScalar> + Clone>(
        setup: &CommitmentKey<HyperKZGEngine>,
        offset: usize,
        scalars: &[T],
    ) -> NovaCommitment {
        CommitmentEngine::commit(
            setup,
            &itertools::repeat_n(BNScalar::ZERO, offset)
                .chain(scalars.iter().map(Into::into))
                .map(Into::into)
                .collect_vec(),
            &NovaScalar::ZERO,
        )
    }

    #[test]
    fn we_can_compute_commitment_with_hyperkzg_repo_for_testing() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 6);

        let result = compute_commitment_with_hyperkzg_repo(&ck, 0, &[0]);

        assert_eq!(
            result,
            ark_to_nova_commitment((&G1Affine::default()).into())
        );
    }

    fn compute_expected_commitments(
        committable_columns: &[CommittableColumn],
        offset: usize,
        ck: &CommitmentKey<HyperKZGEngine>,
    ) -> Vec<NovaCommitment> {
        let mut expected: Vec<NovaCommitment> = Vec::with_capacity(committable_columns.len());
        for column in committable_columns {
            match column {
                CommittableColumn::Boolean(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::Uint8(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::TinyInt(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::SmallInt(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::Int(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::BigInt(vals) | CommittableColumn::TimestampTZ(_, _, vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::Int128(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
                CommittableColumn::Decimal75(_, _, vals)
                | CommittableColumn::Scalar(vals)
                | CommittableColumn::VarChar(vals)
                | CommittableColumn::VarBinary(vals) => {
                    expected.push(compute_commitment_with_hyperkzg_repo(ck, offset, vals));
                }
            }
        }
        expected
    }

    #[test]
    fn we_can_compute_expected_commitments_for_testing() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 6);

        let committable_columns = vec![CommittableColumn::BigInt(&[0; 0])];

        let offset = 0;

        let result = compute_expected_commitments(&committable_columns, offset, &ck);

        assert_eq!(result.len(), 1);
        assert_eq!(
            result[0],
            ark_to_nova_commitment((&G1Affine::default()).into())
        );
    }

    #[test]
    fn we_can_compute_a_commitment_with_only_one_column() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 6);

        let committable_columns = vec![CommittableColumn::BigInt(&[0, 1, 2, 3, 4, 5, 6, 7])];

        let offset = 0;

        let res = HyperKZGCommitment::compute_commitments(
            &committable_columns,
            offset,
            &&nova_commitment_key_to_hyperkzg_public_setup(&ck)[..],
        )
        .into_iter()
        .map(ark_to_nova_commitment)
        .collect::<Vec<_>>();
        let expected = compute_expected_commitments(&committable_columns, offset, &ck);

        assert_eq!(res, expected);
    }

    #[test]
    fn we_can_compute_commitments_with_a_single_empty_column() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 32);

        let committable_columns = vec![CommittableColumn::BigInt(&[0; 0])];

        for offset in 0..32 {
            let res = HyperKZGCommitment::compute_commitments(
                &committable_columns,
                offset,
                &&nova_commitment_key_to_hyperkzg_public_setup(&ck)[..],
            )
            .into_iter()
            .map(ark_to_nova_commitment)
            .collect::<Vec<_>>();
            let expected = compute_expected_commitments(&committable_columns, offset, &ck);

            assert_eq!(res, expected, "Offset: {offset}");
        }
    }

    #[test]
    fn we_can_compute_commitments_with_a_multiple_mixed_empty_columns() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 32);

        let committable_columns = vec![
            CommittableColumn::TinyInt(&[0; 0]),
            CommittableColumn::SmallInt(&[0; 0]),
            CommittableColumn::Uint8(&[0; 0]),
            CommittableColumn::Int(&[0; 0]),
            CommittableColumn::BigInt(&[0; 0]),
            CommittableColumn::Int128(&[0; 0]),
        ];

        for offset in 0..32 {
            let res = HyperKZGCommitment::compute_commitments(
                &committable_columns,
                offset,
                &&nova_commitment_key_to_hyperkzg_public_setup(&ck)[..],
            )
            .into_iter()
            .map(ark_to_nova_commitment)
            .collect::<Vec<_>>();
            let expected = compute_expected_commitments(&committable_columns, offset, &ck);

            assert_eq!(res, expected, "Offset: {offset}");
        }
    }

    #[test]
    fn we_can_compute_a_commitment_with_mixed_columns_of_different_sizes_and_offsets() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 128);

        let committable_columns = vec![
            CommittableColumn::BigInt(&[0, 1]),
            CommittableColumn::Uint8(&[2, 3]),
            CommittableColumn::Int(&[4, 5, 10]),
            CommittableColumn::SmallInt(&[6, 7]),
            CommittableColumn::Int128(&[8, 9]),
            CommittableColumn::Boolean(&[true, true]),
            CommittableColumn::Decimal75(
                Precision::new(1).unwrap(),
                0,
                vec![[10, 0, 0, 0], [11, 0, 0, 0], [12, 0, 0, 0], [13, 0, 0, 0]],
            ),
            CommittableColumn::Scalar(vec![[14, 0, 0, 0], [15, 0, 0, 0]]),
            CommittableColumn::VarChar(vec![[16, 0, 0, 0]]),
            CommittableColumn::TimestampTZ(
                PoSQLTimeUnit::Second,
                PoSQLTimeZone::utc(),
                &[17, 18, 19, 20],
            ),
            CommittableColumn::VarBinary(vec![[21, 0, 0, 0]]),
        ];

        for offset in 0..64 {
            let res = HyperKZGCommitment::compute_commitments(
                &committable_columns,
                offset,
                &&nova_commitment_key_to_hyperkzg_public_setup(&ck)[..],
            )
            .into_iter()
            .map(ark_to_nova_commitment)
            .collect::<Vec<_>>();
            let expected = compute_expected_commitments(&committable_columns, offset, &ck);

            assert_eq!(res, expected, "Offset: {offset}");
        }
    }

    #[test]
    fn we_can_compute_a_commitment_with_mixed_signed_columns_of_different_sizes_and_offsets() {
        let ck: CommitmentKey<HyperKZGEngine> = CommitmentEngine::setup(b"test", 128);

        let committable_columns = vec![
            CommittableColumn::BigInt(&[-1, -2, -3]),
            CommittableColumn::Int(&[-4, -5, -10]),
            CommittableColumn::SmallInt(&[-6, -7]),
            CommittableColumn::Int128(&[-8, -9]),
        ];

        for offset in 0..60 {
            let res = HyperKZGCommitment::compute_commitments(
                &committable_columns,
                offset,
                &&nova_commitment_key_to_hyperkzg_public_setup(&ck)[..],
            )
            .into_iter()
            .map(ark_to_nova_commitment)
            .collect::<Vec<_>>();
            let expected = compute_expected_commitments(&committable_columns, offset, &ck);

            assert_eq!(res, expected, "Offset: {offset}");
        }
    }
}