Skip to content

Commit 6378b6b

Browse files
committed
batch,ecmult: Add tests for core batch APIs and strauss_batch refactor
This commit adds the following tests: 1. GitHub workflow 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 e5bbca6 commit 6378b6b

File tree

6 files changed

+376
-51
lines changed

6 files changed

+376
-51
lines changed

.github/workflows/ci.yml

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ env:
3535
SCHNORRSIG: 'no'
3636
MUSIG: 'no'
3737
ELLSWIFT: 'no'
38+
BATCH: 'no'
3839
### test options
3940
SECP256K1_TEST_ITERS: 64
4041
BENCH: 'yes'
@@ -74,18 +75,18 @@ jobs:
7475
matrix:
7576
configuration:
7677
- env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' }
77-
- env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
78+
- env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
7879
- env_vars: { WIDEMUL: 'int128' }
7980
- env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' }
80-
- env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
81-
- env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' }
81+
- env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
82+
- env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
8283
- env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' }
83-
- env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' }
84-
- env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', CPPFLAGS: '-DVERIFY' }
84+
- env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
85+
- env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CPPFLAGS: '-DVERIFY' }
8586
- env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' }
8687
- env_vars: { CPPFLAGS: '-DDETERMINISTIC' }
8788
- env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' }
88-
- env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
89+
- env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
8990
- env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 }
9091
- env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 }
9192
cc:
@@ -132,6 +133,8 @@ jobs:
132133
SCHNORRSIG: 'yes'
133134
MUSIG: 'yes'
134135
ELLSWIFT: 'yes'
136+
BATCH: 'yes'
137+
EXPERIMENTAL: 'yes'
135138
CC: ${{ matrix.cc }}
136139

137140
steps:
@@ -164,6 +167,8 @@ jobs:
164167
SCHNORRSIG: 'yes'
165168
MUSIG: 'yes'
166169
ELLSWIFT: 'yes'
170+
BATCH: 'yes'
171+
EXPERIMENTAL: 'yes'
167172
CTIMETESTS: 'no'
168173

169174
steps:
@@ -204,6 +209,8 @@ jobs:
204209
SCHNORRSIG: 'yes'
205210
MUSIG: 'yes'
206211
ELLSWIFT: 'yes'
212+
BATCH: 'yes'
213+
EXPERIMENTAL: 'yes'
207214
CTIMETESTS: 'no'
208215

209216
steps:
@@ -237,6 +244,8 @@ jobs:
237244
SCHNORRSIG: 'yes'
238245
MUSIG: 'yes'
239246
ELLSWIFT: 'yes'
247+
BATCH: 'yes'
248+
EXPERIMENTAL: 'yes'
240249
CTIMETESTS: 'no'
241250

242251
strategy:
@@ -280,6 +289,8 @@ jobs:
280289
SCHNORRSIG: 'yes'
281290
MUSIG: 'yes'
282291
ELLSWIFT: 'yes'
292+
BATCH: 'yes'
293+
EXPERIMENTAL: 'yes'
283294
CTIMETESTS: 'no'
284295

285296
steps:
@@ -321,6 +332,8 @@ jobs:
321332
SCHNORRSIG: 'yes'
322333
MUSIG: 'yes'
323334
ELLSWIFT: 'yes'
335+
BATCH: 'yes'
336+
EXPERIMENTAL: 'yes'
324337
CTIMETESTS: 'no'
325338
SECP256K1_TEST_ITERS: 2
326339

@@ -360,6 +373,8 @@ jobs:
360373
SCHNORRSIG: 'yes'
361374
MUSIG: 'yes'
362375
ELLSWIFT: 'yes'
376+
BATCH: 'yes'
377+
EXPERIMENTAL: 'yes'
363378
CTIMETESTS: 'no'
364379
CFLAGS: '-fsanitize=undefined,address -g'
365380
UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1'
@@ -413,6 +428,8 @@ jobs:
413428
SCHNORRSIG: 'yes'
414429
MUSIG: 'yes'
415430
ELLSWIFT: 'yes'
431+
BATCH: 'yes'
432+
EXPERIMENTAL: 'yes'
416433
CC: 'clang'
417434
SECP256K1_TEST_ITERS: 32
418435
ASM: 'no'
@@ -449,6 +466,8 @@ jobs:
449466
SCHNORRSIG: 'yes'
450467
MUSIG: 'yes'
451468
ELLSWIFT: 'yes'
469+
BATCH: 'yes'
470+
EXPERIMENTAL: 'yes'
452471
CTIMETESTS: 'no'
453472

454473
strategy:
@@ -492,15 +511,15 @@ jobs:
492511
fail-fast: false
493512
matrix:
494513
env_vars:
495-
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
514+
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
496515
- { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
497-
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
516+
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
498517
- { WIDEMUL: 'int128', RECOVERY: 'yes' }
499-
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
500-
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' }
501-
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
502-
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
503-
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' }
518+
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
519+
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CC: 'gcc' }
520+
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
521+
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
522+
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' }
504523
- BUILD: 'distcheck'
505524

506525
steps:
@@ -669,6 +688,8 @@ jobs:
669688
SCHNORRSIG: 'yes'
670689
MUSIG: 'yes'
671690
ELLSWIFT: 'yes'
691+
BATCH: 'yes'
692+
EXPERIMENTAL: 'yes'
672693

673694
steps:
674695
- name: Checkout

ci/ci.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ print_environment() {
1313
# does not rely on bash.
1414
for var in WERROR_CFLAGS MAKEFLAGS BUILD \
1515
ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \
16-
EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \
16+
EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT BATCH \
1717
SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS SYMBOL_CHECK \
1818
EXAMPLES \
1919
HOST WRAPPER_CMD \
@@ -80,6 +80,7 @@ esac
8080
--enable-module-extrakeys="$EXTRAKEYS" \
8181
--enable-module-schnorrsig="$SCHNORRSIG" \
8282
--enable-module-musig="$MUSIG" \
83+
--enable-module-batch="$BATCH"
8384
--enable-examples="$EXAMPLES" \
8485
--enable-ctime-tests="$CTIMETESTS" \
8586
--with-valgrind="$WITH_VALGRIND" \

src/modules/batch/Makefile.am.include

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include_HEADERS += include/secp256k1_batch.h
2-
noinst_HEADERS += src/modules/batch/main_impl.h
2+
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: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'b', 'a', 't', 'c', 'h'};
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+
/* batch object setup */
61+
secp256k1_batch *batch;
62+
unsigned char aux_rand16[32];
63+
64+
/* 16 byte auxiliary randomness */
65+
testrand256(aux_rand16);
66+
memset(&aux_rand16[16], 0, 16);
67+
68+
/** main test body **/
69+
/* batch_create tests */
70+
batch = secp256k1_batch_create(CTX, N_TERMS, aux_rand16);
71+
CHECK(batch != NULL);
72+
/* ARG_CHECK(max_terms != 0) in `batch_create` should fail*/
73+
CHECK_ILLEGAL(CTX, secp256k1_batch_create(CTX, 0, NULL));
74+
75+
#ifdef ENABLE_MODULE_EXTRAKEYS
76+
/* generate keypair data */
77+
testrand256(sk);
78+
CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1);
79+
CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair) == 1);
80+
81+
/* generate N_TWK_CHECKS tweak check data (tweaked_pk, tweaked_pk_parity, tweak) */
82+
for (i = 0; i < N_TWK_CHECKS; i++) {
83+
testrand256(tweak[i]);
84+
CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &tmp_pk, &pk, tweak[i]));
85+
CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &tmp_xonly_pk, &tweaked_pk_parity[i], &tmp_pk));
86+
CHECK(secp256k1_xonly_pubkey_serialize(CTX, tweaked_pk[i], &tmp_xonly_pk));
87+
CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, tweaked_pk[i], tweaked_pk_parity[i], &pk, tweak[i]));
88+
}
89+
/* add tweak checks to the batch object */
90+
for (i = 0; i < N_TWK_CHECKS; i++) {
91+
CHECK(secp256k1_batch_usable(CTX, batch));
92+
CHECK(secp256k1_batch_add_xonlypub_tweak_check(CTX, batch, tweaked_pk[i], tweaked_pk_parity[i], &pk, tweak[i]));
93+
}
94+
#endif
95+
96+
#ifdef ENABLE_MODULE_SCHNORRSIG
97+
/* generate N_SIGS schnorr signatures */
98+
for (i = 0; i < N_SIGS; i++) {
99+
testrand256(msg[i]);
100+
CHECK(secp256k1_schnorrsig_sign32(CTX, sig[i], msg[i], &keypair, NULL) == 1);
101+
CHECK(secp256k1_schnorrsig_verify(CTX, sig[i], msg[i], sizeof(msg[i]), &pk));
102+
}
103+
/* add schnorrsigs to the batch object */
104+
for (i = 0; i < N_SIGS; i++) {
105+
CHECK(secp256k1_batch_usable(CTX, batch) == 1);
106+
CHECK(secp256k1_batch_add_schnorrsig(CTX, batch, sig[i], msg[i], sizeof(msg[i]), &pk) == 1);
107+
}
108+
#endif
109+
110+
/* batch_verify tests */
111+
CHECK(secp256k1_batch_verify(CTX, batch) == 1);
112+
CHECK_ILLEGAL(CTX, secp256k1_batch_verify(CTX, NULL));
113+
114+
secp256k1_batch_destroy(CTX, batch);
115+
}
116+
#undef N_SIGS
117+
#undef N_TWK_CHECKS
118+
#undef N_TERMS
119+
120+
121+
void run_batch_tests(void) {
122+
test_batch_api();
123+
test_batch_sha256_tagged();
124+
}
125+
126+
#endif /* SECP256K1_MODULE_BATCH_TESTS_H */

0 commit comments

Comments
 (0)