@@ -13,8 +13,8 @@ use openvm_circuit_primitives::bitwise_op_lookup::{
13
13
BitwiseOperationLookupBus , SharedBitwiseOperationLookupChip ,
14
14
} ;
15
15
use openvm_circuit_primitives_derive:: { Chip , ChipUsageGetter } ;
16
- use openvm_ecc_transpiler:: { EccPhantom , Rv32WeierstrassOpcode } ;
17
- use openvm_instructions:: { LocalOpcode , PhantomDiscriminant , VmOpcode } ;
16
+ use openvm_ecc_transpiler:: Rv32WeierstrassOpcode ;
17
+ use openvm_instructions:: { LocalOpcode , VmOpcode } ;
18
18
use openvm_mod_circuit_builder:: ExprBuilderConfig ;
19
19
use openvm_rv32_adapters:: Rv32VecHeapAdapterChip ;
20
20
use openvm_stark_backend:: p3_field:: PrimeField32 ;
@@ -224,228 +224,11 @@ impl<F: PrimeField32> VmExtension<F> for WeierstrassExtension {
224
224
panic ! ( "Modulus too large" ) ;
225
225
}
226
226
}
227
- let non_qr_hint_sub_ex = phantom:: NonQrHintSubEx :: new ( self . supported_curves . clone ( ) ) ;
228
- builder. add_phantom_sub_executor (
229
- non_qr_hint_sub_ex. clone ( ) ,
230
- PhantomDiscriminant ( EccPhantom :: HintNonQr as u16 ) ,
231
- ) ?;
232
- builder. add_phantom_sub_executor (
233
- phantom:: DecompressHintSubEx :: new ( non_qr_hint_sub_ex) ,
234
- PhantomDiscriminant ( EccPhantom :: HintDecompress as u16 ) ,
235
- ) ?;
236
227
237
228
Ok ( inventory)
238
229
}
239
230
}
240
231
241
- pub ( crate ) mod phantom {
242
- use std:: {
243
- iter:: { once, repeat} ,
244
- ops:: Deref ,
245
- } ;
246
-
247
- use eyre:: bail;
248
- use num_bigint:: BigUint ;
249
- use num_integer:: Integer ;
250
- use num_traits:: One ;
251
- use openvm_algebra_circuit:: { find_non_qr, mod_sqrt} ;
252
- use openvm_circuit:: {
253
- arch:: { PhantomSubExecutor , Streams } ,
254
- system:: memory:: MemoryController ,
255
- } ;
256
- use openvm_instructions:: { riscv:: RV32_MEMORY_AS , PhantomDiscriminant } ;
257
- use openvm_rv32im_circuit:: adapters:: unsafe_read_rv32_register;
258
- use openvm_stark_backend:: p3_field:: PrimeField32 ;
259
-
260
- use super :: CurveConfig ;
261
-
262
- // Hint for a decompression
263
- // if possible is true, then `sqrt` is the decompressed y-coordinate
264
- // if possible is false, then `sqrt` is such that
265
- // `sqrt^2 = rhs * non_qr` where `rhs` is the rhs of the curve equation
266
- pub struct DecompressionHint < T > {
267
- pub possible : bool ,
268
- pub sqrt : T ,
269
- }
270
-
271
- #[ derive( derive_new:: new) ]
272
- pub struct DecompressHintSubEx ( NonQrHintSubEx ) ;
273
-
274
- impl Deref for DecompressHintSubEx {
275
- type Target = NonQrHintSubEx ;
276
-
277
- fn deref ( & self ) -> & NonQrHintSubEx {
278
- & self . 0
279
- }
280
- }
281
-
282
- impl < F : PrimeField32 > PhantomSubExecutor < F > for DecompressHintSubEx {
283
- fn phantom_execute (
284
- & mut self ,
285
- memory : & MemoryController < F > ,
286
- streams : & mut Streams < F > ,
287
- _: PhantomDiscriminant ,
288
- a : F ,
289
- b : F ,
290
- c_upper : u16 ,
291
- ) -> eyre:: Result < ( ) > {
292
- let c_idx = c_upper as usize ;
293
- if c_idx >= self . supported_curves . len ( ) {
294
- bail ! (
295
- "Curve index {c_idx} out of range: {} supported curves" ,
296
- self . supported_curves. len( )
297
- ) ;
298
- }
299
- let curve = & self . supported_curves [ c_idx] ;
300
- let rs1 = unsafe_read_rv32_register ( memory, a) ;
301
- let num_limbs: usize = if curve. modulus . bits ( ) . div_ceil ( 8 ) <= 32 {
302
- 32
303
- } else if curve. modulus . bits ( ) . div_ceil ( 8 ) <= 48 {
304
- 48
305
- } else {
306
- bail ! ( "Modulus too large" )
307
- } ;
308
- let mut x_limbs: Vec < u8 > = Vec :: with_capacity ( num_limbs) ;
309
- for i in 0 ..num_limbs {
310
- let limb = memory. unsafe_read_cell (
311
- F :: from_canonical_u32 ( RV32_MEMORY_AS ) ,
312
- F :: from_canonical_u32 ( rs1 + i as u32 ) ,
313
- ) ;
314
- x_limbs. push ( limb. as_canonical_u32 ( ) as u8 ) ;
315
- }
316
- let x = BigUint :: from_bytes_le ( & x_limbs) ;
317
- let rs2 = unsafe_read_rv32_register ( memory, b) ;
318
- let rec_id = memory. unsafe_read_cell (
319
- F :: from_canonical_u32 ( RV32_MEMORY_AS ) ,
320
- F :: from_canonical_u32 ( rs2) ,
321
- ) ;
322
- let hint = self . decompress_point ( x, rec_id. as_canonical_u32 ( ) & 1 == 1 , c_idx) ;
323
- let hint_bytes = once ( F :: from_bool ( hint. possible ) )
324
- . chain ( repeat ( F :: ZERO ) )
325
- . take ( 4 )
326
- . chain (
327
- hint. sqrt
328
- . to_bytes_le ( )
329
- . into_iter ( )
330
- . map ( F :: from_canonical_u8)
331
- . chain ( repeat ( F :: ZERO ) )
332
- . take ( num_limbs) ,
333
- )
334
- . collect ( ) ;
335
- streams. hint_stream = hint_bytes;
336
- Ok ( ( ) )
337
- }
338
- }
339
-
340
- impl DecompressHintSubEx {
341
- /// Given `x` in the coordinate field of the curve, and the recovery id,
342
- /// return the unique `y` such that `(x, y)` is a point on the curve and
343
- /// `y` has the same parity as the recovery id.
344
- ///
345
- /// If no such `y` exists, return the square root of `(x^3 + ax + b) * non_qr`
346
- /// where `non_qr` is a quadratic nonresidue of the field.
347
- fn decompress_point (
348
- & self ,
349
- x : BigUint ,
350
- is_y_odd : bool ,
351
- curve_idx : usize ,
352
- ) -> DecompressionHint < BigUint > {
353
- let curve = & self . supported_curves [ curve_idx] ;
354
- let alpha = ( ( & x * & x * & x) + ( & x * & curve. a ) + & curve. b ) % & curve. modulus ;
355
- match mod_sqrt ( & alpha, & curve. modulus , & self . non_qrs [ curve_idx] ) {
356
- Some ( beta) => {
357
- if is_y_odd == beta. is_odd ( ) {
358
- DecompressionHint {
359
- possible : true ,
360
- sqrt : beta,
361
- }
362
- } else {
363
- DecompressionHint {
364
- possible : true ,
365
- sqrt : & curve. modulus - & beta,
366
- }
367
- }
368
- }
369
- None => {
370
- debug_assert_eq ! (
371
- self . non_qrs[ curve_idx]
372
- . modpow( & ( ( & curve. modulus - BigUint :: one( ) ) >> 1 ) , & curve. modulus) ,
373
- & curve. modulus - BigUint :: one( )
374
- ) ;
375
- let sqrt = mod_sqrt (
376
- & ( & alpha * & self . non_qrs [ curve_idx] ) ,
377
- & curve. modulus ,
378
- & self . non_qrs [ curve_idx] ,
379
- )
380
- . unwrap ( ) ;
381
- DecompressionHint {
382
- possible : false ,
383
- sqrt,
384
- }
385
- }
386
- }
387
- }
388
- }
389
-
390
- #[ derive( Clone ) ]
391
- pub struct NonQrHintSubEx {
392
- pub supported_curves : Vec < CurveConfig > ,
393
- pub non_qrs : Vec < BigUint > ,
394
- }
395
-
396
- impl NonQrHintSubEx {
397
- pub fn new ( supported_curves : Vec < CurveConfig > ) -> Self {
398
- let non_qrs = supported_curves
399
- . iter ( )
400
- . map ( |curve| find_non_qr ( & curve. modulus ) )
401
- . collect ( ) ;
402
- Self {
403
- supported_curves,
404
- non_qrs,
405
- }
406
- }
407
- }
408
-
409
- impl < F : PrimeField32 > PhantomSubExecutor < F > for NonQrHintSubEx {
410
- fn phantom_execute (
411
- & mut self ,
412
- _: & MemoryController < F > ,
413
- streams : & mut Streams < F > ,
414
- _: PhantomDiscriminant ,
415
- _: F ,
416
- _: F ,
417
- c_upper : u16 ,
418
- ) -> eyre:: Result < ( ) > {
419
- let c_idx = c_upper as usize ;
420
- if c_idx >= self . supported_curves . len ( ) {
421
- bail ! (
422
- "Curve index {c_idx} out of range: {} supported curves" ,
423
- self . supported_curves. len( )
424
- ) ;
425
- }
426
- let curve = & self . supported_curves [ c_idx] ;
427
-
428
- let num_limbs: usize = if curve. modulus . bits ( ) . div_ceil ( 8 ) <= 32 {
429
- 32
430
- } else if curve. modulus . bits ( ) . div_ceil ( 8 ) <= 48 {
431
- 48
432
- } else {
433
- bail ! ( "Modulus too large" )
434
- } ;
435
-
436
- let hint_bytes = self . non_qrs [ c_idx]
437
- . to_bytes_le ( )
438
- . into_iter ( )
439
- . map ( F :: from_canonical_u8)
440
- . chain ( repeat ( F :: ZERO ) )
441
- . take ( num_limbs)
442
- . collect ( ) ;
443
- streams. hint_stream = hint_bytes;
444
- Ok ( ( ) )
445
- }
446
- }
447
- }
448
-
449
232
// Convenience constants for constructors
450
233
lazy_static ! {
451
234
// The constants are taken from: https://en.bitcoin.it/wiki/Secp256k1
0 commit comments