kimchi_stubs/
pasta_fp_plonk_index.rs1use crate::{
2 arkworks::CamlFp, gate_vector::fp::CamlPastaFpPlonkGateVectorPtr, srs::fp::CamlFpSrs,
3 WithLagrangeBasis,
4};
5use ark_poly::EvaluationDomain;
6use kimchi::{
7 circuits::{
8 constraints::ConstraintSystem,
9 gate::CircuitGate,
10 lookup::{
11 runtime_tables::{caml::CamlRuntimeTableCfg, RuntimeTableCfg},
12 tables::{caml::CamlLookupTable, LookupTable},
13 },
14 },
15 linearization::expr_linearization,
16 prover_index::ProverIndex,
17};
18use mina_curves::pasta::{Fp, Pallas, Vesta, VestaParameters};
19use mina_poseidon::{constants::PlonkSpongeConstantsKimchi, sponge::DefaultFqSponge};
20use poly_commitment::{ipa::OpeningProof, SRS as _};
21use serde::{Deserialize, Serialize};
22use std::{
23 fs::{File, OpenOptions},
24 io::{BufReader, BufWriter, Seek, SeekFrom::Start},
25};
26
27#[derive(ocaml_gen::CustomType)]
29pub struct CamlPastaFpPlonkIndex(pub Box<ProverIndex<Vesta, OpeningProof<Vesta>>>);
30pub type CamlPastaFpPlonkIndexPtr<'a> = ocaml::Pointer<'a, CamlPastaFpPlonkIndex>;
31
32extern "C" fn caml_pasta_fp_plonk_index_finalize(v: ocaml::Raw) {
33 unsafe {
34 let mut v: CamlPastaFpPlonkIndexPtr = v.as_pointer();
35 v.as_mut_ptr().drop_in_place();
36 }
37}
38
39impl ocaml::custom::Custom for CamlPastaFpPlonkIndex {
40 const NAME: &'static str = "CamlPastaFpPlonkIndex\0";
41 const USED: usize = 1;
42 const MAX: usize = 12;
44 const OPS: ocaml::custom::CustomOps = ocaml::custom::CustomOps {
45 identifier: Self::NAME.as_ptr() as *const ocaml::sys::Char,
46 finalize: Some(caml_pasta_fp_plonk_index_finalize),
47 ..ocaml::custom::DEFAULT_CUSTOM_OPS
48 };
49}
50
51#[ocaml_gen::func]
52#[ocaml::func]
53pub fn caml_pasta_fp_plonk_index_create(
54 gates: CamlPastaFpPlonkGateVectorPtr,
55 public: ocaml::Int,
56 lookup_tables: Vec<CamlLookupTable<CamlFp>>,
57 runtime_tables: Vec<CamlRuntimeTableCfg<CamlFp>>,
58 prev_challenges: ocaml::Int,
59 srs: CamlFpSrs,
60 lazy_mode: bool,
61) -> Result<CamlPastaFpPlonkIndex, ocaml::Error> {
62 let gates: Vec<_> = gates
63 .as_ref()
64 .0
65 .iter()
66 .map(|gate| CircuitGate::<Fp> {
67 typ: gate.typ,
68 wires: gate.wires,
69 coeffs: gate.coeffs.clone(),
70 })
71 .collect();
72
73 let runtime_tables: Vec<RuntimeTableCfg<Fp>> =
74 runtime_tables.into_iter().map(Into::into).collect();
75
76 let lookup_tables: Vec<LookupTable<Fp>> = lookup_tables.into_iter().map(Into::into).collect();
77
78 let cs = match ConstraintSystem::<Fp>::create(gates)
80 .public(public as usize)
81 .prev_challenges(prev_challenges as usize)
82 .max_poly_size(Some(srs.0.max_poly_size()))
83 .lookup(lookup_tables)
84 .runtime(if runtime_tables.is_empty() {
85 None
86 } else {
87 Some(runtime_tables)
88 })
89 .lazy_mode(lazy_mode)
90 .build()
91 {
92 Err(e) => return Err(e.into()),
93 Ok(cs) => cs,
94 };
95
96 let (endo_q, _endo_r) = poly_commitment::ipa::endos::<Pallas>();
98
99 srs.0.with_lagrange_basis(cs.domain.d1);
100
101 let mut index =
103 ProverIndex::<Vesta, OpeningProof<Vesta>>::create(cs, endo_q, srs.clone(), lazy_mode);
104 index.compute_verifier_index_digest::<DefaultFqSponge<VestaParameters, PlonkSpongeConstantsKimchi>>();
106
107 Ok(CamlPastaFpPlonkIndex(Box::new(index)))
108}
109
110#[ocaml_gen::func]
111#[ocaml::func]
112pub fn caml_pasta_fp_plonk_index_max_degree(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
113 index.as_ref().0.srs.max_poly_size() as isize
114}
115
116#[ocaml_gen::func]
117#[ocaml::func]
118pub fn caml_pasta_fp_plonk_index_public_inputs(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
119 index.as_ref().0.cs.public as isize
120}
121
122#[ocaml_gen::func]
123#[ocaml::func]
124pub fn caml_pasta_fp_plonk_index_domain_d1_size(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
125 index.as_ref().0.cs.domain.d1.size() as isize
126}
127
128#[ocaml_gen::func]
129#[ocaml::func]
130pub fn caml_pasta_fp_plonk_index_domain_d4_size(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
131 index.as_ref().0.cs.domain.d4.size() as isize
132}
133
134#[ocaml_gen::func]
135#[ocaml::func]
136pub fn caml_pasta_fp_plonk_index_domain_d8_size(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
137 index.as_ref().0.cs.domain.d8.size() as isize
138}
139
140#[ocaml_gen::func]
141#[ocaml::func]
142pub fn caml_pasta_fp_plonk_index_read(
143 offset: Option<ocaml::Int>,
144 srs: CamlFpSrs,
145 path: String,
146) -> Result<CamlPastaFpPlonkIndex, ocaml::Error> {
147 let file = match File::open(path) {
149 Err(_) => {
150 return Err(
151 ocaml::Error::invalid_argument("caml_pasta_fp_plonk_index_read")
152 .err()
153 .unwrap(),
154 )
155 }
156 Ok(file) => file,
157 };
158 let mut r = BufReader::new(file);
159
160 if let Some(offset) = offset {
162 r.seek(Start(offset as u64))?;
163 }
164
165 let mut t = ProverIndex::<Vesta, OpeningProof<Vesta>>::deserialize(
167 &mut rmp_serde::Deserializer::new(r),
168 )?;
169 t.srs = srs.clone();
170
171 let (linearization, powers_of_alpha) = expr_linearization(Some(&t.cs.feature_flags), true);
172 t.linearization = linearization;
173 t.powers_of_alpha = powers_of_alpha;
174
175 Ok(CamlPastaFpPlonkIndex(Box::new(t)))
176}
177
178#[ocaml_gen::func]
179#[ocaml::func]
180pub fn caml_pasta_fp_plonk_index_write(
181 append: Option<bool>,
182 index: CamlPastaFpPlonkIndexPtr<'static>,
183 path: String,
184) -> Result<(), ocaml::Error> {
185 let file = OpenOptions::new()
186 .append(append.unwrap_or(true))
187 .open(path)
188 .map_err(|_| {
189 ocaml::Error::invalid_argument("caml_pasta_fp_plonk_index_write")
190 .err()
191 .unwrap()
192 })?;
193 let w = BufWriter::new(file);
194 index
195 .as_ref()
196 .0
197 .serialize(&mut rmp_serde::Serializer::new(w))
198 .map_err(|e| e.into())
199}