@@ -2522,6 +2522,243 @@ void run_ecmult_const_tests(void) {
2522
2522
ecmult_const_chain_multiply ();
2523
2523
}
2524
2524
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
+
2525
2762
void test_wnaf (const secp256k1_scalar * number , int w ) {
2526
2763
secp256k1_scalar x , two , t ;
2527
2764
int wnaf [256 ];
@@ -4528,6 +4765,7 @@ int main(int argc, char **argv) {
4528
4765
run_ecmult_constants ();
4529
4766
run_ecmult_gen_blind ();
4530
4767
run_ecmult_const_tests ();
4768
+ run_ecmult_multi_tests ();
4531
4769
run_ec_combine ();
4532
4770
4533
4771
/* endomorphism tests */
0 commit comments