@@ -432,6 +432,55 @@ static int secp256k1_bulletproofs_eq65_cb(secp256k1_scalar *sc, secp256k1_ge *pt
432432 return 1 ;
433433}
434434
435+ /** Equation (67) is the sum of these 2 scalar-point multiplications, minus mu*G, plus a
436+ * somewhat complicatied inner product computation.. */
437+ typedef struct {
438+ const secp256k1_bulletproofs_generators * gens ;
439+ const unsigned char * proof ;
440+ const secp256k1_ge * ap ;
441+ const secp256k1_ge * sp ;
442+ secp256k1_scalar x ;
443+ secp256k1_scalar z ;
444+ secp256k1_scalar z_sq_2i ;
445+ secp256k1_scalar y_inv ;
446+ secp256k1_scalar y_neg_i ;
447+ } secp256k1_bulletproofs_eq67_data ;
448+
449+ static int secp256k1_bulletproofs_eq67_cb (secp256k1_scalar * sc , secp256k1_ge * pt , size_t idx , void * data ) {
450+ secp256k1_bulletproofs_eq67_data * ctx = (secp256k1_bulletproofs_eq67_data * ) data ;
451+ secp256k1_scalar lr_i ;
452+ int overflow ;
453+
454+ switch (idx ) {
455+ case 0 : /* A */
456+ * pt = * ctx -> ap ;
457+ secp256k1_scalar_set_int (sc , 1 );
458+ return 1 ;
459+ case 1 : /* xS */
460+ * pt = * ctx -> sp ;
461+ * sc = ctx -> x ;
462+ return 1 ;
463+ }
464+
465+ * pt = ctx -> gens -> gens [idx - 2 ];
466+ secp256k1_scalar_set_b32 (& lr_i , & ctx -> proof [194 + 32 * (idx - 2 )], & overflow );
467+ VERIFY_CHECK (overflow == 0 ); /* checked in main_impl.h */
468+ /* (-z - l_i) G_i */
469+ if (idx % 2 == 0 ) {
470+ secp256k1_scalar_add (sc , & ctx -> z , & lr_i );
471+ secp256k1_scalar_negate (sc , sc );
472+ /* (z + (2^i*z^2 - r)/y^i) H_i */
473+ } else {
474+ secp256k1_scalar_negate (sc , & lr_i );
475+ secp256k1_scalar_add (sc , sc , & ctx -> z_sq_2i );
476+ secp256k1_scalar_mul (sc , sc , & ctx -> y_neg_i );
477+ secp256k1_scalar_add (sc , sc , & ctx -> z );
478+
479+ secp256k1_scalar_mul (& ctx -> y_neg_i , & ctx -> y_neg_i , & ctx -> y_inv );
480+ secp256k1_scalar_add (& ctx -> z_sq_2i , & ctx -> z_sq_2i , & ctx -> z_sq_2i );
481+ }
482+ return 1 ;
483+ }
435484
436485static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl (
437486 const secp256k1_context * ctx ,
@@ -442,6 +491,8 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
442491 const uint64_t min_value ,
443492 const secp256k1_ge * commitp ,
444493 const secp256k1_ge * asset_genp ,
494+ const secp256k1_ge * ap ,
495+ const secp256k1_ge * sp ,
445496 const secp256k1_ge * t1p ,
446497 const secp256k1_ge * t2p ,
447498 const secp256k1_bulletproofs_generators * gens ,
@@ -528,8 +579,32 @@ static int secp256k1_bulletproofs_rangeproof_uncompressed_verify_impl(
528579 if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , & ctx -> ecmult_ctx , scratch , & res_j , & neg_tau_x , secp256k1_bulletproofs_eq65_cb , (void * ) & eq65 , 4 )) {
529580 return 0 ;
530581 }
531- return secp256k1_gej_is_infinity (& res_j );
582+ if (!secp256k1_gej_is_infinity (& res_j )) {
583+ return 0 ;
584+ }
532585 }
586+ /* Then (66-67) */
587+ {
588+ secp256k1_gej res_j ;
589+ secp256k1_bulletproofs_eq67_data eq67 ;
590+ eq67 .gens = gens ;
591+ eq67 .proof = proof ;
592+ eq67 .ap = ap ;
593+ eq67 .sp = sp ;
594+ eq67 .x = x ;
595+ eq67 .z = z ;
596+ secp256k1_scalar_sqr (& eq67 .z_sq_2i , & z );
597+ secp256k1_scalar_inverse_var (& eq67 .y_inv , & y );
598+ secp256k1_scalar_set_int (& eq67 .y_neg_i , 1 );
599+
600+ if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , & ctx -> ecmult_ctx , scratch , & res_j , & neg_mu , secp256k1_bulletproofs_eq67_cb , (void * ) & eq67 , 2 + 2 * n_bits )) {
601+ return 0 ;
602+ }
603+ if (!secp256k1_gej_is_infinity (& res_j )) {
604+ return 0 ;
605+ }
606+ }
607+ return 1 ;
533608}
534609
535610#endif
0 commit comments