Skip to content

Commit 9f402f7

Browse files
committed
Finish verifier index deserialization
1 parent 95e702c commit 9f402f7

3 files changed

Lines changed: 110 additions & 10 deletions

File tree

operator/mina/lib/Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

operator/mina/lib/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ crate-type = ["cdylib", "staticlib", "lib"]
88

99
[dependencies]
1010
kimchi = { git = "https://github.com/openmina/proof-systems", branch = "ledger-newtypes-rampup4-vrf" }
11+
poly-commitment = { git = "https://github.com/openmina/proof-systems", branch = "ledger-newtypes-rampup4-vrf" }
12+
mina-curves = { git = "https://github.com/openmina/proof-systems", branch = "ledger-newtypes-rampup4-vrf" }
1113
o1-utils = { git = "https://github.com/lambdaclass/proof-systems", branch = "add-verifier-serializations" }
1214
ark-ff = { version = "0.3.0", features = ["parallel", "asm"] }
1315
ark-ec = { version = "0.3.0", features = ["parallel"] }
@@ -22,6 +24,7 @@ mina-p2p-messages = { git = "https://github.com/lambdaclass/openmina/", branch =
2224
base64 = "0.22.1"
2325
bs58 = "0.5.1"
2426
lazy_static = "1.5.0"
27+
once_cell = "1.19.0"
2528

2629
[patch.crates-io]
2730
ark-ff = { git = "https://github.com/openmina/algebra", branch = "openmina" }

operator/mina/lib/src/verifier_index.rs

Lines changed: 104 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
1-
use std::array;
1+
use std::{array, sync::Arc};
22

3-
use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
3+
use ark_ff::Field;
4+
use ark_poly::{
5+
univariate::DensePolynomial, EvaluationDomain, Radix2EvaluationDomain, UVPolynomial,
6+
};
47
use kimchi::{
5-
mina_curves::pasta::{Fp, Fq, Pallas},
8+
circuits::{
9+
constraints::FeatureFlags,
10+
expr::Linearization,
11+
lookup::lookups::{LookupFeatures, LookupPatterns},
12+
},
13+
linearization::expr_linearization,
14+
mina_curves::pasta::{Fp, Fq, Pallas, Vesta},
615
o1_utils::FieldHelpers,
7-
poly_commitment::PolyComm,
16+
poly_commitment::{srs::SRS, PolyComm},
817
verifier_index::VerifierIndex,
918
};
1019
use serde::Deserialize;
@@ -111,6 +120,8 @@ impl TryInto<PolyComm<Pallas>> for JSONPolyComm {
111120
pub fn deserialize_blockchain_vk(json_str: &str) -> Result<VerifierIndex<Pallas>, String> {
112121
let vk: BlockchainVerificationKey =
113122
serde_json::from_str(json_str).map_err(|err| err.to_string())?;
123+
124+
let max_poly_size = vk.index.max_poly_size;
114125
let domain = Radix2EvaluationDomain::new(1 << vk.index.domain.log_size_of_group)
115126
.ok_or("failed to create domain".to_owned())?;
116127

@@ -129,7 +140,7 @@ pub fn deserialize_blockchain_vk(json_str: &str) -> Result<VerifierIndex<Pallas>
129140
let sigma_comm = {
130141
let mut new_sigma_comm = array::from_fn(empty_poly_comm);
131142
for (comm, new_comm) in sigma_comm.into_iter().zip(new_sigma_comm.iter_mut()) {
132-
new_comm = &mut comm.try_into()?
143+
*new_comm = comm.try_into()?
133144
}
134145
new_sigma_comm
135146
};
@@ -139,7 +150,7 @@ pub fn deserialize_blockchain_vk(json_str: &str) -> Result<VerifierIndex<Pallas>
139150
.into_iter()
140151
.zip(new_coefficients_comm.iter_mut())
141152
{
142-
new_comm = &mut comm.try_into()?
153+
*new_comm = comm.try_into()?
143154
}
144155
new_coefficients_comm
145156
};
@@ -154,14 +165,65 @@ pub fn deserialize_blockchain_vk(json_str: &str) -> Result<VerifierIndex<Pallas>
154165
let shift = {
155166
let mut new_shift = array::from_fn(|_| Fq::from(0));
156167
for (comm, new_comm) in shift.into_iter().zip(new_shift.iter_mut()) {
157-
new_comm = &mut comm.try_into()?
168+
*new_comm = comm.try_into()?
158169
}
159170
new_shift
160171
};
161172

162-
let verifier_index = VerifierIndex {
173+
// The code below was taken from OpenMina
174+
// https://github.com/openmina/openmina/blob/main/ledger/src/proofs/verifier_index.rs#L151
175+
176+
let (endo, _) = poly_commitment::srs::endos::<Vesta>();
177+
178+
let feature_flags = FeatureFlags {
179+
range_check0: false,
180+
range_check1: false,
181+
foreign_field_add: false,
182+
foreign_field_mul: false,
183+
xor: false,
184+
rot: false,
185+
lookup_features: LookupFeatures {
186+
patterns: LookupPatterns {
187+
xor: false,
188+
lookup: false,
189+
range_check: false,
190+
foreign_field_mul: false,
191+
},
192+
joint_lookup_used: false,
193+
uses_runtime_tables: false,
194+
},
195+
};
196+
197+
let (mut linearization, powers_of_alpha) = expr_linearization(Some(&feature_flags), true);
198+
199+
let linearization = Linearization {
200+
constant_term: linearization.constant_term,
201+
index_terms: {
202+
// Make the verifier index deterministic
203+
linearization
204+
.index_terms
205+
.sort_by_key(|&(columns, _)| columns);
206+
linearization.index_terms
207+
},
208+
};
209+
210+
// https://github.com/o1-labs/proof-systems/blob/2702b09063c7a48131173d78b6cf9408674fd67e/kimchi/src/verifier_index.rs#L310-L314
211+
let srs = {
212+
let mut srs = SRS::create(max_poly_size);
213+
srs.add_lagrange_basis(domain);
214+
Arc::new(srs)
215+
};
216+
217+
// https://github.com/o1-labs/proof-systems/blob/2702b09063c7a48131173d78b6cf9408674fd67e/kimchi/src/verifier_index.rs#L319
218+
let zkpm = zk_polynomial(domain);
219+
220+
// https://github.com/o1-labs/proof-systems/blob/2702b09063c7a48131173d78b6cf9408674fd67e/kimchi/src/verifier_index.rs#L324
221+
let w = zk_w3(domain);
222+
223+
Ok(VerifierIndex {
163224
domain,
164225
max_poly_size: vk.index.max_poly_size,
226+
srs: once_cell::sync::OnceCell::from(srs),
165227
public: vk.index.public,
166228
prev_challenges: vk.index.prev_challenges,
167229

@@ -180,8 +242,40 @@ pub fn deserialize_blockchain_vk(json_str: &str) -> Result<VerifierIndex<Pallas>
180242
foreign_field_mul_comm: None,
181243
xor_comm: None,
182244
rot_comm: None,
183-
};
184-
todo!()
245+
246+
shift,
247+
zkpm: once_cell::sync::OnceCell::from(zkpm),
248+
w: once_cell::sync::OnceCell::from(w),
249+
endo,
250+
lookup_index: None,
251+
linearization,
252+
powers_of_alpha,
253+
})
254+
}
255+
256+
/// Returns the end of the circuit, which is used for introducing zero-knowledge in the permutation polynomial
257+
pub fn zk_w3(domain: Radix2EvaluationDomain<Fq>) -> Fq {
258+
const ZK_ROWS: u64 = 3;
259+
domain.group_gen.pow([domain.size - (ZK_ROWS)])
260+
}
261+
262+
/// Computes the zero-knowledge polynomial for blinding the permutation polynomial: `(x-w^{n-k})(x-w^{n-k-1})...(x-w^n)`.
263+
/// Currently, we use k = 3 for 2 blinding factors,
264+
/// see <https://www.plonk.cafe/t/noob-questions-plonk-paper/73>
265+
pub fn zk_polynomial(domain: Radix2EvaluationDomain<Fq>) -> DensePolynomial<Fq> {
266+
let w3 = zk_w3(domain);
267+
let w2 = domain.group_gen * w3;
268+
let w1 = domain.group_gen * w2;
269+
270+
// (x-w3)(x-w2)(x-w1) =
271+
// x^3 - x^2(w1+w2+w3) + x(w1w2+w1w3+w2w3) - w1w2w3
272+
let w1w2 = w1 * w2;
273+
DensePolynomial::from_coefficients_slice(&[
274+
-w1w2 * w3, // 1
275+
w1w2 + (w1 * w3) + (w3 * w2), // x
276+
-w1 - w2 - w3, // x^2
277+
Fq::from(1), // x^3
278+
])
185279
}
186280

187281
#[cfg(test)]

0 commit comments

Comments
 (0)