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