kimchi_stubs/
srs.rs

1use crate::lagrange_basis::WithLagrangeBasis;
2use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain, Evaluations};
3use paste::paste;
4use poly_commitment::{
5    commitment::{b_poly_coefficients, caml::CamlPolyComm},
6    ipa::SRS,
7    SRS as _,
8};
9use serde::{Deserialize, Serialize};
10use std::{
11    fs::{File, OpenOptions},
12    io::{BufReader, BufWriter, Seek, SeekFrom::Start},
13};
14
15macro_rules! impl_srs {
16    ($name: ident, $CamlF: ty, $CamlG: ty, $F: ty, $G: ty) => {
17
18        impl_shared_reference!($name => SRS<$G>);
19
20        paste! {
21            #[ocaml_gen::func]
22            #[ocaml::func]
23            pub fn [<$name:snake _create>](depth: ocaml::Int) -> $name {
24                $name::new(SRS::create(depth as usize))
25            }
26
27            #[ocaml_gen::func]
28            #[ocaml::func]
29            pub fn [<$name:snake _write>](
30                append: Option<bool>,
31                srs: $name,
32                path: String,
33            ) -> Result<(), ocaml::Error> {
34                let file = OpenOptions::new()
35                    .append(append.unwrap_or(true))
36                    .open(path)
37                    .map_err(|_| {
38                        ocaml::Error::invalid_argument("CamlSRS::write")
39                            .err()
40                            .unwrap()
41                    })?;
42                let file = BufWriter::new(file);
43
44                srs.0.serialize(&mut rmp_serde::Serializer::new(file))
45                .map_err(|e| e.into())
46            }
47
48            #[ocaml_gen::func]
49            #[ocaml::func]
50            pub fn [<$name:snake _read>](
51                offset: Option<ocaml::Int>,
52                path: String,
53            ) -> Result<Option<$name>, ocaml::Error> {
54                let file = File::open(path).map_err(|_| {
55                    ocaml::Error::invalid_argument("CamlSRS::read")
56                        .err()
57                        .unwrap()
58                })?;
59                let mut reader = BufReader::new(file);
60
61                if let Some(offset) = offset {
62                    reader.seek(Start(offset as u64))?;
63                }
64
65                // TODO: shouldn't we just error instead of returning None?
66                let srs = match SRS::<$G>::deserialize(&mut rmp_serde::Deserializer::new(reader)) {
67                    Ok(srs) => srs,
68                    Err(_) => return Ok(None),
69                };
70
71                Ok(Some($name::new(srs)))
72            }
73
74            #[ocaml_gen::func]
75            #[ocaml::func]
76            /// This is same as _lagrange_commitments, but returns the result for every
77            /// i <= domain_size.
78            pub fn [<$name:snake _lagrange_commitments_whole_domain>](
79                srs: $name,
80                domain_size: ocaml::Int,
81            ) -> Vec<CamlPolyComm<$CamlG>> {
82                srs.get_lagrange_basis_from_domain_size(domain_size as usize).clone().into_iter().map(|x| x.into()).collect()
83            }
84
85
86            #[ocaml_gen::func]
87            #[ocaml::func]
88            pub fn [<$name:snake _lagrange_commitment>](
89                srs: $name,
90                domain_size: ocaml::Int,
91                i: ocaml::Int,
92            ) -> Result<CamlPolyComm<$CamlG>, ocaml::Error> {
93                let x_domain = EvaluationDomain::<$F>::new(domain_size as usize).ok_or_else(|| {
94                    ocaml::Error::invalid_argument("CamlSRS::lagrange_commitment")
95                        .err()
96                        .unwrap()
97                })?;
98                srs.with_lagrange_basis(x_domain);
99                let vec_polycomm = srs.get_lagrange_basis_from_domain_size(domain_size as usize);
100                Ok(vec_polycomm[i as usize].clone().into())
101            }
102
103            #[ocaml_gen::func]
104            #[ocaml::func]
105            pub fn [<$name:snake _add_lagrange_basis>](
106                srs: $name,
107                log2_size: ocaml::Int,
108            ) {
109                let domain = EvaluationDomain::<$F>::new(1 << (log2_size as usize)).expect("invalid domain size");
110                srs.with_lagrange_basis(domain);
111            }
112
113            #[ocaml_gen::func]
114            #[ocaml::func]
115            pub fn [<$name:snake _commit_evaluations>](
116                srs: $name,
117                domain_size: ocaml::Int,
118                evals: Vec<$CamlF>,
119            ) -> Result<CamlPolyComm<$CamlG>, ocaml::Error> {
120                    let x_domain = EvaluationDomain::<$F>::new(domain_size as usize).ok_or_else(|| {
121                        ocaml::Error::invalid_argument("CamlSRS::evaluations")
122                            .err()
123                            .unwrap()
124                    })?;
125
126                let evals = evals.into_iter().map(Into::into).collect();
127                let p = Evaluations::<$F>::from_vec_and_domain(evals, x_domain).interpolate();
128
129                Ok(srs.commit_non_hiding(&p, 1).into())
130            }
131
132            #[ocaml_gen::func]
133            #[ocaml::func]
134            pub fn [<$name:snake _b_poly_commitment>](
135                srs: $name,
136                chals: Vec<$CamlF>,
137            ) -> Result<CamlPolyComm<$CamlG>, ocaml::Error> {
138                let chals: Vec<$F> = chals.into_iter().map(Into::into).collect();
139                let coeffs = b_poly_coefficients(&chals);
140                let p = DensePolynomial::<$F>::from_coefficients_vec(coeffs);
141
142                Ok(srs.commit_non_hiding(&p, 1).into())
143            }
144
145            #[ocaml_gen::func]
146            #[ocaml::func]
147            pub fn [<$name:snake _batch_accumulator_check>](
148                srs: $name,
149                comms: Vec<$CamlG>,
150                chals: Vec<$CamlF>,
151            ) -> bool {
152                let comms: Vec<_> = comms.into_iter().map(Into::into).collect();
153                let chals: Vec<_> = chals.into_iter().map(Into::into).collect();
154                crate::urs_utils::batch_dlog_accumulator_check(&srs, &comms, &chals)
155            }
156
157            #[ocaml_gen::func]
158            #[ocaml::func]
159            pub fn [<$name:snake _batch_accumulator_generate>](
160                srs: $name,
161                comms: ocaml::Int,
162                chals: Vec<$CamlF>,
163            ) -> Vec<$CamlG> {
164                crate::urs_utils::batch_dlog_accumulator_generate::<$G>(
165                    &srs,
166                    comms as usize,
167                    &chals.into_iter().map(From::from).collect(),
168                ).into_iter().map(Into::into).collect()
169            }
170
171            #[ocaml_gen::func]
172            #[ocaml::func]
173            pub fn [<$name:snake _h>](srs: $name) -> $CamlG {
174                srs.h.into()
175            }
176        }
177    }
178}
179
180//
181// Fp
182//
183
184pub mod fp {
185    use super::*;
186    use crate::arkworks::{CamlFp, CamlGVesta};
187    use mina_curves::pasta::{Fp, Vesta};
188
189    impl_srs!(CamlFpSrs, CamlFp, CamlGVesta, Fp, Vesta);
190}
191
192pub mod fq {
193    use super::*;
194    use crate::arkworks::{CamlFq, CamlGPallas};
195    use mina_curves::pasta::{Fq, Pallas};
196
197    impl_srs!(CamlFqSrs, CamlFq, CamlGPallas, Fq, Pallas);
198}