7 #ifndef SECP256K1_ECMULT_IMPL_H
8 #define SECP256K1_ECMULT_IMPL_H
17 #if defined(EXHAUSTIVE_TEST_ORDER)
21 # if EXHAUSTIVE_TEST_ORDER > 128
24 # elif EXHAUSTIVE_TEST_ORDER > 8
36 #ifdef USE_ENDOMORPHISM
45 #ifdef USE_ENDOMORPHISM
50 #define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
51 #define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
54 #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
57 #define PIPPENGER_SCRATCH_OBJECTS 6
58 #define STRAUSS_SCRATCH_OBJECTS 6
60 #define PIPPENGER_MAX_BUCKET_WINDOW 12
63 #ifdef USE_ENDOMORPHISM
64 #define ECMULT_PIPPENGER_THRESHOLD 88
66 #define ECMULT_PIPPENGER_THRESHOLD 160
69 #ifdef USE_ENDOMORPHISM
70 #define ECMULT_MAX_POINTS_PER_BATCH 5000000
72 #define ECMULT_MAX_POINTS_PER_BATCH 10000000
87 secp256k1_gej_double_var(&d, a, NULL);
97 secp256k1_ge_set_gej_zinv(&a_ge, a, &d.
z);
104 for (i = 1; i < n; i++) {
105 secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]);
112 secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.
z);
147 secp256k1_ecmult_odd_multiples_table(n, prej, zr, a);
149 secp256k1_ge_set_table_gej_var(prea, prej, zr, n);
151 for (i = 0; i < n; i++) {
152 secp256k1_ge_to_storage(&pre[i], &prea[i]);
162 #define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
163 VERIFY_CHECK(((n) & 1) == 1); \
164 VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
165 VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
167 *(r) = (pre)[((n)-1)/2]; \
169 secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \
173 #define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \
174 VERIFY_CHECK(((n) & 1) == 1); \
175 VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
176 VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
178 secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
180 secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
181 secp256k1_ge_neg((r), (r)); \
187 #ifdef USE_ENDOMORPHISM
188 ctx->pre_g_128 = NULL;
195 if (ctx->
pre_g != NULL) {
200 secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
207 #ifdef USE_ENDOMORPHISM
216 for (i = 0; i < 128; i++) {
217 secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
226 if (src->
pre_g == NULL) {
233 #ifdef USE_ENDOMORPHISM
234 if (src->pre_g_128 == NULL) {
235 dst->pre_g_128 = NULL;
239 memcpy(dst->pre_g_128, src->pre_g_128, size);
245 return ctx->
pre_g != NULL;
250 #ifdef USE_ENDOMORPHISM
251 free(ctx->pre_g_128);
253 secp256k1_ecmult_context_init(ctx);
263 static int secp256k1_ecmult_wnaf(
int *wnaf,
int len,
const secp256k1_scalar *a,
int w) {
265 int last_set_bit = -1;
275 memset(wnaf, 0, len *
sizeof(wnaf[0]));
277 if (secp256k1_scalar_get_bits(&s, 255, 1)) {
278 secp256k1_scalar_negate(&s, &s);
285 if (secp256k1_scalar_get_bits(&s, bit, 1) == (
unsigned int)carry) {
291 if (now > len - bit) {
295 word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry;
297 carry = (word >> (w-1)) & 1;
300 wnaf[bit] = sign * word;
308 CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
311 return last_set_bit + 1;
315 #ifdef USE_ENDOMORPHISM
318 int wnaf_na_lam[130];
332 #ifdef USE_ENDOMORPHISM
341 #ifdef USE_ENDOMORPHISM
346 int wnaf_ng_128[129];
357 for (np = 0; np < num; ++np) {
358 if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) {
362 #ifdef USE_ENDOMORPHISM
364 secp256k1_scalar_split_lambda(&state->
ps[no].na_1, &state->
ps[no].na_lam, &na[np]);
367 state->
ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->
ps[no].wnaf_na_1, 130, &state->
ps[no].na_1,
WINDOW_A);
368 state->
ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->
ps[no].wnaf_na_lam, 130, &state->
ps[no].na_lam,
WINDOW_A);
371 if (state->
ps[no].bits_na_1 > bits) {
372 bits = state->
ps[no].bits_na_1;
374 if (state->
ps[no].bits_na_lam > bits) {
375 bits = state->
ps[no].bits_na_lam;
400 for (np = 1; np < no; ++np) {
412 secp256k1_fe_set_int(&Z, 1);
415 #ifdef USE_ENDOMORPHISM
416 for (np = 0; np < no; ++np) {
424 secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
427 bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1,
WINDOW_G);
428 bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128,
WINDOW_G);
429 if (bits_ng_1 > bits) {
432 if (bits_ng_128 > bits) {
438 bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng,
WINDOW_G);
439 if (bits_ng > bits) {
445 secp256k1_gej_set_infinity(r);
447 for (i = bits - 1; i >= 0; i--) {
449 secp256k1_gej_double_var(r, r, NULL);
450 #ifdef USE_ENDOMORPHISM
451 for (np = 0; np < no; ++np) {
452 if (i < state->ps[np].bits_na_1 && (n = state->
ps[np].wnaf_na_1[i])) {
454 secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
456 if (i < state->ps[np].bits_na_lam && (n = state->
ps[np].wnaf_na_lam[i])) {
458 secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
461 if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
463 secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
465 if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
467 secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
470 for (np = 0; np < no; ++np) {
473 secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
476 if (i < bits_ng && (n = wnaf_ng[i])) {
478 secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
484 secp256k1_fe_mul(&r->
z, &r->
z, &Z);
493 #ifdef USE_ENDOMORPHISM
501 #ifdef USE_ENDOMORPHISM
502 state.pre_a_lam = pre_a_lam;
505 secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
508 static size_t secp256k1_strauss_scratch_size(
size_t n_points) {
509 #ifdef USE_ENDOMORPHISM
514 return n_points*point_size;
523 secp256k1_gej_set_infinity(r);
524 if (inp_g_sc == NULL && n_points == 0) {
528 if (!secp256k1_scratch_allocate_frame(scratch, secp256k1_strauss_scratch_size(n_points),
STRAUSS_SCRATCH_OBJECTS)) {
535 #ifdef USE_ENDOMORPHISM
543 for (i = 0; i < n_points; i++) {
545 if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) {
546 secp256k1_scratch_deallocate_frame(scratch);
549 secp256k1_gej_set_ge(&points[i], &point);
551 secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc);
552 secp256k1_scratch_deallocate_frame(scratch);
558 return secp256k1_ecmult_strauss_batch(actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
572 static int secp256k1_wnaf_fixed(
int *wnaf,
const secp256k1_scalar *s,
int w) {
579 if (secp256k1_scalar_is_zero(s)) {
580 for (pos = 0; pos <
WNAF_SIZE(w); pos++) {
586 if (secp256k1_scalar_is_even(s)) {
590 wnaf[0] = secp256k1_scalar_get_bits_var(work, 0, w) + skew;
597 for (pos =
WNAF_SIZE(w) - 1; pos > 0; pos--) {
598 int val = secp256k1_scalar_get_bits_var(work, pos * w, pos ==
WNAF_SIZE(w)-1 ? last_w : w);
607 while (pos <= max_pos) {
608 int val = secp256k1_scalar_get_bits_var(work, pos * w, pos ==
WNAF_SIZE(w)-1 ? last_w : w);
609 if ((val & 1) == 0) {
610 wnaf[pos - 1] -= (1 << w);
611 wnaf[pos] = (val + 1);
620 if (pos >= 2 && ((wnaf[pos - 1] == 1 && wnaf[pos - 2] < 0) || (wnaf[pos - 1] == -1 && wnaf[pos - 2] > 0))) {
621 if (wnaf[pos - 1] == 1) {
622 wnaf[pos - 2] += 1 << w;
624 wnaf[pos - 2] -= 1 << w;
652 size_t n_wnaf =
WNAF_SIZE(bucket_window+1);
658 for (np = 0; np < num; ++np) {
659 if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) {
663 state->
ps[no].
skew_na = secp256k1_wnaf_fixed(&state->
wnaf_na[no*n_wnaf], &sc[np], bucket_window+1);
666 secp256k1_gej_set_infinity(r);
672 for (i = n_wnaf - 1; i >= 0; i--) {
676 secp256k1_gej_set_infinity(&buckets[j]);
679 for (np = 0; np < no; ++np) {
680 int n = state->
wnaf_na[np*n_wnaf + i];
687 int skew = point_state.
skew_na;
689 secp256k1_ge_neg(&tmp, &pt[point_state.
input_pos]);
690 secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL);
695 secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.
input_pos], NULL);
698 secp256k1_ge_neg(&tmp, &pt[point_state.
input_pos]);
699 secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL);
703 for(j = 0; j < bucket_window; j++) {
704 secp256k1_gej_double_var(r, r, NULL);
707 secp256k1_gej_set_infinity(&running_sum);
717 secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL);
718 secp256k1_gej_add_var(r, r, &running_sum, NULL);
721 secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL);
722 secp256k1_gej_double_var(r, r, NULL);
723 secp256k1_gej_add_var(r, r, &running_sum, NULL);
732 static int secp256k1_pippenger_bucket_window(
size_t n) {
733 #ifdef USE_ENDOMORPHISM
738 }
else if (n <= 20) {
740 }
else if (n <= 57) {
742 }
else if (n <= 136) {
744 }
else if (n <= 235) {
746 }
else if (n <= 1260) {
748 }
else if (n <= 4420) {
750 }
else if (n <= 7880) {
752 }
else if (n <= 16050) {
760 }
else if (n <= 11) {
762 }
else if (n <= 45) {
764 }
else if (n <= 100) {
766 }
else if (n <= 275) {
768 }
else if (n <= 625) {
770 }
else if (n <= 1850) {
772 }
else if (n <= 3400) {
774 }
else if (n <= 9630) {
776 }
else if (n <= 17900) {
778 }
else if (n <= 32800) {
789 static size_t secp256k1_pippenger_bucket_window_inv(
int bucket_window) {
790 switch(bucket_window) {
791 #ifdef USE_ENDOMORPHISM
801 case 10:
return 7880;
802 case 11:
return 16050;
814 case 10:
return 17900;
815 case 11:
return 32800;
823 #ifdef USE_ENDOMORPHISM
826 secp256k1_scalar_split_lambda(s1, s2, &tmp);
827 secp256k1_ge_mul_lambda(p2, p1);
829 if (secp256k1_scalar_is_high(s1)) {
830 secp256k1_scalar_negate(s1, s1);
831 secp256k1_ge_neg(p1, p1);
833 if (secp256k1_scalar_is_high(s2)) {
834 secp256k1_scalar_negate(s2, s2);
835 secp256k1_ge_neg(p2, p2);
844 static size_t secp256k1_pippenger_scratch_size(
size_t n_points,
int bucket_window) {
845 #ifdef USE_ENDOMORPHISM
846 size_t entries = 2*n_points + 2;
848 size_t entries = n_points + 1;
858 #ifdef USE_ENDOMORPHISM
859 size_t entries = 2*n_points + 2;
861 size_t entries = n_points + 1;
868 size_t point_idx = 0;
873 secp256k1_gej_set_infinity(r);
874 if (inp_g_sc == NULL && n_points == 0) {
878 bucket_window = secp256k1_pippenger_bucket_window(n_points);
879 if (!secp256k1_scratch_allocate_frame(scratch, secp256k1_pippenger_scratch_size(n_points, bucket_window),
PIPPENGER_SCRATCH_OBJECTS)) {
882 points = (
secp256k1_ge *) secp256k1_scratch_alloc(scratch, entries *
sizeof(*points));
883 scalars = (
secp256k1_scalar *) secp256k1_scratch_alloc(scratch, entries *
sizeof(*scalars));
886 state_space->
wnaf_na = (
int *) secp256k1_scratch_alloc(scratch, entries*(
WNAF_SIZE(bucket_window+1)) *
sizeof(
int));
887 buckets = (
secp256k1_gej *) secp256k1_scratch_alloc(scratch, (1<<bucket_window) *
sizeof(*buckets));
889 if (inp_g_sc != NULL) {
890 scalars[0] = *inp_g_sc;
891 points[0] = secp256k1_ge_const_g;
893 #ifdef USE_ENDOMORPHISM
894 secp256k1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]);
899 while (point_idx < n_points) {
900 if (!cb(&scalars[idx], &points[idx], point_idx + cb_offset, cbdata)) {
901 secp256k1_scratch_deallocate_frame(scratch);
905 #ifdef USE_ENDOMORPHISM
906 secp256k1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]);
912 secp256k1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx);
915 for(i = 0; (size_t)i < idx; i++) {
916 secp256k1_scalar_clear(&scalars[i]);
918 for(j = 0; j <
WNAF_SIZE(bucket_window+1); j++) {
922 for(i = 0; i < 1<<bucket_window; i++) {
923 secp256k1_gej_clear(&buckets[i]);
925 secp256k1_scratch_deallocate_frame(scratch);
931 return secp256k1_ecmult_pippenger_batch(actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
946 size_t max_points = secp256k1_pippenger_bucket_window_inv(bucket_window);
947 size_t space_for_points;
948 size_t space_overhead;
951 #ifdef USE_ENDOMORPHISM
952 entry_size = 2*entry_size;
955 if (space_overhead > max_alloc) {
958 space_for_points = max_alloc - space_overhead;
960 n_points = space_for_points/entry_size;
961 n_points = n_points > max_points ? max_points : n_points;
962 if (n_points > res) {
965 if (n_points < max_points) {
982 size_t n_batch_points;
984 secp256k1_gej_set_infinity(r);
985 if (inp_g_sc == NULL && n == 0) {
989 secp256k1_scalar_set_int(&szero, 0);
990 secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc);
994 max_points = secp256k1_pippenger_max_points(scratch);
995 if (max_points == 0) {
1000 n_batches = (n+max_points-1)/max_points;
1001 n_batch_points = (n+n_batches-1)/n_batches;
1004 f = secp256k1_ecmult_pippenger_batch;
1006 max_points = secp256k1_strauss_max_points(scratch);
1007 if (max_points == 0) {
1010 n_batches = (n+max_points-1)/max_points;
1011 n_batch_points = (n+n_batches-1)/n_batches;
1012 f = secp256k1_ecmult_strauss_batch;
1014 for(i = 0; i < n_batches; i++) {
1015 size_t nbp = n < n_batch_points ? n : n_batch_points;
1016 size_t offset = n_batch_points*i;
1018 if (!f(ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
1021 secp256k1_gej_add_var(r, r, &tmp, NULL);
int() secp256k1_ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data)
#define STRAUSS_SCRATCH_OBJECTS
#define ECMULT_TABLE_GET_GE_STORAGE(r, pre, n, w)
#define ECMULT_PIPPENGER_THRESHOLD
#define ECMULT_MAX_POINTS_PER_BATCH
#define PIPPENGER_MAX_BUCKET_WINDOW
#define ECMULT_TABLE_SIZE(w)
The number of entries a table with precomputed multiples needs to have.
#define PIPPENGER_SCRATCH_OBJECTS
int(* secp256k1_ecmult_multi_func)(const secp256k1_ecmult_context *, secp256k1_scratch *, secp256k1_gej *, const secp256k1_scalar *, secp256k1_ecmult_multi_callback cb, void *, size_t)
#define ECMULT_TABLE_GET_GE(r, pre, n, w)
The following two macro retrieves a particular odd multiple from a table of precomputed multiples.
#define WINDOW_G
larger numbers may result in slightly better performance, at the cost of exponentially larger precomp...
void * memcpy(void *a, const void *b, size_t c)
secp256k1_ge_storage(* pre_g)[]
A group element of the secp256k1 curve, in affine coordinates.
A group element of the secp256k1 curve, in jacobian coordinates.
struct secp256k1_pippenger_point_state * ps
A scalar modulo the group order of the secp256k1 curve.
struct secp256k1_strauss_point_state * ps
#define VERIFY_CHECK(cond)