@@ -2783,8 +2783,56 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
27832783 }
27842784}
27852785
2786+ void test_secp256k1_pippenger_bucket_window_inv (void ) {
2787+ int i ;
2788+
2789+ CHECK (secp256k1_pippenger_bucket_window_inv (0 ) == 0 );
2790+ for (i = 1 ; i <= PIPPENGER_MAX_BUCKET_WINDOW ; i ++ ) {
2791+ #ifdef USE_ENDOMORPHISM
2792+ /* Bucket_window of 8 is not used with endo */
2793+ if (i == 8 ) {
2794+ continue ;
2795+ }
2796+ #endif
2797+ CHECK (secp256k1_pippenger_bucket_window (secp256k1_pippenger_bucket_window_inv (i )) == i );
2798+ if (i != PIPPENGER_MAX_BUCKET_WINDOW ) {
2799+ CHECK (secp256k1_pippenger_bucket_window (secp256k1_pippenger_bucket_window_inv (i )+ 1 ) > i );
2800+ }
2801+ }
2802+ }
2803+
2804+ /**
2805+ * Probabilistically test the function returning the maximum number of possible points
2806+ * for a given scratch space.
2807+ */
2808+ void test_ecmult_multi_pippenger_max_points (void ) {
2809+ size_t scratch_size = secp256k1_rand_int (256 );
2810+ size_t max_size = secp256k1_pippenger_scratch_size (secp256k1_pippenger_bucket_window_inv (PIPPENGER_MAX_BUCKET_WINDOW - 1 )+ 512 , 12 );
2811+ secp256k1_scratch * scratch ;
2812+ size_t n_points_supported ;
2813+ int bucket_window = 0 ;
2814+
2815+ for (; scratch_size < max_size ; scratch_size += 256 ) {
2816+ scratch = secp256k1_scratch_create (& ctx -> error_callback , 0 , scratch_size );
2817+ CHECK (scratch != NULL );
2818+ n_points_supported = secp256k1_pippenger_max_points (scratch );
2819+ if (n_points_supported == 0 ) {
2820+ secp256k1_scratch_destroy (scratch );
2821+ continue ;
2822+ }
2823+ bucket_window = secp256k1_pippenger_bucket_window (n_points_supported );
2824+ CHECK (secp256k1_scratch_resize (scratch , secp256k1_pippenger_scratch_size (n_points_supported , bucket_window ), PIPPENGER_SCRATCH_OBJECTS ));
2825+ secp256k1_scratch_destroy (scratch );
2826+ }
2827+ CHECK (bucket_window == PIPPENGER_MAX_BUCKET_WINDOW );
2828+ }
2829+
2830+ /**
2831+ * Run secp256k1_ecmult_multi_var with num points and a scratch space restricted to
2832+ * 1 <= i <= num points.
2833+ */
27862834void test_ecmult_multi_batching (void ) {
2787- static const int n_points = 3 * MAX_BATCH_SIZE ;
2835+ static const int n_points = 2 * ECMULT_PIPPENGER_THRESHOLD ;
27882836 secp256k1_scalar scG ;
27892837 secp256k1_scalar szero ;
27902838 secp256k1_scalar * sc = (secp256k1_scalar * )checked_malloc (& ctx -> error_callback , sizeof (secp256k1_scalar ) * n_points );
@@ -2795,18 +2843,21 @@ void test_ecmult_multi_batching(void) {
27952843 int i ;
27962844 secp256k1_scratch * scratch ;
27972845
2798- int test_n_points [] = { MAX_BATCH_SIZE , MAX_BATCH_SIZE + 1 , MAX_BATCH_SIZE + 2 , 2 * MAX_BATCH_SIZE , 2 * MAX_BATCH_SIZE + 1 , 3 * MAX_BATCH_SIZE };
27992846 secp256k1_gej_set_infinity (& r2 );
28002847 secp256k1_scalar_set_int (& szero , 0 );
28012848
2802- /* Get random scalars and group elements */
2849+ /* Get random scalars and group elements and compute result */
28032850 random_scalar_order (& scG );
28042851 secp256k1_ecmult (& ctx -> ecmult_ctx , & r2 , & r2 , & szero , & scG );
28052852 for (i = 0 ; i < n_points ; i ++ ) {
28062853 secp256k1_ge ptg ;
2854+ secp256k1_gej ptgj ;
28072855 random_group_element_test (& ptg );
2856+ secp256k1_gej_set_ge (& ptgj , & ptg );
28082857 pt [i ] = ptg ;
28092858 random_scalar_order (& sc [i ]);
2859+ secp256k1_ecmult (& ctx -> ecmult_ctx , & ptgj , & ptgj , & sc [i ], NULL );
2860+ secp256k1_gej_add_var (& r2 , & r2 , & ptgj , NULL );
28102861 }
28112862 data .sc = sc ;
28122863 data .pt = pt ;
@@ -2822,10 +2873,8 @@ void test_ecmult_multi_batching(void) {
28222873 CHECK (!secp256k1_ecmult_multi_var (& ctx -> ecmult_ctx , scratch , & r , & scG , ecmult_multi_callback , & data , 1 ));
28232874 secp256k1_scratch_destroy (scratch );
28242875
2825- /* Run secp256k1_ecmult_multi_var with i points and a scratch space
2826- * restricted to i points. */
2827- for (i = 1 ; i <= ECMULT_PIPPENGER_THRESHOLD + 2 ; i ++ ) {
2828- secp256k1_gej ptgj ;
2876+ secp256k1_gej_neg (& r2 , & r2 );
2877+ for (i = 1 ; i <= n_points ; i ++ ) {
28292878 if (i > ECMULT_PIPPENGER_THRESHOLD ) {
28302879 int bucket_window = secp256k1_pippenger_bucket_window (i );
28312880 size_t scratch_size = secp256k1_pippenger_scratch_size (i , bucket_window );
@@ -2834,48 +2883,29 @@ void test_ecmult_multi_batching(void) {
28342883 size_t scratch_size = secp256k1_strauss_scratch_size (i );
28352884 scratch = secp256k1_scratch_create (& ctx -> error_callback , 0 , scratch_size + STRAUSS_SCRATCH_OBJECTS * ALIGNMENT );
28362885 }
2837- CHECK (secp256k1_ecmult_multi_var (& ctx -> ecmult_ctx , scratch , & r , & scG , ecmult_multi_callback , & data , i ));
2838-
2839- /* compute running result */
2840- secp256k1_gej_set_ge (& ptgj , & pt [i - 1 ]);
2841- secp256k1_ecmult (& ctx -> ecmult_ctx , & ptgj , & ptgj , & sc [i - 1 ], NULL );
2842- secp256k1_gej_add_var (& r2 , & r2 , & ptgj , NULL );
2843-
2844- secp256k1_gej_neg (& r , & r );
2886+ CHECK (secp256k1_ecmult_multi_var (& ctx -> ecmult_ctx , scratch , & r , & scG , ecmult_multi_callback , & data , n_points ));
28452887 secp256k1_gej_add_var (& r , & r , & r2 , NULL );
28462888 CHECK (secp256k1_gej_is_infinity (& r ));
28472889 secp256k1_scratch_destroy (scratch );
28482890 }
2849-
2850- scratch = secp256k1_scratch_create (& ctx -> error_callback , 0 , secp256k1_strauss_scratch_size (n_points ) + STRAUSS_SCRATCH_OBJECTS * ALIGNMENT );
2851-
2852- for (i = 0 ; i < (int )(sizeof (test_n_points ) / sizeof (test_n_points [0 ])); i ++ ) {
2853- secp256k1_gej ptgj ;
2854- CHECK (secp256k1_ecmult_multi_var (& ctx -> ecmult_ctx , scratch , & r , & scG , ecmult_multi_callback , & data , test_n_points [i ]- 1 ));
2855- secp256k1_gej_set_infinity (& r2 );
2856- secp256k1_gej_add_var (& r2 , & r2 , & r , NULL );
2857- CHECK (secp256k1_ecmult_multi_var (& ctx -> ecmult_ctx , scratch , & r , & scG , ecmult_multi_callback , & data , test_n_points [i ]));
2858- secp256k1_gej_set_ge (& ptgj , & pt [test_n_points [i ]- 1 ]);
2859- secp256k1_ecmult (& ctx -> ecmult_ctx , & ptgj , & ptgj , & sc [test_n_points [i ]- 1 ], NULL );
2860- secp256k1_gej_add_var (& r2 , & r2 , & ptgj , NULL );
2861-
2862- secp256k1_gej_neg (& r , & r );
2863- secp256k1_gej_add_var (& r , & r , & r2 , NULL );
2864- CHECK (secp256k1_gej_is_infinity (& r ));
2865- }
2866-
2867- secp256k1_scratch_destroy (scratch );
28682891 free (sc );
28692892 free (pt );
28702893}
28712894
28722895void run_ecmult_multi_tests (void ) {
28732896 secp256k1_scratch * scratch ;
28742897
2898+ test_secp256k1_pippenger_bucket_window_inv ();
2899+ test_ecmult_multi_pippenger_max_points ();
28752900 scratch = secp256k1_scratch_create (& ctx -> error_callback , 0 , 819200 );
2876- test_ecmult_multi (scratch , & secp256k1_ecmult_multi_var );
2877- test_ecmult_multi (scratch , & secp256k1_ecmult_pippenger_batch_single );
2878- test_ecmult_multi (scratch , & secp256k1_ecmult_strauss_batch_single );
2901+ test_ecmult_multi (scratch , secp256k1_ecmult_multi_var );
2902+ test_ecmult_multi (scratch , secp256k1_ecmult_pippenger_batch_single );
2903+ test_ecmult_multi (scratch , secp256k1_ecmult_strauss_batch_single );
2904+ secp256k1_scratch_destroy (scratch );
2905+
2906+ /* Run test_ecmult_multi with space for exactly one point */
2907+ scratch = secp256k1_scratch_create (& ctx -> error_callback , 0 , secp256k1_strauss_scratch_size (1 ) + STRAUSS_SCRATCH_OBJECTS * ALIGNMENT );
2908+ test_ecmult_multi (scratch , secp256k1_ecmult_multi_var );
28792909 secp256k1_scratch_destroy (scratch );
28802910
28812911 test_ecmult_multi_batching ();
0 commit comments