@@ -2522,6 +2522,243 @@ void run_ecmult_const_tests(void) {
25222522 ecmult_const_chain_multiply ();
25232523}
25242524
2525+ typedef struct {
2526+ secp256k1_scalar * sc ;
2527+ secp256k1_ge * pt ;
2528+ } ecmult_multi_data ;
2529+
2530+ static int ecmult_multi_callback (secp256k1_scalar * sc , secp256k1_ge * pt , size_t idx , void * cbdata ) {
2531+ ecmult_multi_data * data = (ecmult_multi_data * ) cbdata ;
2532+ * sc = data -> sc [idx ];
2533+ * pt = data -> pt [idx ];
2534+ return 1 ;
2535+ }
2536+
2537+ void run_ecmult_multi_tests (void ) {
2538+ int ncount ;
2539+ secp256k1_scalar szero ;
2540+ secp256k1_scalar sc [32 ];
2541+ secp256k1_ge pt [32 ];
2542+ secp256k1_gej r ;
2543+ secp256k1_gej r2 ;
2544+ ecmult_multi_data data ;
2545+ secp256k1_scratch * scratch = secp256k1_scratch_create (& ctx -> error_callback , 1024 , 8192 );
2546+
2547+ data .sc = sc ;
2548+ data .pt = pt ;
2549+
2550+ secp256k1_scalar_set_int (& szero , 0 );
2551+
2552+ /* Check 1- and 2-point multiplies against ecmult */
2553+ for (ncount = 0 ; ncount < count ; ncount ++ ) {
2554+ secp256k1_ge ptg ;
2555+ secp256k1_gej ptgj ;
2556+ random_scalar_order (& sc [0 ]);
2557+ random_scalar_order (& sc [1 ]);
2558+
2559+ random_group_element_test (& ptg );
2560+ secp256k1_gej_set_ge (& ptgj , & ptg );
2561+ pt [0 ] = ptg ;
2562+ pt [1 ] = secp256k1_ge_const_g ;
2563+
2564+ /* 1-point */
2565+ secp256k1_ecmult (& ctx -> ecmult_ctx , & r2 , & ptgj , & sc [0 ], & szero );
2566+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 1 ));
2567+ secp256k1_gej_neg (& r2 , & r2 );
2568+ secp256k1_gej_add_var (& r , & r , & r2 , NULL );
2569+ CHECK (secp256k1_gej_is_infinity (& r ));
2570+
2571+ /* 2-point */
2572+ secp256k1_ecmult (& ctx -> ecmult_ctx , & r2 , & ptgj , & sc [0 ], & sc [1 ]);
2573+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 2 ));
2574+ secp256k1_gej_neg (& r2 , & r2 );
2575+ secp256k1_gej_add_var (& r , & r , & r2 , NULL );
2576+ CHECK (secp256k1_gej_is_infinity (& r ));
2577+
2578+ /* 2-point with G scalar */
2579+ secp256k1_ecmult (& ctx -> ecmult_ctx , & r2 , & ptgj , & sc [0 ], & sc [1 ]);
2580+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & sc [1 ], ecmult_multi_callback , & data , 1 ));
2581+ secp256k1_gej_neg (& r2 , & r2 );
2582+ secp256k1_gej_add_var (& r , & r , & r2 , NULL );
2583+ CHECK (secp256k1_gej_is_infinity (& r ));
2584+ }
2585+
2586+ /* Check infinite outputs of various forms */
2587+ for (ncount = 0 ; ncount < count ; ncount ++ ) {
2588+ secp256k1_ge ptg ;
2589+ size_t i , j ;
2590+ size_t sizes [] = { 2 , 10 , 32 };
2591+
2592+ for (j = 0 ; j < 3 ; j ++ ) {
2593+ for (i = 0 ; i < 32 ; i ++ ) {
2594+ random_scalar_order (& sc [i ]);
2595+ secp256k1_ge_set_infinity (& pt [i ]);
2596+ }
2597+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , sizes [j ]));
2598+ CHECK (secp256k1_gej_is_infinity (& r ));
2599+ }
2600+
2601+ for (j = 0 ; j < 3 ; j ++ ) {
2602+ for (i = 0 ; i < 32 ; i ++ ) {
2603+ random_group_element_test (& ptg );
2604+ pt [i ] = ptg ;
2605+ secp256k1_scalar_set_int (& sc [i ], 0 );
2606+ }
2607+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , sizes [j ]));
2608+ CHECK (secp256k1_gej_is_infinity (& r ));
2609+ }
2610+
2611+ for (j = 0 ; j < 3 ; j ++ ) {
2612+ random_group_element_test (& ptg );
2613+ for (i = 0 ; i < 16 ; i ++ ) {
2614+ random_scalar_order (& sc [2 * i ]);
2615+ secp256k1_scalar_negate (& sc [2 * i + 1 ], & sc [2 * i ]);
2616+ pt [2 * i ] = ptg ;
2617+ pt [2 * i + 1 ] = ptg ;
2618+ }
2619+
2620+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , sizes [j ]));
2621+ CHECK (secp256k1_gej_is_infinity (& r ));
2622+
2623+ random_scalar_order (& sc [0 ]);
2624+ for (i = 0 ; i < 16 ; i ++ ) {
2625+ random_group_element_test (& ptg );
2626+
2627+ sc [2 * i ] = sc [0 ];
2628+ sc [2 * i + 1 ] = sc [0 ];
2629+ pt [2 * i ] = ptg ;
2630+ secp256k1_ge_neg (& pt [2 * i + 1 ], & pt [2 * i ]);
2631+ }
2632+
2633+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , sizes [j ]));
2634+ CHECK (secp256k1_gej_is_infinity (& r ));
2635+ }
2636+
2637+ random_group_element_test (& ptg );
2638+ secp256k1_scalar_set_int (& sc [0 ], 0 );
2639+ pt [0 ] = ptg ;
2640+ for (i = 1 ; i < 32 ; i ++ ) {
2641+ pt [i ] = ptg ;
2642+
2643+ random_scalar_order (& sc [i ]);
2644+ secp256k1_scalar_add (& sc [0 ], & sc [0 ], & sc [i ]);
2645+ secp256k1_scalar_negate (& sc [i ], & sc [i ]);
2646+ }
2647+
2648+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 32 ));
2649+ CHECK (secp256k1_gej_is_infinity (& r ));
2650+ }
2651+
2652+ /* Check random points, constant scalar */
2653+ for (ncount = 0 ; ncount < count ; ncount ++ ) {
2654+ size_t i ;
2655+ secp256k1_gej_set_infinity (& r );
2656+
2657+ random_scalar_order (& sc [0 ]);
2658+ for (i = 0 ; i < 20 ; i ++ ) {
2659+ secp256k1_ge ptg ;
2660+ sc [i ] = sc [0 ];
2661+ random_group_element_test (& ptg );
2662+ pt [i ] = ptg ;
2663+ secp256k1_gej_add_ge_var (& r , & r , & pt [i ], NULL );
2664+ }
2665+
2666+ secp256k1_ecmult (& ctx -> ecmult_ctx , & r2 , & r , & sc [0 ], & szero );
2667+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 20 ));
2668+ secp256k1_gej_neg (& r2 , & r2 );
2669+ secp256k1_gej_add_var (& r , & r , & r2 , NULL );
2670+ CHECK (secp256k1_gej_is_infinity (& r ));
2671+ }
2672+
2673+ /* Check random scalars, constant point */
2674+ for (ncount = 0 ; ncount < count ; ncount ++ ) {
2675+ size_t i ;
2676+ secp256k1_ge ptg ;
2677+ secp256k1_gej p0j ;
2678+ secp256k1_scalar rs ;
2679+ secp256k1_scalar_set_int (& rs , 0 );
2680+
2681+ random_group_element_test (& ptg );
2682+ for (i = 0 ; i < 20 ; i ++ ) {
2683+ random_scalar_order (& sc [i ]);
2684+ pt [i ] = ptg ;
2685+ secp256k1_scalar_add (& rs , & rs , & sc [i ]);
2686+ }
2687+
2688+ secp256k1_gej_set_ge (& p0j , & pt [0 ]);
2689+ secp256k1_ecmult (& ctx -> ecmult_ctx , & r2 , & p0j , & rs , & szero );
2690+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 20 ));
2691+ secp256k1_gej_neg (& r2 , & r2 );
2692+ secp256k1_gej_add_var (& r , & r , & r2 , NULL );
2693+ CHECK (secp256k1_gej_is_infinity (& r ));
2694+ }
2695+
2696+ /* Sanity check that zero scalars don't cause problems */
2697+ secp256k1_scalar_clear (& sc [0 ]);
2698+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 20 ));
2699+ secp256k1_scalar_clear (& sc [1 ]);
2700+ secp256k1_scalar_clear (& sc [2 ]);
2701+ secp256k1_scalar_clear (& sc [3 ]);
2702+ secp256k1_scalar_clear (& sc [4 ]);
2703+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 6 ));
2704+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & r , & szero , ecmult_multi_callback , & data , 5 ));
2705+ CHECK (secp256k1_gej_is_infinity (& r ));
2706+
2707+ /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
2708+ {
2709+ const size_t TOP = 8 ;
2710+ size_t s0i , s1i ;
2711+ size_t t0i , t1i ;
2712+ secp256k1_ge ptg ;
2713+ secp256k1_gej ptgj ;
2714+
2715+ random_group_element_test (& ptg );
2716+ secp256k1_gej_set_ge (& ptgj , & ptg );
2717+
2718+ for (t0i = 0 ; t0i < TOP ; t0i ++ ) {
2719+ for (t1i = 0 ; t1i < TOP ; t1i ++ ) {
2720+ secp256k1_gej t0p , t1p ;
2721+ secp256k1_scalar t0 , t1 ;
2722+
2723+ secp256k1_scalar_set_int (& t0 , (t0i + 1 ) / 2 );
2724+ secp256k1_scalar_cond_negate (& t0 , t0i & 1 );
2725+ secp256k1_scalar_set_int (& t1 , (t1i + 1 ) / 2 );
2726+ secp256k1_scalar_cond_negate (& t1 , t1i & 1 );
2727+
2728+ secp256k1_ecmult (& ctx -> ecmult_ctx , & t0p , & ptgj , & t0 , & szero );
2729+ secp256k1_ecmult (& ctx -> ecmult_ctx , & t1p , & ptgj , & t1 , & szero );
2730+
2731+ for (s0i = 0 ; s0i < TOP ; s0i ++ ) {
2732+ for (s1i = 0 ; s1i < TOP ; s1i ++ ) {
2733+ secp256k1_scalar tmp1 , tmp2 ;
2734+ secp256k1_gej expected , actual ;
2735+
2736+ secp256k1_ge_set_gej (& pt [0 ], & t0p );
2737+ secp256k1_ge_set_gej (& pt [1 ], & t1p );
2738+
2739+ secp256k1_scalar_set_int (& sc [0 ], (s0i + 1 ) / 2 );
2740+ secp256k1_scalar_cond_negate (& sc [0 ], s0i & 1 );
2741+ secp256k1_scalar_set_int (& sc [1 ], (s1i + 1 ) / 2 );
2742+ secp256k1_scalar_cond_negate (& sc [1 ], s1i & 1 );
2743+
2744+ secp256k1_scalar_mul (& tmp1 , & t0 , & sc [0 ]);
2745+ secp256k1_scalar_mul (& tmp2 , & t1 , & sc [1 ]);
2746+ secp256k1_scalar_add (& tmp1 , & tmp1 , & tmp2 );
2747+
2748+ secp256k1_ecmult (& ctx -> ecmult_ctx , & expected , & ptgj , & tmp1 , & szero );
2749+ CHECK (secp256k1_ecmult_multi (& ctx -> ecmult_ctx , scratch , & actual , & szero , ecmult_multi_callback , & data , 2 ));
2750+ secp256k1_gej_neg (& expected , & expected );
2751+ secp256k1_gej_add_var (& actual , & actual , & expected , NULL );
2752+ CHECK (secp256k1_gej_is_infinity (& actual ));
2753+ }
2754+ }
2755+ }
2756+ }
2757+ }
2758+
2759+ secp256k1_scratch_destroy (scratch );
2760+ }
2761+
25252762void test_wnaf (const secp256k1_scalar * number , int w ) {
25262763 secp256k1_scalar x , two , t ;
25272764 int wnaf [256 ];
@@ -4528,6 +4765,7 @@ int main(int argc, char **argv) {
45284765 run_ecmult_constants ();
45294766 run_ecmult_gen_blind ();
45304767 run_ecmult_const_tests ();
4768+ run_ecmult_multi_tests ();
45314769 run_ec_combine ();
45324770
45334771 /* endomorphism tests */
0 commit comments