11 "This script converts BIP MuSig2 test vectors in a given directory to a C file that can be used in the test framework."
13 print(
"Usage: %s <dir>" % sys.argv[0])
18 return ", ".join([f
"0x{b:02X}" for b
in bytes.fromhex(str)])
23static const struct musig_%s_vector musig_%s_vector = {
35 s = textwrap.indent(
"{\n", 4 *
" ")
39 s += textwrap.indent(
"\n},\n", 4 *
" ")
44 return " %d, { %s }" % (
46 ", ".join(map(str, array)
if len(array) > 0
else "0"),
51 if len(case[
"tweak_indices"]) > 0:
52 return ", ".join(map(
lambda x:
"1" if x
else "0", case[
"is_xonly"]))
61 s = textwrap.indent(
"{\n", 4 *
" ")
62 for (i, case)
in enumerate(cases):
63 s += textwrap.indent(
"%s\n" % f(case), 8 *
" ")
64 s += textwrap.indent(
"},\n", 4 *
" ")
74 * Automatically generated by %s.
76 * The test vectors for the KeySort function are included in this file. They can
77 * be found in src/modules/extrakeys/tests_impl.h. */
97with open(sys.argv[1] + "/key_agg_vectors.json", "r") as f:
100 max_key_indices = max(
101 len(test_case["key_indices"])
for test_case
in data[
"valid_test_cases"]
103 max_tweak_indices = max(
104 len(test_case[
"tweak_indices"])
for test_case
in data[
"error_test_cases"]
106 num_pubkeys = len(data[
"pubkeys"])
107 max_pubkeys = max(num_pubkeys, max_pubkeys)
108 num_tweaks = len(data[
"tweaks"])
109 num_valid_cases = len(data[
"valid_test_cases"])
110 num_error_cases = len(data[
"error_test_cases"])
115struct musig_key_agg_valid_test_case {
116 size_t key_indices_len;
117 size_t key_indices[%d];
118 unsigned char expected[32];
124struct musig_key_agg_error_test_case {
125 size_t key_indices_len;
126 size_t key_indices[%d];
127 size_t tweak_indices_len;
128 size_t tweak_indices[%d];
130 enum MUSIG_ERROR error;
140struct musig_key_agg_vector {
141 unsigned char pubkeys[%d][33];
142 unsigned char tweaks[%d][32];
143 struct musig_key_agg_valid_test_case valid_case[%d];
144 struct musig_key_agg_error_test_case error_case[%d];
160 data[
"valid_test_cases"],
161 lambda case:
"{ %s, { %s }},"
166 comment = case[
"comment"]
167 if "public key" in comment.lower():
168 return "MUSIG_PUBKEY"
169 elif "tweak" in comment.lower():
172 sys.exit(
"Unknown error")
176 data[
"error_test_cases"],
177 lambda case:
"{ %s, %s, { %s }, %s },"
189with open(sys.argv[1] +
"/nonce_gen_vectors.json",
"r")
as f:
193 data[
"test_cases"] = list(
194 filter(
lambda c: c[
"msg"]
is None or len(c[
"msg"]) == 64, data[
"test_cases"])
197 num_tests = len(data[
"test_cases"])
200struct musig_nonce_gen_test_case {
201 unsigned char rand_[32];
203 unsigned char sk[32];
204 unsigned char pk[33];
206 unsigned char aggpk[32];
208 unsigned char msg[32];
210 unsigned char extra_in[32];
211 unsigned char expected_secnonce[97];
212 unsigned char expected_pubnonce[66];
218struct musig_nonce_gen_vector {
219 struct musig_nonce_gen_test_case test_case[%d];
228 return "%d , { %s }" % (
229 0
if array
is None else 1,
235 lambda case:
"{ { %s }, %s, { %s }, %s, %s, %s, { %s }, { %s } },"
251with open(sys.argv[1] +
"/nonce_agg_vectors.json",
"r")
as f:
254 num_pnonces = len(data[
"pnonces"])
255 num_valid_cases = len(data[
"valid_test_cases"])
256 num_error_cases = len(data[
"error_test_cases"])
258 pnonce_indices_len = 2
259 for case
in data[
"valid_test_cases"] + data[
"error_test_cases"]:
260 assert len(case[
"pnonce_indices"]) == pnonce_indices_len
264struct musig_nonce_agg_test_case {
265 size_t pnonce_indices[2];
267 unsigned char expected[66];
269 int invalid_nonce_idx;
274struct musig_nonce_agg_vector {
275 unsigned char pnonces[%d][66];
276 struct musig_nonce_agg_test_case valid_case[%d];
277 struct musig_nonce_agg_test_case error_case[%d];
288 for cases
in (data[
"valid_test_cases"], data[
"error_test_cases"]):
291 lambda case:
"{ { %s }, { %s }, %d },"
293 ", ".join(map(str, case[
"pnonce_indices"])),
295 case[
"error"][
"signer"]
if "error" in case
else 0,
301with open(sys.argv[1] +
"/sign_verify_vectors.json",
"r")
as f:
305 assert list(filter(
lambda x: len(x) == 64, data[
"msgs"]))[0] == data[
"msgs"][0]
306 data[
"msgs"] = [data[
"msgs"][0]]
309 return list(filter(
lambda x: x[
"msg_index"] == 0, data[k]))
311 data[
"valid_test_cases"] =
filter_msg32(
"valid_test_cases")
312 data[
"sign_error_test_cases"] =
filter_msg32(
"sign_error_test_cases")
313 data[
"verify_error_test_cases"] =
filter_msg32(
"verify_error_test_cases")
314 data[
"verify_fail_test_cases"] =
filter_msg32(
"verify_fail_test_cases")
316 num_pubkeys = len(data[
"pubkeys"])
317 max_pubkeys = max(num_pubkeys, max_pubkeys)
318 num_secnonces = len(data[
"secnonces"])
319 num_pubnonces = len(data[
"pnonces"])
320 num_aggnonces = len(data[
"aggnonces"])
321 num_msgs = len(data[
"msgs"])
322 num_valid_cases = len(data[
"valid_test_cases"])
323 num_sign_error_cases = len(data[
"sign_error_test_cases"])
324 num_verify_fail_cases = len(data[
"verify_fail_test_cases"])
325 num_verify_error_cases = len(data[
"verify_error_test_cases"])
328 data[
"valid_test_cases"]
329 + data[
"sign_error_test_cases"]
330 + data[
"verify_error_test_cases"]
331 + data[
"verify_fail_test_cases"]
333 max_key_indices = max(len(test_case[
"key_indices"])
for test_case
in all_cases)
334 max_nonce_indices = max(
335 len(test_case[
"nonce_indices"])
if "nonce_indices" in test_case
else 0
336 for test_case
in all_cases
341/* Omit pubnonces in the test vectors because our partial signature verification
342 * implementation is able to accept the aggnonce directly. */
343struct musig_valid_case {
344 size_t key_indices_len;
345 size_t key_indices[%d];
346 size_t aggnonce_index;
349 unsigned char expected[32];
357struct musig_sign_error_case {
358 size_t key_indices_len;
359 size_t key_indices[%d];
360 size_t aggnonce_index;
362 size_t secnonce_index;
363 enum MUSIG_ERROR error;
370struct musig_verify_fail_error_case {
371 unsigned char sig[32];
372 size_t key_indices_len;
373 size_t key_indices[%d];
374 size_t nonce_indices_len;
375 size_t nonce_indices[%d];
378 enum MUSIG_ERROR error;
387struct musig_sign_verify_vector {
388 unsigned char sk[32];
389 unsigned char pubkeys[%d][33];
390 unsigned char secnonces[%d][194];
391 unsigned char pubnonces[%d][194];
392 unsigned char aggnonces[%d][66];
393 unsigned char msgs[%d][32];
394 struct musig_valid_case valid_case[%d];
395 struct musig_sign_error_case sign_error_case[%d];
396 struct musig_verify_fail_error_case verify_fail_case[%d];
397 struct musig_verify_fail_error_case verify_error_case[%d];
406 num_sign_error_cases,
407 num_verify_fail_cases,
408 num_verify_error_cases,
420 data[
"valid_test_cases"],
421 lambda case:
"{ %s, %d, %d, %d, { %s }},"
424 case[
"aggnonce_index"],
426 case[
"signer_index"],
432 comment = case[
"comment"]
433 if "pubkey" in comment
or "public key" in comment:
434 return "MUSIG_PUBKEY"
435 elif "Aggregate nonce" in comment:
436 return "MUSIG_AGGNONCE"
437 elif "Secnonce" in comment:
438 return "MUSIG_SECNONCE"
440 sys.exit(
"Unknown sign error")
443 data[
"sign_error_test_cases"],
444 lambda case:
"{ %s, %d, %d, %d, %s },"
447 case[
"aggnonce_index"],
449 case[
"secnonce_index"],
455 comment = case[
"comment"]
456 if "exceeds" in comment:
458 elif "Wrong signer" in comment
or "Wrong signature" in comment:
459 return "MUSIG_SIG_VERIFY"
460 elif "pubnonce" in comment:
461 return "MUSIG_PUBNONCE"
462 elif "pubkey" in comment:
463 return "MUSIG_PUBKEY"
465 sys.exit(
"Unknown verify error")
467 for cases
in (
"verify_fail_test_cases",
"verify_error_test_cases"):
470 lambda case:
"{ { %s }, %s, %s, %d, %d, %s },"
476 case[
"signer_index"],
484with open(sys.argv[1] +
"/tweak_vectors.json",
"r")
as f:
487 num_pubkeys = len(data[
"pubkeys"])
488 max_pubkeys = max(num_pubkeys, max_pubkeys)
489 num_pubnonces = len(data[
"pnonces"])
490 num_tweaks = len(data[
"tweaks"])
491 num_valid_cases = len(data[
"valid_test_cases"])
492 num_error_cases = len(data[
"error_test_cases"])
494 all_cases = data[
"valid_test_cases"] + data[
"error_test_cases"]
495 max_key_indices = max(len(test_case[
"key_indices"])
for test_case
in all_cases)
496 max_tweak_indices = max(len(test_case[
"tweak_indices"])
for test_case
in all_cases)
497 max_nonce_indices = max(len(test_case[
"nonce_indices"])
for test_case
in all_cases)
500struct musig_tweak_case {
501 size_t key_indices_len;
502 size_t key_indices[%d];
503 size_t nonce_indices_len;
504 size_t nonce_indices[%d];
505 size_t tweak_indices_len;
506 size_t tweak_indices[%d];
509 unsigned char expected[32];
520struct musig_tweak_vector {
521 unsigned char sk[32];
522 unsigned char secnonce[97];
523 unsigned char aggnonce[66];
524 unsigned char msg[32];
525 unsigned char pubkeys[%d][33];
526 unsigned char pubnonces[%d][194];
527 unsigned char tweaks[%d][32];
528 struct musig_tweak_case valid_case[%d];
529 struct musig_tweak_case error_case[%d];
548 data[
"valid_test_cases"],
549 lambda case:
"{ %s, %s, %s, { %s }, %d, { %s }},"
555 case[
"signer_index"],
561 data[
"error_test_cases"],
562 lambda case:
"{ %s, %s, %s, { %s }, %d, { %s }},"
568 case[
"signer_index"],
576with open(sys.argv[1] +
"/sig_agg_vectors.json",
"r")
as f:
579 num_pubkeys = len(data[
"pubkeys"])
580 max_pubkeys = max(num_pubkeys, max_pubkeys)
581 num_tweaks = len(data[
"tweaks"])
582 num_psigs = len(data[
"psigs"])
583 num_valid_cases = len(data[
"valid_test_cases"])
584 num_error_cases = len(data[
"error_test_cases"])
586 all_cases = data[
"valid_test_cases"] + data[
"error_test_cases"]
587 max_key_indices = max(len(test_case[
"key_indices"])
for test_case
in all_cases)
588 max_tweak_indices = max(len(test_case[
"tweak_indices"])
for test_case
in all_cases)
589 max_psig_indices = max(len(test_case[
"psig_indices"])
for test_case
in all_cases)
593/* Omit pubnonces in the test vectors because they're only needed for
594 * implementations that do not directly accept an aggnonce. */
595struct musig_sig_agg_case {
596 size_t key_indices_len;
597 size_t key_indices[%d];
598 size_t tweak_indices_len;
599 size_t tweak_indices[%d];
601 unsigned char aggnonce[66];
602 size_t psig_indices_len;
603 size_t psig_indices[%d];
605 unsigned char expected[64];
618struct musig_sig_agg_vector {
619 unsigned char pubkeys[%d][33];
620 unsigned char tweaks[%d][32];
621 unsigned char psigs[%d][32];
622 unsigned char msg[32];
623 struct musig_sig_agg_case valid_case[%d];
624 struct musig_sig_agg_case error_case[%d];
640 for cases
in (data[
"valid_test_cases"], data[
"error_test_cases"]):
643 lambda case:
"{ %s, %s, { %s }, { %s }, %s, { %s }, %d },"
651 case[
"error"][
"signer"]
if "error" in case
else 0,
655s +=
"enum { MUSIG_VECTORS_MAX_PUBKEYS = %d };" % max_pubkeys
def comment_to_error(case)
def init_array_maybe(array)
def hexstr_to_intarray(str)
def init_optional_expected(case)