@@ -386,4 +386,202 @@ int secp256k1_bulletproofs_pp_rangeproof_norm_product_prove(
386
386
* proof_len = start_idx + 64 ;
387
387
return 1 ;
388
388
}
389
+
390
+ typedef struct ec_mult_verify_cb_data1 {
391
+ const unsigned char * proof ;
392
+ const secp256k1_ge * commit ;
393
+ const secp256k1_scalar * challenges ;
394
+ } ec_mult_verify_cb_data1 ;
395
+
396
+ static int ec_mult_verify_cb1 (secp256k1_scalar * sc , secp256k1_ge * pt , size_t idx , void * cbdata ) {
397
+ ec_mult_verify_cb_data1 * data = (ec_mult_verify_cb_data1 * ) cbdata ;
398
+ if (idx == 0 ) {
399
+ * pt = * data -> commit ;
400
+ secp256k1_scalar_set_int (sc , 1 );
401
+ return 1 ;
402
+ }
403
+ idx -= 1 ;
404
+ if (idx % 2 == 0 ) {
405
+ unsigned char pk_buf [33 ];
406
+ idx /= 2 ;
407
+ * sc = data -> challenges [idx ];
408
+ pk_buf [0 ] = 2 | (data -> proof [65 * idx ] >> 1 );
409
+ memcpy (& pk_buf [1 ], & data -> proof [65 * idx + 1 ], 32 );
410
+ if (!secp256k1_eckey_pubkey_parse (pt , pk_buf , sizeof (pk_buf ))) {
411
+ return 0 ;
412
+ }
413
+ } else {
414
+ unsigned char pk_buf [33 ];
415
+ secp256k1_scalar neg_one ;
416
+ idx /= 2 ;
417
+ secp256k1_scalar_set_int (& neg_one , 1 );
418
+ secp256k1_scalar_negate (& neg_one , & neg_one );
419
+ * sc = data -> challenges [idx ];
420
+ secp256k1_scalar_sqr (sc , sc );
421
+ secp256k1_scalar_add (sc , sc , & neg_one ); /* Ignore overflow */
422
+ pk_buf [0 ] = 2 | data -> proof [65 * idx ];
423
+ memcpy (& pk_buf [1 ], & data -> proof [65 * idx + 33 ], 32 );
424
+ if (!secp256k1_eckey_pubkey_parse (pt , pk_buf , sizeof (pk_buf ))) {
425
+ return 0 ;
426
+ }
427
+ }
428
+ return 1 ;
429
+ }
430
+
431
+ typedef struct ec_mult_verify_cb_data2 {
432
+ const secp256k1_scalar * s_g ;
433
+ const secp256k1_scalar * s_h ;
434
+ const secp256k1_ge * g_vec ;
435
+ size_t g_vec_len ;
436
+ } ec_mult_verify_cb_data2 ;
437
+
438
+ static int ec_mult_verify_cb2 (secp256k1_scalar * sc , secp256k1_ge * pt , size_t idx , void * cbdata ) {
439
+ ec_mult_verify_cb_data2 * data = (ec_mult_verify_cb_data2 * ) cbdata ;
440
+ if (idx < data -> g_vec_len ) {
441
+ * sc = data -> s_g [idx ];
442
+ } else {
443
+ * sc = data -> s_h [idx - data -> g_vec_len ];
444
+ }
445
+ * pt = data -> g_vec [idx ];
446
+ return 1 ;
447
+ }
448
+
449
+ /* Verify the proof */
450
+ int secp256k1_bulletproofs_pp_rangeproof_norm_product_verify (
451
+ const secp256k1_context * ctx ,
452
+ secp256k1_scratch_space * scratch ,
453
+ unsigned char * proof ,
454
+ size_t proof_len ,
455
+ unsigned char * transcript_hash32 ,
456
+ const secp256k1_scalar * r_ch ,
457
+ secp256k1_bulletproofs_generators * g_vec ,
458
+ size_t g_len ,
459
+ secp256k1_scalar * c_vec ,
460
+ size_t c_vec_len ,
461
+ const secp256k1_ge * commit
462
+ ) {
463
+ secp256k1_scalar q , r , v , n , l , r_inv , h_c ;
464
+ secp256k1_scalar * es , * s_g , * s_h , * r_inv_pows ;
465
+ secp256k1_gej res1 , res2 ;
466
+ size_t i = 0 , scratch_checkpoint ;
467
+ int overflow ;
468
+ secp256k1_sha256 sha256 ;
469
+ unsigned char ser_commit [33 ];
470
+ size_t log_n = secp256k1_bulletproofs_pp_log2 (g_len ), log_m = secp256k1_bulletproofs_pp_log2 (c_vec_len );
471
+ size_t n_rounds = log_n > log_m ? log_n : log_m ;
472
+ size_t h_len = c_vec_len ;
473
+ secp256k1_ge comm = * commit ;
474
+
475
+ if (g_vec -> n != (h_len + g_len ) || (proof_len != 65 * n_rounds + 64 )) {
476
+ return 0 ;
477
+ }
478
+
479
+ if (!secp256k1_check_power_of_two (g_len ) || !secp256k1_check_power_of_two (h_len )) {
480
+ return 0 ;
481
+ }
482
+
483
+ secp256k1_scalar_set_b32 (& n , & proof [n_rounds * 65 ], & overflow ); /* n */
484
+ if (overflow ) return 0 ;
485
+ secp256k1_scalar_set_b32 (& l , & proof [n_rounds * 65 + 32 ], & overflow ); /* l */
486
+ if (overflow ) return 0 ;
487
+ if (secp256k1_scalar_is_zero (r_ch )) return 0 ;
488
+
489
+ /* Compute powers of q_inv. Later used in g_factor computations*/
490
+ r = * r_ch ;
491
+ secp256k1_scalar_inverse_var (& r_inv , & r );
492
+ scratch_checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
493
+
494
+ r_inv_pows = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , log_n * sizeof (secp256k1_scalar ));
495
+ secp256k1_bulletproofs_powers_of_r (r_inv_pows , & r_inv , log_n );
496
+
497
+ secp256k1_sha256_initialize (& sha256 );
498
+ secp256k1_sha256_write (& sha256 , transcript_hash32 , 32 );
499
+ secp256k1_fe_normalize_var (& comm .x );
500
+ secp256k1_fe_normalize_var (& comm .y );
501
+ ser_commit [0 ] = 0x02 | secp256k1_fe_is_odd (& comm .y );
502
+ secp256k1_fe_get_b32 (& ser_commit [1 ], & comm .x );
503
+ secp256k1_sha256_write (& sha256 , ser_commit , 33 );
504
+ secp256k1_sha256_finalize (& sha256 , transcript_hash32 );
505
+
506
+ for (i = 0 ; i < log_n ; i ++ ) {
507
+ secp256k1_scalar_sqr (& r , & r );
508
+ }
509
+
510
+ /* Collect the challenges in a new vector */
511
+ es = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , n_rounds * sizeof (secp256k1_scalar ));
512
+ s_g = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_len * sizeof (secp256k1_scalar ));
513
+ s_h = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , h_len * sizeof (secp256k1_scalar ));
514
+ if (es == NULL || s_g == NULL || s_h == NULL ) {
515
+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , scratch_checkpoint );
516
+ return 0 ;
517
+ }
518
+
519
+ for (i = 0 ; i < n_rounds ; i ++ ) {
520
+ secp256k1_scalar e ;
521
+ secp256k1_sha256_initialize (& sha256 );
522
+ secp256k1_sha256_write (& sha256 , transcript_hash32 , 32 );
523
+ secp256k1_sha256_write (& sha256 , & proof [i * 65 ], 65 );
524
+ secp256k1_sha256_finalize (& sha256 , transcript_hash32 );
525
+ /* Ignore overflow, output of an hash function will fall in curve order with high probability*/
526
+ secp256k1_scalar_set_b32 (& e , transcript_hash32 , & overflow );
527
+ es [i ] = e ;
528
+ }
529
+ /* s_g[0] = n * r^(n - 1) = n * (r)^n * r_inv = n * q * r_inv */
530
+ secp256k1_scalar_mul (& s_g [0 ], & n , & r );
531
+ secp256k1_scalar_mul (& s_g [0 ], & s_g [0 ], & r_inv );
532
+ for (i = 1 ; i < g_len ; i ++ ) {
533
+ size_t log_i = secp256k1_bulletproofs_pp_log2 (i );
534
+ size_t nearest_pow_of_two = (size_t )1 << log_i ;
535
+ secp256k1_scalar_mul (& s_g [i ], & s_g [i - nearest_pow_of_two ], & es [log_i ]);
536
+ secp256k1_scalar_mul (& s_g [i ], & s_g [i ], & r_inv_pows [log_i ]);
537
+ }
538
+ s_h [0 ] = l ;
539
+ secp256k1_scalar_set_int (& h_c , 0 );
540
+ for (i = 1 ; i < h_len ; i ++ ) {
541
+ size_t log_i = secp256k1_bulletproofs_pp_log2 (i );
542
+ size_t nearest_pow_of_two = (size_t )1 << log_i ;
543
+ secp256k1_scalar_mul (& s_h [i ], & s_h [i - nearest_pow_of_two ], & es [log_i ]);
544
+ }
545
+ secp256k1_scalar_inner_product (& h_c , c_vec , 0 /* a_offset */ , s_h , 0 /* b_offset */ , 1 /* step */ , h_len );
546
+ /* Compute v = n*n*q + l*h_c*/
547
+ secp256k1_scalar_sqr (& q , & r );
548
+ secp256k1_scalar_mul (& v , & n , & n );
549
+ secp256k1_scalar_mul (& v , & v , & q );
550
+ secp256k1_scalar_add (& v , & v , & h_c );
551
+
552
+ {
553
+ ec_mult_verify_cb_data1 data ;
554
+ secp256k1_gej temp1 , temp2 ;
555
+ secp256k1_scalar one ;
556
+ data .proof = proof ;
557
+ data .commit = commit ;
558
+ data .challenges = es ;
559
+
560
+ secp256k1_gej_set_ge (& temp2 , commit );
561
+ secp256k1_scalar_set_int (& one , 1 );
562
+ secp256k1_ecmult (& temp1 , & temp2 , & one , NULL );
563
+
564
+ if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , scratch , & res1 , NULL , ec_mult_verify_cb1 , & data , 2 * n_rounds + 1 )) {
565
+ return 0 ;
566
+ }
567
+ }
568
+ {
569
+ ec_mult_verify_cb_data2 data ;
570
+ data .g_vec = g_vec -> gens ;
571
+ data .g_vec_len = g_len ;
572
+ data .s_g = s_g ;
573
+ data .s_h = s_h ;
574
+
575
+ if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , scratch , & res2 , & v , ec_mult_verify_cb2 , & data , g_len + h_len )) {
576
+ return 0 ;
577
+ }
578
+ }
579
+
580
+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , scratch_checkpoint );
581
+
582
+ /* res1 and res2 should be equal. Could not find a simpler way to compare them */
583
+ secp256k1_gej_neg (& res1 , & res1 );
584
+ secp256k1_gej_add_var (& res1 , & res1 , & res2 , NULL );
585
+ return secp256k1_gej_is_infinity (& res1 );
586
+ }
389
587
#endif
0 commit comments