@@ -439,6 +439,55 @@ static int secp256k1_bulletproofs_eq65_cb(secp256k1_scalar *sc, secp256k1_ge *pt
439
439
return 1 ;
440
440
}
441
441
442
+ /** Equation (67) is the sum of these 2 scalar-point multiplications, minus mu*G, plus a
443
+ * somewhat complicatied inner product computation.. */
444
+ typedef struct {
445
+ const secp256k1_bulletproofs_generators * gens ;
446
+ const unsigned char * proof ;
447
+ const secp256k1_ge * ap ;
448
+ const secp256k1_ge * sp ;
449
+ secp256k1_scalar x ;
450
+ secp256k1_scalar z ;
451
+ secp256k1_scalar z_sq_2i ;
452
+ secp256k1_scalar y_inv ;
453
+ secp256k1_scalar y_neg_i ;
454
+ } secp256k1_bulletproofs_eq67_data ;
455
+
456
+ static int secp256k1_bulletproofs_eq67_cb (secp256k1_scalar * sc , secp256k1_ge * pt , size_t idx , void * data ) {
457
+ secp256k1_bulletproofs_eq67_data * ctx = (secp256k1_bulletproofs_eq67_data * ) data ;
458
+ secp256k1_scalar lr_i ;
459
+ int overflow ;
460
+
461
+ switch (idx ) {
462
+ case 0 : /* A */
463
+ * pt = * ctx -> ap ;
464
+ secp256k1_scalar_set_int (sc , 1 );
465
+ return 1 ;
466
+ case 1 : /* xS */
467
+ * pt = * ctx -> sp ;
468
+ * sc = ctx -> x ;
469
+ return 1 ;
470
+ }
471
+
472
+ * pt = ctx -> gens -> gens [idx - 2 ];
473
+ secp256k1_scalar_set_b32 (& lr_i , & ctx -> proof [194 + 32 * (idx - 2 )], & overflow );
474
+ VERIFY_CHECK (overflow == 0 ); /* checked in main_impl.h */
475
+ /* (-z - l_i) G_i */
476
+ if (idx % 2 == 0 ) {
477
+ secp256k1_scalar_add (sc , & ctx -> z , & lr_i );
478
+ secp256k1_scalar_negate (sc , sc );
479
+ /* (z + (2^i*z^2 - r)/y^i) H_i */
480
+ } else {
481
+ secp256k1_scalar_negate (sc , & lr_i );
482
+ secp256k1_scalar_add (sc , sc , & ctx -> z_sq_2i );
483
+ secp256k1_scalar_mul (sc , sc , & ctx -> y_neg_i );
484
+ secp256k1_scalar_add (sc , sc , & ctx -> z );
485
+
486
+ secp256k1_scalar_mul (& ctx -> y_neg_i , & ctx -> y_neg_i , & ctx -> y_inv );
487
+ secp256k1_scalar_add (& ctx -> z_sq_2i , & ctx -> z_sq_2i , & ctx -> z_sq_2i );
488
+ }
489
+ return 1 ;
490
+ }
442
491
443
492
static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl (
444
493
const secp256k1_context * ctx ,
@@ -449,6 +498,8 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
449
498
const uint64_t min_value ,
450
499
const secp256k1_ge * commitp ,
451
500
const secp256k1_ge * asset_genp ,
501
+ const secp256k1_ge * ap ,
502
+ const secp256k1_ge * sp ,
452
503
const secp256k1_ge * t1p ,
453
504
const secp256k1_ge * t2p ,
454
505
const secp256k1_bulletproofs_generators * gens ,
@@ -534,8 +585,32 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
534
585
if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , scratch , & res_j , & neg_tau_x , secp256k1_bulletproofs_eq65_cb , (void * ) & eq65 , 4 )) {
535
586
return 0 ;
536
587
}
537
- return secp256k1_gej_is_infinity (& res_j );
588
+ if (!secp256k1_gej_is_infinity (& res_j )) {
589
+ return 0 ;
590
+ }
538
591
}
592
+ /* Then (66-67) */
593
+ {
594
+ secp256k1_gej res_j ;
595
+ secp256k1_bulletproofs_eq67_data eq67 ;
596
+ eq67 .gens = gens ;
597
+ eq67 .proof = proof ;
598
+ eq67 .ap = ap ;
599
+ eq67 .sp = sp ;
600
+ eq67 .x = x ;
601
+ eq67 .z = z ;
602
+ secp256k1_scalar_sqr (& eq67 .z_sq_2i , & z );
603
+ secp256k1_scalar_inverse_var (& eq67 .y_inv , & y );
604
+ secp256k1_scalar_set_int (& eq67 .y_neg_i , 1 );
605
+
606
+ if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , scratch , & res_j , & neg_mu , secp256k1_bulletproofs_eq67_cb , (void * ) & eq67 , 2 + 2 * n_bits )) {
607
+ return 0 ;
608
+ }
609
+ if (!secp256k1_gej_is_infinity (& res_j )) {
610
+ return 0 ;
611
+ }
612
+ }
613
+ return 1 ;
539
614
}
540
615
541
616
#endif
0 commit comments