Skip to content

Commit 40839e2

Browse files
committed
Merge bitcoin-core#592: Use trivial algorithm in ecmult_multi if scratch space is small
9ab96f7 Use trivial algorithm in ecmult_multi if scratch space is small (Jonas Nick) Pull request description: `ecmult_multi` already selects the trivial algorithm if the scratch space is NULL. With this PR the trivial algorithm is also selected if the scratch space is too small to use pippenger or strauss instead of returning 0. That makes it more easier to avoid consensus relevant inconsistencies just because scratch space construction was messed up. ACKs for commit 9ab96f: real-or-random: utACK 9ab96f7 Tree-SHA512: aa451adf8880af15cf167a59cb07fc411edc43f26c8eb0873bdae2774382ba182e2a1c54487912f8f2999cb0402d554b9d293e2fb9483234471348a1f43c6653
2 parents a484e00 + 9ab96f7 commit 40839e2

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed

src/ecmult_impl.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,16 +1174,18 @@ static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp2
11741174
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
11751175
}
11761176

1177-
/* Compute the batch sizes for pippenger given a scratch space. If it's greater than a threshold
1178-
* use pippenger. Otherwise use strauss */
1177+
/* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than
1178+
* a threshold use Pippenger's algorithm. Otherwise use Strauss' algorithm.
1179+
* As a first step check if there's enough space for Pippenger's algo (which requires less space
1180+
* than Strauss' algo) and if not, use the simple algorithm. */
11791181
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(scratch), n)) {
1180-
return 0;
1182+
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
11811183
}
11821184
if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) {
11831185
f = secp256k1_ecmult_pippenger_batch;
11841186
} else {
11851187
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(scratch), n)) {
1186-
return 0;
1188+
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
11871189
}
11881190
f = secp256k1_ecmult_strauss_batch;
11891191
}

src/tests.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,7 +2649,6 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
26492649
secp256k1_gej r;
26502650
secp256k1_gej r2;
26512651
ecmult_multi_data data;
2652-
secp256k1_scratch *scratch_empty;
26532652

26542653
data.sc = sc;
26552654
data.pt = pt;
@@ -2684,11 +2683,6 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
26842683
secp256k1_gej_add_var(&r, &r, &r2, NULL);
26852684
CHECK(secp256k1_gej_is_infinity(&r));
26862685

2687-
/* Try to multiply 1 point, but scratch space is empty */
2688-
scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0);
2689-
CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
2690-
secp256k1_scratch_destroy(scratch_empty);
2691-
26922686
/* Try to multiply 1 point, but callback returns false */
26932687
CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
26942688

@@ -2886,6 +2880,24 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
28862880
}
28872881
}
28882882

2883+
void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) {
2884+
secp256k1_scalar szero;
2885+
secp256k1_scalar sc[32];
2886+
secp256k1_ge pt[32];
2887+
secp256k1_gej r;
2888+
ecmult_multi_data data;
2889+
secp256k1_scratch *scratch_empty;
2890+
2891+
data.sc = sc;
2892+
data.pt = pt;
2893+
secp256k1_scalar_set_int(&szero, 0);
2894+
2895+
/* Try to multiply 1 point, but scratch space is empty.*/
2896+
scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0);
2897+
CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
2898+
secp256k1_scratch_destroy(scratch_empty);
2899+
}
2900+
28892901
void test_secp256k1_pippenger_bucket_window_inv(void) {
28902902
int i;
28912903

@@ -3009,19 +3021,25 @@ void test_ecmult_multi_batching(void) {
30093021
}
30103022
data.sc = sc;
30113023
data.pt = pt;
3024+
secp256k1_gej_neg(&r2, &r2);
30123025

3013-
/* Test with empty scratch space */
3026+
/* Test with empty scratch space. It should compute the correct result using
3027+
* ecmult_mult_simple algorithm which doesn't require a scratch space. */
30143028
scratch = secp256k1_scratch_create(&ctx->error_callback, 0);
3015-
CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1));
3029+
CHECK(secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
3030+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
3031+
CHECK(secp256k1_gej_is_infinity(&r));
30163032
secp256k1_scratch_destroy(scratch);
30173033

30183034
/* Test with space for 1 point in pippenger. That's not enough because
3019-
* ecmult_multi selects strauss which requires more memory. */
3035+
* ecmult_multi selects strauss which requires more memory. It should
3036+
* therefore select the simple algorithm. */
30203037
scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT);
3021-
CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1));
3038+
CHECK(secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
3039+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
3040+
CHECK(secp256k1_gej_is_infinity(&r));
30223041
secp256k1_scratch_destroy(scratch);
30233042

3024-
secp256k1_gej_neg(&r2, &r2);
30253043
for(i = 1; i <= n_points; i++) {
30263044
if (i > ECMULT_PIPPENGER_THRESHOLD) {
30273045
int bucket_window = secp256k1_pippenger_bucket_window(i);
@@ -3049,7 +3067,9 @@ void run_ecmult_multi_tests(void) {
30493067
test_ecmult_multi(scratch, secp256k1_ecmult_multi_var);
30503068
test_ecmult_multi(NULL, secp256k1_ecmult_multi_var);
30513069
test_ecmult_multi(scratch, secp256k1_ecmult_pippenger_batch_single);
3070+
test_ecmult_multi_batch_single(secp256k1_ecmult_pippenger_batch_single);
30523071
test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single);
3072+
test_ecmult_multi_batch_single(secp256k1_ecmult_strauss_batch_single);
30533073
secp256k1_scratch_destroy(scratch);
30543074

30553075
/* Run test_ecmult_multi with space for exactly one point */

0 commit comments

Comments
 (0)