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