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 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 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
180pub 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}