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) -> Result<CamlPastaFpPlonkIndex, ocaml::Error> {
61 let gates: Vec<_> = gates
62 .as_ref()
63 .0
64 .iter()
65 .map(|gate| CircuitGate::<Fp> {
66 typ: gate.typ,
67 wires: gate.wires,
68 coeffs: gate.coeffs.clone(),
69 })
70 .collect();
71
72 let runtime_tables: Vec<RuntimeTableCfg<Fp>> =
73 runtime_tables.into_iter().map(Into::into).collect();
74
75 let lookup_tables: Vec<LookupTable<Fp>> = lookup_tables.into_iter().map(Into::into).collect();
76
77 let cs = match ConstraintSystem::<Fp>::create(gates)
79 .public(public as usize)
80 .prev_challenges(prev_challenges as usize)
81 .max_poly_size(Some(srs.0.max_poly_size()))
82 .lookup(lookup_tables)
83 .runtime(if runtime_tables.is_empty() {
84 None
85 } else {
86 Some(runtime_tables)
87 })
88 .build()
89 {
90 Err(e) => return Err(e.into()),
91 Ok(cs) => cs,
92 };
93
94 let (endo_q, _endo_r) = poly_commitment::ipa::endos::<Pallas>();
96
97 srs.0.with_lagrange_basis(cs.domain.d1);
98
99 let mut index = ProverIndex::<Vesta, OpeningProof<Vesta>>::create(cs, endo_q, srs.clone());
101 index.compute_verifier_index_digest::<DefaultFqSponge<VestaParameters, PlonkSpongeConstantsKimchi>>();
103
104 Ok(CamlPastaFpPlonkIndex(Box::new(index)))
105}
106
107#[ocaml_gen::func]
108#[ocaml::func]
109pub fn caml_pasta_fp_plonk_index_max_degree(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
110 index.as_ref().0.srs.max_poly_size() as isize
111}
112
113#[ocaml_gen::func]
114#[ocaml::func]
115pub fn caml_pasta_fp_plonk_index_public_inputs(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
116 index.as_ref().0.cs.public as isize
117}
118
119#[ocaml_gen::func]
120#[ocaml::func]
121pub fn caml_pasta_fp_plonk_index_domain_d1_size(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
122 index.as_ref().0.cs.domain.d1.size() as isize
123}
124
125#[ocaml_gen::func]
126#[ocaml::func]
127pub fn caml_pasta_fp_plonk_index_domain_d4_size(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
128 index.as_ref().0.cs.domain.d4.size() as isize
129}
130
131#[ocaml_gen::func]
132#[ocaml::func]
133pub fn caml_pasta_fp_plonk_index_domain_d8_size(index: CamlPastaFpPlonkIndexPtr) -> ocaml::Int {
134 index.as_ref().0.cs.domain.d8.size() as isize
135}
136
137#[ocaml_gen::func]
138#[ocaml::func]
139pub fn caml_pasta_fp_plonk_index_read(
140 offset: Option<ocaml::Int>,
141 srs: CamlFpSrs,
142 path: String,
143) -> Result<CamlPastaFpPlonkIndex, ocaml::Error> {
144 let file = match File::open(path) {
146 Err(_) => {
147 return Err(
148 ocaml::Error::invalid_argument("caml_pasta_fp_plonk_index_read")
149 .err()
150 .unwrap(),
151 )
152 }
153 Ok(file) => file,
154 };
155 let mut r = BufReader::new(file);
156
157 if let Some(offset) = offset {
159 r.seek(Start(offset as u64))?;
160 }
161
162 let mut t = ProverIndex::<Vesta, OpeningProof<Vesta>>::deserialize(
164 &mut rmp_serde::Deserializer::new(r),
165 )?;
166 t.srs = srs.clone();
167
168 let (linearization, powers_of_alpha) = expr_linearization(Some(&t.cs.feature_flags), true);
169 t.linearization = linearization;
170 t.powers_of_alpha = powers_of_alpha;
171
172 Ok(CamlPastaFpPlonkIndex(Box::new(t)))
173}
174
175#[ocaml_gen::func]
176#[ocaml::func]
177pub fn caml_pasta_fp_plonk_index_write(
178 append: Option<bool>,
179 index: CamlPastaFpPlonkIndexPtr<'static>,
180 path: String,
181) -> Result<(), ocaml::Error> {
182 let file = OpenOptions::new()
183 .append(append.unwrap_or(true))
184 .open(path)
185 .map_err(|_| {
186 ocaml::Error::invalid_argument("caml_pasta_fp_plonk_index_write")
187 .err()
188 .unwrap()
189 })?;
190 let w = BufWriter::new(file);
191 index
192 .as_ref()
193 .0
194 .serialize(&mut rmp_serde::Serializer::new(w))
195 .map_err(|e| e.into())
196}