Skip to content

Commit d0446a8

Browse files
committed
batch,ecmult: Add tests for core batch APIs and strauss_batch refactor
This commit adds the following tests: 1. Cirrus scripts 2. Batch API tests (ordered) 3. Tagged SHA256 test 4. BIP340 test vectors: https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv 5. Large random test for `strauss_batch` refactor
1 parent b3d370f commit d0446a8

File tree

6 files changed

+444
-40
lines changed

6 files changed

+444
-40
lines changed

.cirrus.yml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ env:
1818
ECDH: no
1919
RECOVERY: no
2020
SCHNORRSIG: no
21+
BATCH: no
2122
### test options
2223
SECP256K1_TEST_ITERS:
2324
BENCH: yes
@@ -67,12 +68,12 @@ task:
6768
<< : *LINUX_CONTAINER
6869
matrix: &ENV_MATRIX
6970
- env: {WIDEMUL: int64, RECOVERY: yes}
70-
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes}
71+
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, BATCH: yes}
7172
- env: {WIDEMUL: int128}
72-
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes}
73-
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes}
73+
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, BATCH: yes}
74+
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, BATCH: yes}
7475
- env: {WIDEMUL: int128, ASM: x86_64}
75-
- env: { RECOVERY: yes, SCHNORRSIG: yes}
76+
- env: { RECOVERY: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, BATCH: yes}
7677
- env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETEST: no, BENCH: no}
7778
- env: {CPPFLAGS: -DDETERMINISTIC}
7879
- env: {CFLAGS: -O0, CTIMETEST: no}
@@ -96,6 +97,8 @@ task:
9697
ECDH: yes
9798
RECOVERY: yes
9899
SCHNORRSIG: yes
100+
EXPERIMENTAL: yes
101+
BATCH: yes
99102
matrix:
100103
- env:
101104
CC: i686-linux-gnu-gcc
@@ -178,6 +181,8 @@ task:
178181
ECDH: yes
179182
RECOVERY: yes
180183
SCHNORRSIG: yes
184+
EXPERIMENTAL: yes
185+
BATCH: yes
181186
CTIMETEST: no
182187
<< : *MERGE_BASE
183188
test_script:
@@ -197,6 +202,8 @@ task:
197202
ECDH: yes
198203
RECOVERY: yes
199204
SCHNORRSIG: yes
205+
EXPERIMENTAL: yes
206+
BATCH: yes
200207
CTIMETEST: no
201208
matrix:
202209
- env: {}
@@ -217,6 +224,8 @@ task:
217224
ECDH: yes
218225
RECOVERY: yes
219226
SCHNORRSIG: yes
227+
EXPERIMENTAL: yes
228+
BATCH: yes
220229
CTIMETEST: no
221230
<< : *MERGE_BASE
222231
test_script:
@@ -234,6 +243,8 @@ task:
234243
ECDH: yes
235244
RECOVERY: yes
236245
SCHNORRSIG: yes
246+
EXPERIMENTAL: yes
247+
BATCH: yes
237248
CTIMETEST: no
238249
<< : *MERGE_BASE
239250
test_script:
@@ -271,6 +282,8 @@ task:
271282
RECOVERY: yes
272283
EXPERIMENTAL: yes
273284
SCHNORRSIG: yes
285+
EXPERIMENTAL: yes
286+
BATCH: yes
274287
CTIMETEST: no
275288
# Set non-essential options that affect the CLI messages here.
276289
# (They depend on the user's taste, so we don't want to set them automatically in configure.ac.)
@@ -304,6 +317,8 @@ task:
304317
ECDH: yes
305318
RECOVERY: yes
306319
SCHNORRSIG: yes
320+
EXPERIMENTAL: yes
321+
BATCH: yes
307322
CTIMETEST: no
308323
matrix:
309324
- name: "Valgrind (memcheck)"
@@ -352,6 +367,8 @@ task:
352367
ECDH: yes
353368
RECOVERY: yes
354369
SCHNORRSIG: yes
370+
EXPERIMENTAL: yes
371+
BATCH: yes
355372
<< : *MERGE_BASE
356373
test_script:
357374
- ./ci/cirrus.sh

ci/cirrus.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ $WRAPPER_CMD --version || true
2929
--with-ecmult-gen-precision="$ECMULTGENPRECISION" \
3030
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \
3131
--enable-module-schnorrsig="$SCHNORRSIG" \
32+
--enable-module-batch="$BATCH" \
3233
--enable-examples="$EXAMPLES" \
3334
--with-valgrind="$WITH_VALGRIND" \
3435
--host="$HOST" $EXTRAFLAGS

src/modules/batch/Makefile.am.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include_HEADERS += include/secp256k1_batch.h
22
noinst_HEADERS += src/modules/batch/main_impl.h
3+
noinst_HEADERS += src/modules/batch/tests_impl.h

src/modules/batch/tests_impl.h

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#ifndef SECP256K1_MODULE_BATCH_TESTS_H
2+
#define SECP256K1_MODULE_BATCH_TESTS_H
3+
4+
#include "../../../include/secp256k1_batch.h"
5+
#ifdef ENABLE_MODULE_SCHNORRSIG
6+
#include "../../../include/secp256k1_schnorrsig.h"
7+
#include "../../../include/secp256k1_schnorrsig_batch.h"
8+
#endif
9+
#ifdef ENABLE_MODULE_EXTRAKEYS
10+
#include "../../../include/secp256k1_extrakeys.h"
11+
#include "../../../include/secp256k1_tweak_check_batch.h"
12+
#endif
13+
14+
/* Tests for the equality of two sha256 structs. This function only produces a
15+
* correct result if an integer multiple of 64 many bytes have been written
16+
* into the hash functions. */
17+
void test_batch_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) {
18+
/* Is buffer fully consumed? */
19+
CHECK((sha1->bytes & 0x3F) == 0);
20+
21+
CHECK(sha1->bytes == sha2->bytes);
22+
CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0);
23+
}
24+
25+
/* Checks that hash initialized by secp256k1_batch_sha256_tagged has the
26+
* expected state. */
27+
void test_batch_sha256_tagged(void) {
28+
unsigned char tag[13] = "BIP0340/batch";
29+
secp256k1_sha256 sha;
30+
secp256k1_sha256 sha_optimized;
31+
32+
secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag));
33+
secp256k1_batch_sha256_tagged(&sha_optimized);
34+
test_batch_sha256_eq(&sha, &sha_optimized);
35+
}
36+
37+
#define N_SIGS 10
38+
#define N_TWK_CHECKS 10
39+
#define N_TERMS (N_TWK_CHECKS + 2*N_SIGS)
40+
void test_batch_api(void) {
41+
42+
#ifdef ENABLE_MODULE_EXTRAKEYS
43+
unsigned char sk[32];
44+
secp256k1_keypair keypair;
45+
secp256k1_xonly_pubkey pk;
46+
/* xonly pubkey tweak checks data */
47+
unsigned char tweaked_pk[N_TWK_CHECKS][32];
48+
int tweaked_pk_parity[N_TWK_CHECKS];
49+
unsigned char tweak[N_TWK_CHECKS][32];
50+
secp256k1_pubkey tmp_pk;
51+
secp256k1_xonly_pubkey tmp_xonly_pk;
52+
size_t i;
53+
#endif
54+
55+
#ifdef ENABLE_MODULE_SCHNORRSIG
56+
/* schnorr verification data */
57+
unsigned char msg[N_SIGS][32];
58+
unsigned char sig[N_SIGS][64];
59+
#endif
60+
/* context and batch setup */
61+
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
62+
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
63+
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
64+
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
65+
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
66+
secp256k1_batch *batch_none;
67+
secp256k1_batch *batch_sign;
68+
secp256k1_batch *batch_vrfy;
69+
secp256k1_batch *batch_both;
70+
secp256k1_batch *batch_sttc;
71+
unsigned char aux_rand16[32];
72+
int ecount;
73+
74+
secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
75+
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
76+
secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
77+
secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
78+
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
79+
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
80+
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
81+
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
82+
secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
83+
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
84+
85+
/* 16 byte auxiliary randomness */
86+
secp256k1_testrand256(aux_rand16);
87+
memset(&aux_rand16[16], 0, 16);
88+
89+
#ifdef ENABLE_MODULE_EXTRAKEYS
90+
/* generate keypair data */
91+
secp256k1_testrand256(sk);
92+
CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
93+
CHECK(secp256k1_keypair_xonly_pub(sign, &pk, NULL, &keypair) == 1);
94+
95+
/* generate N_TWK_CHECKS tweak check data (tweaked_pk, tweaked_pk_parity, tweak) */
96+
for (i = 0; i < N_TWK_CHECKS; i++) {
97+
secp256k1_testrand256(tweak[i]);
98+
CHECK(secp256k1_xonly_pubkey_tweak_add(vrfy, &tmp_pk, &pk, tweak[i]));
99+
CHECK(secp256k1_xonly_pubkey_from_pubkey(vrfy, &tmp_xonly_pk, &tweaked_pk_parity[i], &tmp_pk));
100+
CHECK(secp256k1_xonly_pubkey_serialize(vrfy, tweaked_pk[i], &tmp_xonly_pk));
101+
CHECK(secp256k1_xonly_pubkey_tweak_add_check(vrfy, tweaked_pk[i], tweaked_pk_parity[i], &pk, tweak[i]));
102+
}
103+
#endif
104+
105+
#ifdef ENABLE_MODULE_SCHNORRSIG
106+
/* generate N_SIGS schnorr verify data (msg, sig) */
107+
for (i = 0; i < N_SIGS; i++) {
108+
secp256k1_testrand256(msg[i]);
109+
CHECK(secp256k1_schnorrsig_sign32(sign, sig[i], msg[i], &keypair, NULL) == 1);
110+
CHECK(secp256k1_schnorrsig_verify(vrfy, sig[i], msg[i], sizeof(msg[i]), &pk));
111+
}
112+
#endif
113+
114+
/** main test body **/
115+
/* batch_create tests */
116+
ecount = 0;
117+
batch_none = secp256k1_batch_create(none, 1, NULL);
118+
CHECK(batch_none != NULL);
119+
CHECK(ecount == 0);
120+
/* 2*N_SIGS since one schnorrsig creates two scalar-point pair in batch */
121+
batch_sign = secp256k1_batch_create(sign, 2*N_SIGS, NULL);
122+
CHECK(batch_sign != NULL);
123+
CHECK(ecount == 0);
124+
batch_vrfy = secp256k1_batch_create(vrfy, N_TWK_CHECKS - 1, aux_rand16);
125+
CHECK(batch_vrfy != NULL);
126+
CHECK(ecount == 0);
127+
batch_both = secp256k1_batch_create(both, N_TERMS/4, aux_rand16);
128+
CHECK(batch_both != NULL);
129+
CHECK(ecount == 0);
130+
/* ARG_CHECK(max_terms != 0) in `batch_create` should fail*/
131+
batch_sttc = secp256k1_batch_create(sttc, 0, NULL);
132+
CHECK(batch_sttc == NULL);
133+
CHECK(ecount == 1);
134+
135+
#ifdef ENABLE_MODULE_SCHNORRSIG
136+
ecount = 0;
137+
for (i = 0; i < N_SIGS; i++) {
138+
CHECK(secp256k1_batch_usable(sign, batch_sign) == 1);
139+
CHECK(ecount == 0);
140+
CHECK(secp256k1_batch_add_schnorrsig(sign, batch_sign, sig[i], msg[i], sizeof(msg[i]), &pk) == 1);
141+
CHECK(ecount == 0);
142+
}
143+
#endif
144+
145+
#ifdef ENABLE_MODULE_EXTRAKEYS
146+
ecount = 0;
147+
for (i = 0; i < N_TWK_CHECKS; i++) {
148+
CHECK(secp256k1_batch_usable(vrfy, batch_vrfy));
149+
CHECK(ecount == 0);
150+
CHECK(secp256k1_batch_add_xonlypub_tweak_check(vrfy, batch_vrfy, tweaked_pk[i], tweaked_pk_parity[i], &pk, tweak[i]));
151+
CHECK(ecount == 0);
152+
}
153+
#endif
154+
155+
#if defined(ENABLE_MODULE_SCHNORRSIG) && defined(ENABLE_MODULE_EXTRAKEYS)
156+
/* secp256k1_batch_add_tests for batch_both */
157+
ecount = 0;
158+
for (i = 0; i < N_SIGS; i++) {
159+
CHECK(secp256k1_batch_usable(both, batch_both) == 1);
160+
CHECK(ecount == 0);
161+
CHECK(secp256k1_batch_add_schnorrsig(both, batch_both, sig[i], msg[i], sizeof(msg[i]), &pk) == 1);
162+
CHECK(ecount == 0);
163+
}
164+
for (i = 0; i < N_TWK_CHECKS; i++) {
165+
CHECK(secp256k1_batch_usable(both, batch_both));
166+
CHECK(ecount == 0);
167+
CHECK(secp256k1_batch_add_xonlypub_tweak_check(both, batch_both, tweaked_pk[i], tweaked_pk_parity[i], &pk, tweak[i]));
168+
CHECK(ecount == 0);
169+
}
170+
#endif
171+
172+
/* batch_verify tests */
173+
ecount = 0;
174+
CHECK(secp256k1_batch_verify(none, batch_none) == 1);
175+
CHECK(ecount == 0);
176+
CHECK(secp256k1_batch_verify(sign, batch_sign) == 1);
177+
CHECK(ecount == 0);
178+
CHECK(secp256k1_batch_verify(vrfy, batch_vrfy) == 1);
179+
CHECK(ecount == 0);
180+
CHECK(secp256k1_batch_verify(both, batch_both) == 1);
181+
CHECK(ecount == 0);
182+
CHECK(secp256k1_batch_verify(sttc, NULL) == 0);
183+
CHECK(ecount == 1);
184+
185+
ecount = 0;
186+
secp256k1_batch_destroy(none, batch_none);
187+
CHECK(ecount == 0);
188+
secp256k1_batch_destroy(sign, batch_sign);
189+
CHECK(ecount == 0);
190+
secp256k1_batch_destroy(vrfy, batch_vrfy);
191+
CHECK(ecount == 0);
192+
secp256k1_batch_destroy(both, batch_both);
193+
CHECK(ecount == 0);
194+
secp256k1_batch_destroy(sttc, NULL);
195+
CHECK(ecount == 0);
196+
197+
secp256k1_context_destroy(none);
198+
secp256k1_context_destroy(sign);
199+
secp256k1_context_destroy(vrfy);
200+
secp256k1_context_destroy(both);
201+
secp256k1_context_destroy(sttc);
202+
}
203+
#undef N_SIGS
204+
#undef N_TWK_CHECKS
205+
#undef N_TERMS
206+
207+
208+
void run_batch_tests(void) {
209+
test_batch_api();
210+
test_batch_sha256_tagged();
211+
}
212+
213+
#endif /* SECP256K1_MODULE_BATCH_TESTS_H */

0 commit comments

Comments
 (0)