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+ } ;
47use 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} ;
1019use serde:: Deserialize ;
@@ -111,6 +120,8 @@ impl TryInto<PolyComm<Pallas>> for JSONPolyComm {
111120pub 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