1use crate::{diff::Diff, utils, Sponge};
2use ark_ec::{AffineRepr, CurveGroup, VariableBaseMSM};
3use ark_poly::univariate::DensePolynomial;
4use kimchi::curve::KimchiCurve;
5use poly_commitment::{ipa::SRS, SRS as _};
6use rayon::prelude::*;
7use tracing::instrument;
8
9fn get_lagrange_basis<G: KimchiCurve>(srs: &SRS<G>) -> Vec<G> {
10 srs.get_lagrange_basis_from_domain_size(crate::SRS_SIZE)
11 .iter()
12 .map(|x| x.chunks[0])
13 .collect()
14}
15
16#[instrument(skip_all, level = "debug")]
19pub fn commit_to_field_elems<G: KimchiCurve>(srs: &SRS<G>, data: &[G::ScalarField]) -> Vec<G>
20where
21 <G as AffineRepr>::Group: VariableBaseMSM,
22{
23 let basis = get_lagrange_basis(srs);
24
25 let commitments_projective = (0..data.len() / crate::SRS_SIZE)
26 .into_par_iter()
27 .map(|idx| {
28 G::Group::msm(
29 &basis,
30 &data[crate::SRS_SIZE * idx..crate::SRS_SIZE * (idx + 1)],
31 )
32 .unwrap()
33 })
34 .collect::<Vec<_>>();
35
36 let commitments = G::Group::normalize_batch(commitments_projective.as_slice());
37
38 commitments
39}
40
41pub fn commit_poly<G: KimchiCurve>(srs: &SRS<G>, poly: &DensePolynomial<G::ScalarField>) -> G {
43 srs.commit_non_hiding(poly, 1).chunks[0]
44}
45
46pub fn commit_sparse<G: KimchiCurve>(
53 srs: &SRS<G>,
54 sparse_data: &[G::ScalarField],
55 indexes: &[u64],
56) -> G {
57 if sparse_data.len() != indexes.len() {
58 panic!(
59 "commitment::commit_sparse: size mismatch (sparse_data: {}, indexes: {})",
60 sparse_data.len(),
61 indexes.len()
62 )
63 };
64 let basis = get_lagrange_basis(srs);
65 let basis: Vec<G> = indexes.iter().map(|&i| basis[i as usize]).collect();
66 G::Group::msm(&basis, sparse_data).unwrap().into()
67}
68
69#[instrument(skip_all, level = "debug")]
72pub fn combine_commitments<G: AffineRepr, Spng: Sponge<G::BaseField, G, G::ScalarField>>(
73 sponge: &mut Spng,
74 commitments: &[G],
75) -> (G, G::ScalarField) {
76 for commitment in commitments.iter() {
77 sponge.absorb_g(std::slice::from_ref(commitment))
78 }
79 let alpha = sponge.challenge();
80 let combined_data_commitment = utils::aggregate_commitments(alpha, commitments);
81 (combined_data_commitment, alpha)
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct Commitment<G: KimchiCurve> {
89 pub cm: G,
90}
91
92impl<G: KimchiCurve> From<G> for Commitment<G> {
93 fn from(cm: G) -> Self {
94 Self { cm }
95 }
96}
97
98impl<G: KimchiCurve> Commitment<G> {
99 pub fn from_data(srs: &SRS<G>, data: &[G::ScalarField]) -> Commitment<G> {
102 Commitment {
103 cm: commit_to_field_elems::<G>(srs, data)[0],
104 }
105 }
106
107 pub fn update(&self, srs: &SRS<G>, diff: Diff<G::ScalarField>) -> Commitment<G> {
113 let cm_diff = commit_sparse(srs, &diff.diff_values, &diff.addresses);
115 Commitment {
116 cm: self.cm.add(cm_diff).into(),
117 }
118 }
119}